我如何解析像
这样的东西f x y
进入
APPLY (APPLY f x) y
使用快乐?现在我有一条规则说
%left APP
Expr : Expr Expr %prec APP { APPLY $1 $2 }
但是,将上述内容解析为
APPLY f (APPLY x y)
答案 0 :(得分:3)
接受的答案并不令人满意。
解决此问题的正确方法是:
%nonassoc VAR LPAREN -- etc...
%nonassoc APP
Expr : Expr Expr %prec APP { APPLY $1 $2 }
那是:
添加名为APP
的幽灵优先权令牌,无需将其设为left
或right
,因为它不相关,因此您可以保留它nonassoc
1}}没有得到错误的直觉,这很重要
用Expr
标记%prec APP
规则
,最重要且经常被遗忘,您需要提供可能显示为Expr
作品的第一个标记的所有标记的优先级低于{{1通常通过在上面某处列出它们来实现,对于那些不关联的<{p>
APP
,left
或right
您的试用失败的原因可能是您错过了最后一步。
需要最后一步的原因是算法在决定是否移动下一个令牌或减少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 }