1 /*
2     Copyright (c) 2008-2009 NetAllied Systems GmbH
3 
4     This file is part of COLLADASaxFrameworkLoader.
5 
6     Licensed under the MIT Open Source License,
7     for details please see LICENSE file or the website
8     http://www.opensource.org/licenses/mit-license.php
9 */
10 
11 #include "COLLADASaxFWLStableHeaders.h"
12 #include "COLLADASaxFWLFormulasLoader.h"
13 
14 #include "COLLADASaxFWLFileLoader.h"
15 #include "COLLADASaxFWLFilePartLoader.h"
16 #include "COLLADASaxFWLCOLLADACsymbol.h"
17 
18 #include "COLLADAFWFormula.h"
19 #include "COLLADAFWFormulaNewParam.h"
20 
21 #include "GeneratedSaxParserUtils.h"
22 
23 #include "MathMLASTUnaryArithmeticExpression.h"
24 #include "MathMLASTArithmeticExpression.h"
25 #include "MathMLASTConstantExpression.h"
26 #include "MathMLASTVariableExpression.h"
27 #include "MathMLASTLogicExpression.h"
28 #include "MathMLASTBinaryComparisionExpression.h"
29 #include "MathMLASTFunctionExpression.h"
30 #include "MathMLParserConstants.h"
31 
32 
33 namespace COLLADASaxFWL
34 {
35 
36 	//-----------------------------------------------------------------
FormulasLoader()37 	FormulasLoader::FormulasLoader( )
38 		: mCurrentFormula( 0 )
39 		, mSepOccurred( false )
40 		, mCurrentCSymbolFunctionUniqueId(COLLADAFW::UniqueId::INVALID)
41 		, mCurrentCSymbolIsFunction(false)
42 		, mCurrentApplyHasChild(false)
43 		, mWithinNewParam(false)
44 		, mCurrentFormulaNewParam(0)
45 	{
46 	}
47 
48 	//-----------------------------------------------------------------
~FormulasLoader()49 	FormulasLoader::~FormulasLoader()
50 	{
51 	}
52 
53     //-----------------------------------------------------------------
getUniqueId()54     const COLLADAFW::UniqueId& FormulasLoader::getUniqueId ()
55     {
56         if ( mCurrentFormula )
57             return mCurrentFormula->getUniqueId ();
58         return COLLADAFW::UniqueId::INVALID;
59     }
60 
61 	//-----------------------------------------------------------------
begin__formula(const formula__AttributeData & attributeData)62 	bool FormulasLoader::begin__formula( const formula__AttributeData& attributeData )
63 	{
64 		mCurrentFormula = FW_NEW COLLADAFW::Formula( getHandlingFilePartLoader()->createUniqueIdFromId( attributeData.id, COLLADAFW::Formula::ID()) );
65 		if ( attributeData.name )
66 			mCurrentFormula->setName( attributeData.name );
67 		else if ( attributeData.id )
68 			mCurrentFormula->setName( attributeData.id );
69 		else if ( attributeData.sid )
70 			mCurrentFormula->setName( attributeData.sid );
71 
72 		if ( attributeData.id )
73 			mCurrentFormula->setOriginalId ( attributeData.id );
74 
75 		getHandlingFilePartLoader()->addToSidTree( attributeData.id, attributeData.sid, mCurrentFormula );
76 
77 		return true;
78 	}
79 
80 	//-----------------------------------------------------------------
end__formula()81 	bool FormulasLoader::end__formula()
82 	{
83 		getHandlingFilePartLoader()->getFileLoader()->addFormula( mCurrentFormula );
84 		mCurrentFormula = 0;
85 		getHandlingFilePartLoader()->moveUpInSidTree();
86 
87 		return true;
88 	}
89 
90 	//-----------------------------------------------------------------
begin__newparam(const formula_newparam_type__AttributeData & attributeData)91 	bool FormulasLoader::begin__newparam( const formula_newparam_type__AttributeData& attributeData )
92 	{
93 		mWithinNewParam = true;
94 		if ( attributeData.sid )
95 		{
96 			mCurrentFormulaNewParamSid = attributeData.sid;
97 		}
98 		return true;
99 	}
100 
101 	//-----------------------------------------------------------------
end__newparam()102 	bool FormulasLoader::end__newparam()
103 	{
104 		COLLADAFW::FormulaNewParamPointerArray& newParams = mCurrentFormula->getNewParams();
105 		newParams.append(mCurrentFormulaNewParam);
106 		mWithinNewParam = false;
107 		mCurrentFormulaNewParamSid.clear();
108 		mCurrentFormulaNewParam = 0;
109 		return true;
110 	}
111 
112 	//-----------------------------------------------------------------
begin__float()113 	bool FormulasLoader::begin__float()
114 	{
115 		if ( mWithinNewParam )
116 		{
117 			mCurrentFormulaNewParam = FW_NEW COLLADAFW::FormulaNewParam(COLLADAFW::FormulaNewParam::VALUETYPE_FLOAT);
118 			mCurrentFormulaNewParam->setName(mCurrentFormulaNewParamSid);
119 		}
120 		return true;
121 	}
122 
123 	//-----------------------------------------------------------------
end__float()124 	bool FormulasLoader::end__float()
125 	{
126 		return true;
127 	}
128 
129 	//-----------------------------------------------------------------
data__float(float value)130 	bool FormulasLoader::data__float( float value )
131 	{
132 		if ( mWithinNewParam )
133 		{
134 			mCurrentFormulaNewParam->setDoubleValue( value );
135 		}
136 		return true;
137 	}
138 
139 	//-----------------------------------------------------------------
begin__int()140 	bool FormulasLoader::begin__int()
141 	{
142 		if ( mWithinNewParam )
143 		{
144 			mCurrentFormulaNewParam = FW_NEW COLLADAFW::FormulaNewParam(COLLADAFW::FormulaNewParam::VALUETYPE_INT);
145 			mCurrentFormulaNewParam->setName(mCurrentFormulaNewParamSid);
146 		}
147 		return true;
148 	}
149 
150 	//-----------------------------------------------------------------
end__int()151 	bool FormulasLoader::end__int()
152 	{
153 		return true;
154 	}
155 
156 	//-----------------------------------------------------------------
data__int(int value)157 	bool FormulasLoader::data__int( int value )
158 	{
159 		if ( mWithinNewParam )
160 		{
161 			mCurrentFormulaNewParam->setIntValue( value );
162 		}
163 		return true;
164 	}
165 
166 	//-----------------------------------------------------------------
begin__bool()167 	bool FormulasLoader::begin__bool()
168 	{
169 		if ( mWithinNewParam )
170 		{
171 			mCurrentFormulaNewParam = FW_NEW COLLADAFW::FormulaNewParam(COLLADAFW::FormulaNewParam::VALUETYPE_BOOL);
172 			mCurrentFormulaNewParam->setName(mCurrentFormulaNewParamSid);
173 		}
174 		return true;
175 	}
176 
177 	//-----------------------------------------------------------------
end__bool()178 	bool FormulasLoader::end__bool()
179 	{
180 		return true;
181 	}
182 
183 	//-----------------------------------------------------------------
data__bool(bool value)184 	bool FormulasLoader::data__bool( bool value )
185 	{
186 		if ( mWithinNewParam )
187 		{
188 			mCurrentFormulaNewParam->setBoolValue( value );
189 		}
190 		return true;
191 	}
192 
193 	//-----------------------------------------------------------------
begin__math(const math__AttributeData & attributeData)194 	bool FormulasLoader::begin__math( const math__AttributeData& attributeData )
195 	{
196 		NodeVector newArray;
197 		mNodeListStack.push( newArray );
198 		return true;
199 	}
200 
201 	//-----------------------------------------------------------------
end__math()202 	bool FormulasLoader::end__math()
203 	{
204 		return end__apply();
205 	}
206 
207 	//-----------------------------------------------------------------
begin__apply(const apply__AttributeData & attributeData)208 	bool FormulasLoader::begin__apply( const apply__AttributeData& attributeData )
209 	{
210 		mCurrentApplyHasChild = false;
211 		NodeVector newArray;
212 		mNodeListStack.push( newArray );
213 		return true;
214 	}
215 
216 	//-----------------------------------------------------------------
end__apply()217 	bool FormulasLoader::end__apply()
218 	{
219 		mCurrentApplyHasChild = true;
220 
221 		if ( mNodeListStack.empty() )
222 		{
223 			// TODO error handling
224 			return false;
225 		}
226 
227 		NodeVector nodes = mNodeListStack.top();
228 		mNodeListStack.pop();
229 		size_t numOfNodes = nodes.size();
230 
231 		if ( numOfNodes == 0 )
232 		{
233 			// TODO error handling
234 			return false;
235 		}
236 
237 		if ( mOperatorStack.empty() )
238 		{
239 			mCurrentFormula->getMathmlAsts().allocMemory( nodes.size() );
240 			for (size_t i=0; i<nodes.size(); ++i)
241 			{
242 				mCurrentFormula->getMathmlAsts().append( nodes[ i ] );
243 			}
244 		}
245 		else
246 		{
247 			Operator op = mOperatorStack.top();
248 			mOperatorStack.pop();
249 
250 			if ( isFunction( op ) )
251 			{
252 				MathML::AST::INode* node = createFunctionOperation( nodes, op );
253 				appendNewNode( node );
254 			}
255 			else if ( op == USER_DEFINED_FUNCTION )
256 			{
257 				MathML::AST::INode* node = createUserDefinedFunctionOperation( nodes );
258 				appendNewNode( node );
259 			}
260 			else
261 			{
262 				switch ( numOfNodes )
263 				{
264 
265 				case 1:
266 					{
267 						MathML::AST::INode* node = createUnaryOperation( nodes, op );
268 						appendNewNode( node );
269 						break;
270 					}
271 				default:
272 					{
273 						MathML::AST::INode* node = createMultiOperandOperation( nodes, op );
274 						appendNewNode( node );
275 						break;
276 					}
277 				}
278 			}
279 		}
280 
281 		return true;
282 	}
283 
284 	//-----------------------------------------------------------------
appendNewNode(MathML::AST::INode * node)285 	bool FormulasLoader::appendNewNode( MathML::AST::INode* node )
286 	{
287 		if ( node )
288 		{
289 			if ( mNodeListStack.empty() )
290 				mCurrentFormula->getMathmlAsts().append( node );
291 			else
292 				mNodeListStack.top().push_back( node );
293 		}
294 		else
295 		{
296 			// TODO error handling
297 		}
298 		return true;
299 	}
300 
301 	//-----------------------------------------------------------------
createUnaryOperation(const NodeVector & nodes,Operator op)302 	MathML::AST::INode* FormulasLoader::createUnaryOperation( const NodeVector& nodes, Operator op )
303 	{
304 		MathML::AST::UnaryExpression::Operator mmlOp;
305 		switch ( op )
306 		{
307 		case ADD:
308 			mmlOp = MathML::AST::UnaryExpression::ADD;
309 			break;
310 		case SUB:
311 			mmlOp = MathML::AST::UnaryExpression::SUB;
312 			break;
313 		case NOT:
314 			mmlOp = MathML::AST::UnaryExpression::NOT;
315 			break;
316 		default:
317 			// invalid operator
318 			return 0;
319 		}
320 
321 		MathML::AST::UnaryExpression* expression = new MathML::AST::UnaryExpression();
322 		expression->setOperator( mmlOp );
323 		expression->setOperand( nodes[ 0 ] );
324 
325 		return expression;
326 	}
327 
328 	//-----------------------------------------------------------------
createMultiOperandOperation(const NodeVector & nodes,Operator op)329 	MathML::AST::INode* FormulasLoader::createMultiOperandOperation( const NodeVector& nodes, Operator op )
330 	{
331 		MathML::AST::INode* node;
332 		switch ( op )
333 		{
334 		case ADD:
335 		case SUB:
336 		case MUL:
337 		case DIV:
338 			node = createArithmeticOperation( nodes, op );
339 			break;
340 		case AND:
341 		case OR:
342 		case XOR:
343 			node = createLogicOperation( nodes, op );
344 			break;
345 		case EQ:
346 		case NEQ:
347 		case LT:
348 		case LTE:
349 		case GT:
350 		case GTE:
351 			node = createBinaryComparisonOperation( nodes, op );
352 			break;
353 		default:
354 			// invalid operator
355 			node = 0;
356 		}
357 
358 		return node;
359 	}
360 
361 	//-----------------------------------------------------------------
createArithmeticOperation(const NodeVector & nodes,Operator op)362 	MathML::AST::INode* FormulasLoader::createArithmeticOperation( const NodeVector& nodes, Operator op )
363 	{
364 		MathML::AST::ArithmeticExpression::Operator mmlOp;
365 		switch ( op )
366 		{
367 		case ADD:
368 			mmlOp = MathML::AST::ArithmeticExpression::ADD;
369 			break;
370 		case SUB:
371 			mmlOp = MathML::AST::ArithmeticExpression::SUB;
372 			break;
373 		case MUL:
374 			mmlOp = MathML::AST::ArithmeticExpression::MUL;
375 			break;
376 		case DIV:
377 			mmlOp = MathML::AST::ArithmeticExpression::DIV;
378 			break;
379 		default:
380 			// invalid operator
381 			return 0;
382 		}
383 
384 		MathML::AST::ArithmeticExpression* expression = new MathML::AST::ArithmeticExpression();
385 		expression->setOperator( mmlOp );
386 		for (size_t i=0; i<nodes.size(); ++i)
387 		{
388 			expression->addOperand( nodes[ i ] );
389 		}
390 
391 		return expression;
392 	}
393 
394 	//-----------------------------------------------------------------
createLogicOperation(const NodeVector & nodes,Operator op)395 	MathML::AST::INode* FormulasLoader::createLogicOperation( const NodeVector& nodes, Operator op )
396 	{
397 		MathML::AST::LogicExpression::Operator mmlOp;
398 		switch ( op )
399 		{
400 		case AND:
401 			mmlOp = MathML::AST::LogicExpression::AND;
402 			break;
403 		case OR:
404 			mmlOp = MathML::AST::LogicExpression::OR;
405 			break;
406 		case XOR:
407 			mmlOp = MathML::AST::LogicExpression::XOR;
408 			break;
409 		default:
410 			// invalid operator
411 			return 0;
412 		}
413 
414 		MathML::AST::LogicExpression* expression = new MathML::AST::LogicExpression();
415 		expression->setOperator( mmlOp );
416 		for (size_t i=0; i<nodes.size(); ++i)
417 		{
418 			expression->addOperand( nodes[ i ] );
419 		}
420 
421 		return expression;
422 	}
423 
424 	//-----------------------------------------------------------------
createBinaryComparisonOperation(const NodeVector & nodes,Operator op)425 	MathML::AST::INode* FormulasLoader::createBinaryComparisonOperation( const NodeVector& nodes, Operator op )
426 	{
427 		if ( nodes.size() != 2 )
428 		{
429 			// TODO error handling
430 			return 0;
431 		}
432 
433 		MathML::AST::BinaryComparisonExpression::Operator mmlOp;
434 		switch ( op )
435 		{
436 		case EQ:
437 			mmlOp = MathML::AST::BinaryComparisonExpression::EQ;
438 			break;
439 		case NEQ:
440 			mmlOp = MathML::AST::BinaryComparisonExpression::NEQ;
441 			break;
442 		case LT:
443 			mmlOp = MathML::AST::BinaryComparisonExpression::LT;
444 			break;
445 		case LTE:
446 			mmlOp = MathML::AST::BinaryComparisonExpression::LTE;
447 			break;
448 		case GT:
449 			mmlOp = MathML::AST::BinaryComparisonExpression::GT;
450 			break;
451 		case GTE:
452 			mmlOp = MathML::AST::BinaryComparisonExpression::GTE;
453 			break;
454 		default:
455 			// invalid operator
456 			return 0;
457 		}
458 
459 		MathML::AST::BinaryComparisonExpression* expression = new MathML::AST::BinaryComparisonExpression();
460 		expression->setOperator( mmlOp );
461 		expression->setLeftOperand( nodes[ 0 ] );
462 		expression->setRightOperand( nodes[ 1 ] );
463 
464 		return expression;
465 	}
466 
467 	//-----------------------------------------------------------------
createFunctionOperation(const NodeVector & nodes,Operator op)468 	MathML::AST::INode* FormulasLoader::createFunctionOperation( const NodeVector& nodes, Operator op )
469 	{
470 		const MathML::String* functionName;
471 		switch ( op )
472 		{
473 		case POW:
474 			functionName = &MathML::FUNCTION_POW;
475 			break;
476 		case FACTORIAL:
477 			functionName = &MathML::FUNCTION_FACTORIAL;
478 			break;
479 		case ABS:
480 			functionName = &MathML::FUNCTION_ABS;
481 			break;
482 		case EXP:
483 			functionName = &MathML::FUNCTION_EXP;
484 			break;
485 		case LN:
486 			functionName = &MathML::FUNCTION_LOGN;
487 			break;
488 		case MIN:
489 			functionName = &MathML::FUNCTION_MIN;
490 			break;
491 		case MAX:
492 			functionName = &MathML::FUNCTION_MAX;
493 			break;
494 		case CEIL:
495 			functionName = &MathML::FUNCTION_CEILING;
496 			break;
497 		case FLOOR:
498 			functionName = &MathML::FUNCTION_FLOOR;
499 			break;
500 		case GCD:
501 			functionName = &MathML::FUNCTION_GCD;
502 			break;
503 		case LCM:
504 			functionName = &MathML::FUNCTION_LCM;
505 			break;
506 		case REM:
507 			functionName = &MathML::FUNCTION_REM;
508 			break;
509 		case ROOT:
510 			functionName = &MathML::FUNCTION_ROOT;
511 			break;
512 		case LOG:
513 			functionName = &MathML::FUNCTION_LOG;
514 			break;
515 		case SIN:
516 			functionName = &MathML::FUNCTION_SIN;
517 			break;
518 		case COS:
519 			functionName = &MathML::FUNCTION_COS;
520 			break;
521 		case TAN:
522 			functionName = &MathML::FUNCTION_TAN;
523 			break;
524 		case SEC:
525 			functionName = &MathML::FUNCTION_SEC;
526 			break;
527 		case CSC:
528 			functionName = &MathML::FUNCTION_CSC;
529 			break;
530 		case COT:
531 			functionName = &MathML::FUNCTION_COT;
532 			break;
533 		case ARCSIN:
534 			functionName = &MathML::FUNCTION_ARCSIN;
535 			break;
536 		case ARCCOS:
537 			functionName = &MathML::FUNCTION_ARCCOS;
538 			break;
539 		case ARCTAN:
540 			functionName = &MathML::FUNCTION_ARCTAN;
541 			break;
542 		case ARCSEC:
543 			functionName = &MathML::FUNCTION_ARCSEC;
544 			break;
545 		case ARCCSC:
546 			functionName = &MathML::FUNCTION_ARCCSC;
547 			break;
548 		case ARCCOT:
549 			functionName = &MathML::FUNCTION_ARCCOT;
550 			break;
551 		case SINH:
552 			functionName = &MathML::FUNCTION_SINH;
553 			break;
554 		case COSH:
555 			functionName = &MathML::FUNCTION_COSH;
556 			break;
557 		case TANH:
558 			functionName = &MathML::FUNCTION_TANH;
559 			break;
560 		case SECH:
561 			functionName = &MathML::FUNCTION_SECH;
562 			break;
563 		case CSCH:
564 			functionName = &MathML::FUNCTION_CSCH;
565 			break;
566 		case COTH:
567 			functionName = &MathML::FUNCTION_COTH;
568 			break;
569 		case ARCSINH:
570 			functionName = &MathML::FUNCTION_ARCSINH;
571 			break;
572 		case ARCCOSH:
573 			functionName = &MathML::FUNCTION_ARCCOSH;
574 			break;
575 		case ARCTANH:
576 			functionName = &MathML::FUNCTION_ARCTANH;
577 			break;
578 		case ARCCOTH:
579 			functionName = &MathML::FUNCTION_ARCCOTH;
580 			break;
581 		case ARCSECH:
582 			functionName = &MathML::FUNCTION_ARCSECH;
583 			break;
584 		case ARCCSCH:
585 			functionName = &MathML::FUNCTION_ARCCSCH;
586 			break;
587 		default:
588 			// invalid operator
589 			return 0;
590 		}
591 
592 		MathML::AST::FunctionExpression* expression = new MathML::AST::FunctionExpression( *functionName );
593 		expression->setParameterList( nodes );
594 
595 		return expression;
596 	}
597 
598 
599 	//-----------------------------------------------------------------
createUserDefinedFunctionOperation(const NodeVector & nodes)600 	MathML::AST::INode* FormulasLoader::createUserDefinedFunctionOperation( const NodeVector& nodes )
601 	{
602 		COLLADABU_ASSERT(!nodes.empty());
603 		MathML::AST::INode* firstNode = nodes.front();
604 
605 		COLLADABU_ASSERT( firstNode->getNodeType() == MathML::AST::INode::USERDEFINED);
606 		COLLADACsymbol* csymbol = (COLLADACsymbol*)firstNode;
607 		size_t nodesCount = nodes.size();
608 		if ( nodesCount > 1)
609 		{
610 			//we have parameters. copy them into csymbol
611 			COLLADACsymbol::ParameterList& parameterList = csymbol->getParameterList();
612 			parameterList.reserve( nodesCount - 1 );
613 			NodeVector::const_iterator it = nodes.begin() + 1;
614 			for ( ; it != nodes.end(); ++it)
615 			{
616 				parameterList.push_back(*it);
617 			}
618 		}
619 
620 		return csymbol;
621 	}
622 
623 	//-----------------------------------------------------------------
isFunction(Operator op)624 	bool FormulasLoader::isFunction( Operator op )
625 	{
626 		switch ( op )
627 		{
628 		case POW:
629 		case FACTORIAL:
630 		case ABS:
631 		case EXP:
632 		case LN:
633 		case MIN:
634 		case MAX:
635 		case CEIL:
636 		case FLOOR:
637 		case GCD:
638 		case LCM:
639 		case REM:
640 		case ROOT:
641 		case LOG:
642 		case SIN:
643 		case COS:
644 		case TAN:
645 		case SEC:
646 		case CSC:
647 		case COT:
648 		case ARCSIN:
649 		case ARCCOS:
650 		case ARCTAN:
651 		case ARCSEC:
652 		case ARCCSC:
653 		case ARCCOT:
654 		case SINH:
655 		case COSH:
656 		case TANH:
657 		case SECH:
658 		case CSCH:
659 		case COTH:
660 		case ARCSINH:
661 		case ARCCOSH:
662 		case ARCTANH:
663 		case ARCCOTH:
664 		case ARCSECH:
665 		case ARCCSCH:
666 			return true;
667 		default:
668 			return false;
669 		}
670 	}
671 
672 	//-----------------------------------------------------------------
begin__quotient(const quotient__AttributeData & attributeData)673 	bool FormulasLoader::begin__quotient( const quotient__AttributeData& attributeData )
674 	{
675 		mCurrentApplyHasChild = true;
676 		mOperatorStack.push( DIV );
677 		return true;
678 	}
679 
680 	//-----------------------------------------------------------------
begin__divide(const divide__AttributeData & attributeData)681 	bool FormulasLoader::begin__divide( const divide__AttributeData& attributeData )
682 	{
683 		mCurrentApplyHasChild = true;
684 		mOperatorStack.push( DIV );
685 		return true;
686 	}
687 
688 	//-----------------------------------------------------------------
begin__minus(const minus__AttributeData & attributeData)689 	bool FormulasLoader::begin__minus( const minus__AttributeData& attributeData )
690 	{
691 		mCurrentApplyHasChild = true;
692 		mOperatorStack.push( SUB );
693 		return true;
694 	}
695 
696 	//-----------------------------------------------------------------
begin__plus(const plus__AttributeData & attributeData)697 	bool FormulasLoader::begin__plus( const plus__AttributeData& attributeData )
698 	{
699 		mCurrentApplyHasChild = true;
700 		mOperatorStack.push( ADD );
701 		return true;
702 	}
703 
704 	//-----------------------------------------------------------------
begin__times(const times__AttributeData & attributeData)705 	bool FormulasLoader::begin__times( const times__AttributeData& attributeData )
706 	{
707 		mCurrentApplyHasChild = true;
708 		mOperatorStack.push( MUL );
709 		return true;
710 	}
711 
712 	//-----------------------------------------------------------------
begin__sum(const sum__AttributeData & attributeData)713 	bool FormulasLoader::begin__sum( const sum__AttributeData& attributeData )
714 	{
715 		mCurrentApplyHasChild = true;
716 		mOperatorStack.push( ADD );
717 		return true;
718 	}
719 
720 	//-----------------------------------------------------------------
begin__product(const product__AttributeData & attributeData)721 	bool FormulasLoader::begin__product( const product__AttributeData& attributeData )
722 	{
723 		mCurrentApplyHasChild = true;
724 		mOperatorStack.push( MUL );
725 		return true;
726 	}
727 
728 	//-----------------------------------------------------------------
begin__cn(const cn__AttributeData & attributeData)729 	bool FormulasLoader::begin__cn( const cn__AttributeData& attributeData )
730 	{
731 		mCurrentApplyHasChild = true;
732 		return true;
733 	}
734 
735 	//-----------------------------------------------------------------
end__cn()736 	bool FormulasLoader::end__cn()
737 	{
738 		MathML::AST::INode* node;
739 
740 		if ( mSepOccurred )
741 		{
742 			// TODO support for other types than rational
743 			MathML::AST::ConstantExpression* constant1 = createConstant( mCurrentTextData );
744 			MathML::AST::ConstantExpression* constant2 = createConstant( mCurrentTextDataAfterSep );
745 			MathML::AST::ArithmeticExpression* expression = new MathML::AST::ArithmeticExpression();
746 			expression->setOperator( MathML::AST::ArithmeticExpression::DIV );
747 			expression->addOperand( constant1 );
748 			expression->addOperand( constant2 );
749 			node = expression;
750 		}
751 		else
752 		{
753 			MathML::AST::ConstantExpression* constant = createConstant( mCurrentTextData );
754 			node = constant;
755 		}
756 
757 		mNodeListStack.top().push_back( node );
758 		mSepOccurred = false;
759 		mCurrentTextDataAfterSep.clear();
760 		mCurrentTextData.clear();
761 
762 		return true;
763 	}
764 
765 	//-----------------------------------------------------------------
data__cn(const ParserChar * value,size_t length)766 	bool FormulasLoader::data__cn( const ParserChar* value, size_t length )
767 	{
768 		if ( mSepOccurred )
769 		{
770 			mCurrentTextDataAfterSep.append( value, length );
771 		}
772 		else
773 		{
774 			mCurrentTextData.append( value, length );
775 		}
776 		return true;
777 	}
778 
779 	//-----------------------------------------------------------------
createConstant(const String & value)780 	MathML::AST::ConstantExpression* FormulasLoader::createConstant( const String& value )
781 	{
782 		MathML::AST::ConstantExpression* constant = FW_NEW MathML::AST::ConstantExpression( value );
783 
784 		bool failed = false;
785 		double doubleValue = GeneratedSaxParser::Utils::toDouble( value.c_str(), failed );
786 		if ( !failed )
787 		{
788 			constant->setValue( doubleValue );
789 		}
790 		else
791 		{
792 			bool boolValue = GeneratedSaxParser::Utils::toBool( value.c_str(), failed );
793 			if ( !failed )
794 			{
795 				constant->setValue( boolValue );
796 			}
797 		}
798 
799 		return constant;
800 	}
801 
802 	//-----------------------------------------------------------------
begin__ci(const ci__AttributeData & attributeData)803 	bool FormulasLoader::begin__ci( const ci__AttributeData& attributeData )
804 	{
805 		mCurrentApplyHasChild = true;
806 		return true;
807 	}
808 
809 	//-----------------------------------------------------------------
end__ci()810 	bool FormulasLoader::end__ci()
811 	{
812 		MathML::AST::VariableExpression* variable = FW_NEW MathML::AST::VariableExpression( mCurrentTextData );
813 		mCurrentTextData.clear();
814 		mNodeListStack.top().push_back( variable );
815 
816 		return true;
817 	}
818 
819 	//-----------------------------------------------------------------
data__ci(const ParserChar * value,size_t length)820 	bool FormulasLoader::data__ci( const ParserChar* value, size_t length )
821 	{
822 		mCurrentTextData.append( value, length );
823 		return true;
824 	}
825 
826 	//-----------------------------------------------------------------
begin__csymbol(const csymbol__AttributeData & attributeData)827 	bool FormulasLoader::begin__csymbol( const csymbol__AttributeData& attributeData )
828 	{
829 		if ( !mCurrentApplyHasChild )
830 		{
831 			// The csymbol appears as first child of apply. I must be a user defined function.
832 			mOperatorStack.push(USER_DEFINED_FUNCTION);
833 			mCurrentCSymbolIsFunction = true;
834 			if (attributeData.definitionURL)
835 			{
836 				mCurrentCSymbolFunctionUniqueId = getHandlingFilePartLoader()->createUniqueIdFromUrl(attributeData.definitionURL, COLLADAFW::Formula::ID());
837 			}
838 		}
839 		mCurrentApplyHasChild = true;
840 		return true;
841 	}
842 
843 	//-----------------------------------------------------------------
end__csymbol()844 	bool FormulasLoader::end__csymbol()
845 	{
846 		COLLADACsymbol* csymbol = 0;
847 		if ( mCurrentCSymbolIsFunction )
848 		{
849 			csymbol = FW_NEW COLLADACsymbol( mCurrentTextData, mCurrentCSymbolFunctionUniqueId );
850 		}
851 		else
852 		{
853 			csymbol = FW_NEW COLLADACsymbol( mCurrentTextData);
854 		}
855 		mCurrentTextData.clear();
856 		mNodeListStack.top().push_back( csymbol );
857 		mCurrentCSymbolIsFunction = false;
858 		mCurrentCSymbolFunctionUniqueId = COLLADAFW::UniqueId::INVALID;
859 		return true;
860 	}
861 
862 	//-----------------------------------------------------------------
data__csymbol(const ParserChar * value,size_t length)863 	bool FormulasLoader::data__csymbol( const ParserChar* value, size_t length )
864 	{
865 		mCurrentTextData.append( value, length );
866 		return true;
867 	}
868 
869 	//-----------------------------------------------------------------
begin__exponentiale(const exponentiale__AttributeData & attributeData)870 	bool FormulasLoader::begin__exponentiale( const exponentiale__AttributeData& attributeData )
871 	{
872 		mCurrentApplyHasChild = true;
873 		MathML::AST::ConstantExpression* constant = FW_NEW MathML::AST::ConstantExpression( MathML::EULERS_NUMBER );
874 		mNodeListStack.top().push_back( constant );
875 
876 		return true;
877 	}
878 
879 	//-----------------------------------------------------------------
begin__pi(const pi__AttributeData & attributeData)880 	bool FormulasLoader::begin__pi( const pi__AttributeData& attributeData )
881 	{
882 		mCurrentApplyHasChild = true;
883 		MathML::AST::ConstantExpression* constant = FW_NEW MathML::AST::ConstantExpression( MathML::PI_NUMBER );
884 		mNodeListStack.top().push_back( constant );
885 
886 		return true;
887 	}
888 
889 	//-----------------------------------------------------------------
begin__true(const true__AttributeData & attributeData)890 	bool FormulasLoader::begin__true( const true__AttributeData& attributeData )
891 	{
892 		mCurrentApplyHasChild = true;
893 		MathML::AST::ConstantExpression* constant = FW_NEW MathML::AST::ConstantExpression( true );
894 		mNodeListStack.top().push_back( constant );
895 
896 		return true;
897 	}
898 
899 	//-----------------------------------------------------------------
begin__false(const false__AttributeData & attributeData)900 	bool FormulasLoader::begin__false( const false__AttributeData& attributeData )
901 	{
902 		mCurrentApplyHasChild = true;
903 		MathML::AST::ConstantExpression* constant = FW_NEW MathML::AST::ConstantExpression( false );
904 		mNodeListStack.top().push_back( constant );
905 
906 		return true;
907 	}
908 
909 	//-----------------------------------------------------------------
begin__and(const and__AttributeData & attributeData)910 	bool FormulasLoader::begin__and( const and__AttributeData& attributeData )
911 	{
912 		mCurrentApplyHasChild = true;
913 		mOperatorStack.push( AND);
914 		return true;
915 	}
916 
917 	//-----------------------------------------------------------------
begin__or(const or__AttributeData & attributeData)918 	bool FormulasLoader::begin__or( const or__AttributeData& attributeData )
919 	{
920 		mCurrentApplyHasChild = true;
921 		mOperatorStack.push( OR );
922 		return true;
923 	}
924 
925 	//-----------------------------------------------------------------
begin__xor(const xor__AttributeData & attributeData)926 	bool FormulasLoader::begin__xor( const xor__AttributeData& attributeData )
927 	{
928 		mCurrentApplyHasChild = true;
929 		mOperatorStack.push( XOR );
930 		return true;
931 	}
932 
933 	//-----------------------------------------------------------------
begin__not(const not__AttributeData & attributeData)934 	bool FormulasLoader::begin__not( const not__AttributeData& attributeData )
935 	{
936 		mCurrentApplyHasChild = true;
937 		mOperatorStack.push( NOT );
938 		return true;
939 	}
940 
941 	//-----------------------------------------------------------------
begin__eq(const eq__AttributeData & attributeData)942 	bool FormulasLoader::begin__eq( const eq__AttributeData& attributeData )
943 	{
944 		mCurrentApplyHasChild = true;
945 		mOperatorStack.push( EQ );
946 		return true;
947 	}
948 
949 	//-----------------------------------------------------------------
begin__neq(const neq__AttributeData & attributeData)950 	bool FormulasLoader::begin__neq( const neq__AttributeData& attributeData )
951 	{
952 		mCurrentApplyHasChild = true;
953 		mOperatorStack.push( NEQ );
954 		return true;
955 	}
956 
957 	//-----------------------------------------------------------------
begin__leq(const leq__AttributeData & attributeData)958 	bool FormulasLoader::begin__leq( const leq__AttributeData& attributeData )
959 	{
960 		mCurrentApplyHasChild = true;
961 		mOperatorStack.push( LTE );
962 		return true;
963 	}
964 
965 	//-----------------------------------------------------------------
begin__lt(const lt__AttributeData & attributeData)966 	bool FormulasLoader::begin__lt( const lt__AttributeData& attributeData )
967 	{
968 		mCurrentApplyHasChild = true;
969 		mOperatorStack.push( LT );
970 		return true;
971 	}
972 
973 	//-----------------------------------------------------------------
begin__geq(const geq__AttributeData & attributeData)974 	bool FormulasLoader::begin__geq( const geq__AttributeData& attributeData )
975 	{
976 		mCurrentApplyHasChild = true;
977 		mOperatorStack.push( GTE );
978 		return true;
979 	}
980 
981 	//-----------------------------------------------------------------
begin__gt(const gt__AttributeData & attributeData)982 	bool FormulasLoader::begin__gt( const gt__AttributeData& attributeData )
983 	{
984 		mCurrentApplyHasChild = true;
985 		mOperatorStack.push( GT );
986 		return true;
987 	}
988 
989 	//-----------------------------------------------------------------
begin__equivalent(const equivalent__AttributeData & attributeData)990 	bool FormulasLoader::begin__equivalent( const equivalent__AttributeData& attributeData )
991 	{
992 		mCurrentApplyHasChild = true;
993 		mOperatorStack.push( EQ );
994 		return true;
995 	}
996 
997 	//-----------------------------------------------------------------
begin__abs(const abs__AttributeData & attributeData)998 	bool FormulasLoader::begin__abs( const abs__AttributeData& attributeData )
999 	{
1000 		mCurrentApplyHasChild = true;
1001 		mOperatorStack.push( ABS );
1002 		return true;
1003 	}
1004 
1005 	//-----------------------------------------------------------------
begin__factorial(const factorial__AttributeData & attributeData)1006 	bool FormulasLoader::begin__factorial( const factorial__AttributeData& attributeData )
1007 	{
1008 		mCurrentApplyHasChild = true;
1009 		mOperatorStack.push( FACTORIAL );
1010 		return true;
1011 	}
1012 
1013 	//-----------------------------------------------------------------
begin__floor(const floor__AttributeData & attributeData)1014 	bool FormulasLoader::begin__floor( const floor__AttributeData& attributeData )
1015 	{
1016 		mCurrentApplyHasChild = true;
1017 		mOperatorStack.push( FLOOR );
1018 		return true;
1019 	}
1020 
1021 	//-----------------------------------------------------------------
begin__ceiling(const ceiling__AttributeData & attributeData)1022 	bool FormulasLoader::begin__ceiling( const ceiling__AttributeData& attributeData )
1023 	{
1024 		mCurrentApplyHasChild = true;
1025 		mOperatorStack.push( CEIL );
1026 		return true;
1027 	}
1028 
1029 	//-----------------------------------------------------------------
begin__rem(const rem__AttributeData & attributeData)1030 	bool FormulasLoader::begin__rem( const rem__AttributeData& attributeData )
1031 	{
1032 		mCurrentApplyHasChild = true;
1033 		mOperatorStack.push( REM );
1034 		return true;
1035 	}
1036 
1037 	//-----------------------------------------------------------------
begin__power(const power__AttributeData & attributeData)1038 	bool FormulasLoader::begin__power( const power__AttributeData& attributeData )
1039 	{
1040 		mCurrentApplyHasChild = true;
1041 		mOperatorStack.push( POW );
1042 		return true;
1043 	}
1044 
1045 	//-----------------------------------------------------------------
begin__root(const root__AttributeData & attributeData)1046 	bool FormulasLoader::begin__root( const root__AttributeData& attributeData )
1047 	{
1048 		mCurrentApplyHasChild = true;
1049 		mOperatorStack.push( ROOT );
1050 		return true;
1051 	}
1052 
1053 	//-----------------------------------------------------------------
begin__max(const max__AttributeData & attributeData)1054 	bool FormulasLoader::begin__max( const max__AttributeData& attributeData )
1055 	{
1056 		mCurrentApplyHasChild = true;
1057 		mOperatorStack.push( MAX );
1058 		return true;
1059 	}
1060 
1061 	//-----------------------------------------------------------------
begin__min(const min__AttributeData & attributeData)1062 	bool FormulasLoader::begin__min( const min__AttributeData& attributeData )
1063 	{
1064 		mCurrentApplyHasChild = true;
1065 		mOperatorStack.push( MIN );
1066 		return true;
1067 	}
1068 
1069 	//-----------------------------------------------------------------
begin__gcd(const gcd__AttributeData & attributeData)1070 	bool FormulasLoader::begin__gcd( const gcd__AttributeData& attributeData )
1071 	{
1072 		mCurrentApplyHasChild = true;
1073 		mOperatorStack.push( GCD );
1074 		return true;
1075 	}
1076 
1077 	//-----------------------------------------------------------------
begin__lcm(const lcm__AttributeData & attributeData)1078 	bool FormulasLoader::begin__lcm( const lcm__AttributeData& attributeData )
1079 	{
1080 		mCurrentApplyHasChild = true;
1081 		mOperatorStack.push( LCM );
1082 		return true;
1083 	}
1084 
1085 	//-----------------------------------------------------------------
begin__exp(const exp__AttributeData & attributeData)1086 	bool FormulasLoader::begin__exp( const exp__AttributeData& attributeData )
1087 	{
1088 		mCurrentApplyHasChild = true;
1089 		mOperatorStack.push( EXP );
1090 		return true;
1091 	}
1092 
1093 	//-----------------------------------------------------------------
begin__ln(const ln__AttributeData & attributeData)1094 	bool FormulasLoader::begin__ln( const ln__AttributeData& attributeData )
1095 	{
1096 		mCurrentApplyHasChild = true;
1097 		mOperatorStack.push( LN );
1098 		return true;
1099 	}
1100 
1101 	//-----------------------------------------------------------------
begin__log(const log__AttributeData & attributeData)1102 	bool FormulasLoader::begin__log( const log__AttributeData& attributeData )
1103 	{
1104 		mCurrentApplyHasChild = true;
1105 		mOperatorStack.push( LOG );
1106 		return true;
1107 	}
1108 
1109 	//-----------------------------------------------------------------
begin__logbase(const logbase__AttributeData & attributeData)1110 	bool FormulasLoader::begin__logbase( const logbase__AttributeData& attributeData )
1111 	{
1112 		mCurrentApplyHasChild = true;
1113 		NodeVector newArray;
1114 		mNodeListStack.push( newArray );
1115 		return true;
1116 	}
1117 
1118 	//-----------------------------------------------------------------
end__logbase()1119 	bool FormulasLoader::end__logbase()
1120 	{
1121 		if ( mNodeListStack.empty() )
1122 		{
1123 			// TODO error handling
1124 			return false;
1125 		}
1126 
1127 		NodeVector nodes = mNodeListStack.top();
1128 		mNodeListStack.pop();
1129 		size_t numOfNodes = nodes.size();
1130 
1131 		if ( numOfNodes == 0 )
1132 		{
1133 			// TODO error handling
1134 			return false;
1135 		}
1136 
1137 		appendNewNode( nodes[ 0 ] );
1138 
1139 		return true;
1140 	}
1141 
1142 	//-----------------------------------------------------------------
begin__sin(const sin__AttributeData & attributeData)1143 	bool FormulasLoader::begin__sin( const sin__AttributeData& attributeData )
1144 	{
1145 		mCurrentApplyHasChild = true;
1146 		mOperatorStack.push( SIN );
1147 		return true;
1148 	}
1149 
1150 	//-----------------------------------------------------------------
begin__cos(const cos__AttributeData & attributeData)1151 	bool FormulasLoader::begin__cos( const cos__AttributeData& attributeData )
1152 	{
1153 		mCurrentApplyHasChild = true;
1154 		mOperatorStack.push( COS );
1155 		return true;
1156 	}
1157 
1158 	//-----------------------------------------------------------------
begin__tan(const tan__AttributeData & attributeData)1159 	bool FormulasLoader::begin__tan( const tan__AttributeData& attributeData )
1160 	{
1161 		mCurrentApplyHasChild = true;
1162 		mOperatorStack.push( TAN );
1163 		return true;
1164 	}
1165 
1166 	//-----------------------------------------------------------------
begin__sec(const sec__AttributeData & attributeData)1167 	bool FormulasLoader::begin__sec( const sec__AttributeData& attributeData )
1168 	{
1169 		mCurrentApplyHasChild = true;
1170 		mOperatorStack.push( SEC );
1171 		return true;
1172 	}
1173 
1174 	//-----------------------------------------------------------------
begin__csc(const csc__AttributeData & attributeData)1175 	bool FormulasLoader::begin__csc( const csc__AttributeData& attributeData )
1176 	{
1177 		mCurrentApplyHasChild = true;
1178 		mOperatorStack.push( CSC );
1179 		return true;
1180 	}
1181 
1182 	//-----------------------------------------------------------------
begin__cot(const cot__AttributeData & attributeData)1183 	bool FormulasLoader::begin__cot( const cot__AttributeData& attributeData )
1184 	{
1185 		mCurrentApplyHasChild = true;
1186 		mOperatorStack.push( COT );
1187 		return true;
1188 	}
1189 
1190 	//-----------------------------------------------------------------
begin__arcsin(const arcsin__AttributeData & attributeData)1191 	bool FormulasLoader::begin__arcsin( const arcsin__AttributeData& attributeData )
1192 	{
1193 		mCurrentApplyHasChild = true;
1194 		mOperatorStack.push( ARCSIN );
1195 		return true;
1196 	}
1197 
1198 	//-----------------------------------------------------------------
begin__arccos(const arccos__AttributeData & attributeData)1199 	bool FormulasLoader::begin__arccos( const arccos__AttributeData& attributeData )
1200 	{
1201 		mCurrentApplyHasChild = true;
1202 		mOperatorStack.push( ARCCOS );
1203 		return true;
1204 	}
1205 
1206 	//-----------------------------------------------------------------
begin__arctan(const arctan__AttributeData & attributeData)1207 	bool FormulasLoader::begin__arctan( const arctan__AttributeData& attributeData )
1208 	{
1209 		mCurrentApplyHasChild = true;
1210 		mOperatorStack.push( ARCTAN );
1211 		return true;
1212 	}
1213 
1214 	//-----------------------------------------------------------------
begin__arcsec(const arcsec__AttributeData & attributeData)1215 	bool FormulasLoader::begin__arcsec( const arcsec__AttributeData& attributeData )
1216 	{
1217 		mCurrentApplyHasChild = true;
1218 		mOperatorStack.push( ARCSEC );
1219 		return true;
1220 	}
1221 
1222 	//-----------------------------------------------------------------
begin__arccsc(const arccsc__AttributeData & attributeData)1223 	bool FormulasLoader::begin__arccsc( const arccsc__AttributeData& attributeData )
1224 	{
1225 		mCurrentApplyHasChild = true;
1226 		mOperatorStack.push( ARCCSC );
1227 		return true;
1228 	}
1229 
1230 	//-----------------------------------------------------------------
begin__arccot(const arccot__AttributeData & attributeData)1231 	bool FormulasLoader::begin__arccot( const arccot__AttributeData& attributeData )
1232 	{
1233 		mCurrentApplyHasChild = true;
1234 		mOperatorStack.push( ARCCOT );
1235 		return true;
1236 	}
1237 
1238 	//-----------------------------------------------------------------
begin__sinh(const sinh__AttributeData & attributeData)1239 	bool FormulasLoader::begin__sinh( const sinh__AttributeData& attributeData )
1240 	{
1241 		mCurrentApplyHasChild = true;
1242 		mOperatorStack.push( SINH );
1243 		return true;
1244 	}
1245 
1246 	//-----------------------------------------------------------------
begin__cosh(const cosh__AttributeData & attributeData)1247 	bool FormulasLoader::begin__cosh( const cosh__AttributeData& attributeData )
1248 	{
1249 		mCurrentApplyHasChild = true;
1250 		mOperatorStack.push( COSH );
1251 		return true;
1252 	}
1253 
1254 	//-----------------------------------------------------------------
begin__tanh(const tanh__AttributeData & attributeData)1255 	bool FormulasLoader::begin__tanh( const tanh__AttributeData& attributeData )
1256 	{
1257 		mCurrentApplyHasChild = true;
1258 		mOperatorStack.push( TANH );
1259 		return true;
1260 	}
1261 
1262 	//-----------------------------------------------------------------
begin__sech(const sech__AttributeData & attributeData)1263 	bool FormulasLoader::begin__sech( const sech__AttributeData& attributeData )
1264 	{
1265 		mCurrentApplyHasChild = true;
1266 		mOperatorStack.push( SECH );
1267 		return true;
1268 	}
1269 
1270 	//-----------------------------------------------------------------
begin__csch(const csch__AttributeData & attributeData)1271 	bool FormulasLoader::begin__csch( const csch__AttributeData& attributeData )
1272 	{
1273 		mCurrentApplyHasChild = true;
1274 		mOperatorStack.push( CSCH );
1275 		return true;
1276 	}
1277 
1278 	//-----------------------------------------------------------------
begin__coth(const coth__AttributeData & attributeData)1279 	bool FormulasLoader::begin__coth( const coth__AttributeData& attributeData )
1280 	{
1281 		mCurrentApplyHasChild = true;
1282 		mOperatorStack.push( COTH );
1283 		return true;
1284 	}
1285 
1286 	//-----------------------------------------------------------------
begin__arccosh(const arccosh__AttributeData & attributeData)1287 	bool FormulasLoader::begin__arccosh( const arccosh__AttributeData& attributeData )
1288 	{
1289 		mCurrentApplyHasChild = true;
1290 		mOperatorStack.push( ARCCOSH );
1291 		return true;
1292 	}
1293 
1294 	//-----------------------------------------------------------------
begin__arccoth(const arccoth__AttributeData & attributeData)1295 	bool FormulasLoader::begin__arccoth( const arccoth__AttributeData& attributeData )
1296 	{
1297 		mCurrentApplyHasChild = true;
1298 		mOperatorStack.push( ARCCOTH );
1299 		return true;
1300 	}
1301 
1302 	//-----------------------------------------------------------------
begin__arccsch(const arccsch__AttributeData & attributeData)1303 	bool FormulasLoader::begin__arccsch( const arccsch__AttributeData& attributeData )
1304 	{
1305 		mCurrentApplyHasChild = true;
1306 		mOperatorStack.push( ARCCSCH );
1307 		return true;
1308 	}
1309 
1310 	//-----------------------------------------------------------------
begin__arcsech(const arcsech__AttributeData & attributeData)1311 	bool FormulasLoader::begin__arcsech( const arcsech__AttributeData& attributeData )
1312 	{
1313 		mCurrentApplyHasChild = true;
1314 		mOperatorStack.push( ARCSECH );
1315 		return true;
1316 	}
1317 
1318 	//-----------------------------------------------------------------
begin__arcsinh(const arcsinh__AttributeData & attributeData)1319 	bool FormulasLoader::begin__arcsinh( const arcsinh__AttributeData& attributeData )
1320 	{
1321 		mCurrentApplyHasChild = true;
1322 		mOperatorStack.push( ARCSINH );
1323 		return true;
1324 	}
1325 
1326 	//-----------------------------------------------------------------
begin__arctanh(const arctanh__AttributeData & attributeData)1327 	bool FormulasLoader::begin__arctanh( const arctanh__AttributeData& attributeData )
1328 	{
1329 		mCurrentApplyHasChild = true;
1330 		mOperatorStack.push( ARCTANH );
1331 		return true;
1332 	}
1333 
1334 } // namespace COLLADASaxFWL
1335