Восстановление токенов ошибок при разборе (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 (без пробелов между токенами).