2

在实现真实世界(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记录传递给 和 的语义操作的每次调用,parseAparseB相应地更新列表元素。

这甚至可以使用menhir,还是必须使用使用可变全局变量的丑陋技巧?

4

1 回答 1

1

好吧,你在 menhir/ocamlyacc 语义动作中被允许做的事情非常有限。如果你觉得这真的很令人沮丧,你可以尝试类似 parsec 的解析器,例如 mparser,它允许你在你的规则中完全使用 OCaml。

对于这类问题,我个人的方法是在解析器中保持最原始的水平,而不尝试定义任何复杂的东西,然后将解析器的输出提升到更高的水平。

但你的情况对我来说看起来很简单。在这里,您可以手动编写一个列表规则,并在其语义规则中生成一个集合,而不是使用参数化的 menhir 规则。nonempty_list是一种语法糖,与任何其他糖一样,在大多数情况下都有效,但一般来说不太通用。

于 2015-01-05T11:48:53.070 回答