That grammar surely produced at least one shift/reduce conflict along with a warning that the production attrbt: /* nothing */
is useless because of the conflict. (If that's not the case, it's because GPPG doesn't provide as many warnings as bison. But I'm certain that it will at least flag the shift/reduce conflict.)
The conflict arises in the rules:
defLine : "DEF" kwType attrbt ID
defLine : "DEF" kwType ID fieldSuff
because attrbt
can be empty, but cannot precede ID
in the second rule. Suppose the parser has encountered DEF INT
and the next symbol is ID
. At this point, the parser does not know which of the two productions for defLine
to use, but the difference matters. In the first case, the parser must reduce an empty attrbt
before shifting the ID
. In the second case, creating the attrbt
would be a mistake.
Yacc-like parser generators always resolve shift/reduce conflicts in favour of shifting (unless there are precedence declarations), so in this case the ID
will always be shifted. That means that it is impossible to ever reduce the production attrbt: /* nothing */
. (Bison, at least, would warn you about this fact.
Furthermore, since the shift of ID
will occur in that case, only the second production for defLine
will be available, so the parser will require fieldStuff
to follow the ID
, and fieldStuff
must start with [
. Hence the parsing error you encounter.
To fix this, you need to remove the shift/reduce conflict. One simple way would be to allow attrbt
in both defLine
productions (you can detect the error in the semantic action). Another possibility is to remove the empty production for attrbt
and explicitly allow it to be missing:
attrbt : "PHU" intValue
defLine : "DEF" kwType ID
| "DEF" kwType attrbt ID
| "DEF" kwType ID fieldSuff