1 #include "MathMLSolverStableHeaders.h" 2 #include "MathMLSymbolTable.h" 3 #include "MathMLASTConstantExpression.h" 4 #include "MathMLError.h" 5 6 #include <string.h> 7 8 namespace MathML 9 { 10 //--------------------------------------------------------------------------------- SymbolTable(ErrorHandler * errorHandler)11 SymbolTable::SymbolTable( ErrorHandler* errorHandler ) 12 : mErrorHandler( errorHandler ) 13 {} 14 15 //----------------------------------------------------------------------- SymbolTable(const SymbolTable & symbolTable)16 SymbolTable::SymbolTable( const SymbolTable& symbolTable ) 17 { 18 mVariables = symbolTable.mVariables; 19 mFunctions = symbolTable.mFunctions; 20 mErrorHandler = symbolTable.mErrorHandler; 21 } 22 //--------------------------------------------------------------------------------- ~SymbolTable()23 SymbolTable::~SymbolTable() 24 {} 25 26 //--------------------------------------------------------------------------------- getVariable(const String & name) const27 AST::INode* SymbolTable::getVariable( const String& name ) const 28 { 29 SymbolTable::VariableMap::const_iterator it = findVariable(name); 30 if ( it != mVariables.end() ) 31 { 32 return it->second; 33 } 34 35 //variable not found 36 return 0; 37 } 38 39 //--------------------------------------------------------------------------------- removeVariable(const String & name)40 AST::INode* SymbolTable::removeVariable( const String& name ) 41 { 42 SymbolTable::VariableMap::iterator it = findVariable(name); 43 44 if ( it != mVariables.end() ) 45 { 46 AST::INode* node = ( *it ).second; 47 mVariables.erase( it ); 48 return node; 49 } 50 51 //variable not found 52 return 0; 53 } 54 55 //--------------------------------------------------------------------------------- getVariables() const56 const SymbolTable::VariableMap& SymbolTable::getVariables() const 57 { 58 return mVariables; 59 } 60 61 //--------------------------------------------------------------------------------- setVariable(const String & name,AST::INode * value)62 void SymbolTable::setVariable( const String& name, AST::INode* value ) 63 { 64 VariableMap::iterator iter = findVariable(name); 65 if (iter == mVariables.end()) 66 { 67 mVariables[ name ] = value; 68 } 69 else 70 { 71 mVariables[iter->first] = value; 72 } 73 } 74 //----------------------------------------------------------------------- setVariable(const String & name,double value)75 void SymbolTable::setVariable( const String& name, double value ) 76 { 77 // TODO avoid mem leak 78 setVariable(name, new AST::ConstantExpression(value)); 79 } 80 //----------------------------------------------------------------------- setVariable(const String & name,long value)81 void SymbolTable::setVariable( const String& name, long value ) 82 { 83 // TODO avoid mem leak 84 setVariable(name, new AST::ConstantExpression(value)); 85 } 86 //----------------------------------------------------------------------- setVariable(const String & name,bool value)87 void SymbolTable::setVariable( const String& name, bool value ) 88 { 89 // TODO avoid mem leak 90 setVariable(name, new AST::ConstantExpression(value)); 91 } 92 //--------------------------------------------------------------------------------- getFunction(const String & name) const93 const SymbolTable::FunctionInfo* SymbolTable::getFunction( const String& name ) const 94 { 95 SymbolTable::FunctionMap::const_iterator it = findFunction(name); 96 if ( it != mFunctions.end() ) 97 { 98 return &( *it ).second; 99 } 100 101 //@todo: BAD_FUNCTION_CALL 102 if ( mErrorHandler ) 103 { 104 Error error( Error::ERR_INVALIDPARAMS, "function: " + name + " not found" ); 105 mErrorHandler->handleError( &error ); 106 } 107 return 0; 108 } 109 110 //--------------------------------------------------------------------------------- existsFunction(const String & name) const111 bool SymbolTable::existsFunction( const String& name ) const 112 { 113 SymbolTable::FunctionMap::const_iterator it = findFunction( name ); 114 115 if ( it != mFunctions.end() ) 116 { 117 return true; 118 } 119 120 return false; 121 } 122 123 //--------------------------------------------------------------------------------- getFunctions() const124 const SymbolTable::FunctionMap& SymbolTable::getFunctions() const 125 { 126 return mFunctions; 127 } 128 129 //--------------------------------------------------------------------------------- addFunction(const String & name,FunctionInfo function)130 void SymbolTable::addFunction( const String& name, FunctionInfo function ) 131 { 132 FunctionMap::iterator iter = findFunction(name); 133 if (iter == mFunctions.end()) 134 { 135 mFunctions[ name ] = function; 136 } 137 else 138 { 139 mFunctions[iter->first] = function; 140 } 141 } 142 143 //--------------------------------------------------------------------------------- addFunction(const String & name,int argc,FunctionPtr function)144 void SymbolTable::addFunction( const String& name, int argc, FunctionPtr function ) 145 { 146 FunctionInfo info( argc, function ); 147 mFunctions[ name ] = info; 148 } 149 150 //--------------------------------------------------------------------------------- evaluateFunction(AST::ConstantExpression & result,const String & name,const ScalarList & evaluatedArgs)151 void SymbolTable::evaluateFunction( AST::ConstantExpression& result, const String& name, const ScalarList& evaluatedArgs ) 152 { 153 String funcname = name; 154 155 const FunctionInfo* fi = getFunction( funcname ); 156 157 if ( !fi ) 158 { 159 // note: getFunction( funcname ); calls errorHandler 160 return; 161 } 162 163 if ( fi->argc >= -1 ) // -1 means any parameter count 164 { 165 166 if ( fi->argc == 0 && evaluatedArgs.size() != 0 ) 167 { 168 //@todo BadFunctionCallException 169 if ( mErrorHandler ) 170 { 171 Error err( Error::ERR_INVALIDPARAMS, "Function " + funcname + "() does not take any parameter." ); 172 mErrorHandler->handleError( &err ); 173 } 174 } 175 176 else if ( fi->argc == 1 && evaluatedArgs.size() != 1 ) 177 { 178 //@todo BadFunctionCallException 179 if ( mErrorHandler ) 180 { 181 Error err( Error::ERR_INVALIDPARAMS, "Function " + funcname + "() takes exactly one parameter." ); 182 mErrorHandler->handleError( &err ); 183 } 184 } 185 186 else if ( fi->argc == -1 ) 187 { 188 // ok 189 } 190 191 else if ( static_cast<unsigned int>( fi->argc ) != evaluatedArgs.size() ) 192 { 193 std::ostringstream oss; 194 oss << "Function " << funcname << "() takes exactly " << fi->argc << " parameters."; 195 //@todo BadFunctionCallException 196 if ( mErrorHandler ) 197 { 198 Error err( Error::ERR_INVALIDPARAMS, oss.str() ); 199 mErrorHandler->handleError( &err ); 200 } 201 } 202 203 fi->func( result, evaluatedArgs, mErrorHandler ); 204 return ; 205 } 206 207 208 //@todo UnknownSymbolException(std::string("Unknown function ") + funcname + "()")); 209 if ( mErrorHandler ) 210 { 211 Error err( Error::ERR_INVALIDPARAMS, "Unknown function " + funcname + "()" ); 212 mErrorHandler->handleError( &err ); 213 } 214 } 215 //----------------------------------------------------------------------- operator =(const SymbolTable & symbolTable)216 SymbolTable& SymbolTable::operator=( const SymbolTable& symbolTable ) 217 { 218 mVariables = symbolTable.mVariables; 219 mFunctions = symbolTable.mFunctions; 220 return *this; 221 } 222 //----------------------------------------------------------------------- findVariable(const String & name) const223 SymbolTable::VariableMap::const_iterator SymbolTable::findVariable( const String& name )const 224 { 225 VariableMap::const_iterator it = mVariables.find( name ); 226 227 if ( it != mVariables.end() ) 228 { 229 return it; 230 } 231 232 for(it = mVariables.begin();it != mVariables.end(); ++it) 233 { 234 String key = it->first; 235 if(key == name) 236 { 237 return it; 238 } 239 else if(strcmp(key.c_str(), name.c_str()) == 0) 240 { 241 return it; 242 } 243 } 244 245 return mVariables.end(); 246 } 247 //----------------------------------------------------------------------- findVariable(const String & name)248 SymbolTable::VariableMap::iterator SymbolTable::findVariable( const String& name ) 249 { 250 VariableMap::iterator it = mVariables.find( name ); 251 252 if ( it != mVariables.end() ) 253 { 254 return it; 255 } 256 257 for(it = mVariables.begin();it != mVariables.end(); ++it) 258 { 259 String key = it->first; 260 if(key == name) 261 { 262 return it; 263 } 264 else if(strcmp(key.c_str(), name.c_str()) == 0) 265 { 266 return it; 267 } 268 } 269 270 return mVariables.end(); 271 } 272 //----------------------------------------------------------------------- findFunction(const String & name) const273 SymbolTable::FunctionMap::const_iterator SymbolTable::findFunction( const String& name )const 274 { 275 FunctionMap::const_iterator it = mFunctions.find( name ); 276 277 if ( it != mFunctions.end() ) 278 { 279 return it; 280 } 281 282 for(it = mFunctions.begin();it != mFunctions.end(); ++it) 283 { 284 String key = it->first; 285 if(key == name) 286 { 287 return it; 288 } 289 else if(strcmp(key.c_str(), name.c_str()) == 0) 290 { 291 return it; 292 } 293 } 294 295 return mFunctions.end(); 296 } 297 //----------------------------------------------------------------------- findFunction(const String & name)298 SymbolTable::FunctionMap::iterator SymbolTable::findFunction( const String& name ) 299 { 300 FunctionMap::iterator it = mFunctions.find( name ); 301 302 if ( it != mFunctions.end() ) 303 { 304 return it; 305 } 306 307 for(it = mFunctions.begin();it != mFunctions.end(); ++it) 308 { 309 String key = it->first; 310 if(key == name) 311 { 312 return it; 313 } 314 else if(strcmp(key.c_str(), name.c_str()) == 0) 315 { 316 return it; 317 } 318 } 319 320 return mFunctions.end(); 321 } 322 //----------------------------------------------------------------------- appendSymbolTable(const SymbolTable & symbolTable)323 void SymbolTable::appendSymbolTable( const SymbolTable& symbolTable ) 324 { 325 VariableMap::const_iterator itVar = symbolTable.mVariables.begin(); 326 for (; itVar != symbolTable.mVariables.end(); ++itVar) 327 { 328 setVariable(itVar->first, itVar->second); 329 } 330 331 FunctionMap::const_iterator itFunc = symbolTable.mFunctions.begin(); 332 for (; itFunc != symbolTable.mFunctions.end(); ++itFunc) 333 { 334 addFunction(itFunc->first, itFunc->second); 335 } 336 } 337 } //namespace MathML 338