为lambda表达式编写解析器,
data expr = Symbol of string | Lambda of string * expr | App of expr * expr
在编写.mly
文件时,我如何表达一系列表达式
e1 e2 e3 e4
应解析为
App ((App (App e1 e2) e3) e4)
使用规则:
%public expr_expr:
| ID { Symbol ($1) }
| NUMBER { Symbol ($1) }
| LPAREN expr_expr RPAREN { ($2) }
| LAMBDA ID ARROW expr_expr { Lambda ($2, $4) }
| expr_expr expr_expr { Apply ($1, $2) }
给出结构(e1 , (e2 , (e3 , e4)))
而不是(((e1, e2), e3), e4)
。有没有办法控制规则的相关性而不是令牌?
答案 0 :(得分:2)
免责声明:我使用的是ocamlyacc
,而不是menhir
,因此我的答案基于前者。 AFAIUI,后者向后兼容它,所以我认为我的答案无论如何都可能有用。
引用文档http://caml.inria.fr/pub/docs/manual-ocaml/lexyacc.html:
规则也可以在右侧包含%prec符号指令 side part,覆盖默认的优先级和关联性 规则与给定符号的优先级和关联性。
所以我会尝试
%left Application
使规则保持关联(在您定义优先级的位置;您至少需要定义应用程序和lambda抽象的相对优先级),然后将规则更改为
| expr_expr expr_expr { Apply ($1, $2) } %prec Application
这使Application
成为虚拟符号,仅用于指定关联性和优先级。
注1:以上是我的部分猜测。显然我从未(成功)以这种方式自己尝试过。当我曾经写过一个lambda语法时,我通过修改语法强制了关联性。
注意2:如果它不能如上所述,您可以看一下OCaml源代码。 OCaml语言具有相同的应用语法。