/*
* This file is part of rasdaman community.
*
* Rasdaman community is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Rasdaman community is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with rasdaman community. If not, see .
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
rasdaman GmbH.
*
* For more information please see
* or contact Peter Baumann via .
*/
#include "rasdl/parse.hh"
#include "symbtbl.hh"
#include "yparse.hh"
#include
#include "debug/debug.hh"
#include "raslib/rmdebug.hh"
#include "catalogmgr/typefactory.hh"
#include "relcatalogif/alltypes.hh"
extern void output_scope(FILE*out,const YSymbolTable::Scope*scope);
Parse_info::Parse_info()
: line(0), column(0), file(NULL), token(NULL)
{
}
Parse_info::Parse_info( long lineNo, int columnNo, const char* fileName, const char* tokenName )
: line( lineNo ), column( columnNo ), file(NULL), token(NULL)
{
if( fileName )
file = strdup( fileName );
if( tokenName )
token = strdup( tokenName );
}
Parse_info::Parse_info( YWhere &where, const char* tokenName )
: line( where.line ), column( where.column ), file(NULL), token(NULL)
{
if( where.file )
file = strdup( where.file );
if( tokenName )
token = strdup( tokenName );
}
Parse_info::Parse_info( const Parse_info& obj )
{
line = obj.line;
column = obj.column;
file = obj.file ? strdup( obj.file ) : NULL;
token = obj.token ? strdup( obj.token ) : NULL;
}
Parse_info::~Parse_info()
{
if( file ) { free( file ); file = NULL; }
if( token ) { free( token ); token = NULL; }
}
const Parse_info&
Parse_info::operator=( const Parse_info& obj )
{
if( this != &obj )
{
line = obj.line;
column = obj.column;
file = obj.file ? strdup( obj.file ) : NULL;
token = obj.token ? strdup( obj.token ) : NULL;
}
return *this;
}
/* THE ATOM */
Parse_atom::Parse_atom()
{
kind =Atom;
name =NULL;
symbol =NULL;
}
Parse_atom::~Parse_atom()
{
}
void Parse_atom::insertData() const throw( r_Equery_execution_failed )
{
RMDBGONCE(4, RMDebug::module_rasdl, "Parse_atom", "printData() kind " << kind << ", name " << name << ", symbol " << symbol)
TALK( "Parse_atom::insertData: doing nothing with name=" << name << ", symbol=" << symbol)
}
void Parse_atom::setParseInfo( const Parse_info &token )
{
parseInfo = token;
}
const Parse_info& Parse_atom::getParseInfo()
{
return parseInfo;
}
/* THE TYPE */
Parse_type::Parse_type()
{
kind =Type;
forward =false;
};
Parse_type::~Parse_type()
{
}
const Type*
Parse_type::getType( const char* /*typeName*/ ) const
{
std::cerr << "Internal error: getType() for a subclass of Parse_type not implemented." << std::endl;
return NULL;
}
Parse_typereference::Parse_typereference()
{
kind =Typereference;
type =NULL;
}
Parse_typereference::~Parse_typereference()
{
}
void Parse_typereference::output(FILE*stream)const
{
fprintf(stream,"%s",type->name);
};
const Type*
Parse_typereference::getType( const char* /*typeName*/ ) const
{
const BaseType* catBaseType = TypeFactory::mapType( (char*)type->name );
if( !catBaseType )
// Error: Type reference not found..
throw( r_Equery_execution_failed( 902, symbol->where.line, symbol->where.column, symbol->get_name() ) );
return catBaseType;
}
/* composite */
Parse_composite::Parse_composite()
{
kind =Composite;
elements =NULL;
};
Parse_composite::Element::Element()
{
readonly =false;
type =NULL;
name =NULL;
access =Private;
next =NULL;
};
Parse_composite::Element::~Element()
{
}
void Parse_composite::Element::output(FILE*stream)const
{
fprintf(stream," ");
type->output(stream);
fprintf(stream," %s;",name);
if(readonly)
fprintf(stream,"// ___readonly___\n");
else
fprintf(stream,"\n");
};
/* struct */
Parse_struct::Parse_struct()
{
kind =Struct;
};
Parse_struct::~Parse_struct()
{
}
void Parse_struct::output(FILE*stream)const
{
fprintf(stream,"/* STRUCT -------------------------- %s */\n",name);
fprintf(stream,"struct %s {\n",name);
for(Element*scan=elements;scan!=NULL;scan=scan->next)
scan->output(stream);
fprintf(stream,"};\n");
};
void Parse_struct::insertData() const throw( r_Equery_execution_failed )
{
ENTER( "Parse_struct::insertData" );
RMDBGENTER(4, RMDebug::module_rasdl, "Parse_struct", "insertData()")
// get catalog type structure
StructType* catType = (StructType*)getType();
TALK( "got type " << (char*)catType->getTypeName() );
RMDBGMIDDLE(4, RMDebug::module_rasdl, "Parse_struct", "inserting type " << catType->getTypeName())
if( TypeFactory::mapType( (char*)catType->getTypeName() ) )
// Error: Struct type name exists already.
throw( r_Equery_execution_failed( 905, symbol->where.line, symbol->where.column, symbol->get_name() ) );
TALK( "adding to the database as cell struct type" );
TypeFactory::addStructType( catType );
RMDBGEXIT(4, RMDebug::module_rasdl, "Parse_struct", "insertData()")
LEAVE( "Parse_struct::insertData" );
};
const Type*
Parse_struct::getType( const char* /*typeName*/ ) const
{
unsigned int noElements=0;
StructType* structType=NULL;
Element* scan=NULL;
RMDBGENTER(4, RMDebug::module_rasdl, "Parse_struct", "getType()")
for( scan=elements; scan!=NULL; scan=scan->next, noElements++ );
RMDBGMIDDLE(4, RMDebug::module_rasdl, "Parse_struct", "Struct " << name << " has " << noElements << " elements.")
structType = new StructType( (char*)name, noElements );
for( scan=elements; scan!=NULL; scan=scan->next)
if( !scan->type )
std::cerr << "Internal error: struct element doesn't deliver a catalog type" << std::endl;
else
{
RMDBGMIDDLE(4, RMDebug::module_rasdl, "Parse_struct", "Scan->name " << scan->name)
structType->addElement( (char*)(scan->name), (BaseType*)(scan->type->getType()) );
}
RMDBGEXIT(4, RMDebug::module_rasdl, "Parse_struct", "getType()" )
return structType;
}
/* union */
Parse_union::Parse_union()
{
kind =Union;
};
Parse_union::~Parse_union()
{
}
void Parse_union::output(FILE*stream)const
{
fprintf(stream,"/* UNION --------------------------- %s */\n",name);
fprintf(stream,"struct %s {\n",name);
for(Element*scan=elements;scan!=NULL;scan=scan->next)
scan->output(stream);
fprintf(stream,"};\n");
};
/* interface */
Parse_interface::Parse_interface()
{
kind =Interface;
base_classes =NULL;
lifetime =undefined;
methods =NULL;
relationships =NULL;
};
void print_access_mode(FILE*stream,Parse_composite::Access_mode access)
{
switch(access)
{
case Parse_composite::Private:
{
fprintf(stream,"private:\n");
break;
};
case Parse_composite::Public:
{
fprintf(stream,"public:\n");
break;
};
case Parse_composite::Protected:
{
fprintf(stream,"protected:\n");
break;
};
};
};
void Parse_interface::output(FILE*stream)const
{
if(forward)
{
fprintf(stream,"class %s;/**/\n",name);
return;
};
fprintf(stream,"/* CLASS --------------------------- %s */\n",name);
if(base_classes!=NULL)
{
fprintf(stream,"class %s : ",name);
for(Base_class *scan=base_classes;scan!=NULL;scan=scan->next)
{
scan->output(stream);
if(scan->next!=NULL)
fprintf(stream,",");
};
fprintf(stream,"\n{\n");
}
else
fprintf(stream,"class %s {\n",name);
// output all symbols
symbol->defines->output(stream);
Access_mode current_access=Private;
if(methods!=NULL)
{
fprintf(stream,"// operations\n");
methods->output(stream);
};
if(elements!=NULL)
{
fprintf(stream,"// attributes\n");
for(Element *scan=elements;scan!=NULL;scan=scan->next)
{
if(scan->access!=current_access)
{
current_access=scan->access;
print_access_mode(stream,current_access);
};
scan->output(stream);
};
};
if(relationships!=NULL)
{
fprintf(stream,"//relationships\n");
}
fprintf(stream,"};\n");
};
Parse_interface::Base_class::Base_class()
{
base_class =NULL;
access =Private;
next =NULL;
};
void Parse_interface::Base_class::output(FILE*stream)const
{
if(base_class==NULL)
fprintf(stream,"");
else
switch(access)
{
case Private:
fprintf(stream,"private %s",base_class->name);
break;
case Public:
fprintf(stream,"public %s",base_class->name);
break;
case Protected:
fprintf(stream,"protected %s",base_class->name);
break;
};
};
Parse_interface::Method::Method()
{
function =NULL;
access =Private;
next =NULL;
};
void Parse_interface::Method::output(FILE*stream)const
{
function->output(stream);
fprintf(stream,";\n");
};
/* function */
Parse_function::Parse_function()
{
kind =Function;
parameters =NULL;
return_type =NULL;
};
void Parse_function::output(FILE*stream)const
{
return_type->output(stream);
fprintf(stream," %s(",name);
if(parameters!=NULL)
{
parameters->output(stream);
};
fprintf(stream,")");
};
Parse_function::Parameter::Parameter()
{
type =NULL;
state =Unknown;
name =NULL;
next =NULL;
};
void Parse_function::Parameter::output(FILE*stream)const
{
if(state==In)
fprintf(stream,"const ");
type->output(stream);
if(state==Out)
fprintf(stream,"&");
else
fprintf(stream," ");
fprintf(stream,"%s",name);
};
/* operation */
Parse_operation::Parse_operation()
{
kind =Operation;
scope_class =NULL;
};
/* pointer */
Parse_pointer::Parse_pointer()
{
kind =Pointer;
type =NULL;
};
void Parse_pointer::output(FILE*stream)const
{
type->output(stream);
fprintf(stream,"*");
};
/* array */
Parse_array::Parse_array()
{
kind =Array;
size =0;
};
void Parse_array::output(FILE*stream)const
{
type->output(stream);
fprintf(stream,"[%i]",size);
};
/* alias */
Parse_alias::Parse_alias()
{
kind =Alias;
type =NULL;
name =NULL;
};
void Parse_alias::output(FILE*stream)const
{
fprintf(stream,"/* TYPEDEF ------------------------- %s */\n",name);
fprintf(stream,"typedef ");
type->output(stream);
fprintf(stream," %s",name);
fprintf(stream,";\n\n");
};
void Parse_alias::insertData() const throw( r_Equery_execution_failed )
{
ENTER( "Parse_alias::insertData" );
RMDBGENTER(4, RMDebug::module_rasdl, "Parse_alias", "insertData()")
// get catalog type structure
const CType* catType = type->getType( name );
if( !catType )
{
std::cerr << "Internal error: no type in alias definition." << std::endl;
return;
}
TALK( "got type " << name );
RMDBGIF(5, RMDebug::module_rasdl, "Parse_alias", \
{ \
char* typeStructure = catType->getTypeStructure(); \
RMInit::dbgOut << "Name " << catType->getTypeName() << ", structure " << typeStructure << std::endl; \
free( typeStructure ); typeStructure = NULL; \
} )
switch( catType->getType() )
{
case MDDTYPE:
if( TypeFactory::mapMDDType( (char*)catType->getTypeName() ) )
{
delete catType;
// Error: MDD type name exists already.
throw( r_Equery_execution_failed( 906, symbol->where.line, symbol->where.column, symbol->get_name() ) );
}
TALK( "adding to the database as MDD type" );
TypeFactory::addMDDType( (MDDType*)catType );
break;
case SETTYPE:
if( TypeFactory::mapType( (char*)catType->getTypeName() ) )
{
delete catType;
// Error: Set type name exists already.
throw( r_Equery_execution_failed( 907, symbol->where.line, symbol->where.column, symbol->get_name() ) );
}
TALK( "adding to the database as set type" );
TypeFactory::addSetType( (SetType*)catType );
break;
default:
delete catType;
// Error: Type in typedef definition not supported
throw( r_Equery_execution_failed( 900, symbol->where.line, symbol->where.column, symbol->get_name() ) );
}
delete catType;
RMDBGEXIT( 4, RMDebug::module_rasdl, "Parse_alias", "insertData()")
LEAVE( "Parse_alias::insertData" );
};
/* enumerator */
Parse_enum::Parse_enum()
{
kind =Enum;
enumerators =NULL;
};
void Parse_enum::output(FILE*stream)const
{
fprintf(stream,"/* ENUMERATION --------------------- %s */\n",name);
fprintf(stream,"enum %s {",name);
const Enumerator *scan=enumerators;
while(scan!=NULL)
{
fprintf(stream,"%s=%i",scan->name,scan->value);
scan=scan->next;
if(scan!=NULL)
fprintf(stream,",");
};
fprintf(stream,"};\n");
};
void Parse_enum::Enumerator::output(FILE*stream)const
{
fprintf(stream,"// %s = %6i\n",name,value);
};
/* atomic types&classes */
void Parse_atomic::output(FILE*stream)const
{
fprintf(stream,"%s",name);
};
/* any */
Parse_any::Parse_any()
{
kind =Any;
name ="r_Any";
};
/* void */
Parse_void::Parse_void()
{
kind =Void;
name ="void";
};
/* string */
Parse_string::Parse_string()
{
kind =String;
name ="r_String";
length =0;
};
/* boolean */
Parse_boolean::Parse_boolean()
{
kind =Boolean;
name ="r_Boolean";
};
const Type*
Parse_boolean::getType( const char* /*typeName*/ ) const
{
return TypeFactory::mapType("Bool" );
}
/* float */
Parse_float::Parse_float()
{
kind =Float;
name ="float";
accurance =Single;
};
void Parse_float::output(FILE*stream)const
{
switch(accurance)
{
case Single:
fprintf(stream,"r_Float");
break;
case Double:
fprintf(stream,"r_Double");
break;
}
};
const Type*
Parse_float::getType( const char* /*typeName*/ ) const
{
const BaseType* type;
if( accurance == Single )
type = TypeFactory::mapType("Float");
else
type = TypeFactory::mapType("Double");
return type;
}
/* int */
Parse_int::Parse_int()
{
kind =Integer;
name ="int";
width =Short;
sign =Signed;
};
void Parse_int::output(FILE*stream)const
{
switch(sign)
{
case Signed:
switch(width)
{
case Long:
fprintf(stream,"r_Long ");
break;
case Short:
fprintf(stream,"r_Short ");
break;
}
break;
case Unsigned:
switch(width)
{
case Long:
fprintf(stream,"r_ULong ");
break;
case Short:
fprintf(stream,"r_UShort ");
break;
}
break;
}
};
const Type*
Parse_int::getType( const char* /*typeName*/ ) const
{
const BaseType* type;
if( sign == Signed )
{
switch(width)
{
case Long:
type = TypeFactory::mapType("Long" );
break;
case Short:
type = TypeFactory::mapType("Short");
break;
}
}
else
{
switch(width)
{
case Long:
type = TypeFactory::mapType("ULong" );
break;
case Short:
type = TypeFactory::mapType("UShort");
break;
}
}
return type;
}
/* octet */
Parse_octet::Parse_octet()
{
kind =Octet;
name ="r_Octet";
};
const Type*
Parse_octet::getType( const char* /*typeName*/ ) const
{
return TypeFactory::mapType("Octet");
}
/* complex1 */
Parse_complex1::Parse_complex1()
{
kind = Complex1;
name = "r_Complex1";
};
const Type*
Parse_complex1::getType( const char* /*typeName*/ ) const
{
return TypeFactory::mapType("Complex1");
}
/* complex2 */
Parse_complex2::Parse_complex2()
{
kind = Complex2;
name = "r_Complex2";
};
const Type*
Parse_complex2::getType( const char* /*typeName*/ ) const
{
return TypeFactory::mapType("Complex2");
}
/* char */
Parse_char::Parse_char()
{
kind =Char;
name ="r_Char";
};
const Type*
Parse_char::getType( const char* /*typeName*/ ) const
{
return TypeFactory::mapType("Char");
}
// forwiss atomics
Parse_atomic_templates::Parse_atomic_templates()
{
kind =Atomic_template;
base_type =NULL;
};
Parse_MDD::Parse_MDD()
{
kind =MDD;
domain =NULL;
};
void Parse_MDD::output(FILE*stream)const
{
fprintf(stream,"r_Marray<");
if(base_type!=NULL)
base_type->output(stream);
else
fprintf(stream,"no_type");
if(domain!=NULL)
{
fprintf(stream,"/*");
char* stringDomain = domain->get_string_representation();
fprintf(stream,"%s",stringDomain);
free(stringDomain);
fprintf(stream,"*/");
};
fprintf(stream,"> ");
};
const Type*
Parse_MDD::getType( const char* typeName ) const
{
RMDBGENTER( 4, RMDebug::module_rasdl, "Parse_MDD", "getType()" )
if( !base_type ||
( base_type->kind != Typereference && base_type->kind != Boolean &&
base_type->kind != Float && base_type->kind != Integer &&
base_type->kind != Char && base_type->kind != Octet &&
base_type->kind != Complex1 && base_type->kind != Complex2
)
)
// Error: MDD base type has to be a type reference or an atomic type.
throw( r_Equery_execution_failed( 903, parseInfo.line, parseInfo.column, parseInfo.token ) );
// if( !domain )
// // Error: MDD type must have a domain specification.
// throw( r_Equery_execution_failed( 904, parseInfo.line, parseInfo.column, parseInfo.token ) );
if( !typeName )
{
std::cerr << "Internal error: mdd type needs a type name" << std::endl;
return 0;
}
const BaseType* catBaseType = (BaseType*)base_type->getType();
RMDBGIF(4, RMDebug::module_rasdl, "Parse_MDD", \
{ \
char* typeStructure = catBaseType->getTypeStructure(); \
RMInit::dbgOut << " Base type name " << catBaseType->getTypeName() << ", structure " << typeStructure << std::endl; \
free( typeStructure ); typeStructure = NULL; \
} )
RMDBGMIDDLE(4, RMDebug::module_rasdl, "Parse_MDD", "type name " << typeName << ", base typIe name " << catBaseType->getTypeName() )
const MDDType* mddType;
if( domain )
mddType = new MDDDomainType( (char*)typeName, catBaseType, *domain );
else if( dimensionality )
mddType = new MDDDimensionType( (char*)typeName, catBaseType, (r_Dimension)dimensionality );
else
mddType = new MDDBaseType( (char*)typeName, catBaseType );
RMDBGEXIT(4, RMDebug::module_rasdl, "Parse_MDD", "getType()")
return mddType;
}
Parse_set::Parse_set()
{
kind =Set;
};
void Parse_set::output(FILE*stream)const
{
fprintf(stream,"r_Setoutput(stream);
fprintf(stream,"> >");
};
const Type*
Parse_set::getType( const char* typeName ) const
{
RMDBGENTER(4, RMDebug::module_rasdl, "Parse_set", "getType()")
if( !base_type || base_type->kind != Typereference )
// Error: Set template type has to be a type reference.
throw( r_Equery_execution_failed( 901, parseInfo.line, parseInfo.column, parseInfo.token ) );
if( !typeName )
{
std::cerr << "Internal error: mdd type needs a type name" << std::endl;
return NULL;
}
const char* baseTypeName = ((Parse_typereference*)base_type)->type->name;
if( !baseTypeName )
{
std::cerr << "Internal error: set type needs a base type name" << std::endl;
return NULL;
}
RMDBGMIDDLE(4, RMDebug::module_rasdl, "Parse_set", "Base type name " << baseTypeName)
const MDDType* catBaseType = TypeFactory::mapMDDType( (char*)baseTypeName );
if( !catBaseType )
// Error: Type reference not found..
throw( r_Equery_execution_failed( 902, base_type->symbol->where.line, base_type->symbol->where.column, base_type->name ) );
RMDBGIF(5, RMDebug::module_rasdl, "Parse_set", \
{ \
char* typeStructure = catBaseType->getTypeStructure(); \
RMInit::dbgOut << " Name " << catBaseType->getTypeName() << ", structure " << typeStructure << std::endl; \
free( typeStructure ); typeStructure = NULL; \
})
RMDBGMIDDLE(4, RMDebug::module_rasdl, "Parse_set", "type name " << typeName << ", base type name " << baseTypeName )
const SetType* setType = new SetType( (char*)typeName, catBaseType );
RMDBGEXIT(4, RMDebug::module_rasdl, "Parse_set", "getType()")
return setType;
}