我一直在努力完成“ML中的现代编译器实现”,将SML转换为OCaml。本书定义了一种名为Tiger的语言,它具有let ... in ... end
语法,用于在给定表达式的范围内声明类型,变量和函数。此外,应将相同类型的相邻声明组合在一起以允许相互递归。
我试图通过以下语法片段代表这是Menhir:
%right FUNCTION TYPE
.
.
.
decs: l = list(dec) { l }
dec:
| l = nonempty_list(tydec) { A.TypeDec l }
| v = vardec { v }
| l = nonempty_list(fundec) { A.FunctionDec l }
tydec:
| TYPE; name = ID; EQUAL; ty = ty {
A.{
type_name = Symbol.symbol name;
type_ty = ty;
type_pos = Position.make $startpos $endpos
}
}
有了这个,我得到了一个转变/减少冲突,但是Menhir以我想要的方式解决了它。我希望nonempty_list(typec)
贪婪,以便将相邻的TYPE
声明组合在一起。即,在Menhir解决冲突的情况下,我生成的AST看起来像:
(LetExp
(decs
((TypeDec
(((type_name (my_type)) (type_ty (NameTy (int))))
((type_name (my_type2)) (type_ty (NameTy (string))))
))))
(body (SeqExp ())))
我想摆脱警告,但我无法像Menhir一样解决冲突。我尝试使用%inline tydec
,这确实会使警告消失,但TYPE
的转变并未按照我的预期应用。相反,优先考虑decs
中的列表,产生一个如下所示的AST:
(LetExp
(decs
((TypeDec
(((type_name (my_type)) (type_ty (NameTy (int))))))
(TypeDec
(((type_name (my_type2)) (type_ty (NameTy (string)))
)))))
(body (SeqExp ())))
我也试过明确设定优先权,但是Menhir警告我这是一个无用的宣言。
我确信我错过了一些基本的东西。给出产生列表列表的产品,如何让内部列表变得贪婪?