Как управлять компоновкой в разных частях синтаксиса?

#rascal

#rascal

Вопрос:

Я смотрю на пример Exp в руководстве.

Можно ли управлять компоновкой условно? Рассмотрим, например, выражения Python:

  • Новые строки не имеют значения, находясь внутри выражения, заключенного в скобки
  • В противном случае новая строка является терминатором оператора / выражения

Например: (1 n 3)

является допустимым выражением, но 1 n 3

нет.

Если нет, то каков был бы самый простой способ добиться того же результата, если не добавлять новые строки в мою грамматику?

Ответ №1:

Да, это возможно:

  • если вы используете layout нетерминал L в syntax правиле между двумя обычными символами A и B примерно так: syntax NY = «foo» A L B «bar», тогда Rascal не добавит больше нетерминалов разметки между A и L или между L и B
  • вы можете добавить в свою грамматику нетерминалы компоновки, которые не вставляются автоматически все время (для использования в первом пункте), например: layout NoNewLineLayout = @manual [t ]*;

Таким образом, для этого требуется разбрызгивать экземпляры символов NoNewLineLayout в вашей грамматике, а не разбрызгивать новые строки. Обычно я использую короткое имя, например NNL, чтобы сделать это менее навязчивым. Мы использовали этот обходной путь для экспериментов с грамматиками Javascript и другими языками, чувствительными к разметке. В целом, хотя это не идеально, и мы работаем над более элегантными решениями, см. http://dl.acm.org/citation.cfm?id=2814242 для предварительного просмотра.

Второе, менее гибкое решение — использовать область layout определений (которая ограничена модулем). Определение компоновки в текущем модуле имеет приоритет над любыми импортированными определениями компоновки. Таким образом, можно влиять на то, какая нетерминальная компоновка вплетена в какие правила. Это в основном удобно при встраивании языков в другие языки, которые могут иметь разные соглашения о комментариях и тому подобное; для текущего варианта использования я бы этого не советовал.

Комментарии:

1. Спасибо за ответ. Я рассматривал возможность использования области определения макета, определяя выражения, например, в expr.rsc, а затем используя expr_w.rsc, который добавляет макет новой строки и выражение в квадратных скобках, а затем составлял свой окончательный синтаксис из двух, но я не смог заставить его работать. Я попробую другие предложения.

2. (Извините, пришлось разделить на длину) Наконец, в качестве еще одной возможности: поскольку вы упомянули, что макет может содержать нетерминалы: может иметь действие над скобками, которое установит флаг для входа / выхода, а затем использовать нетерминал действие на макете, и «сбой»анализировать, включен ли » n» вне скобок?

3. Грамматики Rascal не имеют побочных эффектов, так что это невозможно сделать. Однако вы могли бы написать фильтр после синтаксического анализа: см. tutor.rascal-mpl.org/Rascal/Rascal.html#/Rascal/Declarations/… . Это просто шаблоны дерева синтаксического анализа, применяемые при построении дерева, которые позволяют вам переписывать его по мере его создания или фильтровать альтернативы, которые вы хотите удалить. Это медленнее, чем исправление грамматики, и в зависимости от кода фильтра может быть слишком медленным. Обычно это тоже трудно понять. Я предпочитаю решение, зависящее от данных, от Afroozeh и Izmaylova, которое мы добавим.