If one of my rules expand the same as part of the other rule, how would I mark precedence? For instance, I have expression IS type
rule that should expand type
as type DOT identifier
recursively. But the in the same rule expression
I have expression DOT identifier
which bison reports as conflict. I would obviously want all DOT
s within as expression's type part to reduce together into type
and not as expression. Ie: a is b.c.d
should parse as (a is b.c.d)
where b.c.d
is type
and not (a is b).c.d
. Here is minimal grammar that shows the conflict:
%require "3.0"
%defines
%define api.pure full
%define parse.trace
%token DOT '.'
%token IS "is"
%left DOT
%left IS
%%
example
: expression
;
expression
: expression DOT identifier
| expression IS type
| identifier
;
type
: fqtypename
;
fqtypename
: identifier
| fqtypename DOT identifier
;
identifier:
"blah"
;
%%
and error:
State 10
5 type: fqtypename •
7 fqtypename: fqtypename • DOT identifier
DOT shift, and go to state 12
DOT [reduce using rule 5 (type)]
$default reduce using rule 5 (type)
As you can see from the conflicted state, the conflict actually has nothing to do with the IS
token. Rather, the conflict is between shifting DOT
and reducing the production type: fqtypename
, and you want that to resolve to shifting DOT
.
In fact, that's the default resolution without any precedence declarations. Bison, like Yacc, automatically resolves shift-reduce conflicts in favour of shifting, and reduce-reduce conflicts in favour of whichever production appears earlier in the grammar file. You can see that resolution in the state table you pasted (DOT
is shifted in that state). Of course, that does leave you looking at a bison warning every time you generate your parser, which is not ideal. You can avoid the warning by using an %expect
declaration, which basically tells Bison the number of shift-reduce conflicts that are expected to be resolved automatically. With recent Bison versions, you can attach the declaration to the production itself, which makes the expectation more precise. See the link to the Bison manual, which shows an example grammar somewhat similar to yours.
With a bit more work, you can use precedence declarations to achieve the same effect, which has the advantage of being slightly more precise, at the cost of making the grammar a bit more mysterious. Here's an example based on the grammar in your question. Note that a %prec
declaration is attached to the production which is actually involved in the conflict. Because that production has no terminal symbols at all, it was necessary to use a pseudo-token to represent the precedence level.
/* I removed the token names for '.' and "is" to make the grammar shorter. */
%left TYPE_UNIT
%left '.'
%%
example
: expression
expression
: expression '.' identifier
| expression "is" type
| identifier
type
: fqtypename %prec TYPE_UNIT
fqtypename
: identifier
| fqtypename '.' identifier
identifier:
"blah"