Question

So I was having the dreaded shift/reduce errors with my grammar. Here's a minimal test case:

%token PLUS MINUS TIMES DIVIDE NUMBER
%token EQUAL NEQUAL GREATER LESS NOT

%left   EQUAL   NEQUAL
%left   GREATER LESS
%left   PLUS    MINUS
%left   TIMES   DIVIDE
%left   UMINUS  NOT

%%

exp             : exp binop exp
                | unop exp
                | NUMBER
                ;

binop           : MINUS
                | PLUS
                | TIMES
                | DIVIDE
                | EQUAL
                | NEQUAL
                | GREATER
                | LESS
                ;

unop            : MINUS %prec UMINUS
                | NOT
                ;

%%

However, through experimentation I somehow managed to make the problem go away:

%token PLUS MINUS TIMES DIVIDE NUMBER
%token EQUAL NEQUAL GREATER LESS NOT

%left   EQUAL   NEQUAL
%left   GREATER LESS
%left   PLUS    MINUS
%left   TIMES   DIVIDE
%left   UMINUS  NOT

%%

exp             : binops
                | unops
                | NUMBER
                ;

unops           : MINUS exp %prec UMINUS
                | NOT exp
                ;

binops          : exp MINUS exp
                | exp PLUS exp
                | exp TIMES exp
                | exp DIVIDE exp
                | exp EQUAL exp
                | exp NEQUAL exp
                | exp GREATER exp
                | exp LESS exp
                ;

%%

Can anyone explain why I was having shift/reduce errors in the first place and why this worked? Is this even a proper solution? If not, what is?

Was it helpful?

Solution

In your first grammar, the precedence declarations do absolutely nothing. Precedence only applies to the alternatives containing the terminal with the precedence; in your first grammar, that would be the productions for binop and unop. But the alternatives for those productions are completely unambiguous; precedence is not required to decide to reduce PLUS to binop.

In your second grammar, the precedence relationships do have an effect because the competing ambiguous alternatives (the productions for binops and unops) directly include the terminals.

In other words, precedence does not "look into" a non-terminal.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top