Re: Обработка ошибок в Nemerle.Peg
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.11.12 09:14
Оценка:
#Имя: FAQ.nemerle.Nemerle.Peg.ErrorReporting
Здравствуйте, Raimon, Вы писали:

R>Хотелось бы получить ссылки на примеры c обработкой ошибок в парсере и выводом сообщений об ошибках пользователю. Был бы очень благодарен, если бы смогли доступно объяснить, как работают вышеуказанные атрибуты и правила Skip/Stop.


PegGrammar автоматически выявляет одну ошибку после чего останавливает парсинг. То как получить и отобразить эту информацию можно поглядеть в коде тестовой утилиты к C#-парсеру (здесь).

Если нужно выявлять ошибки которые парсер отловить не способен, то нужно писать дополнительные правила в которых обрабатывать ошибочные ситуации.

Сами сообщения при этом нужно помещать в AST (создавая для этого специальные ветки) или кидая исключения (в последнем случае будет невозможно обработать более одной ошибки).

Для вынимания сообщений из AST-а можно воспользоваться макросом CollectParseErrors (из пространства имен Nemerle.Peg.AstUtils, макробиблиотеки Nemerle.Peg.Macros.dll). Метод GetParseErrors в AST C#-а сгенерирован именно этим макросом. При этом ветки содержащие ошибки должны иметь определенные имена (если не ошибаюсь, иметь в названии Error).

Для восстановления после обнаружения ошибки можно воспользоваться атрибутом FailureRecovery. Она позволяет пропустить часть некорректного кода и продолжить паринг с корректной позиции.

Пример использования FailureRecovery есть в парсере C#:
[FailureRecovery(statementRecovery, ("}" / statement / switchSection), (space+ / stringLiteral+ / block / [Any]))]
statement     : Statement     = labeledStatement
                              / declarationStatement
                              / embeddedStatement;

Обработчик statementRecovery находится здесь.

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