/******************************************************* * * DESCRIPTION: Modelica's syntax tree nodes classes * * AUTHOR: Mariana C. D'Abreu * * EMAIL: mdabreu@dc.uba.ar * ********************************************************/ #include #include "modsynnode.h" #include "modexcept.h" //****************************************************** //****************************************************** ModSyntaxNodeList::~ModSyntaxNodeList() { NodesList::iterator it; ModSyntaxNode *node; for( it = nodes.begin(); it != nodes.end(); it++ ) { node = *it; if( node != NULL ) delete node; } nodes.clear(); } double ModSyntaxNodeList::evaluate() { NodesList::iterator it; ModSyntaxNode *node; bool aret; for( it = nodes.begin(); it != nodes.end(); it++ ) { node = *it; if( node != NULL ) { aret= node->evaluate(); } } return aret; } bool ModSyntaxNodeList::semanticalValidation() { NodesList::iterator it; ModSyntaxNode *node; for( it = nodes.begin(); it != nodes.end(); it++ ) { node = *it; if( node != NULL ) { node->semanticalValidation(); } } return true; } //****************************************************** //****************************************************** VarSymbol::~VarSymbol() { if( varType != NULL ) delete varType; if( paramsDict != NULL ) { paramsDict->clear(); delete paramsDict; } } //****************************************************** //****************************************************** string TypeSymbol::getIdWithNoPackage() const { string pid = id; pid = pid.substr( pid.find_last_of( "." ) + 1 ); return pid; } string TypeSymbol::getPackageId() const { string pid = ""; int index; if( ( index = id.find_last_of( "." ) ) != -1 ) { pid = id.substr( 0, index ); } return pid; } //****************************************************** //****************************************************** string PackageSymbol::getIdWithNoWildcards() const { string pid = id; int index; if( ( index = pid.find_last_of( "*" ) ) != -1 ) { if( index != (signed int)( pid.length() - 1 ) ) return pid; pid = pid.substr( 0, index - 1 ); } return pid; } //****************************************************** //****************************************************** SymbolTable *SymbolTable::instance = NULL; SymbolTable::~SymbolTable() { SymTable::iterator cursor; for ( cursor = symTable.begin(); cursor != symTable.end(); cursor++ ) { if( cursor->second != NULL ) delete ( cursor->second ); } symTable.clear(); } void SymbolTable::initialize() { // inicializo la tabla con los tipos soportados put( new PackageSymbol( "Modelica.Electrical.Analog.Basic.Ground" ) ); put( new PackageSymbol( "Modelica.Electrical.Analog.Basic.Resistor" ) ); put( new PackageSymbol( "Modelica.Electrical.Analog.Basic.Conductor" ) ); put( new PackageSymbol( "Modelica.Electrical.Analog.Basic.Capacitor" ) ); put( new PackageSymbol( "Modelica.Electrical.Analog.Basic.Inductor" ) ); put( new PackageSymbol( "Modelica.Electrical.Analog.Ideal.IdealTransformer" ) ); put( new PackageSymbol( "Modelica.Electrical.Analog.Ideal.IdealGyrator" ) ); put( new PackageSymbol( "Modelica.Electrical.Analog.Sources.ConstantVoltage" ) ); put( new PackageSymbol( "Modelica.Electrical.Analog.Sources.StepVoltage" ) ); put( new PackageSymbol( "Modelica.Electrical.Analog.Sources.SineVoltage" ) ); put( new PackageSymbol( "Modelica.Electrical.Analog.Sources.PulseVoltage" ) ); put( new PackageSymbol( "Modelica.Electrical.Analog.Sources.ConstantCurrent" ) ); put( new PackageSymbol( "Modelica.Electrical.Analog.Sources.StepCurrent" ) ); put( new PackageSymbol( "Modelica.Electrical.Analog.Sources.SineCurrent" ) ); put( new PackageSymbol( "Modelica.Electrical.Analog.Sources.PulseCurrent" ) ); // y los paquetes put( new PackageSymbol( "Modelica.Electrical.Analog.Basic" ) ); put( new PackageSymbol( "Modelica.Electrical.Analog.Sources" ) ); } SymbolTable &SymbolTable::put( Symbol *symbol ) { assert( symbol ); symTable.insert( SymTable::value_type( symbol->getId(), symbol ) ); return *this; } SymbolTable *SymbolTable::Instance() { if( instance == NULL ) { instance = new SymbolTable(); } return instance; } ostream &SymbolTable::print( ostream &out ) { out << "\nTabla de simbolos: "; SymTable::iterator cursor; for ( cursor = symTable.begin(); cursor != symTable.end(); cursor++ ) { if( cursor->second ) out << "\nId: [" << cursor->second->getId() << "]"; } return out; } //****************************************************** //****************************************************** double Declaration::evaluate() { ParamsDict *pDict = evaluateInitAndCreateParams(); string id = mvar->getId(); mvar->setVarType( type ); mvar->setParamsDict( pDict ); if( SymbolTable::Instance()->get( id ) != NULL ) { throw ModelicaParserException( "Duplicated symbol: " + id ); } SymbolTable::Instance()->put( mvar ); return 0; } ParamsDict *Declaration::evaluateInitAndCreateParams() { ParamsDict *pDict = new ParamsDict(); ParamSymbol *param; assert( pDict ); ModSyntaxNodeList::Iterator it; for( it = initParams->begin(); it != initParams->end(); it++ ) { param = (ParamSymbol *)(*it); pDict->insert( ParamsDict::value_type( param->getId(), param->evaluate() ) ); } return pDict; } bool Declaration::semanticalValidation() { string pid = type->getPackageId(); string tid = type->getIdWithNoPackage(); string did = tid; tid = ( pid != "" ? pid : "Modelica.Electrical.Analog.Basic" ) + "." + did; // chequeo que el tipo sea valido if( SymbolTable::Instance()->get( tid ) == NULL ) { tid = ( pid != "" ? pid : "Modelica.Electrical.Analog.Sources" ) + "." + did; if( SymbolTable::Instance()->get( tid ) == NULL ) { tid = ( pid != "" ? pid : "Modelica.Electrical.Analog.Ideal" ) + "." + did; if( SymbolTable::Instance()->get( tid ) == NULL ) { throw ModelicaParserException( "Data type unknown: " + did ); } } } return true; } //****************************************************** //****************************************************** bool Import::semanticalValidation() { //string pid = package->getIdWithNoWildcards(); string pid = package->getId(); // chequeo que el paquete sea valido if( SymbolTable::Instance()->get( pid ) == NULL ) { throw ModelicaParserException( "Invalid package name: " + pid ); } return true; } //****************************************************** //****************************************************** double Connect::evaluate() { return( ref1->evaluate() && ref2->evaluate() ); } bool Connect::semanticalValidation() { string ref1ContId = ref1->getContextId(); string ref2ContId = ref2->getContextId(); // chequeo que los simbolos existan if( SymbolTable::Instance()->get( ref1ContId ) == NULL ) { throw ModelicaParserException( "Symbol not declared: " + ref1ContId ); } if( SymbolTable::Instance()->get( ref2ContId ) == NULL ) { throw ModelicaParserException( "Symbol not declared: " + ref2ContId ); } string rid1 = ref1->getReferencedId(); string rid2 = ref2->getReferencedId(); if( !isValidReference( rid1 ) ) { throw ModelicaParserException( "Invalid reference: " + rid1 + " on context: " + ref1ContId ); } if( !isValidReference( rid2 ) ) { throw ModelicaParserException( "Invalid reference: " + rid2 + " on context: " + ref2ContId ); } return true; } bool Connect::isValidReference( const string &id ) const { // Implementar en caso de tener contextos anidados return true; }