I have faced a problem dealing with yaac, since I keep getting this note:
1 rule never reduced. 29 shift/reduce conflicts.
So, could anyone help me please to fix this problem?
This is the grammar that I am working on:
%start P
%token DEF IF THEN ELSE WHILE DO FOR
%token Punctuation_element
%token Operator
%token EQL_EQL GREATER_THAN_OR_EQUALS LESS_THAN_OR_EQUALS NOT_EQUALS
%token<sval> Identifier
%token<ival> Literal
%left '-' '+'
%left '*' '/' '%'
%right ELSE
%%
P : D ';' P
| D
;
D : DEF Identifier '(' ARGS ')' '=' E ';'
;
ARGS: Identifier ',' ARGS
| Identifier
;
E: Literal
| Identifier
| IF E OP E THEN E ELSE E
| FOR E DO E
| DO E WHILE E
| E '+' E
| E '-' E
| E '*' E
| E '/' E
| E '%' E
| Identifier '(' E ')'
| E ',' E
;
/* C: E ',' C
| E
; */
OP: EQL_EQL
| '>'
| '<'
| GREATER_THAN_OR_EQUALS
| LESS_THAN_OR_EQUALS
| NOT_EQUALS
| '%'
;
You have two fundamental problems:
%
is both a comparison operator (OP
) and an arithmetic operator (E '%' E
). That creates an ambiguity which bison resolves in favour of the arithmetic operator, because bison favours shift over reduce. That resolution makes it impossible to reduce OP : '%'
, which is the rule not reduced.
You make ,
an arithmetic operator (E ',' E
) but you don't declare a precedence for it. That leads to a lot of shift reduce conflicts for expressions involving ,
and another operator. I doubt that you actually want ,
to be an operator at all; I think you added the production involving it in order to allow function calls with multiple arguments. That's not going to work. Create a separate non-terminal for argument lists and use it in the production for function calls instead of using E
.
(In fact, you have such a non-terminal, mysteriously called C
, but it's commented out and unused. So uncomment it and use it. And consider giving it a more meaningful name.)
LALR parser generators like bison generally prefer left recursion to right recursion. You should consider changing both of your list productions (C
and ARGS
) to left recursion, unless you have a good reason not to.