menhir - 减少表达序列的相关性规则

时间:2016-12-17 23:19:28

标签: ocaml yacc menhir

为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)。有没有办法控制规则的相关性而不是令牌?

1 个答案:

答案 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语言具有相同的应用语法。