I'm trying to create a parser for a simple language, but I can't get rid of some reduce/reduce conflicts because of the rules expr: l_value and r_value: '@' l_value. I tried to fix it determining a precedence for the symbol '@' but it didn't help. A minimal, reproducible example is that:
%{
#include <cstdio>
#include "lexer.hpp"
%}
%define parse.error verbose /*to help me debug the parser*
%token T_if "if"
%token T_then "then"
%token T_do "do"
%token T_begin "begin"
%token T_end "end"
%token T_and "and"
%token T_of "of"
%token T_array "array"
%token T_else "else"
%token T_integer "integer"
%token T_or "or"
%token T_true "true"
%token T_label "label"
%token T_procedure "procedure"
%token T_var "var"
%token T_boolean "boolean"
%token T_false "false"
%token T_mod "mod"
%token T_program "program"
%token T_while "while"
%token T_char "char"
%token T_forward "forward"
%token T_new "new"
%token T_real "real"
%token T_dispose "dispose"
%token T_function "function"
%token T_nil "nil"
%token T_result "result"
%token T_div "div"
%token T_goto "goto"
%token T_not "not"
%token T_return "return"
%token T_id
%token T_realnum
%token T_int
%token T_character
%token T_string
%token T_assign ":="
%token T_greaterequal ">="
%token T_lessequal "<="
%token T_notequal "<>"
%nonassoc '=' '<' '>' "<=" ">=" "<>" ":="
%left '+' '-' "or"
%left '*' '/' "div" "mod" "and"
%left UMINUS
%right '^'
%left '@'
%left '[' '('
%expect 1
%%
expr:
l_value
|r_value
;
l_value:
T_id
|"result"
|T_string
|l_value '[' expr ']'
|expr '^'
|'(' l_value ')'
;
r_value:
T_int
|"true"
|"false"
|T_realnum
|T_character
|'(' r_value ')'
|"nil"
|call
| expr '<' expr
| expr '>' expr
| expr "<=" expr
| expr ">=" expr
| expr '=' expr
| expr "<>" expr
| expr '+' expr
| expr '-' expr
| expr "or" expr
| expr '*' expr
| expr '/' expr
| expr "and" expr
| expr "div" expr
| expr "mod" expr
|"not" expr %prec UMINUS
|'+' expr %prec UMINUS
|'-' expr %prec UMINUS
|'@' l_value
;
call:
T_id '(' expr text6
;
text6:
')' | ',' expr text6
;
%%
extern int lineno;
int main() {
#ifdef YYDEBUG
yydebug = 1;
#endif
int result = yyparse();
if (result == 0) printf("Success.\n");
return result;
}
`
In parser.output I get this:
1 expr: l_value .
6 l_value: l_value . '[' expr ']'
34 r_value: '@' l_value .
'[' shift, and go to state 43
$end reduce using rule 34 (r_value)
"and" reduce using rule 1 (expr)
"and" [reduce using rule 34 (r_value)]
"or" reduce using rule 1 (expr)
"or" [reduce using rule 34 (r_value)]
"mod" reduce using rule 1 (expr)
"mod" [reduce using rule 34 (r_value)]
"div" reduce using rule 1 (expr)
"div" [reduce using rule 34 (r_value)]
">=" reduce using rule 1 (expr)
">=" [reduce using rule 34 (r_value)]
"<=" reduce using rule 1 (expr)
"<=" [reduce using rule 34 (r_value)]
"<>" reduce using rule 1 (expr)
"<>" [reduce using rule 34 (r_value)]
'=' reduce using rule 1 (expr)
'=' [reduce using rule 34 (r_value)]
'<' reduce using rule 1 (expr)
'<' [reduce using rule 34 (r_value)]
'>' reduce using rule 1 (expr)
'>' [reduce using rule 34 (r_value)]
'+' reduce using rule 1 (expr)
'+' [reduce using rule 34 (r_value)]
'-' reduce using rule 1 (expr)
'-' [reduce using rule 34 (r_value)]
'*' reduce using rule 1 (expr)
'*' [reduce using rule 34 (r_value)]
'/' reduce using rule 1 (expr)
'/' [reduce using rule 34 (r_value)]
'^' reduce using rule 1 (expr)
'^' [reduce using rule 34 (r_value)]
']' reduce using rule 34 (r_value)
')' reduce using rule 34 (r_value)
',' reduce using rule 34 (r_value)
$default reduce using rule 1 (expr)