# Class 12: Predictive parsing, continued

Held Wednesday, September 23, 1998

Notes

• Reminder: I'll be away on Friday (as will Raphen, Hilary, Kevin, and Sarah). Have a good weekend.
• Because the most recent programming assignment was so long, I've given you an additional week to write the parser. Use that time wisely.
• There is clearly more in today's outline than we can hope to cover in one day. Hence we will conclude parsing next Monday.

## Opening questions

• Why do we want follow tables anyway?
• Was Jamal's modification for unary minus correct? Why not?

• The construction of the `Follow` table is a little bit more subtle.
• In general, every production can be written as N ::= alpha M beta, where alpha and beta are sequences of tokens and nonterminals.
• Note that there are a variety of ways to write a production in that form. Consider N ::= a B b C D
• We might have M is B, alpha is a, and beta is b C D
• We might have M is C, alpha is a B b, and beta is C D
• We might have M is D, alpha is a B b C, and beta is epsilon
• How do we use this information to build the `Follow` table? We know that M can be followed by anything that can begin a string derivable from beta.
• What if beta can derive epsilon (that is, beta is nullable)? Then anything that can follow N can follow M.
• S =>* aardvark N baboon -- Derivation of a string with N
• => aardvark alpha M beta baboon -- N ::= alpha M beta
• => aardvark alpha M baboon -- beta derives epsilon
• Putting it all together
```for each nonterminal, N
Follow(N) = {};
for each production P
for each form of P, N ::= alpha M beta
Follow(M) = Follow(M) union first(beta)
end for
end for
repeat
for each production P
for each form of P, N :: = alpha M beta
if nullable(beta)
Follow(M) = Follow(M) union Follow(N)
end if
end for
end for
end for
```

## Building a recursive descent parser, revisited

• We can now use these tables to build recursive descent parsers for selected languages.
```for each nonterminal N, build the method parseN as follows
for each production, N ::= Stuff
for each symbol in first(Stuff)
add a case for that symbol, using the steps to parse Stuff
end for
if nullable(Stuff) then
for each symbol in Follow(N)
add a case for that symbol, using the steps to parse Stuff
-- Note that we still parse Stuff, even thoush we
-- ``know'' it nullifies
end for
end if
end for each production
end for each nonterminal
```

Back to Predictive parsing. On to Shift-reduce parsing.

History

• Created Monday, September 21, 1998
• Additional stuff added (some taken from the previous outline) on Wednesday, September 23, 1998
• On Monday, September 28, 1998, I moved the section on the Follow table from the pervious outline to this outline. I also moved most of this outline to the next outline.

Disclaimer Often, these pages were created "on the fly" with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.