如何在没有令牌的情况下定义规则关联?

时间:2015-05-19 04:03:10

标签: parsing compiler-construction grammar yacc happy

我有以下最小化的语法

Exp : let var '=' Exp in Exp end                     { App (Fn $2 $6) $4 }
    | Exp Exp                                        { App $1 $2 }
    | Exp OpCode Exp                                 { Op $1 Add $3 }
    | '(' Exp ')'                                    { $2 }
    | num                                            { Num $1 }
    | var                                            { Ident $1 }
    | '\\' var '.' Exp                               { Fn $2 $4 }

Exp Exp规则用于在值中应用函数。但是,如果我有类似myFunc 1 2的内容,则默认为优先myFunc (1 2),这不是我想要的。我想要(myFunc 1) 2来讨好。

但是如果我没有非终端符号,我怎么能定义关联?试图做%left Exp似乎没有帮助。

1 个答案:

答案 0 :(得分:1)

除非您有一个要转移的终端,否则您无法真正应用优先级或关联性,因为优先级和关联性规则用于解决转移/减少冲突。在减少中你不一定需要一个终端,所以你可以使用假终端并写下:

Exp: Exp Exp %prec CURRY

但这对你没有帮助,因为没有终端可以比较优先级。优先关系总是先行符号(终端)的优先级与可能的减少之间的比较(默认情况下,减少的优先级基于规则中最右边的终端,但如上所述可以明确指定)。

由于你不能以简单的方式做到这一点,你需要回归到老式的风格,你用明确的优先规则写一个明确的语法:

Curry: Term
     | Curry Term

(那是左边的关联,如果是func 1 2被解析为((func 1) 2),那么应用就会与左边相关联。)

假设中缀比应用程序绑定得更紧,那么你就拥有:

Term: Value
    | Term Opcode Value

Value: '(' Exp ')'
     | num
     | var

Exp: Curry

(你必须弄清楚如何将lambdas整合到那里。这取决于你对它们的分组方式,但希望上面的模型是清楚的。)