Как я могу выдать ошибку в ply-yacc внутри специальной функции синтаксического анализа?

#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 себя, нет механизма для передачи нового токена обратно в анализатор. (Восстановление в режиме паники не является оптимальным методом восстановления после ошибок, и не всегда необходимо возвращать токен замены. Так что этот пункт может не применяться.)