Initial Recitation work:
S ---> E ("S" is the start symbol) E ---> E "+" T | T T ---> T "*" F | F F ---> "(" E ")" | id
| id | * | + | ( | ) | $ | -----+-----+-----+-----+-----+-----+-----+ S | | | | | | acc | ( "s" means "shift") E | | | s | | s | r | T | | s | r | | r | r | ( "r" means "reduce") F | | r | r | | r | r | id | | r | r | | r | r | ( "acc" means "accept") * | s | | | s | | | + | s | | | s | | | ( | s | | | s | | | ) | | r | r | | r | r | $ | s | | | s | | | -----+-----+-----+-----+-----+-----+-----+
$ ( id + id ) * id $(Remember that you should initially shift the starting $.)
Stack (top at right) Curr Rest of Input Action Sym -------------------------------------------------------------------------- $ ( id + id ) * id $ shift $ ( id + id ) * id $ shift $ ( id + id ) * id $ reduce: F ---> id $ ( F + id ) * id $ reduce: T ---> F $ ( T + id ) * id $ reduce: E ---> T $ ( E + id ) * id $ shift $ ( E + id ) * id $ shift $ ( E + id ) * id $ reduce: F ---> id $ ( E + F ) * id $ reduce: T ---> F $ ( E + T ) * id $ reduce: E ---> E + T $ ( E ) * id $ shift $ ( E ) * id $ reduce: F ---> ( E ) $ F * id $ reduce: T ---> F $ T * id $ shift $ T * id $ shift $ T * id $ reduce: F ---> id $ T * F $ reduce: T ---> T * F $ T $ reduce: E ---> T $ E $ reduce: S ---> E $ S $ accept
S ---> b M b ("S" is the start symbol) M ---> ( L M ---> a L ---> M a )Use the following shift-reduce table for this grammar:
| b | a | ( | ) | $ | -----+-----+-----+-----+-----+------+ S | | | | | acc | ( "s" means "shift") M | s | s | | | | L | r | r | | | | ( "r" means "reduce") b | | s | s | | r | a | r | r | | s | | ( "acc" means "accept") ( | s | s | s | | | ) | r | r | | | |
$ b ( ( a a ) a ) b $(Remember that you should initially shift the starting $ and then shift the next symbol.)
Key ideas: The shift-reduce parser using a stack is a common strategy. The version shown here is relatively simple, but there are much more sophisticated versions called LR parsers (text, pages 170-174), and LALR parsers (beyond the scope of the course). These parsers are the most capable and are the ones usually employed for real compilers. An LR parser handles the most complex grammar possible using a simple left-to-right scan, and it can determine a syntax error at the earliest possible point.