Update ooo320-m1
[ooovba.git] / svx / source / customshapes / EnhancedCustomShapeFunctionParser.cxx
blobd9db4812e81e6423e4263082f582304d4129f56e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: EnhancedCustomShapeFunctionParser.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include "EnhancedCustomShapeFunctionParser.hxx"
34 #include "EnhancedCustomShape2d.hxx"
35 #include <rtl/ustring.hxx>
36 #include <tools/fract.hxx>
38 // Makes parser a static resource,
39 // we're synchronized externally.
40 // But watch out, the parser might have
41 // state not visible to this code!
42 #define BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
43 #if defined(VERBOSE) && defined(DBG_UTIL)
44 #include <typeinfo>
45 #define BOOST_SPIRIT_DEBUG
46 #endif
47 #include <boost/spirit/include/classic_core.hpp>
49 #if (OSL_DEBUG_LEVEL > 0)
50 #include <iostream>
51 #endif
52 #include <functional>
53 #include <algorithm>
54 #include <stack>
56 #include <math.h> // fabs, sqrt, sin, cos, tan, atan, atan2
57 using namespace EnhancedCustomShape;
58 using namespace com::sun::star;
59 using namespace com::sun::star::drawing;
61 void EnhancedCustomShape::FillEquationParameter( const EnhancedCustomShapeParameter& rSource, const sal_Int32 nDestPara, EnhancedCustomShapeEquation& rDest )
63 sal_Int32 nValue = 0;
64 if ( rSource.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
66 double fValue;
67 if ( rSource.Value >>= fValue )
68 nValue = (sal_Int32)fValue;
70 else
71 rSource.Value >>= nValue;
73 switch( rSource.Type )
75 case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION :
77 if ( nValue & 0x40000000 )
79 nValue ^= 0x40000000;
80 rDest.nOperation |= 0x20000000 << nDestPara; // the bit is indicating that this value has to be adjusted later
82 nValue |= 0x400;
84 break;
85 case com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT : nValue += DFF_Prop_adjustValue; break;
86 case com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM : nValue = DFF_Prop_geoBottom; break;
87 case com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT : nValue = DFF_Prop_geoRight; break;
88 case com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP : nValue = DFF_Prop_geoTop; break;
89 case com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT : nValue = DFF_Prop_geoLeft; break;
91 if ( rSource.Type != com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL )
92 rDest.nOperation |= ( 0x2000 << nDestPara );
93 rDest.nPara[ nDestPara ] = nValue;
96 ExpressionNode::~ExpressionNode()
99 namespace
102 //////////////////////
103 //////////////////////
104 // EXPRESSION NODES
105 //////////////////////
106 //////////////////////
107 class ConstantValueExpression : public ExpressionNode
109 double maValue;
111 public:
113 ConstantValueExpression( double rValue ) :
114 maValue( rValue )
117 virtual double operator()() const
119 return maValue;
121 virtual bool isConstant() const
123 return true;
125 virtual ExpressionFunct getType() const
127 return FUNC_CONST;
129 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /* pOptionalArg */, sal_uInt32 /* nFlags */ )
131 EnhancedCustomShapeParameter aRet;
132 Fraction aFract( maValue );
133 if ( aFract.GetDenominator() == 1 )
135 aRet.Type = EnhancedCustomShapeParameterType::NORMAL;
136 aRet.Value <<= (sal_Int32)aFract.GetNumerator();
138 else
140 EnhancedCustomShapeEquation aEquation;
141 aEquation.nOperation = 1;
142 aEquation.nPara[ 0 ] = 1;
143 aEquation.nPara[ 1 ] = (sal_Int16)aFract.GetNumerator();
144 aEquation.nPara[ 2 ] = (sal_Int16)aFract.GetDenominator();
145 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
146 aRet.Value <<= (sal_Int32)rEquations.size();
147 rEquations.push_back( aEquation );
149 return aRet;
153 class AdjustmentExpression : public ExpressionNode
155 sal_Int32 mnIndex;
156 const EnhancedCustomShape2d& mrCustoShape;
158 public:
160 AdjustmentExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex )
161 : mnIndex ( nIndex )
162 , mrCustoShape( rCustoShape )
166 virtual double operator()() const
168 return mrCustoShape.GetAdjustValueAsDouble( mnIndex );
170 virtual bool isConstant() const
172 return false;
174 virtual ExpressionFunct getType() const
176 return ENUM_FUNC_ADJUSTMENT;
178 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ )
180 EnhancedCustomShapeParameter aRet;
181 aRet.Type = EnhancedCustomShapeParameterType::ADJUSTMENT;
182 aRet.Value <<= mnIndex;
183 return aRet;
187 class EquationExpression : public ExpressionNode
189 sal_Int32 mnIndex;
190 const EnhancedCustomShape2d& mrCustoShape;
192 public:
194 EquationExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex )
195 : mnIndex ( nIndex )
196 , mrCustoShape( rCustoShape )
199 virtual double operator()() const
201 return mrCustoShape.GetEquationValueAsDouble( mnIndex );
203 virtual bool isConstant() const
205 return false;
207 virtual ExpressionFunct getType() const
209 return ENUM_FUNC_EQUATION;
211 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ )
213 EnhancedCustomShapeParameter aRet;
214 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
215 aRet.Value <<= mnIndex | 0x40000000; // the bit is indicating that this equation needs to be adjusted later
216 return aRet;
220 class EnumValueExpression : public ExpressionNode
222 const ExpressionFunct meFunct;
223 const EnhancedCustomShape2d& mrCustoShape;
225 public:
227 EnumValueExpression( const EnhancedCustomShape2d& rCustoShape, const ExpressionFunct eFunct )
228 : meFunct ( eFunct )
229 , mrCustoShape ( rCustoShape )
232 static double getValue( const EnhancedCustomShape2d& rCustoShape, const ExpressionFunct eFunc )
234 EnhancedCustomShape2d::EnumFunc eF;
235 switch( eFunc )
237 case ENUM_FUNC_PI : eF = EnhancedCustomShape2d::ENUM_FUNC_PI; break;
238 case ENUM_FUNC_LEFT : eF = EnhancedCustomShape2d::ENUM_FUNC_LEFT; break;
239 case ENUM_FUNC_TOP : eF = EnhancedCustomShape2d::ENUM_FUNC_TOP; break;
240 case ENUM_FUNC_RIGHT : eF = EnhancedCustomShape2d::ENUM_FUNC_RIGHT; break;
241 case ENUM_FUNC_BOTTOM : eF = EnhancedCustomShape2d::ENUM_FUNC_BOTTOM; break;
242 case ENUM_FUNC_XSTRETCH : eF = EnhancedCustomShape2d::ENUM_FUNC_XSTRETCH; break;
243 case ENUM_FUNC_YSTRETCH : eF = EnhancedCustomShape2d::ENUM_FUNC_YSTRETCH; break;
244 case ENUM_FUNC_HASSTROKE : eF = EnhancedCustomShape2d::ENUM_FUNC_HASSTROKE; break;
245 case ENUM_FUNC_HASFILL : eF = EnhancedCustomShape2d::ENUM_FUNC_HASFILL; break;
246 case ENUM_FUNC_WIDTH : eF = EnhancedCustomShape2d::ENUM_FUNC_WIDTH; break;
247 case ENUM_FUNC_HEIGHT : eF = EnhancedCustomShape2d::ENUM_FUNC_HEIGHT; break;
248 case ENUM_FUNC_LOGWIDTH : eF = EnhancedCustomShape2d::ENUM_FUNC_LOGWIDTH; break;
249 case ENUM_FUNC_LOGHEIGHT : eF = EnhancedCustomShape2d::ENUM_FUNC_LOGHEIGHT; break;
251 default :
252 return 0.0;
254 return rCustoShape.GetEnumFunc( eF );
256 virtual double operator()() const
258 return getValue( mrCustoShape, meFunct );
260 virtual bool isConstant() const
262 return false;
264 virtual ExpressionFunct getType() const
266 return meFunct;
268 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags )
270 EnhancedCustomShapeParameter aRet;
272 sal_Int32 nDummy = 1;
273 aRet.Value <<= nDummy;
275 switch( meFunct )
277 case ENUM_FUNC_WIDTH : // TODO: do not use this as constant value
278 case ENUM_FUNC_HEIGHT :
279 case ENUM_FUNC_LOGWIDTH :
280 case ENUM_FUNC_LOGHEIGHT :
281 case ENUM_FUNC_PI :
283 ConstantValueExpression aConstantValue( getValue( mrCustoShape, meFunct ) );
284 aRet = aConstantValue.fillNode( rEquations, NULL, nFlags );
286 break;
287 case ENUM_FUNC_LEFT : aRet.Type = EnhancedCustomShapeParameterType::LEFT; break;
288 case ENUM_FUNC_TOP : aRet.Type = EnhancedCustomShapeParameterType::TOP; break;
289 case ENUM_FUNC_RIGHT : aRet.Type = EnhancedCustomShapeParameterType::RIGHT; break;
290 case ENUM_FUNC_BOTTOM : aRet.Type = EnhancedCustomShapeParameterType::BOTTOM; break;
292 // not implemented so far
293 case ENUM_FUNC_XSTRETCH :
294 case ENUM_FUNC_YSTRETCH :
295 case ENUM_FUNC_HASSTROKE :
296 case ENUM_FUNC_HASFILL : aRet.Type = EnhancedCustomShapeParameterType::NORMAL; break;
298 default:
299 break;
301 return aRet;
305 /** ExpressionNode implementation for unary
306 function over one ExpressionNode
308 class UnaryFunctionExpression : public ExpressionNode
310 const ExpressionFunct meFunct;
311 ExpressionNodeSharedPtr mpArg;
313 public:
314 UnaryFunctionExpression( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rArg ) :
315 meFunct( eFunct ),
316 mpArg( rArg )
319 static double getValue( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rArg )
321 double fRet = 0;
322 switch( eFunct )
324 case UNARY_FUNC_ABS : fRet = fabs( (*rArg)() ); break;
325 case UNARY_FUNC_SQRT: fRet = sqrt( (*rArg)() ); break;
326 case UNARY_FUNC_SIN : fRet = sin( (*rArg)() ); break;
327 case UNARY_FUNC_COS : fRet = cos( (*rArg)() ); break;
328 case UNARY_FUNC_TAN : fRet = tan( (*rArg)() ); break;
329 case UNARY_FUNC_ATAN: fRet = atan( (*rArg)() ); break;
330 case UNARY_FUNC_NEG : fRet = ::std::negate<double>()( (*rArg)() ); break;
331 default:
332 break;
334 return fRet;
336 virtual double operator()() const
338 return getValue( meFunct, mpArg );
340 virtual bool isConstant() const
342 return mpArg->isConstant();
344 virtual ExpressionFunct getType() const
346 return meFunct;
348 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* pOptionalArg, sal_uInt32 nFlags )
350 EnhancedCustomShapeParameter aRet;
351 switch( meFunct )
353 case UNARY_FUNC_ABS :
355 EnhancedCustomShapeEquation aEquation;
356 aEquation.nOperation |= 3;
357 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
358 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
359 aRet.Value <<= (sal_Int32)rEquations.size();
360 rEquations.push_back( aEquation );
362 break;
363 case UNARY_FUNC_SQRT:
365 EnhancedCustomShapeEquation aEquation;
366 aEquation.nOperation |= 13;
367 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
368 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
369 aRet.Value <<= (sal_Int32)rEquations.size();
370 rEquations.push_back( aEquation );
372 break;
373 case UNARY_FUNC_SIN :
375 EnhancedCustomShapeEquation aEquation;
376 aEquation.nOperation |= 9;
377 if ( pOptionalArg )
378 FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
379 else
380 aEquation.nPara[ 0 ] = 1;
382 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
383 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
384 { // sumangle needed :-(
385 EnhancedCustomShapeEquation _aEquation;
386 _aEquation.nOperation |= 0xe; // sumangle
387 FillEquationParameter( aSource, 1, _aEquation );
388 aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
389 aSource.Value <<= (sal_Int32)rEquations.size();
390 rEquations.push_back( _aEquation );
392 FillEquationParameter( aSource, 1, aEquation );
393 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
394 aRet.Value <<= (sal_Int32)rEquations.size();
395 rEquations.push_back( aEquation );
397 break;
398 case UNARY_FUNC_COS :
400 EnhancedCustomShapeEquation aEquation;
401 aEquation.nOperation |= 10;
402 if ( pOptionalArg )
403 FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
404 else
405 aEquation.nPara[ 0 ] = 1;
407 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
408 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
409 { // sumangle needed :-(
410 EnhancedCustomShapeEquation aTmpEquation;
411 aTmpEquation.nOperation |= 0xe; // sumangle
412 FillEquationParameter( aSource, 1, aTmpEquation );
413 aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
414 aSource.Value <<= (sal_Int32)rEquations.size();
415 rEquations.push_back( aTmpEquation );
417 FillEquationParameter( aSource, 1, aEquation );
418 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
419 aRet.Value <<= (sal_Int32)rEquations.size();
420 rEquations.push_back( aEquation );
422 break;
423 case UNARY_FUNC_TAN :
425 EnhancedCustomShapeEquation aEquation;
426 aEquation.nOperation |= 16;
427 if ( pOptionalArg )
428 FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
429 else
430 aEquation.nPara[ 0 ] = 1;
432 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
433 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
434 { // sumangle needed :-(
435 EnhancedCustomShapeEquation aTmpEquation;
436 aTmpEquation.nOperation |= 0xe; // sumangle
437 FillEquationParameter( aSource, 1, aTmpEquation );
438 aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
439 aSource.Value <<= (sal_Int32)rEquations.size();
440 rEquations.push_back( aTmpEquation );
442 FillEquationParameter( aSource, 1, aEquation );
443 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
444 aRet.Value <<= (sal_Int32)rEquations.size();
445 rEquations.push_back( aEquation );
447 break;
448 case UNARY_FUNC_ATAN:
450 // TODO:
451 aRet.Type = EnhancedCustomShapeParameterType::NORMAL;
453 break;
454 case UNARY_FUNC_NEG:
456 EnhancedCustomShapeEquation aEquation;
457 aEquation.nOperation |= 1;
458 aEquation.nPara[ 1 ] = -1;
459 aEquation.nPara[ 2 ] = 1;
460 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
461 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
462 aRet.Value <<= (sal_Int32)rEquations.size();
463 rEquations.push_back( aEquation );
465 break;
466 default:
467 break;
469 return aRet;
473 /** ExpressionNode implementation for unary
474 function over two ExpressionNodes
476 class BinaryFunctionExpression : public ExpressionNode
478 const ExpressionFunct meFunct;
479 ExpressionNodeSharedPtr mpFirstArg;
480 ExpressionNodeSharedPtr mpSecondArg;
482 public:
484 BinaryFunctionExpression( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rFirstArg, const ExpressionNodeSharedPtr& rSecondArg ) :
485 meFunct( eFunct ),
486 mpFirstArg( rFirstArg ),
487 mpSecondArg( rSecondArg )
490 static double getValue( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rFirstArg, const ExpressionNodeSharedPtr& rSecondArg )
492 double fRet = 0;
493 switch( eFunct )
495 case BINARY_FUNC_PLUS : fRet = (*rFirstArg)() + (*rSecondArg)(); break;
496 case BINARY_FUNC_MINUS: fRet = (*rFirstArg)() - (*rSecondArg)(); break;
497 case BINARY_FUNC_MUL : fRet = (*rFirstArg)() * (*rSecondArg)(); break;
498 case BINARY_FUNC_DIV : fRet = (*rFirstArg)() / (*rSecondArg)(); break;
499 case BINARY_FUNC_MIN : fRet = ::std::min( (*rFirstArg)(), (*rSecondArg)() ); break;
500 case BINARY_FUNC_MAX : fRet = ::std::max( (*rFirstArg)(), (*rSecondArg)() ); break;
501 case BINARY_FUNC_ATAN2: fRet = atan2( (*rFirstArg)(), (*rSecondArg)() ); break;
502 default:
503 break;
505 return fRet;
507 virtual double operator()() const
509 return getValue( meFunct, mpFirstArg, mpSecondArg );
511 virtual bool isConstant() const
513 return mpFirstArg->isConstant() && mpSecondArg->isConstant();
515 virtual ExpressionFunct getType() const
517 return meFunct;
519 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags )
521 EnhancedCustomShapeParameter aRet;
522 switch( meFunct )
524 case BINARY_FUNC_PLUS :
526 if ( nFlags & EXPRESSION_FLAG_SUMANGLE_MODE )
528 if ( mpFirstArg->getType() == ENUM_FUNC_ADJUSTMENT )
530 EnhancedCustomShapeEquation aEquation;
531 aEquation.nOperation |= 0xe; // sumangle
532 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
533 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
534 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
535 aRet.Value <<= (sal_Int32)rEquations.size();
536 rEquations.push_back( aEquation );
538 else if ( mpSecondArg->getType() == ENUM_FUNC_ADJUSTMENT )
540 EnhancedCustomShapeEquation aEquation;
541 aEquation.nOperation |= 0xe; // sumangle
542 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
543 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
544 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
545 aRet.Value <<= (sal_Int32)rEquations.size();
546 rEquations.push_back( aEquation );
548 else
550 EnhancedCustomShapeEquation aSumangle1;
551 aSumangle1.nOperation |= 0xe; // sumangle
552 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags &~EXPRESSION_FLAG_SUMANGLE_MODE ), 1, aSumangle1 );
553 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
554 aRet.Value <<= (sal_Int32)rEquations.size();
555 rEquations.push_back( aSumangle1 );
557 EnhancedCustomShapeEquation aSumangle2;
558 aSumangle2.nOperation |= 0xe; // sumangle
559 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags &~EXPRESSION_FLAG_SUMANGLE_MODE ), 1, aSumangle2 );
560 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
561 aRet.Value <<= (sal_Int32)rEquations.size();
562 rEquations.push_back( aSumangle2 );
564 EnhancedCustomShapeEquation aEquation;
565 aEquation.nOperation |= 0;
566 aEquation.nPara[ 0 ] = ( rEquations.size() - 2 ) | 0x400;
567 aEquation.nPara[ 1 ] = ( rEquations.size() - 1 ) | 0x400;
568 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
569 aRet.Value <<= (sal_Int32)rEquations.size();
570 rEquations.push_back( aEquation );
573 else
575 sal_Bool bFirstIsEmpty = mpFirstArg->isConstant() && ( (*mpFirstArg)() == 0 );
576 sal_Bool bSecondIsEmpty = mpSecondArg->isConstant() && ( (*mpSecondArg)() == 0 );
578 if ( bFirstIsEmpty )
579 aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
580 else if ( bSecondIsEmpty )
581 aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
582 else
584 EnhancedCustomShapeEquation aEquation;
585 aEquation.nOperation |= 0;
586 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
587 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
588 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
589 aRet.Value <<= (sal_Int32)rEquations.size();
590 rEquations.push_back( aEquation );
594 break;
595 case BINARY_FUNC_MINUS:
597 EnhancedCustomShapeEquation aEquation;
598 aEquation.nOperation |= 0;
599 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
600 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
601 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
602 aRet.Value <<= (sal_Int32)rEquations.size();
603 rEquations.push_back( aEquation );
605 break;
606 case BINARY_FUNC_MUL :
608 // in the dest. format the cos function is using integer as result :-(
609 // so we can't use the generic algorithm
610 if ( ( mpFirstArg->getType() == UNARY_FUNC_SIN ) || ( mpFirstArg->getType() == UNARY_FUNC_COS ) || ( mpFirstArg->getType() == UNARY_FUNC_TAN ) )
611 aRet = mpFirstArg->fillNode( rEquations, mpSecondArg.get(), nFlags );
612 else if ( ( mpSecondArg->getType() == UNARY_FUNC_SIN ) || ( mpSecondArg->getType() == UNARY_FUNC_COS ) || ( mpSecondArg->getType() == UNARY_FUNC_TAN ) )
613 aRet = mpSecondArg->fillNode( rEquations, mpFirstArg.get(), nFlags );
614 else
616 if ( mpFirstArg->isConstant() && (*mpFirstArg)() == 1 )
617 aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
618 else if ( mpSecondArg->isConstant() && (*mpSecondArg)() == 1 )
619 aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
620 else if ( ( mpFirstArg->getType() == BINARY_FUNC_DIV ) // don't care of (pi/180)
621 && ( ((BinaryFunctionExpression*)((BinaryFunctionExpression*)mpFirstArg.get())->mpFirstArg.get())->getType() == ENUM_FUNC_PI )
622 && ( ((BinaryFunctionExpression*)((BinaryFunctionExpression*)mpFirstArg.get())->mpSecondArg.get())->getType() == FUNC_CONST ) )
624 aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
626 else if ( ( mpSecondArg->getType() == BINARY_FUNC_DIV ) // don't care of (pi/180)
627 && ( ((BinaryFunctionExpression*)((BinaryFunctionExpression*)mpSecondArg.get())->mpFirstArg.get())->getType() == ENUM_FUNC_PI )
628 && ( ((BinaryFunctionExpression*)((BinaryFunctionExpression*)mpSecondArg.get())->mpSecondArg.get())->getType() == FUNC_CONST ) )
630 aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
632 else
634 EnhancedCustomShapeEquation aEquation;
635 aEquation.nOperation |= 1;
636 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
637 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
638 aEquation.nPara[ 2 ] = 1;
639 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
640 aRet.Value <<= (sal_Int32)rEquations.size();
641 rEquations.push_back( aEquation );
645 break;
646 case BINARY_FUNC_DIV :
648 EnhancedCustomShapeEquation aEquation;
649 aEquation.nOperation |= 1;
650 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
651 aEquation.nPara[ 1 ] = 1;
652 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
653 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
654 aRet.Value <<= (sal_Int32)rEquations.size();
655 rEquations.push_back( aEquation );
657 break;
658 case BINARY_FUNC_MIN :
660 EnhancedCustomShapeEquation aEquation;
661 aEquation.nOperation |= 4;
662 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
663 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
664 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
665 aRet.Value <<= (sal_Int32)rEquations.size();
666 rEquations.push_back( aEquation );
668 break;
669 case BINARY_FUNC_MAX :
671 EnhancedCustomShapeEquation aEquation;
672 aEquation.nOperation |= 5;
673 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
674 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
675 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
676 aRet.Value <<= (sal_Int32)rEquations.size();
677 rEquations.push_back( aEquation );
679 break;
680 case BINARY_FUNC_ATAN2:
682 EnhancedCustomShapeEquation aEquation;
683 aEquation.nOperation |= 8;
684 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
685 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
686 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
687 aRet.Value <<= (sal_Int32)rEquations.size();
688 rEquations.push_back( aEquation );
690 break;
691 default:
692 break;
694 return aRet;
698 class IfExpression : public ExpressionNode
700 ExpressionNodeSharedPtr mpFirstArg;
701 ExpressionNodeSharedPtr mpSecondArg;
702 ExpressionNodeSharedPtr mpThirdArg;
704 public:
706 IfExpression( const ExpressionNodeSharedPtr& rFirstArg,
707 const ExpressionNodeSharedPtr& rSecondArg,
708 const ExpressionNodeSharedPtr& rThirdArg ) :
709 mpFirstArg( rFirstArg ),
710 mpSecondArg( rSecondArg ),
711 mpThirdArg( rThirdArg )
714 virtual bool isConstant() const
716 return
717 mpFirstArg->isConstant() &&
718 mpSecondArg->isConstant() &&
719 mpThirdArg->isConstant();
721 virtual double operator()() const
723 return (*mpFirstArg)() > 0 ? (*mpSecondArg)() : (*mpThirdArg)();
725 virtual ExpressionFunct getType() const
727 return TERNARY_FUNC_IF;
729 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags )
731 EnhancedCustomShapeParameter aRet;
732 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
733 aRet.Value <<= (sal_Int32)rEquations.size();
735 EnhancedCustomShapeEquation aEquation;
736 aEquation.nOperation |= 6;
737 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
738 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
739 FillEquationParameter( mpThirdArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
740 rEquations.push_back( aEquation );
742 return aRet;
746 ////////////////////////
747 ////////////////////////
748 // FUNCTION PARSER
749 ////////////////////////
750 ////////////////////////
752 typedef const sal_Char* StringIteratorT;
754 struct ParserContext
756 typedef ::std::stack< ExpressionNodeSharedPtr > OperandStack;
758 // stores a stack of not-yet-evaluated operands. This is used
759 // by the operators (i.e. '+', '*', 'sin' etc.) to pop their
760 // arguments from. If all arguments to an operator are constant,
761 // the operator pushes a precalculated result on the stack, and
762 // a composite ExpressionNode otherwise.
763 OperandStack maOperandStack;
765 const EnhancedCustomShape2d* mpCustoShape;
769 typedef ::boost::shared_ptr< ParserContext > ParserContextSharedPtr;
771 /** Generate apriori constant value
774 class ConstantFunctor
776 const double mnValue;
777 ParserContextSharedPtr mpContext;
779 public:
781 ConstantFunctor( double rValue, const ParserContextSharedPtr& rContext ) :
782 mnValue( rValue ),
783 mpContext( rContext )
786 void operator()( StringIteratorT /*rFirst*/, StringIteratorT /*rSecond*/ ) const
788 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( mnValue ) ) );
792 /** Generate parse-dependent-but-then-constant value
794 class DoubleConstantFunctor
796 ParserContextSharedPtr mpContext;
798 public:
799 DoubleConstantFunctor( const ParserContextSharedPtr& rContext ) :
800 mpContext( rContext )
803 void operator()( double n ) const
805 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( n ) ) );
809 class EnumFunctor
811 const ExpressionFunct meFunct;
812 double mnValue;
813 ParserContextSharedPtr mpContext;
815 public:
817 EnumFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext )
818 : meFunct( eFunct )
819 , mnValue( 0 )
820 , mpContext( rContext )
823 void operator()( StringIteratorT rFirst, StringIteratorT rSecond ) const
825 /*double nVal = mnValue;*/
826 switch( meFunct )
828 case ENUM_FUNC_ADJUSTMENT :
830 rtl::OUString aVal( rFirst + 1, rSecond - rFirst, RTL_TEXTENCODING_UTF8 );
831 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new AdjustmentExpression( *mpContext->mpCustoShape, aVal.toInt32() ) ) );
833 break;
834 case ENUM_FUNC_EQUATION :
836 rtl::OUString aVal( rFirst + 1, rSecond - rFirst, RTL_TEXTENCODING_UTF8 );
837 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new EquationExpression( *mpContext->mpCustoShape, aVal.toInt32() ) ) );
839 break;
840 default:
841 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new EnumValueExpression( *mpContext->mpCustoShape, meFunct ) ) );
846 class UnaryFunctionFunctor
848 const ExpressionFunct meFunct;
849 ParserContextSharedPtr mpContext;
851 public :
853 UnaryFunctionFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) :
854 meFunct( eFunct ),
855 mpContext( rContext )
858 void operator()( StringIteratorT, StringIteratorT ) const
860 ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
862 if( rNodeStack.size() < 1 )
863 throw ParseError( "Not enough arguments for unary operator" );
865 // retrieve arguments
866 ExpressionNodeSharedPtr pArg( rNodeStack.top() );
867 rNodeStack.pop();
869 if( pArg->isConstant() ) // check for constness
870 rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( UnaryFunctionExpression::getValue( meFunct, pArg ) ) ) );
871 else // push complex node, that calcs the value on demand
872 rNodeStack.push( ExpressionNodeSharedPtr( new UnaryFunctionExpression( meFunct, pArg ) ) );
876 /** Implements a binary function over two ExpressionNodes
878 @tpl Generator
879 Generator functor, to generate an ExpressionNode of
880 appropriate type
883 class BinaryFunctionFunctor
885 const ExpressionFunct meFunct;
886 ParserContextSharedPtr mpContext;
888 public:
890 BinaryFunctionFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) :
891 meFunct( eFunct ),
892 mpContext( rContext )
896 void operator()( StringIteratorT, StringIteratorT ) const
898 ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
900 if( rNodeStack.size() < 2 )
901 throw ParseError( "Not enough arguments for binary operator" );
903 // retrieve arguments
904 ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() );
905 rNodeStack.pop();
906 ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() );
907 rNodeStack.pop();
909 // create combined ExpressionNode
910 ExpressionNodeSharedPtr pNode = ExpressionNodeSharedPtr( new BinaryFunctionExpression( meFunct, pFirstArg, pSecondArg ) );
911 // check for constness
912 if( pFirstArg->isConstant() && pSecondArg->isConstant() ) // call the operator() at pNode, store result in constant value ExpressionNode.
913 rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode)() ) ) );
914 else // push complex node, that calcs the value on demand
915 rNodeStack.push( pNode );
919 class IfFunctor
921 ParserContextSharedPtr mpContext;
923 public :
925 IfFunctor( const ParserContextSharedPtr& rContext ) :
926 mpContext( rContext )
929 void operator()( StringIteratorT, StringIteratorT ) const
931 ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
933 if( rNodeStack.size() < 3 )
934 throw ParseError( "Not enough arguments for ternary operator" );
936 // retrieve arguments
937 ExpressionNodeSharedPtr pThirdArg( rNodeStack.top() );
938 rNodeStack.pop();
939 ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() );
940 rNodeStack.pop();
941 ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() );
942 rNodeStack.pop();
944 // create combined ExpressionNode
945 ExpressionNodeSharedPtr pNode( new IfExpression( pFirstArg, pSecondArg, pThirdArg ) );
946 // check for constness
947 if( pFirstArg->isConstant() && pSecondArg->isConstant() && pThirdArg->isConstant() )
948 rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode)() ) ) ); // call the operator() at pNode, store result in constant value ExpressionNode.
949 else
950 rNodeStack.push( pNode ); // push complex node, that calcs the value on demand
954 // Workaround for MSVC compiler anomaly (stack trashing)
956 // The default ureal_parser_policies implementation of parse_exp
957 // triggers a really weird error in MSVC7 (Version 13.00.9466), in
958 // that the real_parser_impl::parse_main() call of parse_exp()
959 // overwrites the frame pointer _on the stack_ (EBP of the calling
960 // function gets overwritten while lying on the stack).
962 // For the time being, our parser thus can only read the 1.0E10
963 // notation, not the 1.0e10 one.
965 // TODO(F1): Also handle the 1.0e10 case here.
966 template< typename T > struct custom_real_parser_policies : public ::boost::spirit::ureal_parser_policies<T>
968 template< typename ScannerT >
969 static typename ::boost::spirit::parser_result< ::boost::spirit::chlit<>, ScannerT >::type
970 parse_exp(ScannerT& scan)
972 // as_lower_d somehow breaks MSVC7
973 return ::boost::spirit::ch_p('E').parse(scan);
977 /* This class implements the following grammar (more or
978 less literally written down below, only slightly
979 obfuscated by the parser actions):
981 identifier = '$'|'pi'|'e'|'X'|'Y'|'Width'|'Height'
983 function = 'abs'|'sqrt'|'sin'|'cos'|'tan'|'atan'|'acos'|'asin'|'exp'|'log'
985 basic_expression =
986 number |
987 identifier |
988 function '(' additive_expression ')' |
989 '(' additive_expression ')'
991 unary_expression =
992 '-' basic_expression |
993 basic_expression
995 multiplicative_expression =
996 unary_expression ( ( '*' unary_expression )* |
997 ( '/' unary_expression )* )
999 additive_expression =
1000 multiplicative_expression ( ( '+' multiplicative_expression )* |
1001 ( '-' multiplicative_expression )* )
1004 class ExpressionGrammar : public ::boost::spirit::grammar< ExpressionGrammar >
1006 public:
1007 /** Create an arithmetic expression grammar
1009 @param rParserContext
1010 Contains context info for the parser
1012 ExpressionGrammar( const ParserContextSharedPtr& rParserContext ) :
1013 mpParserContext( rParserContext )
1017 template< typename ScannerT > class definition
1019 public:
1020 // grammar definition
1021 definition( const ExpressionGrammar& self )
1023 using ::boost::spirit::str_p;
1024 using ::boost::spirit::range_p;
1025 using ::boost::spirit::lexeme_d;
1026 using ::boost::spirit::real_parser;
1027 using ::boost::spirit::chseq_p;
1029 identifier =
1030 str_p( "pi" )[ EnumFunctor(ENUM_FUNC_PI, self.getContext() ) ]
1031 | str_p( "left" )[ EnumFunctor(ENUM_FUNC_LEFT, self.getContext() ) ]
1032 | str_p( "top" )[ EnumFunctor(ENUM_FUNC_TOP, self.getContext() ) ]
1033 | str_p( "right" )[ EnumFunctor(ENUM_FUNC_RIGHT, self.getContext() ) ]
1034 | str_p( "bottom" )[ EnumFunctor(ENUM_FUNC_BOTTOM, self.getContext() ) ]
1035 | str_p( "xstretch" )[ EnumFunctor(ENUM_FUNC_XSTRETCH, self.getContext() ) ]
1036 | str_p( "ystretch" )[ EnumFunctor(ENUM_FUNC_YSTRETCH, self.getContext() ) ]
1037 | str_p( "hasstroke" )[ EnumFunctor(ENUM_FUNC_HASSTROKE, self.getContext() ) ]
1038 | str_p( "hasfill" )[ EnumFunctor(ENUM_FUNC_HASFILL, self.getContext() ) ]
1039 | str_p( "width" )[ EnumFunctor(ENUM_FUNC_WIDTH, self.getContext() ) ]
1040 | str_p( "height" )[ EnumFunctor(ENUM_FUNC_HEIGHT, self.getContext() ) ]
1041 | str_p( "logwidth" )[ EnumFunctor(ENUM_FUNC_LOGWIDTH, self.getContext() ) ]
1042 | str_p( "logheight" )[ EnumFunctor(ENUM_FUNC_LOGHEIGHT, self.getContext() ) ]
1045 unaryFunction =
1046 (str_p( "abs" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ABS, self.getContext()) ]
1047 | (str_p( "sqrt" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SQRT, self.getContext()) ]
1048 | (str_p( "sin" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SIN, self.getContext()) ]
1049 | (str_p( "cos" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_COS, self.getContext()) ]
1050 | (str_p( "tan" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_TAN, self.getContext()) ]
1051 | (str_p( "atan" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ATAN, self.getContext()) ]
1054 binaryFunction =
1055 (str_p( "min" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MIN, self.getContext()) ]
1056 | (str_p( "max" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MAX, self.getContext()) ]
1057 | (str_p( "atan2") >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_ATAN2,self.getContext()) ]
1060 ternaryFunction =
1061 (str_p( "if" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ IfFunctor( self.getContext() ) ]
1064 funcRef_decl =
1065 lexeme_d[ +( range_p('a','z') | range_p('A','Z') | range_p('0','9') ) ];
1067 functionReference =
1068 (str_p( "?" ) >> funcRef_decl )[ EnumFunctor( ENUM_FUNC_EQUATION, self.getContext() ) ];
1070 modRef_decl =
1071 lexeme_d[ +( range_p('0','9') ) ];
1073 modifierReference =
1074 (str_p( "$" ) >> modRef_decl )[ EnumFunctor( ENUM_FUNC_ADJUSTMENT, self.getContext() ) ];
1076 basicExpression =
1077 real_parser<double, custom_real_parser_policies<double> >()[ DoubleConstantFunctor(self.getContext()) ]
1078 | identifier
1079 | functionReference
1080 | modifierReference
1081 | unaryFunction
1082 | binaryFunction
1083 | ternaryFunction
1084 | '(' >> additiveExpression >> ')'
1087 unaryExpression =
1088 ('-' >> basicExpression)[ UnaryFunctionFunctor( UNARY_FUNC_NEG, self.getContext()) ]
1089 | basicExpression
1092 multiplicativeExpression =
1093 unaryExpression
1094 >> *( ('*' >> unaryExpression)[ BinaryFunctionFunctor( BINARY_FUNC_MUL, self.getContext()) ]
1095 | ('/' >> unaryExpression)[ BinaryFunctionFunctor( BINARY_FUNC_DIV, self.getContext()) ]
1099 additiveExpression =
1100 multiplicativeExpression
1101 >> *( ('+' >> multiplicativeExpression)[ BinaryFunctionFunctor( BINARY_FUNC_PLUS, self.getContext()) ]
1102 | ('-' >> multiplicativeExpression)[ BinaryFunctionFunctor( BINARY_FUNC_MINUS, self.getContext()) ]
1106 BOOST_SPIRIT_DEBUG_RULE(additiveExpression);
1107 BOOST_SPIRIT_DEBUG_RULE(multiplicativeExpression);
1108 BOOST_SPIRIT_DEBUG_RULE(unaryExpression);
1109 BOOST_SPIRIT_DEBUG_RULE(basicExpression);
1110 BOOST_SPIRIT_DEBUG_RULE(unaryFunction);
1111 BOOST_SPIRIT_DEBUG_RULE(binaryFunction);
1112 BOOST_SPIRIT_DEBUG_RULE(ternaryFunction);
1113 BOOST_SPIRIT_DEBUG_RULE(identifier);
1116 const ::boost::spirit::rule< ScannerT >& start() const
1118 return additiveExpression;
1121 private:
1122 // the constituents of the Spirit arithmetic expression grammar.
1123 // For the sake of readability, without 'ma' prefix.
1124 ::boost::spirit::rule< ScannerT > additiveExpression;
1125 ::boost::spirit::rule< ScannerT > multiplicativeExpression;
1126 ::boost::spirit::rule< ScannerT > unaryExpression;
1127 ::boost::spirit::rule< ScannerT > basicExpression;
1128 ::boost::spirit::rule< ScannerT > unaryFunction;
1129 ::boost::spirit::rule< ScannerT > binaryFunction;
1130 ::boost::spirit::rule< ScannerT > ternaryFunction;
1131 ::boost::spirit::rule< ScannerT > funcRef_decl;
1132 ::boost::spirit::rule< ScannerT > functionReference;
1133 ::boost::spirit::rule< ScannerT > modRef_decl;
1134 ::boost::spirit::rule< ScannerT > modifierReference;
1135 ::boost::spirit::rule< ScannerT > identifier;
1138 const ParserContextSharedPtr& getContext() const
1140 return mpParserContext;
1143 private:
1144 ParserContextSharedPtr mpParserContext; // might get modified during parsing
1147 #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
1148 const ParserContextSharedPtr& getParserContext()
1150 static ParserContextSharedPtr lcl_parserContext( new ParserContext() );
1152 // clear node stack (since we reuse the static object, that's
1153 // the whole point here)
1154 while( !lcl_parserContext->maOperandStack.empty() )
1155 lcl_parserContext->maOperandStack.pop();
1157 return lcl_parserContext;
1159 #endif
1163 namespace EnhancedCustomShape {
1165 ExpressionNodeSharedPtr FunctionParser::parseFunction( const ::rtl::OUString& rFunction, const EnhancedCustomShape2d& rCustoShape )
1167 // TODO(Q1): Check if a combination of the RTL_UNICODETOTEXT_FLAGS_*
1168 // gives better conversion robustness here (we might want to map space
1169 // etc. to ASCII space here)
1170 const ::rtl::OString& rAsciiFunction(
1171 rtl::OUStringToOString( rFunction, RTL_TEXTENCODING_ASCII_US ) );
1173 StringIteratorT aStart( rAsciiFunction.getStr() );
1174 StringIteratorT aEnd( rAsciiFunction.getStr()+rAsciiFunction.getLength() );
1176 ParserContextSharedPtr pContext;
1178 #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
1179 // static parser context, because the actual
1180 // Spirit parser is also a static object
1181 pContext = getParserContext();
1182 #else
1183 pContext.reset( new ParserContext() );
1184 #endif
1185 pContext->mpCustoShape = &rCustoShape;
1187 ExpressionGrammar aExpressionGrammer( pContext );
1188 const ::boost::spirit::parse_info<StringIteratorT> aParseInfo(
1189 ::boost::spirit::parse( aStart,
1190 aEnd,
1191 aExpressionGrammer >> ::boost::spirit::end_p,
1192 ::boost::spirit::space_p ) );
1193 OSL_DEBUG_ONLY(::std::cout.flush()); // needed to keep stdout and cout in sync
1195 // input fully congested by the parser?
1196 if( !aParseInfo.full )
1197 throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): string not fully parseable" );
1199 // parser's state stack now must contain exactly _one_ ExpressionNode,
1200 // which represents our formula.
1201 if( pContext->maOperandStack.size() != 1 )
1202 throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): incomplete or empty expression" );
1204 return pContext->maOperandStack.top();