是否可以为OCamlYacc生成的解析器提供显式令牌列表以供分析?
我想使用OCamlLex显式生成一个令牌列表,然后我使用Yacc生成的解析器进行分析.但是,标准用例会生成一个解析器,它会为下一个标记隐式调用词法分析器.这里的标记是在yacc分析期间而不是之前计算的.从概念上讲,解析器应该只对令牌起作用,但是Yacc生成的解析器提供的依赖于词法分析器的接口在我的情况下我不需要.
正如Jeffrey已经提到的,作为运行时库的一部分,Menhir特别为解析器提供了一个模块,其中包含任何类型的令牌流(它只是要求一个unit -> token函数):MenhirLib.Convert.
(您甚至可以在不使用Menhir的情况下使用此代码,而使用ocamlyacc.实际上,转换并不是非常复杂,因此您甚至可以自己重新实现它.)
如果您已经有一个标记列表,您可以采用丑陋的方式并完全忽略词法缓冲区。毕竟,您的解析器期望的 parse-from-lexbuf 函数是一个非纯函数:
let my_tokens = ref [ (* WHATEVER *) ]
let token lexbuf =
match !my_tokens with
| [] -> EOF
| h :: t -> my_tokens := t ; h
let ast = Parser.parse token (Lexbuf.from_string "")
Run Code Online (Sandbox Code Playgroud)
另一方面,从您的评论看来,您实际上有一个类型的函数Lexing.lexbuf -> token list,您正试图将其放入Lexing.lexbuf -> token解析器的签名中。如果是这种情况,您可以轻松地使用队列在两种类型之间编写转换器:
let deflate token =
let q = Queue.create () in
fun lexbuf ->
if not (Queue.is_empty q) then Queue.pop q else
match token lexbuf with
| [ ] -> EOF
| [tok] -> tok
| hd::t -> List.iter (fun tok -> Queue.add tok q) t ; hd
let ast = Parser.parse (deflate my_lexer) lexbuf
Run Code Online (Sandbox Code Playgroud)