stmt => subr_call
=> id ( arg_list )
=> id ( expr args_tail )
=> id ( expr , arg_list )
=> id ( expr , expr args_tail )
=> id ( expr , expr ) // application of args_tail -> epsilon
=> id ( expr , primary expr_tail )
=> id ( expr , primary ) // application of expr_tail -> epsilon
=> id ( expr , id )
=> id ( primary expr_tail , id )
=> id ( primary , id ) // application of expr_tail -> epsilon
=> id ( id , id )
Original grammar:
stmt -> assignment
-> subr_call
assignment -> id := expr
subr_call -> id ( arg_list )
Factor out the id that is common to assignment and subr_call and move it
up to stmt:
stmt -> id rest_of_statement
rest_of_statement -> assignment
-> subr_call
assignment -> := expr
subr_call -> ( arg_list )
Once, we fix the production for subr_call, we have almost fixed
the problem with primary. Here is how we work out the problem
with primary:
Original grammar:
primary -> id
-> subr_call
-> ( expr )
subr_call -> id ( arg_list )
We need to factor out the id from subr_call and move it up to primary:
primary -> id rest_of_primary
-> ( expr )
rest_of_primary -> epsilon
-> subr_call
subr_call -> ( arg_list )
Notice that we had already modified subr_call in a similar fashion
at the end of the first fix. Fortunately, the two modifications agree and
we don't have to perform any further modifications.
In this problem, E appears in four productions: "P -> E $$", "Es -> E Es", "E -> ' E", and "E -> ( E Es )". We can apply our rules as follows:
Predict(Es -> ε) = First(ε) U Follow(Es)
= Follow(Es)
= { ) }
Next the explanation.
Since First(ε) is the empty set, we are left with only
Follow(Es).
To compute Follow(Es), we find
the productions in which Es appears on the RHS:
E -> ( E Es ) // add ) to Follow(Es)
Es -> E Es // add Follow(Es) to Follow(Es)--this is circular so nothing
// more gets added
In the first production, Es is followed by a right
parenthesis, so we add a ) to Follow(Es).
In the second production, Es
appears at the end of the production, and hence we add in the
Follow set for the non-terminal on the LHS, which is also
Es. This is circular and does not add any new information.
| Parse tree |
![]() |
P => E $$
=> ( E Es ) $$
=> ( atom(cdr) Es ) $$
=> ( atom(cdr) E Es ) $$
=> ( atom(cdr) ' E Es ) $$
=> ( atom(cdr) ' ( E Es ) Es ) $$
=> ( atom(cdr) ' ( atom(a) Es ) Es ) $$
=> ( atom(cdr) ' ( atom(a) E Es ) Es ) $$
=> ( atom(cdr) ' ( atom(a) atom(b) Es ) Es ) $$
=> ( atom(cdr) ' ( atom(a) atom(b) E Es ) Es ) $$
=> ( atom(cdr) ' ( atom(a) atom(b) atom(c) Es ) Es) $$
=> ( atom(cdr) ' ( atom(a) atom(b) atom(c) ) Es) $$
=> ( atom(cdr) ' ( atom(a) atom(b) atom(c) ) ) $$