从显式令牌列表中提取ocamlyacc解析器?

时间:2012-06-05 14:49:37

标签: ocaml ocamlyacc

是否可以为OCamlYacc生成的解析器提供显式令牌列表以供分析?

我想使用OCamlLex显式生成一个令牌列表,然后我使用Yacc生成的解析器进行分析。但是,标准用例会生成一个解析器,它会为下一个标记隐式调用词法分析器。这里的标记是在yacc分析期间而不是之前计算的。从概念上讲,解析器应该只对令牌起作用,但是Yacc生成的解析器提供了一个依赖于词法分析器的接口,在我看来我不需要它。

3 个答案:

答案 0 :(得分:7)

正如Jeffrey已经提到的,Menhir作为其运行时库的一部分,特别提供了一个带有任何类型令牌流的解析器模块(它只是要求unit -> token函数):{ {3}}

(您甚至可以在不使用Menhir的情况下使用此代码,而使用ocamlyacc。实际上,转换并不是非常复杂,因此您甚至可以自己重新实现它。)

答案 1 :(得分:4)

如果你已经拥有一个令牌列表,你可以采用丑陋的方式完全忽略lexing缓冲区。毕竟,解析器期望的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 "")

另一方面,从您的评论中可以看出,您实际上具有类型为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

答案 2 :(得分:1)

OCamlYacc界面确实看起来很复杂;它似乎需要Lexing.lexbuf。也许您可以考虑使用Lexing.from_string来提供固定字符串而不是固定的令牌序列。您还可以查看Menhir。我没有使用它,但只要有人提到OCaml解析器生成器,它就会得到很好的评论。它可能有一个更灵活的lexing界面。