/************************************************************************** * PROJECT: DEMETER * MODULE: * FILE: gen_intermediate.c *-------------------------------------------------------------------------- * COPYRIGHT (c) 1990 * Prof. Karl J. Lieberherr *-------------------------------------------------------------------------- * AUTHOR: Walter Hursch * * DATE: November 7, 1990 * REVISED: November 5, 1992 * Include components and external libraries * November 15, 1992 * Fix bug for *inherit* * *-------------------------------------------------------------------------- * DESCRIPTION: * Gen_intermediate.c takes as input a normal class dictionary and * returns the corresponding class dictionary in intermediate notation. * In the MASTER cd this task is called: I-P1 ==> O-P1. * The transformation is done destructively, i.e. if you want to keep * the original cd you have to make a copy of it before invoking gen_ * intermediate. * The main parts in the transformation are the following: * * Normal ==> Intermediate * ------------------------------------------------------------------ * 1. Construct_ns ==> Instantiable * 2. Alternat_ns ==> Abstract * 3. Repetit_n ==> Repetit * * The rest is adjusting inheritance and deleting unused parts. * **************************************************************************/ /************************************************************************** Data dictionary ;;; produced by extract-cd 'O-P1' ; P1 : I-P1: cd ; : O-P1: intermediate notation ;;; O-P1=I-P2 Demeter_in = Input. Input : Cd_graph *common*. Cd_graph = < adjacencies > Nlist(Adjacency) ["*terminal_sets*" Comma_list(Vertex) "."] . Adjacency = < source > Vertex < ns > Neighbors ["*inherits_from*" Comma_list(Term)] "." . Neighbors_wc : Construct_ns | Alternat_ns *common* < construct_ns > List(Any_vertex). Neighbors : Neighbors_wc | ;; Regular only Repetit_n | ;; Regular only Intermediate_ns ;; Intermediate only *common*. Intermediate_ns : Repetit | Non_repetit *common* . Non_repetit : Instantiable | Abstract *common* List(Int_part). Instantiable = "instantiable=". Repetit = "repetition=" Term [ Non_empty]. Non_empty = "*non_empty*". Abstract = "abstract=". Int_part : Required_int_part | Optional_int_part *common* Labeled. Required_int_part = "*required*". Optional_int_part = "*optional*". Construct_ns = "=". Alternat_ns = ":" < alternat_ns > Bar_list(Term) [ Common]. Common = "*common*". Repetit_n = "~" Sandwich(Kernel). Kernel = [ Term ] "{" Sandwich(Term) "}". Any_vertex : Opt_labeled_term | Optional_term | Syntax_vertex | Inherit_term *common*. Vertex = < vertex_name > DemIdent . Syntax_vertex : Regular_syntax | Print_command *common*. Regular_syntax = < string > String . Print_command : Print_indent | Print_unindent | Print_skip | Print_space *common*. Print_indent = "+" . Print_unindent = "-" . Print_skip = "*l" . Print_space = "*s" . Opt_labeled_term : Labeled | Regular *common* Term. Regular = . Labeled = "<" < label_name > DemIdent ">" . Inherit_term = "*inherit*" Comma_list(Term). ;; ;; 11/5/92 Update term to contain component and external terms ;; Term : Normal | CppTerm *common* Vertex TermRef ["(" Comma_list(Term) ")" ]. CppTerm = "$" . Normal = . TermRef : LocalRef | ModuleRef. ModuleRef : CompRef | LibRef *common* DemIdent. LocalRef = . CompRef = "@". LibRef = "@@". Optional_term = "[" Sandwich(Opt_labeled_term) "]". List(S) ~ {S}. Nlist(S) ~ S {S}. Bar_list(S) ~ S {"|" S}. Comma_list(S) ~ S {"," S}. Sandwich(S) = List(Syntax_vertex) S List(Syntax_vertex). **************************************************************************/ #include "generate.h" #include #include /*------------------------------------------------------------------------- * Method: void gen_intermediate() * * Transforms a Neighbors_wc or a Repetit_n into the corresponding Inter- * mediate_ns. *-----------------------------------------------------------------------*/ /* * demeter_in = < input > input . */ void Demeter_in::gen_intermediate() { DBG( cout << "Generating intermediate notation!" << endl; ) input -> gen_intermediate(); } /* * input : cd_graph *common* . */ void Input::gen_intermediate() { } /* * cd_graph = < adjacencies > adjacency-Nlist * [ "*terminal_sets*" < terminal_sets > vertex-comma_List "." ] . */ void Cd_graph::gen_intermediate() { adjacencies -> gen_intermediate(); adjacencies -> write_vertex_base(); } /* * adjacency-Nlist ~ adjacency { adjacency } . */ void Adjacency_Nlist::gen_intermediate() { Adjacency_list_iterator next_Adj(*this); Adjacency_ each_Adj; while ( each_Adj = next_Adj() ) each_Adj -> gen_intermediate( this ); } void Adjacency_Nlist::write_vertex_base() // The vertex base consists of all classes that don't inherit from anyone, // or that only inherit from external library classes (such as class@@MOTIF) // For those classes: inherit from Universal. { Adjacency_list_iterator next_Adj(*this); Adjacency_ each_Adj; while ( each_Adj = next_Adj() ) { if ( !each_Adj -> get_inherits_from() || each_Adj -> get_inherits_from() -> contains_NonDemTerms_only() ) each_Adj -> append_inherit_term( "Construction" ); } } int Term_Comma_list::contains_NonDemTerms_only() // Check whether all terms in the list are NOT Demeter Terms. // if yes, return true, else return false. { Term_list_iterator next_Term( *this ); Term_ each_Term; while ( each_Term = next_Term() ) // if one Demeter Term is encountered, return false if ( ! each_Term->is_NonDemTerm() ) return ( 0 ); // still here, ergo all are Non-Demeter terms return ( 1 ); } /*------------------------------------------------------------------------- * Method: void gen_intermediate( Adjacency_Nlist* ) * * Assigns the newly generated Intermediate_ns to ns. *-----------------------------------------------------------------------*/ /* * adjacency = < source > vertex < ns > neighbors * [ "*inherits_from*" < inherits_from > term-comma_List ] "." . */ void Adjacency::gen_intermediate( Adjacency_Nlist *adjacencies) { set_ns( ns -> get_intermediate_ns( adjacencies, this ) ); } /*------------------------------------------------------------------------- * Method: Intermediate_ns* get_intermediate_ns * (Adjacency_Nlist*, Adjacency* ) * * Generates the Intermediate_ns corresponding to Neighbors. *-----------------------------------------------------------------------*/ /* * neighbors : neighbors_wc | repetit_n | intermediate_ns *common* . */ Intermediate_ns* Neighbors::get_intermediate_ns ( Adjacency_Nlist*, Adjacency* ) { return NULL; } /* * neighbors_wc : construct_ns | alternat_ns * *common* < construct_ns > any_vertex-List . */ Intermediate_ns* Neighbors_wc::get_intermediate_ns ( Adjacency_Nlist*, Adjacency* ) { return NULL; } /* * construct_ns = "=" . */ Intermediate_ns* Construct_ns::get_intermediate_ns ( Adjacency_Nlist*, Adjacency* adj ) { Instantiable* n_instantiable = new Instantiable(); Int_part_List* n_int_part_list = new Int_part_List(); n_instantiable -> set_intermed_ns( n_int_part_list ); Neighbors_wc::form_intermediate_ns( adj, n_instantiable ); return ( n_instantiable ); } /* * alternat_ns = ":" < alternat_ns > term-bar_List [ < common > common ] . */ Intermediate_ns *Alternat_ns::get_intermediate_ns ( Adjacency_Nlist *adjacencies, Adjacency *adj ) { Abstract* n_abstract = new Abstract(); Int_part_List* n_int_part_list = new Int_part_List(); n_abstract -> set_intermed_ns( n_int_part_list ); Normal* n_normal = new Normal(); n_normal -> set_vertex( adj -> get_source() ); TermRef* n_termRef = new LocalRef(); n_normal -> set_moduleRef( n_termRef ); alternat_ns -> write_inheritance( adjacencies, n_normal ); Neighbors_wc::form_intermediate_ns( adj, n_abstract ); return ( n_abstract ); } /* * repetit_n = "~" < sandwiched > kernel-Sandwich . */ Intermediate_ns *Repetit_n::get_intermediate_ns ( Adjacency_Nlist*, Adjacency* adj ) { Repetit* n_repetit = new Repetit(); adj -> append_inherit_term( "Repetition" ); if ( sandwiched -> repetition_non_empty() ) { Non_empty* n_non_empty = new Non_empty(); n_repetit -> set_non_empty( n_non_empty ); } n_repetit -> set_repeated( sandwiched -> get_repeated_term() ); return ( n_repetit ); } /*------------------------------------------------------------------------- * Method: void form_intermediate_ns( Adjacency* adj, Non_repetit* non_rep ) * * This is the common method of Construct_ns and Alternat_ns. It performs * the following: * For each Any_vertex in { * switch( Anyvertex ) { * - Syntax_vertex : --- * - Inherit_term : append to inherits_from * - Optional_term : make Optional_int_part * set non_rep->labeled_int_part to: * --Labeled * append Opt_int_part to Int_part_List * - Opt_labeled_term : make Required_int_part * set labeled-int_part to: Labeled * append Required_int_part to Int_art_List * } * } *-----------------------------------------------------------------------*/ /* * neighbors_wc : construct_ns | alternat_ns * *common* < construct_ns > any_vertex-List . */ void Neighbors_wc::form_intermediate_ns ( Adjacency *adj, Non_repetit *non_rep ) { construct_ns -> form_intermediate_ns( adj, non_rep ); } /* * any_vertex-List ~ { any_vertex } . */ void Any_vertex_List::form_intermediate_ns ( Adjacency* adj, Non_repetit* non_rep ) { Any_vertex_list_iterator next_arg( *this ); Any_vertex_ each_arg; while ( each_arg = next_arg() ) each_arg -> form_intermediate_ns( adj, non_rep ); } /* * any_vertex : opt_labeled_term | optional_term | syntax_vertex | inherit_term * *common* . */ void Any_vertex::form_intermediate_ns ( Adjacency*, Non_repetit* ) { } /* * opt_labeled_term : labeled | regular *common* < vertex > term . */ void Opt_labeled_term::form_intermediate_ns ( Adjacency*, Non_repetit* non_rep ) { Required_int_part* n_rip = new Required_int_part(); n_rip -> set_labeled_int_part( this -> get_labeled() ); n_rip -> set_staticspec( this -> get_staticspec() ); n_rip -> set_accessorspec( this -> get_accessorspec() ); non_rep -> append_int_part( n_rip ); } /* * optional_term = "[" < opt > opt_labeled_term-sandwich "]" . */ void Optional_term::form_intermediate_ns ( Adjacency*, Non_repetit* non_rep ) { Optional_int_part* n_oip = new Optional_int_part(); n_oip -> set_labeled_int_part( opt -> get_labeled() ); n_oip -> set_staticspec( opt -> get_staticspec() ); n_oip -> set_accessorspec( opt -> get_accessorspec() ); non_rep -> append_int_part( n_oip ); } StaticSpec* Opt_labeled_term_Sandwich::get_staticspec() { return ( inner -> get_staticspec() ); } AccessorSpec* Opt_labeled_term_Sandwich::get_accessorspec() { return ( inner -> get_accessorspec() ); } /* * inherit_term = "*inherit*" < inherited > term-comma_List . */ void Inherit_term::form_intermediate_ns ( Adjacency* adj, Non_repetit* non_rep ) { inherited -> form_intermediate_ns( adj, non_rep ); } /* * term-comma_List ~ term { "," term } . */ void Term_Comma_list::form_intermediate_ns( Adjacency* adj, Non_repetit* ) { Term_list_iterator next_arg( *this ); Term_ each_arg; while ( each_arg = next_arg() ) adj -> write_inheritance( each_arg ); } /*------------------------------------------------------------------------- * Method: void append_int_part( Int_part* ) * * Creates an Int_part_List if necessary and appends an Int_part. *-----------------------------------------------------------------------*/ /* * non_repetit : instantiable | abstract * *common* < intermed_ns > int_part-List . */ void Non_repetit::append_int_part( Int_part* ip ) { if ( !intermed_ns ) { intermed_ns = new Int_part_List( ); } intermed_ns -> append( ip ); } /*------------------------------------------------------------------------- * Method: Labeled* get_labeled() * * Returns an object of class Labeled from a Opt_labeled_term. If the class * of the object in Opt_labeled_term is Regular, the object is transformed * to an object of class Labeled with the same as the class- * name but all letters in lower case, otherwise the object is of class * Labeled and the this pointer is returned. *-----------------------------------------------------------------------*/ /* * opt_labeled_term-Sandwich = < first > syntax_vertex-List * < inner > opt_labeled_term < second > syntax_vertex-List . */ Labeled* Opt_labeled_term_Sandwich::get_labeled() { return ( inner -> get_labeled() ); } /* * opt_labeled_term : labeled | regular *common* < vertex > term . */ Labeled* Opt_labeled_term::get_labeled() { return NULL; } /* * labeled = "<" < label_name > ident ">" . */ Labeled* Labeled::get_labeled() { return ( this ); } /* * regular = . */ Labeled* Regular::get_labeled() // transform to Labeled. { // transform vertex_name to all non-capital and assign it to label_name int i = 0; char* non_capital_name = new char[256]; strcpy( non_capital_name, this -> get_class_name() ); while ( non_capital_name[i] ) { if ( isupper( (int)non_capital_name[i] ) ){ non_capital_name[i] = tolower( (int)non_capital_name[i] ); } i++; } DemIdent *n_ident = new DemIdent( non_capital_name ); Labeled *n_labeled = new Labeled( n_ident ); n_labeled -> set_vertex( this -> get_vertex() ); return ( n_labeled ); } /*------------------------------------------------------------------------- * Method: char* get_class_name() * * Already defined in gen_classes.c (see P2) *-----------------------------------------------------------------------*/ /* char* Opt_labeled_term::get_class_name() { return( vertex -> get_class_name() ); } char* Term::get_class_name() { return ( vertex -> get_class_name() ); } char* Vertex::get_class_name() { return ( vertex_name -> get_val() ); } */ /*------------------------------------------------------------------------- * Method: Adjacency* get_adjacency( Adjacency_Nlist* ) * corresponding to Term->vertex get the Adjacency in Adjacency_Nlist *-----------------------------------------------------------------------*/ // Term : Normal *common* < vertex > Vertex . Adjacency* Term::get_adjacency ( Adjacency_Nlist* adjacencies ) { return ( adjacencies -> get_adjacency( vertex ) ); } // Adjacency_Nlist ~Adjacency {Adjacency }. Adjacency* Adjacency_Nlist::get_adjacency( Vertex* vertex ) { Adjacency_list_iterator next_arg( *this ); Adjacency_ each_arg; while ( each_arg = next_arg() ) { if ( each_arg -> get_source() -> g_equal( vertex ) ) return ( each_arg ); } return NULL; } /*------------------------------------------------------------------------- * Method: void append_inherit_term( char* ) * * Appends a term corresponding to the identifier in char* to the inhe- * rits_from list of Adjacency *-----------------------------------------------------------------------*/ /* * adjacency = < source > vertex < ns > neighbors * [ "*inherits_from*" < inherits_from > term-comma_List ] "." . */ void Adjacency::append_inherit_term( char* term_ident ) { // Create a new local Term with vertex name term_ident DemIdent* n_ident = new DemIdent( term_ident ); Vertex* n_vertex = new Vertex( n_ident ); TermRef* n_termRef = new LocalRef(); Normal* n_normal = new Normal(); n_normal -> set_vertex( n_vertex ); n_normal -> set_moduleRef( n_termRef ); // Now append it to the list of superclasses if ( !inherits_from ) { inherits_from = new Term_Comma_list(); } inherits_from -> append( n_normal ); } /*------------------------------------------------------------------------- * Method: void write_inheritance( Adjacency_Nlist*, Term* ) * * Writes the implicit inheritance of an alternation production: * appends the Term to the inherits_from list of each Adjacency in Adja- * cency_Nlist that corresponds to a term in the Term_Bar_list *-----------------------------------------------------------------------*/ /* * term-bar_List ~ term { "|" term } . */ void Term_Bar_list::write_inheritance ( Adjacency_Nlist* adjacencies, Term* inherit_term ) { Term_list_iterator next_arg( *this ); Term_ each_arg; while ( each_arg = next_arg() ) { each_arg -> get_adjacency( adjacencies ) -> write_inheritance( inherit_term ); } } /* * adjacency = < source > vertex < ns > neighbors * [ "*inherits_from*" < inherits_from > term-comma_List ] "." . */ void Adjacency::write_inheritance( Term* inherit_term ) { if ( !inherits_from ) { inherits_from = new Term_Comma_list(); } inherits_from -> append( inherit_term ); } /*------------------------------------------------------------------------- * Method: int repetition_non_empty() * * Looks whether a repetition construction is empty or not *-----------------------------------------------------------------------*/ /* * kernel-Sandwich = < first > syntax_vertex-List < inner > kernel * < second > syntax_vertex-List . */ int Kernel_Sandwich::repetition_non_empty() { return ( inner -> repetition_non_empty() ); } /* * kernel = [ < nonempty > term ] "{" < repeated > term-Sandwich "}" . */ int Kernel::repetition_non_empty() { if ( nonempty ) return 1; else return 0; } /*------------------------------------------------------------------------- * Method: Term* get_repeated_term() * * Gets the repeated term in a repetition construction *-----------------------------------------------------------------------*/ /* * kernel-Sandwich = < first > syntax_vertex-List < inner > kernel * < second > syntax_vertex-List . */ Term* Kernel_Sandwich::get_repeated_term() { return ( inner -> get_repeated_term() ); } /* * kernel = [ < nonempty > term ] "{" < repeated > term-Sandwich "}" . */ Term* Kernel::get_repeated_term() { return ( repeated -> get_repeated_term() ); } /* * term-Sandwich = < first > syntax_vertex-List < inner > term * < second > syntax_vertex-List . */ Term* Term_Sandwich::get_repeated_term() { return ( inner ); }