将值作为参数传递给规则

Pass values as arguments to rules

在实现现实世界(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,还是必须使用使用可变全局变量的丑陋技巧?

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

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

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