/**************************************************************************
* 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 );
}