在实现真实世界(TM)语言时,我经常会遇到这样的情况:
(* language Foo *)
type A = ... (* parsed by parse_A *)
type B = ... (* parsed by parse_B *)
type collection = { as : A list ; bs : B list }
(* parser ParseFoo.mly *)
parseA : ... { A ( ... ) }
parseB : ... { B ( ... ) }
parseCollectionElement : parseA { .. } | parseB { .. }
parseCollection : nonempty_list (parseCollectionElement) { ... }
显然(在函数式中),最好将部分解析的collection
记录传递给parseA
和parseB
的语义操作的每次调用,并相应地更新列表元素
甚至可以使用menhir,还是必须使用使用可变全局变量的丑陋黑客?
答案 0 :(得分:1)
嗯,你在menhir / ocamlyacc语义行为中被允许做的事情非常有限。如果你发现这真的令人沮丧,你可以尝试类似parsec的解析器,例如mparser,允许您在规则中使用OCaml。
我对这类问题的个人理解是在解析器中保持最原始的水平,而不是试图定义任何复杂的东西,并在以后将解析器输出提升到更高的水平。
但是你的案子看起来很简单。在这里,您可以手动编写列表规则,而不是使用参数化的menhir规则,并在其语义规则中生成集合。 nonempty_list
是一种语法糖,与大多数其他糖一样,在大多数情况下都有效,但总的来说不太通用。