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