bisonyaccjison

How to force shift in Yacc?


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?


Solution

  • 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.