Восстановление токенов ошибок при разборе (Lemon)

Я использую Lemon в качестве генератора парсеров, его обработка ошибок такая же, как у yacc и bison, если вы не знаете Lemon.

В Lemon есть возможность определить токен ошибки в наборе правил, чтобы отлавливать ошибки синтаксического анализа. По умолчанию сгенерированный парсер уничтожает токен, вызвавший ошибку; Есть ли способ переопределить это поведение, чтобы я мог сохранить токен?

Вот пример, чтобы показать, что происходит: в основном я добавляю токены для каждого правила вместе, чтобы реформировать входную строку, вот пример грамматики:

input ::= string(A) { printf("%s", A); } // Print the result
string(A) ::= string(B) part(C). { A = append(B, C); }
string(A) ::= part(B). { A = B; }
part(A) ::= NUMBER(B) NAME(C). { A = append(C, B); } // Rearrange the number and name
part(A) ::= error(B). { A = B; } // On error keep the token anyways

На входе:

"Username 1234Joseph"

Я получаю вывод:

"Joseph1234"

Поскольку текст «Имя пользователя» отбрасывается синтаксическим анализатором в правиле часть (A) ::= error (B), но я действительно хочу:

"Username Joseph1234"

как вывод.

Если вы можете решить эту проблему в bison или другом генераторе парсеров, я бы принял это как ответ :)


person Sadly Not    schedule 19.07.2010    source источник


Ответы (2)


При использовании yacc/bison ошибка синтаксического анализа переводит инструмент в режим восстановления после ошибки, если это возможно. Он попытается сбросить токены на пути к «чистому» состоянию.

Я не могу найти ссылку на лимон, поэтому я не могу показать код лимона, чтобы исправить это, но с yacc/bison можно было бы использовать правила здесь.

А именно, вам нужно настроить правило ошибки, чтобы указать, что синтаксический анализатор в порядке с yyerrok, чтобы он не сбрасывал токены. Затем он попытается перечитать «плохой» токен, поэтому вам нужно очистить его с помощью yyclearin. Наконец, поскольку правило, прикрепленное к вашему коду ошибки, содержит содержимое вашего токена, вам нужно будет настроить функцию, которая корректирует ваш входной стек, взяв текущее содержимое токена и создав новый (правильный) токен с тем же содержимым.

Например, если грамматика, определенная как MyOther MyOther, увидела MyTok MyOther:

stack
MyTok: "the text"
MyOther: "new text"

stack
MyOther: "the text"
MyOther: "new text"

Для этого попробуйте использовать yybackup. Я не могу найти альтернативный метод, хотя yybackup не одобряется.

person Spencer Rathbun    schedule 06.06.2012
comment
На случай, если кому-то будет интересно, я перешел на RE2C [ссылка]. Было намного проще получить поведение с макросами RE2C. Я написал макросы таким образом, что любые несопоставленные подстроки просто выводятся, а любые совпавшие подстроки модифицируются RE2C. - person Sadly Not; 05.05.2015

Он старый, но почему бы и нет...

Грамматика должна содержать пробелы. На данный момент грамматика допускает только последовательность токенов NUMBER NAME (без пробелов между токенами).

person Omri Barel    schedule 27.05.2011
comment
Есть значки (Некромант и Возрождение) за ответы на старые вопросы и получение голосов, поэтому есть все основания отвечать на старые вопросы без ответа (или без хорошего ответа). - person Jonathan Leffler; 28.05.2011
comment
Лексический анализатор, по-видимому, имеет дело с пробелами между токенами и т. д. Это стандартное разделение труда — лексический анализатор обрабатывает комментарии, пробелы и строки; грамматика имеет дело с найденными лексическим анализатором лексемами, которые им не съедены. - person Jonathan Leffler; 28.05.2011
comment
@ Джонатан Леффлер, я не мог сделать такое предположение, основываясь на вопросе. Ожидается, что последовательность токенов NUMBER NAME поймает 1234Joseph, но обычно это не так (1234Joseph не является законным токеном). Я надеюсь, вы понимаете, что я имею в виду в отношении пробелов. - person Omri Barel; 28.05.2011
comment
достаточно справедливо - не зная, как лексический анализатор анализирует материал, трудно быть уверенным, что происходит. - person Jonathan Leffler; 28.05.2011