Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>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.</p> <p>Errors must actually be separated in lexical and parse errors, depending on which stage of the parsing process the error happens in.</p> <ul> <li>In <code>mll</code> files, a <code>Failure</code> exception will be raised in case of unexpected patterns</li> <li>in <code>mly</code> files, it's a <code>Parsing.Parse_error</code> exception which will be generated</li> </ul> <p>So you have several solutions:</p> <ul> <li>let the lexer and parser code raise their exceptions, and catch them in the code calling them</li> <li>implement the specific cases of errors in the either of them with <ul> <li>a catch all rule for the lexer (or some more specific patterns if necessary)</li> <li>using the <code>error</code> special terminal in the parser rules to catch errors in specific places</li> </ul></li> </ul> <p>In any case, you will have to make functions to get information about the position of the error in the source. <code>Lexing</code> and <code>Parsing</code> both use a <code>location</code> record, defined in <code>Lexing</code>, with the following fields:</p> <ul> <li>pos_fname : the name of the file currently processed</li> <li>pos_lnum : the line number in the file</li> <li>pos_bol : the character number <em>from the start of the file</em> at the beginning of the line</li> <li>pos_cnum : the character number at the current position </li> </ul> <p>The <code>lexbuf</code> variable used by the lexer has two values like that to track the current token being lexed (<code>lexeme_start_p</code> and <code>lexeme_curr_p</code> in <code>Lexing</code> 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 <code>Parsing</code> functions (<code>rhs_start_pos</code> and <code>rhs_end_pos</code>, as well as <code>symbol_start_pos</code> and <code>symbol_end_pos</code>). </p> <p>Here's a few functions to generate more detailed exceptions:</p> <pre><code>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))) </code></pre> <p>and some basic use case:</p> <p>parser: %token ERR</p> <pre><code>/* ... */ wsorword: WS { $1 } | WORD { $1 } | error { parse_error "wsorword" 1; ERR "" } /* a token needed for typecheck */ ; </code></pre> <p>lexer:</p> <pre><code>rule lexer = parse (* ... *) (* catch all pattern *) | _ { lex_error lexbuf } </code></pre> <p>All that would be left to do is to modify your top level function to catch the exceptions and process them.</p> <p>Finally, for debugging purposes, there is a <code>set_trace</code> function available in <code>Parsing</code> which enable the display messages of the state machine used by the parsing engine: it traces all the internal state changes of the automaton.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload