Восстановление токенов ошибок при разборе (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"

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

"Username Joseph1234"

в качестве вывода.

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

2 ответа

Решение

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам