I have the following constructs as part of a yacc grammar (or rather jison, but the two share the same common base):
Type
: IDENT
| Type "[" "]"
| Type "*"
| "func" "(" Types ")" "=>" Type
;
Types
: /* No arguments */
| Type /* Single argument */
| Types "," Type /* Multiple arguments */
;
This is of course a simplified example, but it should give the general idea and shows the problem in action. I want to parse constructs such as Foo[]
, Foo*
, Foo*[]
into (Foo)[]
, (Foo)*
, ((Foo)*)[]
respectively.
However, Yacc rightfully complains that it doesn't know what to do when it encounters the following construct:
func (A, B) => C[]
It can be parsed into either func (A, B) => (C[])
or (func (A, B) => C)[]
. I would of course like it to be the first (since I have a ( Type )
construct for the second case). Is there any way I can tell yacc (or jison) that I want to shift if it encounters this situation?
Give the last Type
production a precedence, either with a %prec
declaration and a pseudo-terminal, or using the default, which is the precedence of =>
, the last terminal. Then make sure the precedence of the [
token is higher. (You'll also have to make the precedence of *
higher than =>
, to solve the other shift-reduce conflict.)
There are other solutions, but that one is the simplest.
In fact, bison/yacc/jison/etc. always prefer shift in a shift-reduce conflict, so you don't need to do anything to get a shift. The precedence rules will suppress the warning, but you could use an expect
declaration to do that, as well.