MMap MakeLLTables(Grammar& g) { const GrammarSymbol* pMain = g.FindSymbol(L"Main"); if (pMain == nullptr) { throw std::exception("Main syntax must be defined!"); } if (g.GetStartSymbol() == nullptr) { throw std::exception("Main syntax must be defined! (start)"); } const FirstSets first = BuildFirstSets3(g); const FollowSets follow = BuildFolowSets3(g, first); PrintFirst(std::wcout, first); std::wcout << std::endl; PrintFollow(std::wcout, follow); MMap M = BuildMTable(first, follow, g); std::wcout << L"M table" << std::endl; Print(std::wcout, M, g); return M; }
//controi todos os follow(A) da gramatica g FollowSets BuildFolowSets3(Grammar& g, const FirstSets& first) { FollowSets follow; //Follow(start-symbol):= {$}; follow.AddToSet(g.GetStartSymbol(), g.endmarker()); //for all nonterminals A != start-symbol do Follow(A):={}; for (int i = 0 ; i < g.GetNumOfGrammarSymbols(); i++) { const GrammarSymbol* pgs = g.GetSymbol(i); if (!pgs->IsTerminal() && pgs != g.GetStartSymbol()) { follow.CreateGet(pgs); } } bool changed = true; while (changed) { changed = false; // Para cada producao A -> X1...Xn for (int k = 0 ; k < g.GetNumOfProductions(); k++) { const Production& A = g.GetProduction(k); Print(std::wcout, A); std::wcout << std::endl; for (int i = 0 ; i < A.GetNumOfRightSymbols(); i++) { //If there is a production A -> alfa B beta , then everything in FIRST(beta) except epsilon //is in FOLLOW(B). const GrammarSymbol* Xi = A.GetRightSymbol(i); //Para cada nao terminal Xi da producao if (!Xi->IsTerminal()) { //add First(Xi+1..Xn) - {epsilon} to Follow(Xi) std::set<const GrammarSymbol*> firstXi1_Xn; bool epsilon_is_in_firstXi1_Xn = false; //se Xi não é o ultimo if (i < (A.GetNumOfRightSymbols() - 1)) { firstXi1_Xn = GetFirstSet(first, g, A, i + 1); for (auto it = firstXi1_Xn.begin(); it != firstXi1_Xn.end(); ++it) { if (*it != g.epsilon()) { if (follow.AddToSet(Xi, *it)) { changed = true; } } else { epsilon_is_in_firstXi1_Xn = true; } } } // If there is a production A -> alfaB, or a production A -> alfa B beta , where // FIRST(beta) contains epsilon, then everything in FOLLOW (A) is in FOLLOW (B) . if (i == (A.GetNumOfRightSymbols() - 1) || epsilon_is_in_firstXi1_Xn) { //add Follow(A) to Follow(Xi) auto FollowA = follow.Get(A.GetLeftSymbol()); for (auto it = FollowA.begin(); it != FollowA.end(); ++it) { if (follow.AddToSet(Xi, *it)) { changed = true; } } } }//para este Xi } //para cada Xi } //para cada producao } //enquando mudar... return follow; }