Токенизация оставшихся данных с помощью lex/yacc

Простите меня, я совсем новичок в парсинге и lex/yacc, и я, вероятно, запутался, но тем не менее:

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

Серая область — это ввод, состоящий из частей, похожих на уравнения, которые синтаксический анализатор возьмет и обработает. Это не то, что я хочу - мне нужно иметь возможность определить, не были ли выбраны и размечены части строки, чтобы я мог вернуть ошибку, но я понятия не имею, как это сделать.

Кто-нибудь знает, как я могу определить, в основном, токен «поймай все, что осталось»? Или есть лучший способ справиться с этим?


person bck    schedule 08.05.2009    source источник


Ответы (4)


В yacc есть встроенный токен error. Обычно вы делаете что-то вроде:

line: goodline | badline ;

badline : error '\n' /* Error-handling action, if needed */

goodline : equation '\n' ;

Любая строка, не соответствующая equation, будет обработана badline.

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

person Don    schedule 08.05.2009
comment
В этом была хитрость. Я добавил токен t_error, который только что вернул false, и все происходит отлично. Спасибо! - person bck; 12.05.2009

Определите токен (конец ввода) и заставьте ваш лексер выводить его в конце ввода.

Итак, раньше, если у вас были эти токены:

'1' 'PLUS' '1'

Теперь у вас будет:

'1' 'PLUS' '1' 'END_OF_INPUT'

Теперь вы можете определить свое правило верхнего уровня в своем синтаксическом анализаторе. Вместо (например):

Equation ::= EXPRESSION

У вас будет

Equation ::= EXPRESSION END_OF_INPUT

Очевидно, вам придется переписать их в синтаксисе PLY, но это должно помочь вам в большинстве случаев.

person Community    schedule 11.05.2009
comment
Точно так же работает стандартный yacc — он принимает только тогда, когда больше не осталось токенов. - person Ingo; 25.10.2010

Обычно я использую отдельный «командный считыватель» для получения полной команды — возможно, строки в вашем случае — в строку переменной хоста, а затем организую, чтобы лексический анализатор анализировал строку, в том числе сообщал мне, когда она не достигла конец. Это сложно настроить, но это упрощает отчеты об ошибках для некоторых классов. В одном из мест, где я обычно использовал эту технику, есть многострочные команды с 3 соглашениями о комментариях, два набора строк в кавычках и некоторые другие гадости, чтобы набить мне зубы (контекстно-зависимая токенизация - фу!).

В противном случае совет Дона с токеном «ошибка» Yacc хорош.

person Jonathan Leffler    schedule 09.05.2009

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

Вы говорите, что используете PLY, но не потому ли, что хотите, чтобы компилятор работал в среде Python? Если это так, вы можете рассмотреть и другие инструменты. Для таких заданий я часто использую ANTLR (http://www.antlr.org), в котором есть генератор кода Python. . В ANTLR есть множество приемов для выполнения таких задач, как прием большого количества входных данных на уровне лексера, чтобы синтаксический анализатор их никогда не видел (например, комментарии), возможность вызова подправила (например, уравнения) в рамках более крупной грамматики (которая должна завершиться, как только правило было сопоставлено без обработки каких-либо дополнительных входных данных... похоже на то, что вы хотите сделать) и очень хороший алгоритм левого факторинга.

Возможность синтаксического анализа ANTLR в сочетании с использованием механизма StringTemplate (http://www.stringtemplate.org) делает хорошая комбинация, и оба поддерживают Python (среди многих других).

person Michael Tiller    schedule 12.05.2009