I'm currently writing a Visual Basic-like LALR(1) grammar, and face this particular shift/reduce conflict which I have no idea how to solve it properly.
The problematic parts of the grammar are (Please see EDIT 1 and EDIT 2 for clarification):
Expression
: IndexExpression
| /* other expressions */
IndexExpression
: MemberExpression
| MemberExpression '(' ArgumentList ')'
MemberExpression
: ParenthesizedExpression
| Identifier
ParenthesizedExpression
: '(' Expression ')'
ArgumentList
: Expression
| Expression ',' ArgumentList
| ',' ArgumentList
And the shift/reduce conflict is this:
State 109
237 ParenthesizedExpression: '(' Expression ')' .
$default reduce using rule 237 (ParenthesizedExpression)
...
State 295
231 IndexExpression: MemberExpression '(' . ArgumentList ')'
237 ParenthesizedExpression: '(' . Expression ')'
...
Expression go to state 352
...
State 352
182 ArgumentList: Expression .
183 | Expression . ',' ArgumentList
237 ParenthesizedExpression: '(' Expression . ')'
...
')' shift, and go to state 109
')' [reduce using rule 182 (ArgumentList)]
In other words, the parser is unsure when facing an expression wrapped by parentheses, whether it is an ArgumentList with a single expression or a ParenthesizedExpression.
Is there any way to fix this conflict, while maintaining the grammar to be LALR(1)?
Thank you.
EDIT 1:
/* other expressions */ in Expression is actually not an empty expression, I just wrote it in such a way for brevity. In actuality it has other alternative expressions:
Expression
: IndexExpression
| Expression '+' Expression
| ...
EDIT 2:
Here are additional parts of the grammar which @rici points out might be problematic (particularly the 1st right-hand rule of Statement):
Statement
: MemberExpression ArgumentList
| MemberExpression '=' Expression
| MemberExpression '(' ArgumentList ')' '=' Expression
| ...
argument_list
syntax is very odd. Why do you find it useful to write it with left-recursion, which should generally be avoided in LALR(1) parsers? And what do multiple missing arguments mean? And if all the other arguments can be omitted, why can't the last one be? – riciParenthesizedExpression: '(' Expression ')'
. That's the grammar equivalent of Redundant Comment Syndrome(++count; /* Increase the count by 1 */
) – rici