// // MODULE: cdgraph.pp // // DESCRIPTION: this module contains the propagation patterns which // traverse cd-cd. // // PPs: // InitLearn // Learn // // LookUpAdjacency // NewAdjacency // UpdateAdjacency // AppendNewAdjacency // // NewAlternation // NewConstruction // NewRepetition // // CheckAlternation // LookUpAlternative // AddAlternative // InsertAlternative // // CheckOldParts // AddNewParts // LabeledVertex // LabelAppear // CheckDupLabel // LookUpVertex // ResetVertex // SetNthEnt // // OptionalTerm // Alternation // GetNumAdjacencies // // ReplaceName // RemoveDuplicates // // History: // Cristina Lopes, Dec. 92 - created from an old version // of cd-learn. // // // InitLearn (*in* Cd_graph *cd_in) // // WHAT : Initialize the class dictionary graph with the input cdg. // INDEP: 1 // *operation* void InitLearn (Cd_graph *cd_in) *wrapper* Cd_graph *prefix* (@ this->set_adjacencies(cd_in->get_adjacencies()); @) // // Learn (*in* Object *obj) // // WHAT : learn with an object description. // INDEP: 1 // *operation* void Learn (Object *obj) *wrapper* Cd_graph *prefix* (@ //Learn from Object and modify the current Cd_graph. Adjacency *adj = 0; Ident* name = 0; obj->GetIdentifier(name); this->LookUpAdjacency (name->get_val(), adj); if (adj) { // The class already exist in class dictionary adj->UpdateAdjacency (this, obj); } else { // The class doesn't exist in class dictionary this->NewAdjacency (obj, name->get_val()); } @) // // LookUpAdjacency (*in* char *classname, *out* Adjacency *&adj) // // WHAT : search a previous learned adjacency with name classname. // INDEP: 1 // *operation* void LookUpAdjacency (char *classname, Adjacency *&adj) *traverse* *from* Cd_graph *to* Adjacency_Nlist *wrapper* Adjacency_Nlist *prefix* (@ Adjacency_list_iterator next_adjacency(*this); Ident *name = 0; while ((adj = next_adjacency())) { adj->GetIdentifier (name); if (!strcmp(name->get_val(), classname)) break; } @) // // NewAdjacency (*in* Object *obj, *in* char *classname) // // WHAT : learn a new adjacency into the cdg. // INDEP: 1 (considering the interface extension) // *operation* void NewAdjacency (Object *obj, char *classname) *wrapper* Cd_graph *prefix* (@ adjacencies->NewAdjacency (obj, classname, this); @) *operation* void NewAdjacency (Object *obj, char *classname, Cd_graph *cd_out) *wrapper* Adjacency_Nlist *prefix* (@ // The new class has not been learned, create new class in Cd. // Don't add constructions for primitive classes if (!(strcmp(classname, "Number")) || !(strcmp(classname, "Ident")) || !(strcmp(classname, "Real")) || !(strcmp(classname, "String"))) return; obj->AbstractAdjacency (classname, cd_out); @) // // UpdateAdjacency (*in* Cd_graph *cd_out, *in* Object *obj) // // WHAT : update a previously learn adjacency with the new // object description. // INDEP: 1 // *operation* void UpdateAdjacency (Cd_graph *cd_out, Object *obj) *traverse* *from* Adjacency *to* {Any_vertex_List, Repetit_n} *wrapper* Adjacency *prefix* (@ int is = 0; obj->ToBeExtended (is); if (is) { @) *wrapper* Adjacency *suffix* (@ obj->LearnParts (cd_out); } @) *wrapper* Any_vertex_List *prefix* (@ this->CheckOldParts (cd_out, obj); this->AddNewParts (obj); @) // Repetition objects cannot update Contruction classes with the same name. *wrapper* Construct_ns *prefix* (@ Ident *name; int is = 0; obj->Repetition (is); if (is) { obj->GetIdentifier (name); cerr<<"Error: class \"" << name->get_val() <<"\" is being redefined as Repetition class," <<"\n but previously was defined as construction class.\n"; exit(1); } else this->Neighbors_wc::UpdateAdjacency (cd_out, obj); @) *wrapper* Repetit_n *prefix* (@ /* Modify Repetit_n adjacency to clear nonempty part; and/or Alternate adjacency to add one or more alternates if necessary */ Adjacency* iAdj; int is; Ident *id; char* name; Object_Comma_list* iRep; Term_Sandwich *sand2; obj->Repetition (is); if (!is) { obj->GetIdentifier (id); cerr <<"Error: class \""<< id->get_val() <<"\" is being redefined as non repetition class," <<"\n which was previously defined as Repetition class.\n"; exit(1); } obj->GetRepetitionParts (iRep); if (!iRep) this->SetNonempty(); this->GetRepeated (sand2); sand2->GetIdentifier (id); //name = sandwiched->get_inner()->get_repeated()->get_inner()->get_VertexVal(); cd_out->LookUpAdjacency(id->get_val(), iAdj); if (!iAdj) { cerr << "Error: can not find the existed class" << id->get_val() << ".\n"; exit (1); } else if (iRep) iRep->AddAlternative (iAdj); @) // // AppendNewAdjacency (*in* Adjacency *adj) // // WHAT : append the learned adjacency to the class dictionary graph. // INDEP: 1 // *operation* void AppendNewAdjacency (Adjacency *adj) *traverse* *from* Cd_graph *to* Adjacency_Nlist *wrapper* Adjacency_Nlist *prefix* (@ this->append (adj); @) // // NewAlternation (*in* char *newname, *in* char *name_in_obj, // *in* char *name_in_term, *in* Opt_label_term *vert, // *out* Adjacency *&adj) // // WHAT : build a new alternation vertex and return it. // INDEP: 1 // *operation* void NewAlternation (char *newname, char *name_in_obj, char *name_in_term, Opt_labeled_term *vert, Adjacency *&adj) *traverse* *from* Cd_graph *to* Adjacency_Nlist *wrapper* Adjacency_Nlist *prefix* (@ // create a new alternation adjacency with newname vertex name, // name_in_obj and name_in_term as two alternatives. Adjacency* iAdj; Term* a1 = new Normal(); a1->set_vertex(new Vertex (new Ident (name_in_obj))); Term* a2 = new Normal(); a2->set_vertex(new Vertex(new Ident(name_in_term))); Term_Bar_list* alt_list = new Term_Bar_list(); alt_list->append(a1); alt_list->append(a2); Alternat_ns* newalternat = new Alternat_ns(alt_list); ((Neighbors_wc*)newalternat)->set_construct_ns(new Any_vertex_List()); Ident* classid = new Ident (newname); Vertex* cn = new Vertex (classid); iAdj = new Adjacency (cn, newalternat); this->append (iAdj); vert->ResetVertex (classid); //((Labeled*)vert)->get_vertex()->ResetVertex(classid); adj = iAdj; @) // // NewConstruction (*in* char *name, *in* Any_vertex_List *vl) // // WHAT : build a new construction vertex. // INDEP: 1 // *operation* void NewConstruction (char *name, Any_vertex_List *vl) *traverse* *from* Cd_graph *to* Adjacency_Nlist *wrapper* Adjacency_Nlist *prefix* (@ Neighbors_wc* neighbor = new Construct_ns(); Adjacency* new_adj = new Adjacency(); neighbor->set_construct_ns((Any_vertex_List *)vl); new_adj->set_source((Vertex *)new Vertex(new Ident(name))); new_adj->set_ns(neighbor); this->append(new_adj); @) // // NewRepetition (*in* char *name, *in* Term *t, // *in* Object_comma_list *parts) // // WHAT : build a new repetition vertex. // INDEP: 1 // *operation* void NewRepetition (char *name, Term *t, Object_Comma_list *parts) *traverse* *from* Cd_graph *to* Adjacency_Nlist *wrapper* Adjacency_Nlist *prefix* (@ Term_Sandwich* iSand = new Term_Sandwich(new Syntax_vertex_List(), t, new Syntax_vertex_List()); Kernel* iKernel = new Kernel(); iKernel->set_repeated(iSand); if (parts) iKernel->set_nonempty(t); Kernel_Sandwich* iKelSand = new Kernel_Sandwich( new Syntax_vertex_List(), iKernel, new Syntax_vertex_List()); Repetit_n* iRepetit = new Repetit_n(iKelSand); Vertex* iVertex = new Vertex(new Ident (name)); this->append(new Adjacency(iVertex, iRepetit)); @) // // CheckAlternation (*in* Cd_graph *cd_out, *in* Opt_labeled_term *vert, // *in* Labeled_part *part, *in* Object *obj) // // WHAT : test if a new alternative is needed, and build it if so. // INDEP: 1 // *operation* void CheckAlternation (Cd_graph *cd_out, Opt_labeled_term *vert, Labeled_part *part, Object *obj) *wrapper* Any_vertex_List *prefix* (@ Adjacency* iAdj = 0; Ident *name; char *name_obj, *name_term; int is = 0; part->GetIdentifier (name); name_obj = name->get_val(); vert->GetIdentifier (name); name_term = name->get_val(); // If the same label refer to a different class, we need an alternation if (strcmp (name_term, name_obj)) { cd_out->LookUpAdjacency(name_term, iAdj); if (iAdj) iAdj->Alternation (is); if (!iAdj || !is) { // The alternation name will be "_": part->GetLabelIdent(name); char* labelname = name->get_val(); obj->GetIdentifier (name); char* objname = name->get_val(); char* newname = new (char[strlen(objname)+strlen(labelname)+2]); sprintf(newname, "%s_%s",objname, labelname); // if we haven't created alternation , do it now if (strcmp(newname, name_term)) cd_out->NewAlternation (newname, name_obj, name_term, (Opt_labeled_term*)vert, iAdj); else { //Otherwise, just add another alternative if necessary cd_out->LookUpAdjacency(newname, iAdj); iAdj->AddAlternative(name_obj); } } else { iAdj->AddAlternative(name_obj); } } @) // // AddAlternative (*in* char *name_obj) // // WHAT : add a new alternative to the alternation adjacency. // INDEP: 1 // *operation* void AddAlternative (char *name_obj) *traverse* *from* Adjacency *to* Alternat_ns *traverse* Alternat_ns *prefix* (@ Term *t = 0; this->LookUpAlternative (name_obj, t); if (!(t)) { Ident* classid = new Ident(name_obj); Term* alt = new Normal(); alt->set_vertex(new Vertex(classid)); this->InsertAlternative (alt); } @) // // LookUpAlternative (*in* char *name, *out* Term *&t) // // WHAT : search in the list of alternative terms if there is already // one with the given name, and return it if so. // INDEP: 1 // *operation* void LookUpAlternative (char *name, Term *&t) *traverse* *from* Alternat_ns *to* Term_Bar_list *wrapper* Term_Bar_list *prefix* (@ Term_list_iterator next_alt(*this); Ident *id; while (t = next_alt()) { t->GetIdentifier (id); if (!strcmp(id->get_val(), name)) break; } @) // // InsertAlternative (*in* Term *alt) // // WHAT : insert a new alternative in the alternative term list. // INDEP: 1 // *operation* void InsertAlternative (Term *alt) *traverse* *from* Alternat_ns *to* Term_Bar_list *wrapper* Term_Bar_list *prefix* (@ this->append (alt); @) // // CheckOldParts (*in* Cd_graph *cd_out, *in* Object *obj) // // WHAT : search in Any_vertex_List to see if there are part objects // that match with the part objects of "obj". // INDEP: 1 // *operation* void CheckOldParts (Cd_graph *cd_out, Object *obj) *wrapper* Any_vertex_List *prefix* (@ Any_vertex_list_iterator next_vertex(*this); Any_vertex *vert; Labeled_part *ladj = 0; int item_number = 0, is = 0; while (vert = next_vertex()){ item_number++; vert->OptionalTerm (is); if (is) { vert->LabelAppear(obj, ladj); if (ladj) this->CheckAlternation(cd_out, (Opt_labeled_term*) ( ((Optional_term*)vert)->get_opt()->get_inner()), ladj, obj); } else { vert->LabeledVertex (is); if (is) { /* vert is Labeled type */ vert->LabelAppear(obj, ladj); if (!(ladj)) { // Same label does not appear in new obj create optional part Opt_labeled_term_Sandwich* OptSand = new Opt_labeled_term_Sandwich( new Syntax_vertex_List(), (Opt_labeled_term*)vert,new Syntax_vertex_List()); Optional_term* opterm = new Optional_term (OptSand); this->SetNthEnt(item_number, (Any_vertex*)opterm); } else this->CheckAlternation(cd_out, (Opt_labeled_term*)vert, ladj, obj); } else continue; } } @) // // AddNewParts (*in* Object *obj) // // WHAT : add new part objects to the learned adjacency. // INDEP: 1 // *operation* void AddNewParts (Object *obj) *wrapper* Any_vertex_List *prefix* (@ //Check all parts in the new object if they have been represented // in the current class dictionary. int n = 0; Ident *adjname, *name, *classname; Any_vertex *v; obj->GetNumParts (n); if (n > 0) { Labeled_part_list_iterator next_adj(* (Labeled_part_list_*)(obj->GetLabeledPartBody())); Labeled_part* iAdj; while (iAdj = next_adj()) { iAdj->GetLabelIdent (adjname); iAdj->GetIdentifier (name); classname = new Ident (name->get_val()); this->LookUpVertex(adjname->get_val(), v); if (!(v)) { /* return any_vertex if any, otherwise is null When is null, we need add an optional vertex */ Opt_labeled_term* iLabeled = new Labeled(adjname); Term* iNormal = new Normal(); iNormal->set_vertex (new Vertex(classname)); iLabeled->set_vertex (iNormal); Opt_labeled_term_Sandwich* iSand = new Opt_labeled_term_Sandwich(new Syntax_vertex_List(), iLabeled,new Syntax_vertex_List()); Optional_term* iOpt_term = new Optional_term (iSand); this->append (iOpt_term); } } } @) // // LabeledVertex (*out* int &is) // // WHAT : test if it's a LabeledVertex object. // INDEP: 1 // *operation* void LabeledVertex (int &is) *traverse* *from* Any_vertex *to* Labeled *bypassing* -> *, *, * *wrapper* Any_vertex *prefix* (@ is = 0; @) *wrapper* Labeled *prefix* (@ is = 1; @) // // LabelAppear (*in* Object *obj, *out* Labeled_part *&part) // // WHAT : check if the labeled vertex in CD also appears in the // new object. // INDEP: 1 *operation* void LabelAppear (Object *obj, Labeled_part *&part) *traverse* *from* Any_vertex *to* Labeled *wrapper* Any_vertex *prefix* (@ part = 0; @) *wrapper* Labeled *prefix* (@ //Check if the labeled vertex in CD also appear in the new object obj->LookUpVertex (label_name->get_val(), part); @) // // CheckDupLabel (*in* Ident *name, *out* int &p) // // WHAT : check if there is already a label with this name. // INDEP: 1 // *operation* void CheckDupLabel (Ident *name, int &p) *traverse* *from* Any_vertex_List *to* Labeled *wrapper* Any_vertex_List *prefix* (@ p = 0; @) *wrapper* Labeled *prefix* (@ if (this->label_name->g_equal ((Universal *)name)) p = 1; @) // // LookUpVertex (*in* char *aname, *out* Any_vertex *&v) // // WHAT : search a vertex with the given name in the existing // vertices. // INDEP: 1 // *operation* void LookUpVertex (char *aname, Any_vertex *&v) *wrapper* Any_vertex_List *prefix* (@ Any_vertex_list_iterator next_vertex(*this); Ident *name; while (v = next_vertex()) { v->GetLabelIdent (name); if (!strcmp(aname, name->get_val())) break; } @) // // ResetVertex (*in* Ident *classid) // // WHAT : set a new vertex id to the optional term. // INDEP: 1 // *operation* void ResetVertex (Ident *classid) *traverse* *from* Opt_labeled_term *to* Vertex *wrapper* Vertex *prefix* (@ this->rset_vertex_name (classid); @) // // SetNthEnt (*in* int number, *in* Any_vertex *vert) // // WHAT : Replace the nth element in the list by vert. // INDEP: 1 // *operation* void SetNthEnt (int number, Any_vertex *vert) *wrapper* Any_vertex_List *prefix* (@ //Replace the nth element in the list by vert. Any_vertex* iVertex; int count = 1; if (number > this->list_length()) { cerr<<"can't set element because the length of the list is \n"; cout<<"less than the input number\n"; exit(1); } Any_vertex_List* templist = new Any_vertex_List(); while (count < number ) { iVertex = this->get(); templist->insert(iVertex); count++; } this->get(); this->insert(vert); while (--count > 0) { iVertex = templist->get(); this->insert(iVertex); } @) // // SetNonempty() // // WHAT : reset the nonempty part of a kernel part of a Repetit_n // INDEP: 1 // *operation* void SetNonempty() *traverse* *from* Adjacency *to-stop* Kernel *wrapper* Kernel *prefix* (@ this->set_nonempty(0); @) // // GetRepeated (*out* Term_Sandwich *&s) // // WHAT : get the repeated term_sandwich of a Repetit_n object. // INDEP: 1 // *operation* void GetRepeated (Term_Sandwich *&s) *traverse* *from* Repetit_n *to-stop* Kernel *wrapper* Kernel *prefix* (@ s = this->get_repeated(); @) // // OptionalTerm (*out* int &is) // // WHAT : check if it's a OptionalTerm object. // INDEP: 1 // *operation* void OptionalTerm (int &is) *traverse* *from* Any_vertex *to* Optional_term *wrapper* Any_vertex *prefix* (@ is = 0; @) *wrapper* Optional_term *prefix* (@ is = 1; @) // // Alternation (*out* int &is) // // WHAT : check if it's an Alternat_ns object. // INDEP: 1 // *operation* void Alternation (int& is) *traverse* *from* Adjacency *to* Alternat_ns *wrapper* Adjacency *prefix* (@ is = 0; @) *wrapper* Alternat_ns *prefix* (@ is = 1; @) // // GetNumAdjacencies (*out* int &n) // // WHAT : return the number of learned adjacencies. // INDEP: 1 // *operation* void GetNumAdjacencies (int &n) *traverse* *from* Cd_graph *to* Adjacency_Nlist *wrapper* Adjacency_Nlist *prefix* (@ n = this->list_length(); @) // // ReplaceName (*in* Conversion *rule) // // WHAT : replace an old name with a new name. // INDEP: 1 // *operation* void ReplaceName(Conversion* rule) *traverse* *from* Cd_graph *to* Vertex *bypassing* -> *, terminal_sets, * *wrapper* Vertex *prefix* (@ Ident* oldname, *newname; rule->GetOldIdent (oldname); rule->GetNewIdent (newname); if (vertex_name->g_equal((Universal*)oldname)) this->rset_vertex_name(newname); @) // // RemoveDuplicates (*out* Adjacency_Nlist *&n_list) // // WHAT : return an Adjacency_Nlist which is equal to this one, // but without duplicated elements. // INDEP: 1 // *operation* void RemoveDuplicates (Adjacency_Nlist *&n_list) *wrapper* Adjacency_Nlist *prefix* (@ Adjacency_list_iterator my_next_adj(*this), next2(*n_list); Adjacency *myadj, *adj; int dup; while (myadj = my_next_adj()) { dup = 0; while (adj = next2()) if (myadj->g_equal ((Universal *)adj)) { dup = 1; break; } if (!dup) n_list->append(myadj); } @)