Homework 4 Solutions
- Rewrite production 1 in a way that it could be recognized
using bison:
(1) stmt -> directive?
(2) directive -> left | right
Any of the following three solutions is correct, with my
preference being for the first one, because it most closely captures
the spirit of an optional non-terminal:
-
stmt -> ε | directive
directive -> left | right
-
stmt -> ε | left | right
-
stmt -> directive
directive -> ε | left | right
Rewrite production 1 in a way that it could be recognized
using bison:
(1) stmt -> directive+
(2) directive -> left | right
stmt -> directiveList
directiveList -> directiveList directive
| directive
Rewrite production 1 in a way that it could be recognized
using bison:
(1) stmt -> directive*
(2) directive -> left | right
stmt -> directiveList
directiveList -> directiveList directive
| ε
Rewrite production 1 in a way that it could be recognized
using bison:
(1) stmt -> directive number (, directive number)*
(2) directive -> left | right
stmt -> command commandList
commandList -> commandList , command
| ε
command -> directive number
Another way to write the solution, without introducing the command
non-terminal, is:
stmt -> directive number commandList
commandList -> commandList , directive number
| ε
Take a look at the bison specification in
exp.yacc. It contains a Shift/Reduce conflict which you will
be debugging in this problem.
- Look at the output file produced by the -v flag. In which state
does the Shift/Reduce conflict occur?
State 5
- What token is causing the Shift/Reduce conflict?
PLUS
- Which production can be potentially reduced?
exp -> exp PLUS exp
- Which production can be potentially recognized in the future
if we shift the token?
exp -> exp PLUS exp
- What directive can we add to the bison specification to
eliminate the conflict?
The shift reduce conflict is being caused by ambiguity about the
associativity of the plus operator, which can be resolved by
using the following directive to specify
the operator as left associative:
%left PLUS
Take a look at the bison specification in
sections.yacc. It contains a Shift/Reduce conflict which you
will be debugging in this problem. Compile this
file using the command:
bison -v sections.yacc
- Look at the output file produced by the -v flag. In which state
does the Shift/Reduce conflict occur?
State 2
- What token is causing the Shift/Reduce conflict?
ID
- Which production can be potentially reduced?
edgelist -> ε
- Which production can be potentially recognized in the future
if we shift the token?
assignmentList -> assignmentList assignment
If you were not sure which of the two productions might be
recognized if there is a shift, then notice that the shift action
is to go to state 4. If you look at state 4, you can see that
an assignment production is being recognized, which means that
a shift operation would potentially recognize the assignmentList
production.
- The problem with the grammar as it is written is that
both the assignments and edges are optional.
If I allow you to add a requirement that there
be at least one assignment and one edge, then you
can rewrite the grammar to eliminate the Shift/Reduce
conflict. Show me the rewritten grammar.
The productions that were causing the Shift/Reduce conflict
are the ones for assignmentList and edgeList that allow them to
be potentially empty. Here are the offending productions in the
original grammar:
assignmentList : assignmentList assignment
|
;
edgeList : edgeList edge
|
;
I allowed you to add a requirement that there be at least one
assignment and one edge, so I can rewrite these productions as
follows to require that there be at least one of each:
assignmentList : assignmentList assignment
| assignment
;
edgeList : edgeList edge
| edge
;
In the previous problem, I allowed you to add a requirement that
there be at least one assignment statement and one edge statement.
Suppose though that I really wanted to allow both assignments
and edges to be optional.
Now I cannot rewrite the grammar to reduce the shift/reduce conflict.
What could I instead add to the grammar in order to eliminate
the shift/reduce conflict? Describe informally what you would do and then
write the one production that you would change. You only need to add
something to one production in order for the grammar to become unambiguous.
I must add some type of delimiter between the assignment and
edge statements, so that the parser will know unambiguously when one
section has ended and the next is to begin. The delimiter should be
added to the top level production:
stmt : assignmentList edges edgeList
It is good to use a delimiter that your potential users can easily
remember. In this case, the user is starting to enumerate the
edges, so a good delimiter name is edges. However, I accepted
any answer that had some sort of distinguishing delimiter.
The bison parser for:
- The yacc and
lex specification for the
simplified "edges" grammar.
- The yacc and
lex specification for the
full graph grammar.