【问题标题】:Parsing function application with Happy用 Happy 解析函数应用
【发布时间】:2014-12-24 01:17:29
【问题描述】:

我将如何解析类似的东西

f x y

进入

APPLY (APPLY f x) y

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

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

但这会将上面的内容解析为

APPLY f (APPLY x y)

【问题讨论】:

    标签: parsing haskell happy


    【解决方案1】:

    接受的答案不令人满意。

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

    %nonassoc VAR LPAREN -- etc...
    %nonassoc APP
    
    Expr : Expr Expr %prec APP { APPLY $1 $2 }
    

    即:

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

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

    • 最重要且经常被遗忘,您需要为所有可能作为Expr 产生式的第一个标记出现的标记赋予低于APP 的优先级,通常通过在上面的某处列出它们来实现,对于那些不相关的,可以使用leftrightnonassoc

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

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

    Expr Expr . LPAREN VAR RPAREN
    

    例如,它将比较 APP 规则的优先级(减少)和 LPAREN 的优先级(转移),除非你设置正确,否则它会转移,并做错东西。


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

    【讨论】:

    • 这对我有帮助。谢谢。
    • @paulotorrens 如果你想要更深入的解释,我写了一篇关于这个问题的博客文章:ptival.github.io/2017/05/16/…
    【解决方案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 }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-26
      • 2020-07-02
      • 1970-01-01
      相关资源
      最近更新 更多