Я использую ocamlyacc и ocamllex. У меня есть ошибочное производство в моей грамматике, которая сигнализирует о пользовательском исключении. До сих пор я могу заставить это сообщать об ошибочном положении:
| error { raise (Parse_failure (string_of_position (symbol_start_pos ()))) }
Но, я также хочу знать, какой маркер был считан. Должен быть путь---, кто-либо знает?
Спасибо.
Токены генерируются лексером, поэтому вы можете использовать текущий токен лексера при возникновении ошибки:
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
следует обновить в лексере, чтобы он содержал правильные позиции. ( источник )
Я думаю, что, как и yacc, токены хранятся в переменных, соответствующих символам в правиле грамматики. Здесь, поскольку есть один символ (ошибка), вы можете просто вывести $1, используя printf
, и т.д.
Edit: response to comment.
Why do you use a error terminal? Я читаю учебник ocamlyacc, в котором говорится, что при возникновении ошибки при разборе вызывается специальная рутина обработки ошибок. Например:
3.1.5. Error Reporting Routine
When ther parser function detects a синтаксическая ошибка, она вызывает функцию под названием
parse_error
со строкой "синтаксическая ошибка" в качестве аргумента. по умолчаниюparse_error
функция делает следующее ничего и возвращается, таким образом инициируя исправление ошибок (см. "Восстановление ошибок"). Пользователь может определить настраиваемый функция parse_error в заголовке раздел грамматического файла, такой как:
let parse_error s = (* Called by the parser function on error *)
print_endline s;
flush stdout
Ну, похоже, что с помощью этой функции вы получаете только "синтаксическую ошибку". Оставайтесь с нами для дополнительной информации.
Наилучший способ отладки парсера ocamlyacc
- это установить параметр OCAMLRUNPARAM
для включения символа p
- это приведет к заставить парсер печатать все состояния, через которые он проходит, и каждый сдвиг / уменьшение, которое он выполняет.
Если вы используете bash, вы можете сделать это с помощью следующей команды:
$ export OCAMLRUNPARAM='p'