I have the following minimized grammar
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 }
The Exp Exp
rule is used to apply a function in a value. But if I have something like myFunc 1 2
it defaults to precendence myFunc (1 2)
, which is not what I want. I want (myFunc 1) 2
, for currying.
But how can I define the association if I don't have a non-terminal symbol? Trying to do %left Exp
don't seems to help.
You can't really apply precedence or associativity unless you have a terminal to shift, because precedence and associativity rules are used to resolve shift/reduce conflicts. You don't necessarily need a terminal in the reduction, so you could use a fake terminal and write:
Exp: Exp Exp %prec CURRY
But that won't help you because there is no terminal to compare precedence with. Precedence relations are always a comparison between the precedence of the lookahead symbol (a terminal) and possible reductions (by default, the precedence of a reduction is based on the rightmost terminal in the rule, but as above you can explicitly specify).
Since you can't do it the short-hand way, you need to fallback to the old-fashioned style where you write an unambiguous grammar with explicit precedence rules:
Curry: Term
| Curry Term
(That's left-associative, by the away. If func 1 2
is parsed as ((func 1) 2)
, then application is associating to the left.)
Assuming that infix binds tighter than application, you'd then have:
Term: Value
| Term Opcode Value
Value: '(' Exp ')'
| num
| var
Exp: Curry
(You'll have to figure out how to integrate lambdas into that. It depends on how you expect them to group, but hopefully the model above is clear.)