Java Reference
In-Depth Information
Figure 4.9 shows the progress of F
as it is invoked on the nonterminals
of Figure 4.1. The level of recursion is shown in the leftmost column. Each
call to F
irst
irst
(
) is shown with nonblank entries in the
X
and
β
columns. A
” indicates that the call does not recurse further. Figure 4.10 shows another
grammar and the computation of its First sets. For brevity, recursive calls to
I
on null strings are omitted.
Termination of First(A) must be handled properly in grammars where the
computation of First(A) appears to depend on First(A), as follows:
nternal
F
irst
A
B
···
B
C
···
C
A
In this grammar, First(A) depends on First(B), which depends on First(C),
which depends on First(A). In computing First(A), we must avoid endless
iteration or recursion. A sophisticated algorithm could preprocess the gram-
mar to determine such cycles of dependence. We leave this as Exercise 19
and present a clearer but slightly less e
cient algorithm in Figure 4.8. This
algorithm avoids endless computation by remembering which nonterminals
have already been visited, as follows:
First(
α
) is computed by invoking F
irst
(
α
).
Before any sets are computed, Marker 9 resets VisitedFirst (A)foreach
nonterminal A.
VisitedFirst (
) is set at Marker 13 to indicate that the productions of A
already participate in the computation of First(
X
α
).
4.5.4 Follow Sets
Parser-construction algorithms often require the computation of the set of
terminals that can follow anonterminalA in some sentential form. Because we
augment grammars to contain an end-of-input token ($), every nonterminal
except the goal symbol must be followed by some terminal. Formally, for
A
N ,
Follow(A)
={
b
∈Σ|
S
+ α
Ab
β}.
Follow(A)providesthe right context associated with nonterminal A.For
example, only those terminals in Follow(A) can occur after a production for A
is applied.
 
 
Search WWH ::




Custom Search