我有以下最小化的语法
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
似乎没有帮助。
答案 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整合到那里。这取决于你对它们的分组方式,但希望上面的模型是清楚的。)