Follow
Finally we want to calculate Follow. This is done by calculating constraints. But first we add the production S \rightarrow S' $ as a start production where S' is the original start production of that grammar. Let M \rightarrow \alpha N \beta be a production where \alpha, \beta be possibly empty. The constraints is now obtained as
- Let m = First(\beta). If m \neq \emptyset, add the constraint m \subset Follow(N)
- If M \neq N and Nullable(\beta), add the constraint Follow(M) \subset Follow(N). Note that \beta = \emptyset \Rightarrow Nullable(\beta) = true
Then we solve the constraints with fixpoint-iteration as follows
- Init empty solved dictionary.
- For every constraint add every First set to solved.
- Now iterate through constraints adding Follow-sets to solved until no new elements are added.
Again this algorithm is bound to stop because we are adding from a finite set. At some point new elements simply can't exist.
The Follow-sets are tiresome at best to calculate. Observe the following grammar
A \rightarrow "a" B "c" D . . . D \rightarrow "(" E ")" E \rightarrow A E E \rightarrowStolen but modified from a problem sheet with answer key. The answer key has a problem, I'm pretty sure. We can loosely calculate
{")"} \subset Follow(E) First(E) \subset Follow(A) Follow(E) \subset Follow(A) \Rightarrow {")"} \subset Follow(A)The last line since Nullable(E) = true. From the same problem sheet, but where I first made a mistake:
C \rightarrow A B "c0" "c1" E FWhere Nullable(A) = Nullable(B) = true. Here
First(B) \subset Follow(A) {"c0"} \subset Follow(A)Anyway. Follow works solely on the right hand side of a grammar. Take this grammar with added S production
S \rightarrow A $ A \rightarrow B C "a" B \rightarrow "b" C | C \rightarrow "c" A |We have Nullable(A) = false, Nullable(B) = Nullable(C) = true. And we have
First(A) = {"a","b","c"} First(B) = {"b"} First(C) = {"c"} First(C "a") = {"c","a"}to calculate Follow we obtain constraints:
{$} \subset Follow(A) First(C "a") \subset Follow(B) First("a") \subset Follow(C) Follow(B) \subset Follow(C) Follow(C) \subset Follow(A)First iteration:
{$} \subset Follow(A) {"a","c"} \subset Follow(B) {"a"} \subset Follow(C) {"a","c"} \subset Follow(C) {"a","c",$} \subset Follow(A)Second iteration
{"a","c"} \subset Follow(C) {"a","c"} \subset Follow(A)No new elements are added, and we have
{"a","c",$} = Follow(A) {"a","c"} = Follow(B) {"a","c"} = Follow(C)Again that spectacular HashSet comes to our rescue. We add elements element wise until all adds return false.