【问题标题】:Happy Context-Dependent Operator Precedence快乐的上下文相关运算符优先级
【发布时间】:2017-06-09 18:39:06
【问题描述】:

我这里有两个 Happy 代码的 sn-ps,一个使用普通优先规则,一个使用上下文相关的优先规则(都在 here 中进行了描述)。

正常:

%left '+'
%left '*'
%%

Exp :: { Exp }
    : Exp '+' Exp { Plus $1 $3 }
    | Exp '*' Exp { Times $1 $3 }
    | var         { Var $1 }

上下文相关:

%left PLUS
%left TIMES
%%

Exp :: { Exp }
    : Exp '+' Exp %prec PLUS  { Plus $1 $3 }
    | Exp '*' Exp %prec TIMES { Times $1 $3 }
    | var                     { Var $1 }

给定输入:

a * b + c * d

普通版给出:

Plus (Times (Var "a") (Var "b")) (Times (Var "c") (Var "d"))

而上下文相关的版本给出:

Times (Var "a") (Plus (Var "b") (Times (Var "c") (Var "c")))

这两者不应该提供相同的输出吗?我在这里做错了什么导致它们生成不同的解析树?

【问题讨论】:

    标签: parsing haskell happy


    【解决方案1】:

    “上下文相关的优先级”是描述该功能的一种非常误导性的方式。不过,上一节中对优先算法的描述在很大程度上是准确的。

    正如它所说,优先比较总是在生产(可以减少)和终端(可以转移)之间进行。这个简单的事实经常被设计优先级声明语法的决定所掩盖,就好像优先级只是终端的一个属性。

    除非有%prec 的显式声明,否则通过复制生产中最后一个终端的优先级来设置生产的优先级。或者换句话说,产生式的优先级使用%prec 子句设置,默认为最后一个标记的优先级。无论哪种方式,您只能通过说它与某些终端的相同来定义生产的优先级。由于这并不总是很方便,解析器生成器为您提供了使用不是语法符号名称的任意名称的选项。实现是将名称视为终结符并忽略它从未在任何语法规则中实际使用的事实,但从逻辑上讲,它是要分配给该特定产生式的优先级的名称。

    在您的第一个示例中,您让产品的优先级默认为每个产品中的最后一个(实际上是唯一的)终端。但是在您的第二个示例中,您已经定义了两个命名的优先级,PLUS 和 TIMES,并且您使用它们来设置两个产生式的优先级。但是您没有声明任何终端的优先级。因此,当解析器生成器尝试检查可以减少的产生式和可以移动的终端的相对优先级时,它发现其中只有一个具有声明的优先级。在这种情况下,它总是会发生变化。

    【讨论】:

    • 如果这是一个愚蠢的问题,请原谅我,因为我以前从未使用过快乐。这是否意味着%left '+'; %left '*'确实声明了'+''*'的优先级,但%left PLUS; %left TIMES没有声明PLUSTIMES的优先级?
    • @DanielWagner:我写的内容有什么不清楚的地方? %left '+'; %left '*' 声明 '+''*' 的优先级,%left PLUS; %left TIMES 声明 PLUSTIMES 的优先级。但是优先级的比较总是在生产和终端之间进行,%left PLUS; %left TIMES 确实not 声明'+''*' 的优先级。为什么会呢?如果'+''*' 没有声明的优先级,则没有什么可以比较PLUSTIMES 的优先级。
    • 谢谢,解决了!我不明白它会尝试在第二个示例中比较 '+'PLUS 的优先级,但没有成功(因为只有 PLUS 在那里声明了优先级)。
    • @DanielWagner:“优先级比较总是在生产(可以减少)和终端(可以转移)之间进行。”我不知道我在关于某个解析器生成器或其他的 SO 答案中写了多少次这句话;它不是特定于快乐的。如果有更好的措辞,请提出建议。
    • 另外,它没有将PLUS+ 进行比较。它将TIMES(可以降低的生产优先级)与+(可以移动的终端)进行比较。稍后,它将PLUS(可以减少的产量)与*(可以转移的终端)进行比较。第一次,reduce 获胜;第二次,换班。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-05
    • 1970-01-01
    • 2021-05-05
    • 2011-07-07
    相关资源
    最近更新 更多