在野牛中,添加
就足够了%verbose-error
到文件以使解析器错误更加冗长。有没有办法获得与ocamlyacc类似的功能?
Here是类似问题的答案,但我无法做出任何改变。这就是我调用词法分析器和解析器函数的方法:
let rec foo () =
try
let line = input_line stdin in
(try
let _ = (Parser.latexstatement lexer_token_safe (Lexing.from_string line)) in
print_string ("SUCCESS\n")
with
LexerException s -> print_string ("$L" ^ line ^ "\n")
| Parsing.Parse_error -> print_string ("$P" ^ line ^ "\n")
| _ -> print_string ("$S " ^ line ^ "\n"));
flush stdout;
foo ();
with
End_of_file -> ()
;;
foo ();;
答案 0 :(得分:9)
我不认为ocamlyacc中有一个选项可以自动执行您想要的操作,所以让我尝试在下面提供一些描述,说明可以采取哪些措施来处理语法错误并提供更多有用的消息。也许这不是你问的。
错误实际上必须在词法和解析错误中分开,具体取决于错误发生在解析过程的哪个阶段。
mll
个文件中,如果出现意外模式,将引发Failure
例外mly
个文件中,这是一个Parsing.Parse_error
例外,将会生成所以你有几个解决方案:
error
特殊终端来捕获特定位置的错误在任何情况下,您都必须创建函数以获取有关错误在源中的位置的信息。
Lexing
和Parsing
都使用location
中定义的Lexing
记录,其中包含以下字段:
词法分析器使用的lexbuf
变量有两个值,用于跟踪当前被刻录的标记(lexeme_start_p
和lexeme_curr_p
Lexing
中允许您访问这些数据的值。解析器有四个跟踪即将合成的当前符号(或非终端),以及当前规则项,可以使用Parsing
函数(rhs_start_pos
和rhs_end_pos
检索,以及symbol_start_pos
和symbol_end_pos
)。
以下是一些生成更详细例外的函数:
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)))
和一些基本用例:
解析器: %token ERR
/* ... */
wsorword:
WS { $1 }
| WORD { $1 }
| error { parse_error "wsorword" 1; ERR "" } /* a token needed for typecheck */
;
词法分析:
rule lexer = parse
(* ... *)
(* catch all pattern *)
| _ { lex_error lexbuf }
剩下要做的就是修改顶级函数以捕获异常并处理它们。
最后,出于调试目的,set_trace
中有一个Parsing
函数可以启用解析引擎使用的状态机的显示消息:它跟踪自动机的所有内部状态变化
答案 1 :(得分:-1)
在<properties>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
模块中(您可以检查here),有一个功能Parsing
可以做到这一点。您可以将其用作:Parsing.set_trace
来启用。此外,您可以使用-v参数运行ocamlyacc,它将输出.output,列出所有状态和tras.ition。