Predictive_Parser::Predictive_Parser(CFG *grammar) { //init vars this->grammar = grammar; first = new map<string, set<string>*> (); follow = new map<string, set<string>*> (); subset_first = new map<pair<string,int>,set<string>*>(); parse_table = new Parse_Table_Entry*[grammar->get_nonterminals()->size()]; //size = size of terminals + 1 (input end marker) for (unsigned int i = 0; i < grammar->get_nonterminals()->size(); ++i) parse_table[i] = new Parse_Table_Entry[grammar->get_terminals()->size() + 1]; //calculate first set<string>* nonterminals = grammar->get_nonterminals(); for (set<string>::iterator it = nonterminals->begin(); it != nonterminals->end(); ++it) { calc_first(*it); } //calculate follow calc_follow(); //generate parsing table generate_table(); }
void LL_construct() { try { prepare_nonterminals(); calc_first(); print_first(); calc_follow(); print_follow(); parse_table_generate(); print_parse_table(); } catch (ConstructException &e) { puts(e.message); puts("Syntax analyzer construct failed."); } }
/* Calculates the value of FOLLOW for all nonterminals (and terminals while we're at it, but they're not useful). Sets symbols[].follow. */ static void precalc_follow (void) { int i; for (i = 0; i < n_symbols; i++) set_init (&symbols[i].follow); set_add (&find_symbol (G[0].left)->follow, '$'); for (;;) { int added = 0; for (i = 0; i < n_grammar; i++) { const struct production *prod; struct symbol *A; int j; prod = &G[i]; A = find_symbol (prod->left); for (j = 0; j < prod->n_right - 1; j++) { struct symbol *B; struct set first_Beta; B = find_symbol (prod->right[j]); calc_first (&first_Beta, &prod->right[j + 1], prod->n_right - (j + 1)); added |= set_merge (&B->follow, &first_Beta, 0); if (set_contains (&first_Beta, 0)) added |= set_merge (&B->follow, &A->follow, 1); set_free (&first_Beta); } if (prod->n_right > 0) { struct symbol *B = find_symbol (prod->right[prod->n_right - 1]); added |= set_merge (&B->follow, &A->follow, 1); } } if (!added) break; } if (debug) { printf ("FOLLOW function:\n"); for (i = 0; i < n_symbols; i++) { struct symbol *sym = &symbols[i]; if (!sym->nonterminal) continue; printf ("\tFOLLOW(%c) = ", sym->sym); set_print (&sym->follow); putchar ('\n'); } } }
void Predictive_Parser::calc_first(string head) { //if already calculated then return if (first->find(head) != first->end()) return; vector<vector<string>*> * productions = (*(grammar->get_productions()))[head]; //init set set<string> * production_first = new set<string> (); (*first)[head] = production_first; //terminal added from this production int added; //loop on productions for (unsigned int i = 0; i < productions->size(); ++i) { //init subset of this production (*subset_first)[make_pair(head,i)] = new set<string>(); added = 0; //loop on tokens of specific production for (unsigned int j = 0; j < productions->at(i)->size(); ++j) { string token = productions->at(i)->at(j); //if terminal if (grammar->get_terminals()->find(token) != grammar->get_terminals()->end()) { ++added; production_first->insert(token); //add to subset first of this production subset_first->find(make_pair(head,i))->second->insert(token); break; } else { //NON terminal if (token == EPSILON_TOKEN) continue; //wasn't calculated before if (first->find(token) == first->end()) { calc_first(token); } bool has_epsilon = false; set<string> * token_first = first->find(token)->second; set<string>::iterator it = token_first->begin(); for (; it != token_first->end(); ++it) { if ((*it) == EPSILON_TOKEN) has_epsilon = true; else { ++added; production_first->insert(*it); //add to subset first of this production subset_first->find(make_pair(head,i))->second->insert(*it); } } //if first of token doesn't contain epsilon then //no need to see the rest of this production if (!has_epsilon) break; } } //add epsilon to first of this non terminal if (added == 0){ production_first->insert(EPSILON_TOKEN); //add to subset first of this production subset_first->find(make_pair(head,i))->second->insert(EPSILON_TOKEN); } } }