//========================================================================================================== //========================================================================================================== void Grammar::calc_follow_table() { calc_first_table(); //------------------------------------------------------------------------------------------------------ // To handle end-of-input correctly, add the EOI (= $) symbol to the follow of the start symbol. // This is instead of add another symbol to be the new start and a production: START' -> START $ // That will have the same effect but causes some overhead of needing to deal with the new symbol and // production. //------------------------------------------------------------------------------------------------------ follow_table[START].insert(EOI); //------------------------------------------------------------------------------------------------------ // Go over the productions: // For a sequence ...NA, add First(A) to Follow(N). // For a sequence ...N, add a constraint: Follow(M) ⊆ Follow(N), where M is the LHS of the production. //------------------------------------------------------------------------------------------------------ vector<pair<Symbol, Symbol>> follow_constraints; // Pair (M,N) means Follow(M) ⊆ Follow(N) for(auto& p: productions) { Symbol M = p[0]; for(int j = 1; j < p.size(); ++j) { if(is_terminal(p[j])) continue; Symbol N = p[j]; if(j < p.size() - 1) { follow_table[N].insert(get_first_set(p[j+1])); } else if(M != N) { follow_constraints.push_back({M,N}); } } } //------------------------------------------------------------------------------------------------------ // Go over the constraints and apply them, until no more changes are made //------------------------------------------------------------------------------------------------------ bool added = true; while(added) { added = false; for(auto& c: follow_constraints) { Symbol M = c.first, N = c.second; int old_size = follow_table[N].size(); follow_table[N].insert(follow_table[M]); added = (added or follow_table[N].size() > old_size); } } } // calc_follow_table()
static PTBL_ParseTable generateParseTable() { int i; ATermList vertex; PTBL_State state; PTBL_States statelist = PTBL_makeStatesEmpty(); PTBL_Gotos gotos; PTBL_Choices actions; calc_first_table(); calc_follow_table(); createDFA(); for (i = PGEN_getNumberOfStates()-1; i >= 0; i--) { vertex = PGEN_getStateOfStateNumber(i); gotos = (PTBL_Gotos)PGEN_getGotosOfState(vertex); if (!gotos) { gotos = PTBL_makeGotosEmpty(); } else if (PGEN_getStatsFlag) { PGEN_STATS_increaseGotos(PTBL_getGotosLength(gotos)); } actions = PGEN_getActionsOfState(vertex); if (!actions) { actions = PTBL_makeChoicesEmpty(); } else if (PGEN_getStatsFlag) { PGEN_STATS_increaseActions(PTBL_getChoicesLength(actions)); } state = PTBL_makeStateDefault(i, gotos, actions); statelist = PTBL_makeStatesMany(state, statelist); } if (PGEN_getStatsFlag) { PGEN_STATS_print(); } return PTBL_makeParseTableParseTable(PTBL_makeVersionDefault(), PGEN_getInitialStateNumber(), PGEN_getLabelSection(), statelist, PGEN_getPrioSection()); }