【问题标题】:ocamlyacc parse error: what token?ocamlyacc 解析错误:什么令牌?
【发布时间】:2009-12-19 14:56:58
【问题描述】:

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

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

但是,我也想知道读取了哪个令牌。一定有办法——有人知道吗?

谢谢。

【问题讨论】:

    标签: ocaml ocamlyacc


    【解决方案1】:

    调试ocamlyacc 解析器的最佳方法是设置OCAMLRUNPARAM 参数以包含字符p - 这将使解析器打印它经历的所有状态,以及它执行的每个移位/减少.

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

    $ export OCAMLRUNPARAM='p'
    

    【讨论】:

      【解决方案2】:

      tokens 是由 lexer 生成的,因此你可以在出错时使用当前的 le​​xer token :

        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)

      【讨论】:

      • 很好的答案。不过,我有一个问题:为什么我们必须使用lexbuf.Lexing.lex_curr_p 而不是lexbuf.lex_curr_p
      • 因为lex_curr_p 属于Lexing 模块。要么打开它,要么等到 OCaml 变得更聪明并理解不合格的记录字段引用。
      • 在哪里可以找到 Sql_lexer。和错误?
      • 有人可以明确说明这个函数应该粘贴在哪里吗?
      【解决方案3】:

      我认为,与 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
      

      嗯,看起来你只得到了这个函数的“语法错误”。请继续关注以获取更多信息。

      【讨论】:

      • 不幸的是,这不起作用:文件“parser.mly”,第 372 行:$1 指的是终端“错误”,它没有参数
      • 你能告诉我整个函数的代码吗?届时我或许可以提供更多见解。
      猜你喜欢
      • 2011-10-16
      • 2022-01-02
      • 2018-08-14
      • 2019-02-19
      • 2017-11-21
      • 2013-09-26
      • 2018-09-12
      • 2017-07-16
      • 1970-01-01
      相关资源
      最近更新 更多