在編寫語法分析程序時,求解非終結(jié)符的FIRST和FOLLOW集合是非常重要的。JAVA語言通過使用算法可以很方便地自動化地實現(xiàn)這個過程。
public void computeFirst(){ for (NonTerminal nt : nonTerminals) { computeFirst(nt); } } private void computeFirst(NonTerminal nt){ if (nt.firstComputed) { return; } nt.firstComputed = true; for (ProductionRule r : nt.productionRules) { List<Symbol> symbols = r.symbols; if (symbols.isEmpty()) { nt.first.add(Token.EPSILON); continue; } int k = 0; while (k < symbols.size()) { Symbol s = symbols.get(k); if (s instanceof Terminal) { nt.first.add(s); break; } else if (s instanceof NonTerminal) { NonTerminal nt2 = (NonTerminal) s; computeFirst(nt2); nt.first.addAll(nt2.first); if (!nt2.first.contains(Token.EPSILON)) { break; } k++; } } if (k == symbols.size()) { nt.first.add(Token.EPSILON); } } } public void computeFollow(){ startSymbol.follow.add(Token.EOF); for (NonTerminal nt : nonTerminals) { computeFollow(nt); } } private void computeFollow(NonTerminal nt){ if (nt.followComputed) { return; } nt.followComputed = true; for (ProductionRule r : nt.productionsUsingThisNonTerminal) { int i = r.symbols.indexOf(nt); if (i == r.symbols.size() - 1) { if (!nt.equals(r.leftHandSide)) { computeFollow(r.leftHandSide); nt.follow.addAll(r.leftHandSide.follow); } } else { Symbol next = r.symbols.get(i + 1); if (next instanceof Terminal) { nt.follow.add(next); } else { NonTerminal nt2 = (NonTerminal) next; computeFirst(nt2); nt.follow.addAll(nt2.first); if (nt2.first.contains(Token.EPSILON)) { computeFollow(nt2); nt.follow.addAll(nt2.follow); } } } } }
以上代碼演示了如何求解非終結(jié)符的FIRST和FOLLOW集合,具體內(nèi)容可以參考上述代碼。