In bison, it is sufficient to add
%verbose-error
to the file to make the parser errors more verbose. Is there any way to gain similar func
I don't think that there's an option in ocamlyacc to do what you want automatically, so let me try to provide below a through description of what could be done to handle syntactic errors and have more useful messages. Maybe it is not what you asked.
Errors must actually be separated in lexical and parse errors, depending on which stage of the parsing process the error happens in.
mll
files, a Failure
exception will be raised in case of unexpected patternsmly
files, it's a Parsing.Parse_error
exception which will be generatedSo you have several solutions:
error
special terminal in the parser rules to catch errors in specific placesIn any case, you will have to make functions to get information about the position of the error in the source.
Lexing
and Parsing
both use a location
record, defined in Lexing
, with the following fields:
The lexbuf
variable used by the lexer has two values like that to track the current token being lexed (lexeme_start_p
and lexeme_curr_p
in Lexing
let you access these data). And the parser has four to track the current symbol (or non-terminal) about to be synthetized, and the current rule items, which can be retrieved with Parsing
functions (rhs_start_pos
and rhs_end_pos
, as well as symbol_start_pos
and symbol_end_pos
).
Here's a few functions to generate more detailed exceptions:
exception LexErr of string
exception ParseErr of string
let error msg start finish =
Printf.sprintf "(line %d: char %d..%d): %s" start.pos_lnum
(start.pos_cnum -start.pos_bol) (finish.pos_cnum - finish.pos_bol) msg
let lex_error lexbuf =
raise ( LexErr (error (lexeme lexbuf) (lexeme_start_p lexbuf) (lexeme_end_p lexbuf)))
let parse_error msg nterm =
raise ( ParseErr (error msg (rhs_start_p nterm) (rhs_end_p nterm)))
and some basic use case:
parser: %token ERR
/* ... */
wsorword:
WS { $1 }
| WORD { $1 }
| error { parse_error "wsorword" 1; ERR "" } /* a token needed for typecheck */
;
lexer:
rule lexer = parse
(* ... *)
(* catch all pattern *)
| _ { lex_error lexbuf }
All that would be left to do is to modify your top level function to catch the exceptions and process them.
Finally, for debugging purposes, there is a set_trace
function available in Parsing
which enable the display messages of the state machine used by the parsing engine: it traces all the internal state changes of the automaton.
In the Parsing
module (you can check it here) there is the function Parsing.set_trace
that will do just that. You can use it as:Parsing.set_trace True
to enable. Also, you can run ocamlyacc with the -v argument and it will output a .output, listing all states and trasitions.