It's because of two rules that start with opening_tag
. The parser has to decide between the rules by lookint at most one token ahead, but it cannot. <FOO>
may lead to either rule, and this requires two more tokens of lookahead.
You can do this:
tag : /* nothing */
| opening_tag contents closing_tag
;
contents: tag
| anything
;
UPDATE This new grammar has a different shift/reduce conflict. (UPDATE2: or perhaps it's the same one). Because a tag can be empty, the parser cannot decide what to do at this input:
<Foo> <...
^
|
input is here
If the next symbol is a slash, then we have a closing tag, and the empty tag rule should be matched. If the next symbol is not a slash, then we have an opening tag, and the non-empty tag rule should be matched. But the parser cannot know, it is only allowed to look at <
.
The solution would be to create a new token, LANGLE_SLASH, for the </
combination.