解析函数应用程序与快乐

时间:2014-12-24 01:17:30

标签: parsing haskell happy

我如何解析像

这样的东西
f x y

进入

APPLY (APPLY f x) y

使用快乐?现在我有一条规则说

%left APP
Expr : Expr Expr %prec APP { APPLY $1 $2 }

但是,将上述内容解析为

APPLY f (APPLY x y)

2 个答案:

答案 0 :(得分:3)

接受的答案并不令人满意。

解决此问题的正确方法是:

%nonassoc VAR LPAREN -- etc...
%nonassoc APP

Expr : Expr Expr %prec APP { APPLY $1 $2 }

那是:

  • 添加名为APP的幽灵优先权令牌,无需将其设为leftright,因为它不相关,因此您可以保留它nonassoc 1}}没有得到错误的直觉,这很重要

  • Expr标记%prec APP规则

  • ,最重要且经常被遗忘,您需要提供可能显示为Expr作品的第一个标记的所有标记的优先级低于{{1通常通过在上面某处列出它们来实现,对于那些不关联的<{p>

  • ,使用APPleftright

您的试用失败的原因可能是您错过了最后一步。

需要最后一步的原因是算法在决定是否移动下一个令牌或减少nonassoc规则时,会将APP规则的优先级与优先级进行比较传入令牌。默认情况下,您没有提及的令牌具有高优先级。所以当面对:

APP
例如,它会比较Expr Expr . LPAREN VAR RPAREN 规则(减少)的优先级,APP的优先级(移位),除非你正确设置它,它会移动,做错了。

分阶段你的语法只是丑陋和不愉快。

答案 1 :(得分:2)

您可以使用语法规则对左/右相关性进行编码。

例如,看看这个基本的lambda演算解析器:

https://github.com/ghulette/haskell-parser-examples/blob/master/src/HappyParser.y

有效的作品是:

Expr : let VAR '=' Expr in Expr    { App (Abs $2 $6) $4 }
     | '\\' VAR '->' Expr          { Abs $2 $4 }
     | Form                        { $1 }

Form : Form '+' Form               { Binop Add $1 $3 }
     | Juxt                        { $1 }

Juxt : Juxt Atom                   { App $1 $2 }
     | Atom                        { $1 }

Atom : '(' Expr ')'                { $2 }
     | NUM                         { Num $1 }
     | VAR                         { Var $1 }