我一直在研究“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 一样解决冲突的方法。我试过 using %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 警告我这是一个无用的声明。
我敢肯定我在这里遗漏了一些基本的东西。给出产生列表列表的产品,我怎样才能使内部列表变得贪婪?