[содержание] [назад] [пред] [вверх] [след] [вперед] 7. восстановление после ошибокобычно программа, заканчивающая работу при ошибке разбора, неприемлема. например, компилятору следует восстановиться настолько, чтобы разобрать остаток входного текста и проверить наличие в ней ошибок, калькулятор должен обработать следующее выражение.
в простом интерактивном анализаторе команд, где каждый вход -- одна строка,
может быть достаточно разрешить
вы можете определять способ восстановления после синтаксической ошибки,
составляя правила, распознающие специальную лексему например: stmnts: /* пустая строка */ | stmnts '\n' | stmnts exp '\n' | stmnts error '\n'
четвёртое правило в этом примере говорит, что ошибка, за которой следует
переход на новую строку, является допустимым дополнением для любого
что случится, если синтаксическая ошибка будет обнаружена внутри
но bison может принудительно привести ситуацию к правилу, отбрасывая часть
семантического контекта и часть входного текста. во-первых, он отбрасывает
состояния и объекты в стеке до тех пор, пока не вернётся к правилу, в котором
приемлема лексема выбор правил грамматики для ошибок -- это выбор стратегии восстановления после ошибки. простая и полезная стратегия -- при обнаружении ошибки просто пропустить остаток текущей входной строки или текущего оператора. stmnt: error ';' /* при ошибке пропускать, пока не будет считана ';' */ также полезно восстанавливать до закрывающего ограничителя, соответствующего уже разобранному открывающему ограничителю. в противном случае закрывающий ограничитель, вероятно, оказался бы без пары, и вызвал новое, ложное сообщение об ошибке. primary: '(' expr ')' | '(' error ')' ... ;
стратегии восстановления после ошибки неизбежно связаны с догадками. когда
догадка неверна, одна синтаксическая ошибка часто приводит к появлению других.
в вышеприведённом примере, правило восстановления после ошибки предполагает,
что ошибка вызвана неправильным входным текстом внутри одного чтобы предотвратить поток сообщений об ошибках, анализатор не будет выводить сообщения об ошибках, произошедших вскоре после первой. возобновит он их вывод только после того, как будет успешно произведён сдвиг трёх лексем подряд.
имейте в виду, что правила, принимающие лексему
вы можете возобновить вывод сообщений об ошибках немедленно, используя в
действиях макрос
сразу после обнаружения ошибки предыдущая предпросмотренная лексема
анализируется заново. если это невозможно, можно использовать макрос
например, предположим, что при ошибке разбора вызывается подпрограмма обработки ошибки, продвигающаяся по входному потоку до некоторой точки, где разбор снова может быть начат. предыдующая предпросмотренная лексема должна быть отброшена с помощью `yyclearin;'.
макрос [содержание] [назад] [пред] [вверх] [след] [вперед] |