The point
Before touching bison, derive some sentences by hand. Ambiguity is easy to define and hard to recognize, and the only reliable way to recognize it is to have once found two trees for the same string yourself.
Do this
- Derive. Using the starter grammar, write a leftmost derivation for
Show every step:int x; x = 1 + 2;program ⇒ stmt_list ⇒ …. Then write the rightmost derivation of the same input and say which one a bottom-up parser would produce in reverse. - Draw the parse tree for that derivation. Confirm that both derivations give the same tree — that is the point of §4.2.3.
- Now the interesting one. Take this fragment, with no precedence declarations:
Draw two different parse trees forexpr -> expr '+' expr | expr '*' expr | NUM1 + 2 * 3. Evaluate both. You should get two different numbers, and that is what ambiguity costs. - Fix it two ways. (a) Rewrite the grammar into
expr → term → factorlayers. (b) Keep the ambiguous grammar and write the%leftdeclarations. Write both out in full. - Check associativity. Under your layered grammar, draw the tree for
17 - 5 - 3and evaluate it. Then make the recursion right-recursive instead and redraw. Which is correct, and what does that tell you about the direction of recursion? - Argue. Which fix would you ship, and why? Write the answer you actually believe, not the one you think is expected — Dragon §4.8 argues for the second and most textbooks teach the first.
If you are stuck on step 6
Layering is portable — it works with any parser generator and with a hand-written recursive-descent parser — and the grammar itself documents the precedence. Declarations are shorter, easier to change, and keep the grammar readable, but they are a yacc/bison feature and they put the precedence somewhere other than the rules. Both arguments are good. Pick one and mean it.
Deliverable
Your worked pages — both derivations, three parse trees, both fixes, the associativity comparison — plus a paragraph answering step 6. This is most of Lab Question 3.