#python #yacc #ply
#python #yacc #ply
Вопрос:
Я работаю с библиотекой ply, чтобы создать анализатор для команд. Код
def p_expr(v):
'expr : token'
... # action with token, set expr value and return
??? raise error ??? # yacc must stop parse and call p_error
def p_error(p):
print('Error!')
Как вызвать ошибку?
Комментарии:
1. Вы пробовали буквально использовать
raise
оператор?2. Почему стандартный способ сделать это с помощью raise не подходит?
Ответ №1:
Обратите внимание, что Ply не «останавливает синтаксический анализ» при обнаружении синтаксической ошибки. Он пытается выполнить восстановление после ошибок, если грамматика была построена с восстановлением ошибок, и в качестве последнего средства он перезапускает синтаксический анализ, как если бы входные данные были удалены до этого момента. Чтобы увидеть это, попробуйте ввести 1 2 error 3 4
пример калькулятора в дистрибутиве Ply. Он выведет сообщение об ошибке для error
(потому что он ожидает оператора), а затем перезапустит синтаксический анализ, чтобы он напечатал 7.
Если вы хотите, чтобы анализатор останавливался при обнаружении ошибки, вам нужно вызвать исключение из p_error
. Обычно лучше определить свой собственный класс исключений для такого рода вещей. Избегайте использования SyntaxError
, потому что Ply обрабатывает это специально в определенных случаях, как мы увидим ниже.
Обычно просто остановка синтаксического анализатора — это не совсем то, что вы хотите сделать — если вы не хотите пытаться восстановить ошибку, вы должны, по крайней мере, сделать что-то вроде удаления остальной части входной строки перед перезапуском синтаксического анализа.
Если вы просто хотите остановить анализатор и для этого создаете исключение в p_error, то лучший способ сообщить о своей собственной ошибке из действия синтаксического анализатора — вызвать p_error
с текущим токеном.
Если вы хотите запустить обычную процедуру восстановления ошибок Ply, вы получаете повышение SyntaxError
из действия синтаксического анализатора. Однако, как указано в руководстве, это не вызывается p_error
, поэтому вам придется сделать это самостоятельно, прежде чем вызывать ошибку.
Если вы выполняете восстановление в режиме паники p_error
, вам может не повезти с пользовательским обнаружением ошибок. Вызов SyntaxError
обходного вызова p_error
; пока вы можете вызывать p_error
себя, нет механизма для передачи нового токена обратно в анализатор. (Восстановление в режиме паники не является оптимальным методом восстановления после ошибок, и не всегда необходимо возвращать токен замены. Так что этот пункт может не применяться.)