用Happy解析函数应用

spa*_*ato 2 parsing haskell happy

我将如何解析类似的东西

f x y
Run Code Online (Sandbox Code Playgroud)

进入

APPLY (APPLY f x) y
Run Code Online (Sandbox Code Playgroud)

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

%left APP
Expr : Expr Expr %prec APP { APPLY $1 $2 }
Run Code Online (Sandbox Code Playgroud)

但这将上述内容解析为

APPLY f (APPLY x y)
Run Code Online (Sandbox Code Playgroud)

Pti*_*val 5

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

解决这个问题的正确方法是:

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

Expr : Expr Expr %prec APP { APPLY $1 $2 }
Run Code Online (Sandbox Code Playgroud)

那是:

  • 添加一个名为 的幽灵优先令牌APP,无需制作它leftright因为它不相关,因此您可以保留它nonassoc以免错误的直觉认为它很重要

  • 像你一样标记你的Expr规则%prec APP

  • 最重要且经常被遗忘的,您需要为所有可能出现在产生式第一个标记中的标记赋予Expr低于 的优先级APP,通常通过将它们列在上面的某处来实现,可以是left, right,也nonassoc可以是那些没有的标记联系

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

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

Expr Expr . LPAREN VAR RPAREN
Run Code Online (Sandbox Code Playgroud)

例如,它会将APP规则的优先级(减少)与LPAREN(移动)的优先级进行比较,除非您正确设置它,否则它会移动并做错误的事情。


分期你的语法是丑陋和不愉快的。

  • @paulotorrens 如果你想要更深入的解释,我写了一篇关于这个问题的博客文章:https://ptival.github.io/2017/05/16/parser-generators-and-function-application/ (2认同)