#include "semcheck.h" /* Program: LL1_enforcer.c */ extern Vertex_Comma_list * terminals; Syntax_vertex *SUGAR_GEN() { static count = 1000000; char * name = new char[15]; char sufix[9]; sprintf(sufix,"%d",count++); sprintf(name,"SUGAR%s",sufix+1); return new Regular_syntax(new DemString(name)); } int Cd_graph::LL1_enforcer(int r) { char *tmp; tmp = tmpfname(); ofstream corrected_grammar(tmp); if (!corrected_grammar) { cerr << toolname << ": unable to open " << tmp << " for output."; exit(1); } if (r==FALSE) { Cd_graph * user_grammar_corrected = this; cout << "\nEnforcing LL1 conditions ... \n" << endl; user_grammar_corrected->get_adjacencies()->FSET_CLEAR_TREATED(); user_grammar_corrected->get_adjacencies()->LL1_enforcer(); user_grammar_corrected->get_adjacencies() ->PRINT_LL1_CORRECTED(corrected_grammar); sem_out << "File notmod/cds/cd-ll1-corrected contains a proposal how to make your\nclass dictionary LL(1)." << endl; } else { corrected_grammar << "// your class dictionary is in LL(1)." << endl; } corrected_grammar.close(); mv_if_change(mv_interactive,tmp,"notmod/cds/cd-ll1-corrected"); return r; } void Adjacency_Nlist::LL1_enforcer() { Adjacency_list_iterator next(*this); Adjacency_ each; while (each = next()) each->LL1_enforcer(this); } void Adjacency::LL1_enforcer(Adjacency_Nlist* adj_Nlist) { ns->LL1_enforcer(this,adj_Nlist); } void Neighbors::LL1_enforcer(Adjacency* rule,Adjacency_Nlist* adj_Nlist) { } void Alternat_ns::LL1_enforcer(Adjacency* rule,Adjacency_Nlist* adj_Nlist) { alternat_ns->LL1_enforcer(rule,adj_Nlist); } void Term_Bar_list::LL1_enforcer(Adjacency* rule,Adjacency_Nlist* adj_Nlist) { static TEpsilon *iepsi = new TEpsilon(); static Ll1SetElement *epsill1 = new Ll1SetElement(NULL, iepsi, NULL, NULL); Ll1SetElement_Comma_list *all_firstset = new Ll1SetElement_Comma_list(); Ll1SetElement_Comma_list *i_firstset = new Ll1SetElement_Comma_list(); Ll1SetElement_Comma_list *l_firstset = new Ll1SetElement_Comma_list(); Ll1SetElement_Comma_list *super_followset = new Ll1SetElement_Comma_list(); Ll1SetElement_Comma_list *intersect; Term_list_iterator next_i(*this); Term_ i; while (i = next_i()) { i_firstset = adj_Nlist->FIRSTSET(i->get_vertex()); Term_list_iterator next_j(*this); Term_ j; while (j=next_j()) if (i->get_vertex()->g_equal(j->get_vertex())) break; while (j=next_j()) { Ll1SetElement_Comma_list *j_firstset = adj_Nlist->FIRSTSET(j->get_vertex()); Ll1SetElement_Comma_list *result = i_firstset->empty_intersection(j_firstset); if (result) { #ifdef DEBUG cout << "LL1: " << endl; i->pp(); cout << endl; j->pp(); cout << endl; #endif /************************************************** * get the set of construction classes * * alternation-reachable from i and j * **************************************************/ Adjacency_List* ia=i->compute_associted(adj_Nlist); Adjacency_List* ja=j->compute_associted(adj_Nlist); Adjacency_list_iterator next_ia(*ia); Adjacency* each_ia,*each_ja; #ifdef DEBUG cout << "LL1 : ia = " << ia->list_length() << "ja = " << ja->list_length() << endl; #endif while (each_ia = next_ia()) { Adjacency_list_iterator next_ja(*ja); while (each_ja = next_ja()) { #ifdef DEBUG cout << "\nLL(1): checking "; each_ia->get_source()->pp(); cout << " and "; each_ja->get_source()->pp(); cout << endl; #endif if (each_ja->get_source()->g_equal(each_ia->get_source())) continue; Ll1SetElement_Comma_list *iafst = adj_Nlist->FIRSTSET(each_ia->get_source()); Ll1SetElement_Comma_list *jafst = adj_Nlist->FIRSTSET(each_ja->get_source()); Ll1SetElement_Comma_list *inter = jafst->empty_intersection(iafst); if (inter) { #ifdef DEBUG cout << "\nAdd sugar to last" << endl; #endif int jlen = jafst->list_length(); int ilen = iafst->list_length(); if (jlen > ilen) each_ja->add_sugar_to_firstset(adj_Nlist); else if (jlen < ilen) each_ia->add_sugar_to_firstset(adj_Nlist); else { each_ia->add_sugar_to_firstset(adj_Nlist); each_ja->add_sugar_to_firstset(adj_Nlist); } } } } } } } Term_list_iterator next_l(*this); Term_ l; while (l = next_l()) { /************************************************** * take the first set of each alternative * **************************************************/ l_firstset = adj_Nlist->FIRSTSET(l->get_vertex()); if (l_firstset->contain(epsill1)) { /*********************************************************** * take the union of the first sets of rest alternatives * ***********************************************************/ Term_list_iterator next_k(*this); Term_ k; while (k=next_k()) if (!k->get_vertex()->g_equal(l->get_vertex())) all_firstset=all_firstset-> join(adj_Nlist->FIRSTSET(k->get_vertex())); /************************************************** * take the follow set of their super class * **************************************************/ super_followset = adj_Nlist->FOLLOWSET(rule->get_source()); intersect = super_followset->empty_intersection(all_firstset); if (intersect) { Adjacency_List* la=l->compute_associted(adj_Nlist); Adjacency_list_iterator next_la(*la); Adjacency* each_la; while (each_la = next_la()) if (adj_Nlist->FIRSTSET(each_la->get_source())-> contain(epsill1)) each_la->add_sugar_to_firstset(adj_Nlist); } } } } void Construct_ns::LL1_enforcer(Adjacency* rule,Adjacency_Nlist *adj_Nlist) { this->rset_construct_ns(this->get_construct_ns() ->LL1_enforcer(rule,adj_Nlist)); } Any_vertex_List * Any_vertex_List::LL1_enforcer(Adjacency* rule,Adjacency_Nlist *adj_Nlist) { static TEpsilon *iepsi = new TEpsilon(); static Ll1SetElement *epsill1 = new Ll1SetElement(NULL, iepsi, NULL, NULL); Any_vertex_List *result = new Any_vertex_List(); Any_vertex_list_iterator next_arg(*this); Any_vertex_ each_arg; while(each_arg = next_arg()) { if (each_arg->is_optional()) { Any_vertex_List * this_tail = each_arg->tail(this); Ll1SetElement_Comma_list *opt_firstset = each_arg->OPT_FIRSTSET_for_enforce(adj_Nlist,rule); Ll1SetElement_Comma_list *opt_followset = each_arg->OPT_FOLLOWSET(this_tail,rule,adj_Nlist); if (opt_firstset->empty_intersection(opt_followset)) { result->append(each_arg); result->append(SUGAR_GEN()); continue; } } result->append(each_arg); } return result; } Ll1SetElement_Comma_list* Any_vertex::OPT_FIRSTSET_for_enforce(Adjacency_Nlist *adj_Nlist,Adjacency *rule) { return NULL; } Ll1SetElement_Comma_list* Optional_term::OPT_FIRSTSET_for_enforce(Adjacency_Nlist *adj_Nlist,Adjacency *rule) { return opt->OPT_FIRSTSET_for_enforce(adj_Nlist,rule); } Ll1SetElement_Comma_list* Opt_labeled_term_Sandwich::OPT_FIRSTSET_for_enforce(Adjacency_Nlist *adj_Nlist,Adjacency *rule) { static TEpsilon *iepsi = new TEpsilon(); static Ll1SetElement *epsill1 = new Ll1SetElement(NULL, iepsi, NULL, NULL); Ll1SetElement_Comma_list* frstst = new Ll1SetElement_Comma_list(); if (first->FIRSTSET()->contain(epsill1)) { Vertex *avertex = inner->get_vertex()->get_vertex(); frstst = adj_Nlist->FIRSTSET(avertex); if (frstst->contain(epsill1)) { if (second->FIRSTSET()->contain(epsill1)) { first->insert((Syntax_vertex*)SUGAR_GEN()); return first->FIRSTSET(); } else { frstst = frstst->join(second->FIRSTSET()); frstst = frstst->remove(epsill1); return frstst; } } return frstst; } else return first->FIRSTSET(); } void Repetit_n::LL1_enforcer(Adjacency* rule,Adjacency_Nlist* adj_Nlist) { sandwiched->LL1_enforcer(rule,adj_Nlist); } void Kernel_Sandwich::LL1_enforcer(Adjacency* rule,Adjacency_Nlist* adj_Nlist) { Ll1SetElement_Comma_list* firstset = inner->get_repeated()->calc_first_for_enforce(adj_Nlist,this,rule); Ll1SetElement_Comma_list* followset = this->calc_follow(rule,adj_Nlist); if (firstset->empty_intersection(followset)) second->insert((Syntax_vertex *)SUGAR_GEN()); } Ll1SetElement_Comma_list* Term_Sandwich::calc_first_for_enforce(Adjacency_Nlist* adj_Nlist,Kernel_Sandwich *sandwich,Adjacency *rule) { TEpsilon *iepsi = new TEpsilon(); Ll1SetElement *epsill1 = new Ll1SetElement(NULL, iepsi, NULL, NULL); Ll1SetElement_Comma_list* first_set; if ((first_set = first->FIRSTSET())->contain(epsill1)) { first_set = adj_Nlist->FIRSTSET(inner->get_vertex()); if (first_set->contain(epsill1)) if (second->FIRSTSET()->contain(epsill1)) first->insert((Syntax_vertex *)SUGAR_GEN()); else { first_set = first_set->join(second->FIRSTSET()); first_set = first_set->remove(epsill1); } } return first_set; } void Cd_graph::PRINT_LL1_CORRECTED(ostream& strm) { adjacencies->PRINT_LL1_CORRECTED(strm); } void Adjacency_Nlist::PRINT_LL1_CORRECTED(ostream& strm) { int length = this->list_length(); int term_length = 0; if (terminals) term_length = terminals->list_length(); Adjacency_list_iterator next_adj(*this); Adjacency_ each_adj; while (each_adj=next_adj()) { each_adj->PRINT_LL1_CORRECTED(strm); length--; if (length==term_length) return; } } void Adjacency::PRINT_LL1_CORRECTED(ostream& strm) { source->pp(strm); if (parameters) { cout << "("; parameters->pp(strm); cout << ")"; } ns->PRINT_LL1_CORRECTED(strlen(this->get_source() ->get_vertex_name()->get_val()),strm); strm << "." << endl; } void Neighbors::PRINT_LL1_CORRECTED(int skips,ostream& strm) { } void Construct_ns::PRINT_LL1_CORRECTED(int skips,ostream& strm) { strm << " = "; this->get_construct_ns()->PRINT_LL1_CORRECTED(skips+4,strm); } void Alternat_ns::PRINT_LL1_CORRECTED(int skips,ostream& strm) { strm << " : "; alternat_ns->PRINT_LL1_CORRECTED(skips+4,strm); if (common) { strm << "\n *common* "; this->get_construct_ns()->PRINT_LL1_CORRECTED(20,strm); } else { strm << " "; this->get_construct_ns()->PRINT_LL1_CORRECTED(20,strm); } } void Repetit_n::PRINT_LL1_CORRECTED(int skips,ostream& strm) { sandwiched->PRINT_LL1_CORRECTED(strm); } void Kernel_Sandwich::PRINT_LL1_CORRECTED(ostream& strm) { strm << " ~ "; first->pp(strm); inner->PRINT_LL1_CORRECTED(strm); strm << " } "; second->pp(strm); } /* Kernel = [ < nonempty > Term ] "{" < repeated > Term_Sandwich "}" . */ void Kernel::PRINT_LL1_CORRECTED(ostream& strm) { if (nonempty) nonempty->pp(strm); strm << " { "; repeated->pp(strm); } void Term_Bar_list::PRINT_LL1_CORRECTED(int len,ostream& strm) { Term_list_iterator next_Term(*this); Term_ each_Term; int length = this->list_length(); int count = 1; int loop=len; while (each_Term=next_Term()) { loop=len; each_Term->PRINT_LL1_CORRECTED(len,strm); if ((length>1)&&(countget_vertex()->pp(strm); if (this->get_actual_parameters()) { strm << "("; this->get_actual_parameters()->pp(strm); strm << ")"; } } void Any_vertex_List::PRINT_LL1_CORRECTED(int skips,ostream& strm) { Any_vertex_list_iterator next_Any_vertex(*this); Any_vertex_ each_Any_vertex; int length = this->list_length(); int loop,count; count=1; while (each_Any_vertex=next_Any_vertex()) { loop=skips; if ((each_Any_vertex->is_some_term())&&(count>1) && (countpp(strm); count++; } } int Any_vertex::is_some_term() { return 0; } int Optional_term::is_some_term() { return 1; } int Opt_labeled_term_Sandwich::is_some_term() { return 1; } void Adjacency::add_sugar_to_firstset(Adjacency_Nlist *adjs) { static DemNumber * mark = new DemNumber(1); if (this->get_treated()==NULL) { ns->add_sugar_to_firstset(adjs); this->set_treated(mark); } } void Neighbors::add_sugar_to_firstset(Adjacency_Nlist *adjs) { } void Neighbors_wc::add_sugar_to_firstset(Adjacency_Nlist *adjs) { } void Repetit_n::add_sugar_to_firstset(Adjacency_Nlist *adjs) { sandwiched->add_sugar_to_firstset(adjs); } void Kernel_Sandwich::add_sugar_to_firstset(Adjacency_Nlist *adjs) { first->insert(SUGAR_GEN()); } void Construct_ns::add_sugar_to_firstset(Adjacency_Nlist *adjs) { this->get_construct_ns()->insert(SUGAR_GEN()); }