Токенизация оставшихся данных с помощью lex / yacc
Вопрос
Простите меня, я совершенно новичок в синтаксическом анализе и lex / yacc, и я, вероятно, перегибаю палку, но тем не менее:
Я пишу довольно простой калькулятор с помощью PLY, но его входные данные не всегда могут быть уравнением, и мне нужно определить, так это или нет, при синтаксическом анализе.Крайними значениями входных данных было бы что-то, что идеально соответствует уравнению, которое оно прекрасно анализирует и вычисляет, или что-то, что совсем не похоже на уравнение, которое не поддается синтаксическому анализу и тоже нормально.
Серая область - это входные данные, содержащие части, похожие на уравнения, из которых синтаксический анализатор будет извлекать и обрабатывать.Это не то, чего я хочу - мне нужно иметь возможность определить, не были ли части строки подобраны и помечены, чтобы я мог выдать ошибку, но я понятия не имею, как это сделать.
Кто-нибудь знает, как я могу определить, по сути, токен "поймать все, что осталось"?Или есть лучший способ, которым я могу справиться с этим?
Решение
Имеется встроенный error
токен в yacc.Обычно вы бы сделали что-то вроде:
линия:хорошая линия | плохая линия ;
плохая линия :ошибка '\ n' /* Действие по обработке ошибок, если необходимо */
goodline : equation '\n' ;
Любая строка, которая не совпадает equation
будет обработан badline
.
Возможно, вы захотите использовать yyerrok
в действии обработки ошибок, чтобы гарантировать, что обработка ошибок будет сброшена для следующей строки.
Другие советы
Определите токен (конец ввода) и сделайте так, чтобы ваш лексер выводил его в конце ввода.
Так что раньше, если у вас были эти токены:
'1' 'PLUS' '1'
Теперь у вас есть:
'1' 'PLUS' '1' 'END_OF_INPUT'
Теперь вы можете определить правило верхнего уровня в вашем парсере. Вместо (например):
Equation ::= EXPRESSION
У вас будет
Equation ::= EXPRESSION END_OF_INPUT
Очевидно, вам придется переписать их в синтаксисе PLY, но это должно помочь вам в большей части.
Обычно я использую отдельное «средство чтения команд», чтобы получить полную команду - возможно, строку в вашем случае - в строку переменных хоста, а затем организую анализатор строки для лексического анализатора, в том числе сообщая мне, когда это не так ». Дойти до конца. Это сложно настроить, но упростит некоторые классы отчетов об ошибках. В одном из мест, где я обычно использовал эту технику, есть многострочные команды с тремя соглашениями о комментариях, двумя наборами строк в кавычках и некоторыми другими неприятностями, чтобы поставить мои зубы на край (контекстно-зависимый токенизация - чёрт!).
В противном случае совет Дона с токеном 'ошибки' Yacc хорош.
Похоже, вы уже нашли решение, но я добавлю еще одно предложение на тот случай, если вы или другие люди заинтересованы в альтернативном подходе.
Вы говорите, что используете PLY, но это потому, что вы хотите, чтобы компилятор работал в среде Python? Если это так, вы можете рассмотреть и другие инструменты. Для таких работ я часто использую ANTLR ( http://www.antlr.org ), в котором есть генератор кода Python , У ANTLR есть много хитростей для выполнения таких вещей, как съедение множества входных данных на уровне лексера, поэтому парсер никогда не видит его (например, комментарии), возможность вызывать подправило (например, уравнение) в пределах более крупной грамматики (которая должна заканчиваться, как только Правило было найдено без дополнительной обработки ввода ... звучит как то, что вы хотите сделать) и очень хороший алгоритм левого факторинга.
Возможность разбора ANTLR в сочетании с использованием StringTemplate ( http://www.stringtemplate.org ) Движок делает хорошую комбинацию, и оба поддерживают Python (среди многих других).