ocamlyacc解析错误:什么令牌?

时间:2009-12-19 14:56:58

标签: ocaml ocamlyacc

我正在使用ocamlyacc和ocamllex。我的语法中出现错误,表示自定义异常。到目前为止,我可以让它报告错误位置:

| error { raise (Parse_failure (string_of_position (symbol_start_pos ()))) }

但是,我也想知道读了哪个令牌。必须有办法---任何人都知道吗?

感谢。

3 个答案:

答案 0 :(得分:20)

调试ocamlyacc解析器的最佳方法是将OCAMLRUNPARAM参数设置为包含字符p - 这将使解析器打印它经历的所有状态,并且每次轮班/减少它的表现。

如果您使用bash,可以使用以下命令执行此操作:

$ export OCAMLRUNPARAM='p'

答案 1 :(得分:15)

标记是由词法分析器生成的,因此您可以在发生错误时使用当前的词法分析器标记:

  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以包含正确的位置。 (source

答案 2 :(得分:2)

我认为,与yacc类似,令牌存储在与语法规则中的符号对应的变量中。这里因为有一个符号(错误),您可以使用printf等输出$ 1。

编辑:回复评论。

为什么使用错误终端?我正在阅读一个ocamlyacc教程,该教程说当发生解析错误时会调用一个特殊的错误处理例程。像这样:

  

3.1.5。错误报告例程

     

当解析器功能检测到时   语法错误,它调用一个函数   用字符串命名parse_error   “语法错误”作为参数。该   默认parse_error函数可以   什么也没有回报,从而开始   错误恢复(请参阅错误恢复)。   用户可以定义自定义   标头中的parse_error函数   语法文件的一部分如:

let parse_error s = (* Called by the parser function on error *)
  print_endline s;
  flush stdout

好吧,看起来你只能通过该功能获得“语法错误”。请继续关注更多信息。