Ocamlyacc ошибка анализа: какой токен?
Я использую ocamlyacc и ocamllex. У меня есть ошибка в моей грамматике, которая сигнализирует о специальном исключении. Пока что я могу сообщить об ошибке:
| error { raise (Parse_failure (string_of_position (symbol_start_pos ()))) }
Но я также хочу знать, какой токен был прочитан. Должен быть какой-то способ - кто-нибудь знает?
Спасибо.
Ответы
Ответ 1
Токены генерируются с помощью lexer, поэтому при возникновении ошибки можно использовать текущий токен лексера:
let parse_buf_exn lexbuf =
try
T.input T.rule lexbuf
with exn ->
begin
let curr = lexbuf.Lexing.lex_curr_p in
let line = curr.Lexing.pos_lnum in
let cnum = curr.Lexing.pos_cnum - curr.Lexing.pos_bol in
let tok = Lexing.lexeme lexbuf in
let tail = Sql_lexer.ruleTail "" lexbuf in
raise (Error (exn,(line,cnum,tok,tail)))
end
Lexing.lexeme lexbuf
- это то, что вам нужно. Другие части не нужны, но полезны.
ruleTail
выполнит все оставшиеся токены в строке, чтобы пользователь мог легко найти местоположение ошибки. lexbuf.Lexing.lex_curr_p
должен быть обновлен в лексере, чтобы содержать правильные позиции. (источник)
Ответ 2
Лучший способ отладки вашего синтаксического анализатора ocamlyacc
- установить параметр OCAMLRUNPARAM
для включения символа p
- это заставит синтаксический анализатор распечатать все состояния, через которые он проходит, и каждая смена /.
Если вы используете bash, вы можете сделать это с помощью следующей команды:
$ export OCAMLRUNPARAM='p'
Ответ 3
Я думаю, что, подобно yacc, токены хранятся в переменных, соответствующих символам в правиле грамматики. Здесь, поскольку есть один символ (ошибка), вы можете просто вывести $1 с помощью printf
и т.д.
Изменить: ответ на комментарий.
Почему вы используете терминал ошибок? Я читаю учебник ocamlyacc, в котором говорится, что специальная процедура обработки ошибок вызывается при возникновении ошибки синтаксического анализа. Например:
3.1.5. Процедура отчетности об ошибках
Когда функция parser обнаруживает синтаксическая ошибка, она вызывает функцию с именем parse_error
со строкой "синтаксическая ошибка" в качестве аргумента. функция по умолчанию parse_error
делает ничего и не возвращает, тем самым инициируя (см. Восстановление ошибок). Пользователь может определить индивидуальный parse_error в заголовке раздел файла грамматики, например:
let parse_error s = (* Called by the parser function on error *)
print_endline s;
flush stdout
Ну, похоже, вы только получаете "синтаксическую ошибку" с этой функцией. Оставайтесь с нами для получения дополнительной информации.