I'd like to do something like this:
// match used as a statement, semicolon is optional
match (1) {}
// match used as an expression, semicolon is required
1 + match (2) {};
statement
: expression_without_block T_SEMICOLON
| expression_with_block
;
expression
: expression_without_block
| expression_with_block
;
expression_without_block
: scalar
| expression_without_block T_PLUS expression
| T_PLUS expression
;
expression_with_block
: T_MATCH T_LEFT expression T_RIGHT T_CURLY_LEFT T_CURLY_RIGHT
;
The idea is that expression_with_block
can't be used at the beginning of a statement, making the following unambiguous:
match (1) {}
+2;
// Can't mean
(match (1) {} + 2);
// because of the line "expression_without_block T_PLUS expression"
The grammar causes a shift/reduce conflicts but I have no idea why. The output says the following (but I'm not sure what to do with it):
State 11 conflicts: 1 shift/reduce
...
State 11
5 expression: expression_without_block .
8 expression_without_block: expression_without_block . T_PLUS expression
T_PLUS shift, and go to state 14
T_PLUS [reduce using rule 5 (expression)]
$default reduce using rule 5 (expression)
The full output file can be found here.
I'm also not even sure this is the right approach because then something like this wouldn't work:
// `match` can't be at the lhs of an expression, even in sub-expressions
func_call(match (10) {} + 20);
Is there a way to achieve what I'm describing here in bison? I'm not a bison expert so I'd really appreciate some help. Thanks!
It's a very classic kind of conflict that happen with left recursive rules, but as the default resolution of a shift/reduce conflict is to do a shift, then everything will be fine here.
Here is how you should read the bison trace:
T_PLUS shift, and go to state 14 -- when next token is T_PLUS shift action is selected
T_PLUS [reduce using rule 5 (expression)] -- the action between [] was disabled by Bison default conflict resolution
To override Bison's default conflict resolution (which is not necessary here), we may use operator precedence (see https://www.gnu.org/software/bison/manual/bison.html#Precedence-Decl) or precedence for non operator (see https://www.gnu.org/software/bison/manual/bison.html#Non-Operators)