/**************************************************************************
* PROJECT: DEMETER
* MODULE: GENERATION
* FILE: gen_pprt.c
*--------------------------------------------------------------------------
* COPYRIGHT (c) 1990 Northeastern University
* Prof. Karl J. Lieberherr
*--------------------------------------------------------------------------
* AUTHOR: Walter Hursch
*
* DATE: January 17, 1990
* REVISED:
* April 1992
* Updated because of a bug in GNU C++ compiler
* November 9, 1992
* Enable components and external libraries
*
*
*--------------------------------------------------------------------------
* DESCRIPTION:
* Gen_pprt generates for each class C of the class dictionary the
* implemention of a method called pp() which pretty prints the object
* represented in class C.
* Gen_pprt appends the function to the implementation file C_DEM.C .
*
**************************************************************************/
/**************************************************************************
Data dictionary P1
;;; 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 |
Repetit_n
|
Intermediate_ns
*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 > Ident .
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 > Ident ">" .
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* Ident.
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"
extern int term_memberfunc( Universal* term1, Universal* term2 );
/*-------------------------------------------------------------------------
* Method: void gen_pprt( char* path )
*
* Generate the pretty print function pp() for every class in the class
* dictionary.
*-----------------------------------------------------------------------*/
/*
* demeter_in = < input > input .
*/
void Demeter_in::gen_pprt( char* target )
{
input -> gen_pprt( target );
}
/*
* input : cd_graph *common* .
*/
void Input::gen_pprt( char* ) { }
/*
* cd_graph = < adjacencies > adjacency-Nlist
* [ "*terminal_sets*" < terminal_sets > vertex-comma_List "." ] .
*/
void Cd_graph::gen_pprt( char* target )
{
DBG( cout << "IN Cd_graph::gen_pprt" << endl );
adjacencies -> gen_pprt( target );
DBG( cout << "OUT Cd_graph::gen_pprt" << endl );
}
/*
* adjacency-Nlist ~ adjacency { adjacency } .
*/
void Adjacency_Nlist::gen_pprt( char* target )
{
const int MAXPATH = 256;
Adjacency_list_iterator next_arg( *this );
Adjacency_ each_arg;
ofstream outFile;
outFile.open( target, ios::app );
if ( !outFile ) {
cerr << "cannot open " << target << " for output.\n";
exit( -1 );
}
while ( each_arg = next_arg() )
each_arg -> gen_pprt( outFile, this );
outFile.close();
}
/*-------------------------------------------------------------------------
* Method:
* void gen_pprt( ofstream& outFile, Adjacency_Nlist* adj_list )
*
* Go further down the graph to Instantiable, Abstract and Repetit.
*
*-----------------------------------------------------------------------*/
/*
* adjacency = < source > vertex < ns > neighbors
* [ "*inherits_from*" < inherits_from > term-comma_List ] "." .
*/
void Adjacency::gen_pprt( ofstream& outFile, Adjacency_Nlist* adj_list )
{
ns -> gen_pprt( outFile, adj_list, this );
}
/*
* neighbors : neighbors_wc | repetit_n | intermediate_ns *common* .
*/
void Neighbors::gen_pprt( ofstream&, Adjacency_Nlist*, Adjacency* ) { }
/*
* neighbors_wc : construct_ns | alternat_ns
* *common* < construct_ns > any_vertex-List .
*/
void Neighbors_wc::gen_pprt
( ofstream& outFile, Adjacency_Nlist* adj_list, Adjacency* adj )
{
outFile << "\n\nvoid " << adj -> get_class_name()
<< "::pp( ostream& strm ) const\n{\n";
construct_ns -> gen_pprt( outFile );
/* get superclass, if any, and have pp invoke pp of superclass
remember: this is still single inheritance version! */
Normal *n_normal = new Normal();
n_normal -> set_vertex( adj -> get_source() );
TermRef *n_termRef = new LocalRef();
n_normal -> set_moduleRef( n_termRef );
Adjacency *base = adj_list -> get_base_class_of( n_normal );
if ( base ) {
outFile << " " << base -> get_class_name() << "::pp( strm );\n";
}
outFile << "}\n\n";
}
/*
* repetit_n = "~" < Sandwiched > kernel-Sandwich .
*/
void Repetit_n::gen_pprt
( ofstream& outFile, Adjacency_Nlist*, Adjacency* adj )
{
outFile << "\n\nvoid " << adj -> get_class_name()
<< "::pp( ostream& strm ) const\n{\n";
sandwiched ->gen_pprt( outFile );
outFile << "}\n\n";
}
/*
* kernel-Sandwich = < first > syntax_vertex-List < inner > kernel
* < second > syntax_vertex-List .
*/
void Kernel_Sandwich::gen_pprt( ofstream& outFile )
{
first -> gen_pprt( outFile );
inner -> gen_pprt( outFile );
second -> gen_pprt( outFile );
}
/*
* kernel = [ < nonempty > term ] "{" < repeated > term-Sandwich "}" .
*/
void Kernel::gen_pprt( ofstream& outFile )
{
char *classname = repeated -> get_class_name();
/* templates
outFile << " D__linked_list_iterator<"
<< classname << "> next_" << classname << "( this );\n"
<< " " << classname << "* each_" << classname << ";\n";
if ( nonempty ) {
outFile << " next_" << classname << "() -> pp( strm );\n";
}
outFile << " while ( each_" << classname
<< " = next_" << classname << "() ) {\n";
END templates */
/* BEGIN non-template */
outFile << " " << classname << "_list_iterator next_"
<< classname << "( *this );\n"
<< " " << classname << "_ each_" << classname << ";\n";
if ( nonempty ) {
outFile << " next_" << classname << "() -> pp( strm );\n";
}
outFile << " while ( each_" << classname
<< " = next_" << classname << "() ) {\n";
/* END non-template */
repeated -> gen_pprt( outFile );
outFile << " }\n";
}
/*
* term-Sandwich = < first > syntax_vertex-List < inner > term
* < second > syntax_vertex-List .
*/
void Term_Sandwich::gen_pprt( ofstream& outFile )
{
first -> gen_pprt( outFile );
outFile << " each_" << this -> get_class_name()
<< " -> pp( strm );\n";
second -> gen_pprt( outFile );
}
char *Term_Sandwich::get_class_name()
{
return ( inner -> get_class_name() );
}
/*
* syntax_vertex-List ~ { syntax_vertex } .
*/
void Syntax_vertex_List::gen_pprt( ofstream& outFile )
{
Syntax_vertex_list_iterator next_arg( *this );
Syntax_vertex_ each_arg;
while ( each_arg = next_arg() )
each_arg -> gen_pprt( outFile );
}
/*
* any_vertex-List ~ { any_vertex } .
*/
void Any_vertex_List::gen_pprt( ofstream &outFile )
{
Any_vertex_list_iterator next_arg( *this );
Any_vertex_ each_arg;
while ( each_arg = next_arg() )
each_arg -> gen_pprt( outFile );
}
/*
* any_vertex : opt_labeled_term | optional_term | syntax_vertex |
* inherit_term *common* .
*/
void Any_vertex::gen_pprt( ofstream& ) { }
/*
* optional_term = "[" < opt > opt_labeled_term-Sandwich "]" .
*/
void Optional_term::gen_pprt( ofstream& outFile )
{
outFile << " if ( " << opt -> get_inner_var_name() << " ) {\n";
opt -> gen_pprt( outFile );
outFile << " }\n";
}
/*
* opt_labeled_term-Sandwich = < first > syntax_vertex-List
* < inner > opt_labeled_term
* < second > syntax_vertex-List .
*/
void Opt_labeled_term_Sandwich::gen_pprt( ofstream& outFile )
{
first -> gen_pprt( outFile );
inner -> gen_pprt( outFile );
second -> gen_pprt( outFile );
}
/*
* opt_labeled_term : labeled | regular *common* < vertex > term .
*
* Assumption: all opt_labeled_terms are labeled. Guaranteed by cd-param-exp.
*/
int Opt_labeled_term::is_NonDemTerm()
{
return ( vertex -> is_NonDemTerm() );
}
void Opt_labeled_term::gen_pprt( ofstream& outFile )
{
if ( ! this->is_NonDemTerm() ) {
outFile << " " << this -> get_labeled() -> get_var_name()
<< " -> pp( strm );" << endl;
}
else {
outFile << " cout << \"external part\"; " << endl;
}
}
char *Opt_labeled_term_Sandwich::get_inner_var_name()
{
return ( inner -> get_inner_var_name() );
}
char *Opt_labeled_term::get_inner_var_name()
{
return ( this -> get_labeled() -> get_var_name() );
}
/*
* syntax_vertex : regular_syntax | print_command *common* .
*/
void Syntax_vertex::gen_pprt( ofstream& ) { }
/*
* regular_syntax = < string > string .
*/
void Regular_syntax::gen_pprt( ofstream& outFile )
{
outFile << " strm << \"" << string -> get_val() << "\";\n";
}
/*
* print_command : print_indent | print_unindent | print_skip | print_space
* *common* .
*/
void Print_command::gen_pprt( ofstream& ) { }
/*
* print_indent = "+" .
*/
void Print_indent::gen_pprt( ofstream& outFile )
{
outFile << " strm << \"\\t\";\n";
}
/*
* print_unindent = "-" .
*/
void Print_unindent::gen_pprt( ofstream& outFile )
{
outFile << " strm << \"\\b\\b\\b\\b\";\n";
}
/*
* print_skip = "*l" .
*/
void Print_skip::gen_pprt( ofstream& outFile )
{
outFile << " strm << \"\\n\";\n";
}
/*
* print_space = "*s" .
*/
void Print_space::gen_pprt( ofstream& outFile )
{
outFile << " strm << \" \";\n";
}
/*
* adjacency-Nlist ~ adjacency { adjacency } .
*/
Adjacency* Adjacency_Nlist::get_base_class_of( Term* derived )
{
Adjacency_list_iterator next_Adj( *this );
Adjacency_ each_Adj;
while ( each_Adj = next_Adj() ) {
if ( each_Adj -> is_base_class_of( derived ) ) {
return ( each_Adj );
}
}
return NULL;
}
/*
* adjacency = < source > vertex < ns > neighbors
* [ "*inherits_from*" < inherits_from > term-comma_List ] "." .
*/
int Adjacency::is_base_class_of( Term* derived )
{
return ( ns -> is_base_class_of( derived ) );
}
/*
* neighbors : neighbors_wc | repetit_n | intermediate_ns *common* .
*/
int Neighbors::is_base_class_of( Term* )
{
return 0;
}
/*
* alternat_ns = ":" < alternat_ns > term-bar_List [ < common > common ] .
*/
int term_memberfunc( Universal*, Universal* );
int Alternat_ns::is_base_class_of( Term* derived )
{
return( alternat_ns -> member(derived, term_memberfunc) );
}