**************************************************************** Getting the right grammar **************** Here is my original EBNF, as accepted by Coco BoolExpr -> BoolTerm { "+" BoolTerm } BoolTerm -> BoolFact { BoolFact } BoolFact -> variable | literal | "~" BoolFact | "(" BoolExpr ")" BoolEquv -> BoolExpr "==" BoolExpr "\n" Program -> { BoolEquv } . **************** Next, I modified the EBNF to have a EOF ($$) marker and to eliminate the implicit recursion of { ... }. Notice that I have no "left" recursion, i.e., I have BoolExpr -> BoolTerm "+" BoolExpr and not BoolExpr -> BoolExpr "+" BoolTerm BoolExpr -> BoolTerm | BoolTerm "+" BoolExpr BoolTerm -> BoolFact | BoolFact BoolTerm BoolFact -> variable | literal | "~" BoolFact | "(" BoolExpr ")" BoolEquv -> BoolExpr "==" BoolExpr "\n" Program -> $$ | BoolEquv Program **************** Finally, I eliminated the |'s by separating these into multiple productions. Here is my "final" grammar BoolExpr -> BoolTerm BoolExpr -> BoolTerm "+" BoolExpr BoolTerm -> BoolFact BoolTerm -> BoolFact BoolTerm BoolFact -> variable BoolFact -> literal BoolFact -> "~" BoolFact BoolFact -> "(" BoolExpr ")" BoolEquv -> BoolExpr "==" BoolExpr "\n" Program -> $$ Program -> BoolEquv Program **************************************************************** Computing the FIRST function **************** First we do the initialization. Note that I have no productions which reduce to eps (epsilon, the empty string or "") for all terminals a, FIRST(a) := {a} for all non-terminals X, FIRST(X) := {} for all products X->eps, add eps to FIRST X FIRST(X) ---------------|-------------------- BoolExpr | { } ---------------|-------------------- BoolTerm | { } ---------------|-------------------- BoolFact | { } ---------------|-------------------- BoolEquv | { } ---------------|-------------------- Program | { } ---------------|-------------------- literal | { literal } ---------------|-------------------- variable | { variable } ---------------|-------------------- "+" | { "+" } ---------------|-------------------- "~" | { "~" } ---------------|-------------------- "(" | { "(" } ---------------|-------------------- ")" | { ")" } ---------------|-------------------- "==" | { "==" } ---------------|-------------------- "\n" | { "\n" } ---------------|-------------------- $$ | { $$ } **************** Here is a rewritten version of the text's algorithm repeat until no progress for all productions X -> Y1 Y2 .... Yk { // Keep this true until we *know* one of Y1..Yi doesn't contain eps epsStillPossible = true for all i in 1 .. k while epsStillPossible { if eps is in FIRST(Yi) { FIRST(X) := FIRST(X) union (FIRST(Yi)-{eps}) ; // epsStillPossible must continue to be true } else { FIRST(X) := FIRST(X) union FIRST(Yi) ; epsStillPossible = false // Yi doesn't contain eps, so neither does Y1 Y2 ... Yk } if (epsStillPossible) { FIRST(X) := FIRST(x) union {eps} } } } **************** Now I go through Pass 1 of the the algorithm Production 1: BoolExpr -> BoolTerm Makes no change as FIRST(BoolTerm) = { } Production 2: BoolExpr -> BoolTerm "+" BoolExpr Makes no change as FIRST(BoolTerm) = { } Production 3: BoolTerm -> BoolFact Makes no change as FIRST(BoolFact) = { } Production 4: BoolTerm -> BoolFact BoolTerm Makes no change as FIRST(BoolFact) = { } Production 5: BoolFact -> variable FIRST(variable) added to FIRST(BoolFact) Production 6: BoolFact -> literal FIRST(literal) added to FIRST(BoolFact) Production 7: BoolFact -> "~" BoolFact FIRST("~") added to FIRST(BoolFact) Production 8: BoolFact -> "(" BoolExpr ")" FIRST("(") added to FIRST(BoolFact) Production 9: BoolEquv -> BoolExpr "==" BoolExpr "\n" Makes no change as FIRST(BoolExpr) = { } Production 10: Program -> $$ FIRST($$) added to First(Program) Production 11: Program -> BoolEquv Program Makes no change as FIRST(BoolEquv) = { } Progress is made on Pass 1, FIRST(BoolFact) and FIRST(Program) are updated X FIRST(X) ---------------|-------------------- BoolFact | { variable, literal, "~", "(" } ---------------|-------------------- Program | { $$ } ---------------|-------------------- **************** Time for Pass 2 Production 1: BoolExpr -> BoolTerm Makes no change as FIRST(BoolTerm) = { } Production 2: BoolExpr -> BoolTerm "+" BoolExpr Makes no change as FIRST(BoolTerm) = { } Production 3: BoolTerm -> BoolFact FIRST(BoolFact) is added to First(BoolTerm) Production 4: BoolTerm -> BoolFact BoolTerm FIRST(BoolFact) is added to First(BoolTerm) Production 5: BoolFact -> variable FIRST(variable) added to FIRST(BoolFact) -- No change! Production 6: BoolFact -> literal FIRST(literal) added to FIRST(BoolFact) -- No change! Production 7: BoolFact -> "~" BoolFact FIRST("~") added to FIRST(BoolFact) -- No change! Production 8: BoolFact -> "(" BoolExpr ")" FIRST("(") added to FIRST(BoolFact) -- No change! Production 9: BoolEquv -> BoolExpr "==" BoolExpr "\n" Makes no change as FIRST(BoolExpr) = { } Production 10: Program -> $$ Makes no change Production 11: Program -> BoolEquv Program Makes no change as FIRST(BoolEquv) = { } Progress is made on Pass 2, FIRST(BoolTerm) is updated X FIRST(X) ---------------|-------------------- BoolTerm | { variable, literal, "~", "(" } ---------------|-------------------- **************** On the next passes, progress will be made as information is passed from BoolTerm to BoolExpr to BoolEquv to Program On Pass 3, FIRST(BoolExpr) is updated X FIRST(X) ---------------|-------------------- BoolExpr | { variable, literal, "~", "(" } ---------------|-------------------- **************** Pass 4 Progress is made on Pass 4, FIRST(BoolEquiv) is updated X FIRST(X) ---------------|-------------------- BoolEquiv | { variable, literal, "~", "(" } ---------------|-------------------- **************** Pass 5 Progress is made on Pass 4, FIRST(BoolEquiv) is added for FIRST(Program) X FIRST(X) ---------------|-------------------- Program | { variable, literal, "~", "(" , $$ } ---------------|-------------------- **************** Pass 6 No change will be made -- Final table (without terminals) is: X FIRST(X) ---------------|-------------------- BoolExpr | { variable, literal, "~", "(" } ---------------|-------------------- BoolTerm | { variable, literal, "~", "(" } ---------------|-------------------- BoolFact | { variable, literal, "~", "(" } ---------------|-------------------- BoolEquv | { variable, literal, "~", "(" } ---------------|-------------------- Program | { variable, literal, "~", "(" , $$ } ---------------|-------------------- **************************************************************** Now we will compute the FOLLOW set Here's the initialization FOLLOW($$) = { eps } FOLLOW(Program) = { eps } for all other symbols X, FOLLOW(X) := { } X FOLLOW(X) ---------------|-------------------- BoolExpr | { } ---------------|-------------------- BoolTerm | { } ---------------|-------------------- BoolFact | { } ---------------|-------------------- BoolEquv | { } ---------------|-------------------- Program | { eps } ---------------|-------------------- literal | { } ---------------|-------------------- variable | { } ---------------|-------------------- "+" | { } ---------------|-------------------- "~" | { } ---------------|-------------------- "(" | { } ---------------|-------------------- ")" | { } ---------------|-------------------- "==" | { } ---------------|-------------------- "\n" | { } ---------------|-------------------- $$ | { eps } **************** Here is the re-expressed algorithm repeat until no more progress for all productions A --> alpha B beta { FOLLOW(B) = FOLLOW(B) union (FIRST(beta) - { eps }) if eps in FIRST(beta) { FOLLOW(B) = FOLLOW(B) union FOLLOW(A) } } for all productions A --> alpha B { FOLLOW(B) = FOLLOW(B) union FOLLOW(A) } } Here's what happens if we blindly follow each this algorithm for each of our production Pass N (blind allegiance) Production 1: BoolExpr -> BoolTerm Adds FOLLOW(BoolExpr) to FOLLOW(BoolTerm) Production 2: BoolExpr -> BoolTerm "+" BoolExpr Adds FIRST("+") to FOLLOW(BoolTerm) -- Can only change on Pass 1 Adds FIRST(BoolExpr) to FOLLOW("+") -- Can only change on Pass 1 Adds FOLLOW(BoolExpr) to FOLLOW(BoolExpr) -- No change of course Production 3: BoolTerm -> BoolFact Adds FOLLOW(BoolTerm) to FOLLOW(BoolFact) Production 4: BoolTerm -> BoolFact BoolTerm Adds FIRST(BoolTerm) to FOLLOW(BoolFact) -- Can only change on Pass 1 Adds FOLLOW(BoolTerm) to FOLLOW(BoolTerm) -- No change of course Production 5: BoolFact -> variable Adds FOLLOW(BoolFact) to FOLLOW( variable) Production 6: BoolFact -> literal Adds FOLLOW(BoolFact) to FOLLOW( literal ) Production 7: BoolFact -> "~" BoolFact Adds FIRST(BoolFact) to FOLLOW( "~" ) -- Can only change on Pass 1 Adds FOLLOW(BoolFact) to FOLLOW(BoolFact) -- No change of course Production 8: BoolFact -> "(" BoolExpr ")" Adds FIRST(BoolExpr) to FOLLOW( "(" ) -- Can only change on Pass 1 Adds FIRST( ")" ) to FOLLOW(BoolExpr) -- Can only change on Pass 1 Adds FOLLOW(BoolFact) to FOLLOW(")") Production 9: BoolEquv -> BoolExpr "==" BoolExpr "\n" Adds First( "==" ) to FOLLOW(BoolExpr) -- Can only change on Pass 1 Adds First( BoolExpr ) to FOLLOW("==") -- Can only change on Pass 1 Adds First( "\n" ) to FOLLOW(BoolExpr) -- Can only change on Pass 1 Adds FOLLOW(BoolEquv) to FOLLOW("\n") Production 10: Program -> $$ Adds FOLLOW(Program) to FOLLOW($$) Production 11: Program -> BoolEquv Program Adds FIRST(Program) to FOLLOW(BoolEquv) -- Can only change on Pass 1 Adds FOLLOW(Program) to FOLLOW(Program) -- No change of course **** Pass N (blind allegiance) Production 1: BoolExpr -> BoolTerm Adds FOLLOW(BoolExpr) to FOLLOW(BoolTerm) Production 2: BoolExpr -> BoolTerm "+" BoolExpr Adds FIRST("+") to FOLLOW(BoolTerm) Adds FIRST(BoolExpr) to FOLLOW("+") Adds FOLLOW(BoolExpr) to FOLLOW(BoolExpr) Production 3: BoolTerm -> BoolFact Adds FOLLOW(BoolTerm) to FOLLOW(BoolFact) Production 4: BoolTerm -> BoolFact BoolTerm Adds FIRST(BoolTerm) to FOLLOW(BoolFact) Adds FOLLOW(BoolTerm) to FOLLOW(BoolTerm) Production 5: BoolFact -> variable Adds FOLLOW(BoolFact) to FOLLOW( variable) Production 6: BoolFact -> literal Adds FOLLOW(BoolFact) to FOLLOW( literal ) Production 7: BoolFact -> "~" BoolFact Adds FIRST(BoolFact) to FOLLOW( "~" ) Adds FOLLOW(BoolFact) to FOLLOW(BoolFact) Production 8: BoolFact -> "(" BoolExpr ")" Adds FIRST(BoolExpr) to FOLLOW( "(" ) Adds FIRST( ")" ) to FOLLOW(BoolExpr) Adds FOLLOW(BoolFact) to FOLLOW(")") Production 9: BoolEquv -> BoolExpr "==" BoolExpr "\n" Adds FIRST( "==" ) to FOLLOW(BoolExpr) Adds FIRST( BoolExpr ) to FOLLOW("==") Adds FIRST( "\n" ) to FOLLOW(BoolExpr) Adds FOLLOW(BoolEquv) to FOLLOW("\n") Production 10: Program -> $$ Adds FOLLOW(Program) to FOLLOW($$) Production 11: Program -> BoolEquv Program Adds FIRST(Program) to FOLLOW(BoolEquv) Adds FOLLOW(Program) to FOLLOW(Program) **** However, note that adding a set to itself makes no sense, so we can eliminate actions like: Adds FOLLOW(Program) to FOLLOW(Program) Also, note that since the FIRST set is fixed, actions like: Adds FIRST( "\n" ) to FOLLOW(BoolExpr) can only change the FOLLOW set once. So, let's be a little smarter, let's do one pass (pass 0) where we do the adds of the FIRST set, as in: Pass 0 Production 2: BoolExpr -> BoolTerm "+" BoolExpr Adds FIRST("+") to FOLLOW(BoolTerm) Adds FIRST(BoolExpr) to FOLLOW("+") Production 4: BoolTerm -> BoolFact BoolTerm Adds FIRST(BoolTerm) to FOLLOW(BoolFact) Production 7: BoolFact -> "~" BoolFact Adds FIRST(BoolFact) to FOLLOW( "~" ) Production 8: BoolFact -> "(" BoolExpr ")" Adds FIRST(BoolExpr) to FOLLOW( "(" ) Adds FIRST( ")" ) to FOLLOW(BoolExpr) Production 9: BoolEquv -> BoolExpr "==" BoolExpr "\n" Adds FIRST( "==" ) to FOLLOW(BoolExpr) Adds FIRST( BoolExpr ) to FOLLOW("==") Adds FIRST( "\n" ) to FOLLOW(BoolExpr) Production 11: Program -> BoolEquv Program Adds FIRST(Program) to FOLLOW(BoolEquv) Then on the subsequent passes, we only worry about the non-trivial adds from the FOLLOW set, as in: Pass i, i>0 Production 1: BoolExpr -> BoolTerm Adds FOLLOW(BoolExpr) to FOLLOW(BoolTerm) Production 3: BoolTerm -> BoolFact Adds FOLLOW(BoolTerm) to FOLLOW(BoolFact) Production 5: BoolFact -> variable Adds FOLLOW(BoolFact) to FOLLOW( variable) Production 6: BoolFact -> literal Adds FOLLOW(BoolFact) to FOLLOW( literal ) Production 8: BoolFact -> "(" BoolExpr ")" Adds FOLLOW(BoolFact) to FOLLOW(")") Production 9: BoolEquv -> BoolExpr "==" BoolExpr "\n" Adds FOLLOW(BoolEquv) to FOLLOW("\n") Production 10: Program -> $$ Adds FOLLOW(Program) to FOLLOW($$) **************** So, here we go. First Pass 0 Production 2: BoolExpr -> BoolTerm "+" BoolExpr Adds FIRST("+") to FOLLOW(BoolTerm) FOLLOW(BoolTerm) = { "+" } Adds FIRST(BoolExpr) to FOLLOW("+") FOLLOW("+") = { variable, literal, "~", "(" } Production 4: BoolTerm -> BoolFact BoolTerm Adds FIRST(BoolTerm) to FOLLOW(BoolFact) FOLLOW(BoolFact) = { variable, literal, "~", "(" } Production 7: BoolFact -> "~" BoolFact Adds FIRST(BoolFact) to FOLLOW( "~" ) FOLLOW("~") = { variable, literal, "~", "(" } Production 8: BoolFact -> "(" BoolExpr ")" Adds FIRST(BoolExpr) to FOLLOW( "(" ) FOLLOW("(") = { variable, literal, "~", "(" } Adds FIRST( ")" ) to FOLLOW(BoolExpr) FOLLOW(BoolExpr) = { ")" } Production 9: BoolEquv -> BoolExpr "==" BoolExpr "\n" Adds FIRST( "==" ) to FOLLOW(BoolExpr) FOLLOW(BoolExpr) = { ")", "==" } Adds FIRST( BoolExpr ) to FOLLOW("==") FOLLOW("==") = { variable, literal, "~", "(" } Adds FIRST( "\n" ) to FOLLOW(BoolExpr) FOLLOW(BoolExpr) = { ")", "==", "\n" } Production 11: Program -> BoolEquv Program Adds FIRST(Program) to FOLLOW(BoolEquv) FOLLOW(BoolEquv) = { variable, literal, "~", "(" , $$ } That was so many changes, we better rewrite the whole table X FOLLOW(X) ---------------|-------------------- BoolExpr | { ")", "==", "\n" } ---------------|-------------------- BoolTerm | { "+" } ---------------|-------------------- BoolFact | { variable, literal, "~", "(" } ---------------|-------------------- BoolEquv | { variable, literal, "~", "(" , $$ } ---------------|-------------------- Program | { eps } ---------------|-------------------- literal | { } ---------------|-------------------- variable | { } ---------------|-------------------- "+" | { variable, literal, "~", "(" } ---------------|-------------------- "~" | { variable, literal, "~", "(" } ---------------|-------------------- "(" | { variable, literal, "~", "(" } ---------------|-------------------- ")" | { } ---------------|-------------------- "==" | { variable, literal, "~", "(" } ---------------|-------------------- "\n" | { } ---------------|-------------------- $$ | { eps } **************** Now it's time for Pass 1 -- remember, no adds of FIRST in here Production 1: BoolExpr -> BoolTerm Adds FOLLOW(BoolExpr) to FOLLOW(BoolTerm) FOLLOW(BoolTerm) = { "+", ")", "==", "\n" } Production 3: BoolTerm -> BoolFact Adds FOLLOW(BoolTerm) to FOLLOW(BoolFact) FOLLOW(BoolFact) = { variable, literal, "~", "+", "(", ")", "==", "\n" } Production 5: BoolFact -> variable Adds FOLLOW(BoolFact) to FOLLOW( variable) FOLLOW(variable) = { variable, literal, "~", "+", "(", ")", "==", "\n" } Production 6: BoolFact -> literal Adds FOLLOW(BoolFact) to FOLLOW( literal ) FOLLOW(literal) = { variable, literal, "~", "+", "(", ")", "==", "\n" } Production 8: BoolFact -> "(" BoolExpr ")" Adds FOLLOW(BoolFact) to FOLLOW(")") FOLLOW(")") = { variable, literal, "~", "+", "(", ")", "==", "\n" } Production 9: BoolEquv -> BoolExpr "==" BoolExpr "\n" Adds FOLLOW(BoolEquv) to FOLLOW("\n") FOLLOW("\n") = { variable, literal, "~", "(" , $$ } Production 10: Program -> $$ Adds FOLLOW(Program) to FOLLOW($$): No change! Again, there were some big changes: X FOLLOW(X) ---------------|-------------------- BoolExpr | { ")", "==", "\n" } ---------------|-------------------- BoolTerm | { "+", ")", "==", "\n" } ---------------|-------------------- BoolFact | { variable, literal, "~", "+", "(", ")", "==", "\n" } ---------------|-------------------- BoolEquv | { variable, literal, "~", "(" , $$ } ---------------|-------------------- Program | { eps } ---------------|-------------------- literal | { variable, literal, "~", "+", "(", ")", "==", "\n" } ---------------|-------------------- variable | { variable, literal, "~", "+", "(", ")", "==", "\n" } ---------------|-------------------- "+" | { variable, literal, "~", "(" } ---------------|-------------------- "~" | { variable, literal, "~", "(" } ---------------|-------------------- "(" | { variable, literal, "~", "(" } ---------------|-------------------- ")" | { variable, literal, "~", "+", "(", ")", "==", "\n" } ---------------|-------------------- "==" | { variable, literal, "~", "(" } ---------------|-------------------- "\n" | { variable, literal, "~", "(" , $$ } ---------------|-------------------- $$ | { eps } **** Now let's try Pass 2 Production 1: BoolExpr -> BoolTerm Adds FOLLOW(BoolExpr) to FOLLOW(BoolTerm) -- NO CHANGE Production 3: BoolTerm -> BoolFact Adds FOLLOW(BoolTerm) to FOLLOW(BoolFact) -- NO CHANGE Production 5: BoolFact -> variable Adds FOLLOW(BoolFact) to FOLLOW( variable) -- NO CHANGE Production 6: BoolFact -> literal Adds FOLLOW(BoolFact) to FOLLOW( literal ) -- NO CHANGE Production 8: BoolFact -> "(" BoolExpr ")" Adds FOLLOW(BoolFact) to FOLLOW(")") -- NO CHANGE Production 9: BoolEquv -> BoolExpr "==" BoolExpr "\n" Adds FOLLOW(BoolEquv) to FOLLOW("\n") -- NO CHANGE Production 10: Program -> $$ Adds FOLLOW(Program) to FOLLOW($$) -- NO CHANGE **************** X FOLLOW(X) ---------------|-------------------- BoolExpr | { ")", "==", "\n" } ---------------|-------------------- BoolTerm | { "+", ")", "==", "\n" } ---------------|-------------------- BoolFact | { variable, literal, "~", "(", "+", ")", "==", "\n" } ---------------|-------------------- BoolEquv | { variable, literal, "~", "(" , $$ } ---------------|-------------------- Program | { eps } ---------------|-------------------- literal | { variable, literal, "~", "(", "+", ")", "==", "\n" } ---------------|-------------------- variable | { variable, literal, "~", "(", "+", ")", "==", "\n" } ---------------|-------------------- "+" | { variable, literal, "~", "(" } ---------------|-------------------- "~" | { variable, literal, "~", "(" } ---------------|-------------------- "(" | { variable, literal, "~", "(" } ---------------|-------------------- ")" | { variable, literal, "~", "(", "+", ")", "==", "\n" } ---------------|-------------------- "==" | { variable, literal, "~", "(" } ---------------|-------------------- "\n" | { variable, literal, "~", "(" , $$ } ---------------|-------------------- $$ | { eps } **** Pass 3 Production 1: BoolExpr -> BoolTerm Adds FOLLOW(BoolExpr) to FOLLOW(BoolTerm) -- No change Production 3: BoolTerm -> BoolFact Adds FOLLOW(BoolTerm) to FOLLOW(BoolFact) -- No change Production 5: BoolFact -> variable Adds FOLLOW(BoolFact) to FOLLOW( variable) -- No change Production 6: BoolFact -> literal Adds FOLLOW(BoolFact) to FOLLOW( literal ) -- No change Production 8: BoolFact -> "(" BoolExpr ")" Adds FOLLOW(BoolFact) to FOLLOW(")") -- No change Production 9: BoolEquv -> BoolExpr "==" BoolExpr "\n" Adds FOLLOW(BoolEquv) to FOLLOW("\n") -- No change Production 10: Program -> $$ Adds FOLLOW(Program) to FOLLOW($$) -- No change No changes -- Follow is DONE! You might want to pause a moment and see if the FIRST and FOLLOW sets really make sense to you! **************************************************************** Now, for PREDICT. The definition says that PREDICT(A --> alpha) = (FIRST(alpha)-{eps}) union FOLLOW(A), if A can generate eps = (FIRST(alpha)-{eps}), otherwise In our language A can never generate eps, so the PREDICT sets are easy Production PREDICT(Production) ---------------------------------------------|--------------------------------- BoolExpr -> BoolTerm | { variable, literal, "~", "(" } ---------------------------------------------|--------------------------------- BoolExpr -> BoolTerm "+" BoolExpr | { variable, literal, "~", "(" } ---------------------------------------------|--------------------------------- BoolTerm -> BoolFact | { variable, literal, "~", "(" } ---------------------------------------------|--------------------------------- BoolTerm -> BoolFact BoolTerm | { variable, literal, "~", "(" } ---------------------------------------------|--------------------------------- BoolFact -> variable | { variable } ---------------------------------------------|--------------------------------- BoolFact -> literal | { literal } ---------------------------------------------|--------------------------------- BoolFact -> "~" BoolFact | { "~" } ---------------------------------------------|--------------------------------- BoolFact -> "(" BoolExpr ")" | { "(" } ---------------------------------------------|--------------------------------- BoolEquv -> BoolExpr "==" BoolExpr "\n" | { variable, literal, "~", "(" } ---------------------------------------------|--------------------------------- Program -> $$ | { $$ } ---------------------------------------------|--------------------------------- Program -> BoolEquv Program | { variable, literal, "~", "(" } ---------------------------------------------|--------------------------------- **************************************************************** Now wait a minute.... PREDICT didn't even use the FOLLOW sets, so this seems like a pretty lame example. OK.... Let's modify our grammar such a tiny bit. Instead of having: BoolTerm -> BoolFact BoolTerm -> BoolFact BoolTerm We'll use the less natural BoolTerm -> BoolFact BoolTail BoolTail -> eps BoolTail -> BoolFact BoolTail Ugh. Now, when we compute the FIRST set, we must do so for BoolTail. Since BoolTail can expand to eps we will ultimately get X FIRST(X) ---------------|-------------------- BoolTail | { variable, literal, "~", "(", eps } ---------------|-------------------- Note that the only difference between FIRST(BoolTail) and FIRST(BoolTerm) is the addition of eps to the set. On to the FOLLOW sets.... Previously, we had the following steps in the calculation involving BoolTerm Pass 0 Production 4: BoolTerm -> BoolFact BoolTerm Adds FIRST(BoolTerm) to FOLLOW(BoolFact) Pass i, i>0 Production 3: BoolTerm -> BoolFact Adds FOLLOW(BoolTerm) to FOLLOW(BoolFact) Now these need to be replaced by different steps Pass 0 Production X: BoolTerm -> BoolFact BoolTail Adds FIRST(BoolTail)-{eps} to FOLLOW(BoolFact) Production Z: BoolTail -> BoolFact BoolTail Adds FIRST(BoolTail)-{eps} to FOLLOW(BoolFact) Note that both of the Adds are the same and that, since FIRST(BoolTail)-{eps} is FIRST(BoolTerm), this is equivalent to Adds FIRST(BoolTerm) to FOLLOW(BoolFact) so there's no change in Pass 0 Pass i, i>0 Production X: BoolTerm -> BoolFact BoolTail Adds FOLLOW(BoolTerm) to FOLLOW(BoolTail) Production Z: BoolTail -> BoolFact BoolTail Adds FOLLOW(BoolTail) to FOLLOW(BoolTail) The add for Production Z, does nothing so there appears to be only one action here: Adds FOLLOW(BoolTail) to FOLLOW(BoolTerm) However, because in these production BoolTerm -> BoolFact BoolTail BoolTail -> BoolFact BoolTail FIRST(BoolTail) *does* contain eps, we must also add Adds FOLLOW(BoolTerm) to Follow(BoolFact) Adds FOLLOW(BoolTail) to Follow(BoolFact) Note that Production Y, BoolTail -> eps, isn't used since there are no symbols on the right-hand side. So the bottom line is that there really no difference between the Pass 0's of the old and new grammar. However, on the Pass i's (i>0), the old grammar had Adds FOLLOW(BoolTerm) to FOLLOW(BoolFact) which for the new grammar is replaced with Adds FOLLOW(BoolTerm) to FOLLOW(BoolTail) Adds FOLLOW(BoolTail) to FOLLOW(BoolTerm) Adds FOLLOW(BoolTail) to FOLLOW(BoolFact) The two actions Adds FOLLOW(BoolTerm) to FOLLOW(BoolTail) Adds FOLLOW(BoolTail) to FOLLOW(BoolTerm) are going to make sure the FOLLOW(BoolTerm) and FOLLOW(BoolTail) will be the same. Since they will be the same, you could replace Adds FOLLOW(BoolTail) to FOLLOW(BoolFact) with Adds FOLLOW(BoolTerm) to FOLLOW(BoolFact) In the end, the only change to FOLLOW is the addition of one new mapping X FOLLOW(X) ---------------|-------------------- BoolTail | { "+", ")", "==", "\n" } ---------------|-------------------- reflecting that FOLLOW(BoolTail) equals FOLLOW(BoolTerm). Now, we must compute PREDICT for our modified productions BoolTerm -> BoolFact BoolTail BoolTail -> eps BoolTail -> BoolFact BoolTail Since the right-hand sides of the first and third productions can't generate eps, they both are equivalent ti FIRST(BoolFact). However, the second product can generate eps (and nothing else), so it ends up being equal to FOLLOW(BoolTail) -- which means we finally are really using FOLLOW. So, here's PREDICT for these productions Production PREDICT(Production) ---------------------------------------------|--------------------------------- BoolTerm -> BoolFact BoolTail | { variable, literal, "~", "(" } ---------------------------------------------|--------------------------------- BoolTail -> eps | { "+", ")", "==", "\n" } ---------------------------------------------|--------------------------------- BoolTail -> BoolFact BoolTail | { variable, literal, "~", "(" } ---------------------------------------------|---------------------------------