I’ve been banging my head over this shift/reduce conflict on a production that has a non-empty list of tokens plus an optional token. Below is a minimal reproducible example:
%name example
%tokentype { Tok }
%token
identifier { TokIdentifier }
string { TokString }
name_it { TokNameIt }
apply { TokApply }
%%
stmts : list(stmt) {}
stmt : func_call_statement {}
var : identifier {}
name : name_it identifier {}
func_call_statement
: list1(both(apply, var)) opt(name) {}
-- Utilities
opt(p)
: { Nothing }
| p { Just $1 }
rev_list1(p)
: p { [$1] }
| rev_list1(p) p { $2 : $1 }
list1(p) : rev_list1(p) { reverse $1 }
list(p)
: list1(p) { $1 }
| { [] }
both(p, q) : p q { ($1, $2) }
Helper productions like opt
, list
, both
are all copied from Happy’s documentation here.
Here’s the state that is causing the conflict:
State 8
list1__both__apply__var____ -> rev_list1__both__apply__var____ . (rule 9)
rev_list1__both__apply__var____ -> rev_list1__both__apply__var____ . both__apply__var__ (rule 14)
name_it reduce using rule 9
apply shift, and enter state 10
(reduce using rule 9)
%eof reduce using rule 9
both__apply__var__goto state 15
I know the problem is with the opt(name)
at the end because if I either remove that or stmts
the problem goes away, but what and how I should do to get rid of the conflict.
I read the portion in Serokell’s post on Happy’s reduce/shift conflict, but the two solutions (%shift
or Indicate the precedence) it described don’t work for me: no matter where I add %shift
the conflict still exists, and there’s no operator for me to define precedence.
Is there a way to solve this conflict, or must I refactor my grammar? Thank you in advance!