Last time, we looked at many aspects of YACC and Lex, but we skipped on important detail
-- the y.output file.
The y.output file contains
a summary of the productions of the grammar, and
a description of the pushdown automaton used to perform parsing.
The descriptions of the states in the y.output file look like:
state 1
date : MONTH . day ',' year (3)
NUMBER shift 6
. error
day goto 7
Each such state description starts with a list of productions annotated with embedded
periods. These productions indicate what rules it believes may become candidates
for applying to reduce the handle in a future step.
The period indicates the parser's
progress toward recognizing an instance of each production.
Everything to the left
of the period must appear on the top of the parser's stack when it reaches this
state.
It is still looking for everything after the period.
After the list of productions there is a list that indicates how the parser should
behave based on the next input symbol.
It either says "shift" (meaning shift the token onto the stack) and includes the
state the parser should move into, or
It says reduce (and specifies what rule to use to match the handle).
A period is used to indicate what to do for input tokens not otherwised mentioned
Finally, there is a description of how to behave if a non-terminal is shifted onto the
stack after reducing a suffix of the stack.
Not all grammars can be used to build deterministic bottom-up parsers.
If Yacc cannot build a deterministic parser for a grammar, it will concisely report the
error in the terminal window and provide more complete details in the y.output file.
There are two problems that may be reported:
A reduce/reduce conflict means that in some state and with certain next token values,
Yacc has realized it should reduce but it does not know how to decide which production
to use when reducing.
A shift/reduce conflict means that in some state Yacc has realized it may not be
able to decide whether to shift or to reduce.