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 addedIn 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) ) ) $$