Как обрабатывать присваивание и переменный синтаксис в интерпретаторе - PullRequest
0 голосов
/ 16 декабря 2018

Большинство интерпретаторов позволяют вам набрать на своей консоли следующее:

>> a = 2
>> a+3
5
>>

Мой вопрос: какие механизмы обычно используются для обработки этого синтаксиса?Каким-то образом синтаксический анализатор может различать присваивание и выражение, даже если они оба могут начинаться с цифры или буквы.Только когда мы получим второй токен, вы узнаете, есть ли у вас назначение или нет.В прошлом я смотрел вперед два токена, и, если второй токен не равен, я толкаю токены обратно в лексический поток и предполагаю, что это выражение.Я полагаю, что можно было бы рассматривать назначение как выражение, которое, я думаю, делают некоторые языки.Я думал об использовании левого факторинга, но я не вижу его работоспособным.

Например,

assignment = variable A
A = '=' expression | empty

Обновление Я нашел этот вопрос в StackOverflow, который отвечает на тот же вопрос: Как изменить грамматику синтаксического анализа, чтобы разрешить операторы присваивания и не присваивания?

1 Ответ

0 голосов
/ 16 декабря 2018

Исходя из того, как вы описываете свой подход - сделав несколько жетонов упреждения, чтобы решить, как обращаться с вещами, - похоже, что вы пытаетесь написать некий нисходящий синтаксический анализатор в соответствии с LL (1)или анализатор LL (2), и вы пытаетесь сразу решить, является ли анализируемое вами выражение переменным присваиванием или арифметическим выражением.Есть несколько способов, которыми вы могли бы анализировать подобные выражения вполне естественным образом, и они, по сути, включают в себя ослабление одного из этих двух предположений.

Первый способ, которым мы могли бы сделать это, - это отказаться от использования синтаксического анализатора, работающего сверху внизпарсер LL (1) или LL (2) для чего-то другого, например парсер LR (0) или SLR (1).Эти парсеры работают снизу вверх, читая большие префиксы входной строки, прежде чем решить, на что они смотрят.В вашем случае анализатор снизу вверх может работать, видя переменную и думая: «Хорошо, я либо собираюсь читать выражение для печати, либо оператор присваивания, но с тем, что я видел до сих пор, я не могупередайте либо ", затем сканируйте больше токенов, чтобы увидеть, что будет дальше.Если они видят знак равенства, отлично!Это заявление о назначении.Если они видят что-то еще, отлично!Это не.Хорошая часть этого заключается в том, что если вы используете стандартный алгоритм синтаксического анализа снизу вверх, такой как LR (0), SLR (1), LALR (1) или LR (1), вы, вероятно, обнаружите, что анализатор обычно обрабатываетпроблемы такого рода достаточно хороши, и никакой специальной логики не требуется.

Другой вариант - проанализировать все выражение, предполагая, что = является допустимым двоичным оператором, как любая другая операция, а затем проверить, является ли чтоВы проанализировали это законное заявление о назначении или нет.Например, если вы используете алгоритм разбора Dijkstra для анализа, вы можете восстановить дерево разбора для всего выражения, независимо от того, является ли оно арифметическим выражением или присваиванием.Затем вы можете пройтись по дереву разбора, чтобы задать вопросы типа

  • , если операция верхнего уровня является присваиванием, является ли левая часть единственной переменной?

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

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

...