1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: EnhancedCustomShapeFunctionParser.cxx,v $
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)
45 #define BOOST_SPIRIT_DEBUG
47 #include <boost/spirit/include/classic_core.hpp>
49 #if (OSL_DEBUG_LEVEL > 0)
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
)
64 if ( rSource
.Value
.getValueTypeClass() == uno::TypeClass_DOUBLE
)
67 if ( rSource
.Value
>>= fValue
)
68 nValue
= (sal_Int32
)fValue
;
71 rSource
.Value
>>= nValue
;
73 switch( rSource
.Type
)
75 case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION
:
77 if ( nValue
& 0x40000000 )
80 rDest
.nOperation
|= 0x20000000 << nDestPara
; // the bit is indicating that this value has to be adjusted later
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()
102 //////////////////////
103 //////////////////////
105 //////////////////////
106 //////////////////////
107 class ConstantValueExpression
: public ExpressionNode
113 ConstantValueExpression( double rValue
) :
117 virtual double operator()() const
121 virtual bool isConstant() const
125 virtual ExpressionFunct
getType() 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();
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
);
153 class AdjustmentExpression
: public ExpressionNode
156 const EnhancedCustomShape2d
& mrCustoShape
;
160 AdjustmentExpression( const EnhancedCustomShape2d
& rCustoShape
, sal_Int32 nIndex
)
162 , mrCustoShape( rCustoShape
)
166 virtual double operator()() const
168 return mrCustoShape
.GetAdjustValueAsDouble( mnIndex
);
170 virtual bool isConstant() const
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
;
187 class EquationExpression
: public ExpressionNode
190 const EnhancedCustomShape2d
& mrCustoShape
;
194 EquationExpression( const EnhancedCustomShape2d
& rCustoShape
, sal_Int32 nIndex
)
196 , mrCustoShape( rCustoShape
)
199 virtual double operator()() const
201 return mrCustoShape
.GetEquationValueAsDouble( mnIndex
);
203 virtual bool isConstant() const
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
220 class EnumValueExpression
: public ExpressionNode
222 const ExpressionFunct meFunct
;
223 const EnhancedCustomShape2d
& mrCustoShape
;
227 EnumValueExpression( const EnhancedCustomShape2d
& rCustoShape
, const ExpressionFunct eFunct
)
229 , mrCustoShape ( rCustoShape
)
232 static double getValue( const EnhancedCustomShape2d
& rCustoShape
, const ExpressionFunct eFunc
)
234 EnhancedCustomShape2d::EnumFunc eF
;
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;
254 return rCustoShape
.GetEnumFunc( eF
);
256 virtual double operator()() const
258 return getValue( mrCustoShape
, meFunct
);
260 virtual bool isConstant() const
264 virtual ExpressionFunct
getType() const
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
;
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
:
283 ConstantValueExpression
aConstantValue( getValue( mrCustoShape
, meFunct
) );
284 aRet
= aConstantValue
.fillNode( rEquations
, NULL
, nFlags
);
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;
305 /** ExpressionNode implementation for unary
306 function over one ExpressionNode
308 class UnaryFunctionExpression
: public ExpressionNode
310 const ExpressionFunct meFunct
;
311 ExpressionNodeSharedPtr mpArg
;
314 UnaryFunctionExpression( const ExpressionFunct eFunct
, const ExpressionNodeSharedPtr
& rArg
) :
319 static double getValue( const ExpressionFunct eFunct
, const ExpressionNodeSharedPtr
& rArg
)
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;
336 virtual double operator()() const
338 return getValue( meFunct
, mpArg
);
340 virtual bool isConstant() const
342 return mpArg
->isConstant();
344 virtual ExpressionFunct
getType() const
348 virtual EnhancedCustomShapeParameter
fillNode( std::vector
< EnhancedCustomShapeEquation
>& rEquations
, ExpressionNode
* pOptionalArg
, sal_uInt32 nFlags
)
350 EnhancedCustomShapeParameter aRet
;
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
);
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
);
373 case UNARY_FUNC_SIN
:
375 EnhancedCustomShapeEquation aEquation
;
376 aEquation
.nOperation
|= 9;
378 FillEquationParameter( pOptionalArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
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
);
398 case UNARY_FUNC_COS
:
400 EnhancedCustomShapeEquation aEquation
;
401 aEquation
.nOperation
|= 10;
403 FillEquationParameter( pOptionalArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
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
);
423 case UNARY_FUNC_TAN
:
425 EnhancedCustomShapeEquation aEquation
;
426 aEquation
.nOperation
|= 16;
428 FillEquationParameter( pOptionalArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
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
);
448 case UNARY_FUNC_ATAN
:
451 aRet
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
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
);
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
;
484 BinaryFunctionExpression( const ExpressionFunct eFunct
, const ExpressionNodeSharedPtr
& rFirstArg
, const ExpressionNodeSharedPtr
& rSecondArg
) :
486 mpFirstArg( rFirstArg
),
487 mpSecondArg( rSecondArg
)
490 static double getValue( const ExpressionFunct eFunct
, const ExpressionNodeSharedPtr
& rFirstArg
, const ExpressionNodeSharedPtr
& rSecondArg
)
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;
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
519 virtual EnhancedCustomShapeParameter
fillNode( std::vector
< EnhancedCustomShapeEquation
>& rEquations
, ExpressionNode
* /*pOptionalArg*/, sal_uInt32 nFlags
)
521 EnhancedCustomShapeParameter aRet
;
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
);
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
);
575 sal_Bool bFirstIsEmpty
= mpFirstArg
->isConstant() && ( (*mpFirstArg
)() == 0 );
576 sal_Bool bSecondIsEmpty
= mpSecondArg
->isConstant() && ( (*mpSecondArg
)() == 0 );
579 aRet
= mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
);
580 else if ( bSecondIsEmpty
)
581 aRet
= mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
698 class IfExpression
: public ExpressionNode
700 ExpressionNodeSharedPtr mpFirstArg
;
701 ExpressionNodeSharedPtr mpSecondArg
;
702 ExpressionNodeSharedPtr mpThirdArg
;
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
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
);
746 ////////////////////////
747 ////////////////////////
749 ////////////////////////
750 ////////////////////////
752 typedef const sal_Char
* StringIteratorT
;
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
;
781 ConstantFunctor( double rValue
, const ParserContextSharedPtr
& rContext
) :
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
;
799 DoubleConstantFunctor( const ParserContextSharedPtr
& rContext
) :
800 mpContext( rContext
)
803 void operator()( double n
) const
805 mpContext
->maOperandStack
.push( ExpressionNodeSharedPtr( new ConstantValueExpression( n
) ) );
811 const ExpressionFunct meFunct
;
813 ParserContextSharedPtr mpContext
;
817 EnumFunctor( const ExpressionFunct eFunct
, const ParserContextSharedPtr
& rContext
)
820 , mpContext( rContext
)
823 void operator()( StringIteratorT rFirst
, StringIteratorT rSecond
) const
825 /*double nVal = mnValue;*/
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() ) ) );
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() ) ) );
841 mpContext
->maOperandStack
.push( ExpressionNodeSharedPtr( new EnumValueExpression( *mpContext
->mpCustoShape
, meFunct
) ) );
846 class UnaryFunctionFunctor
848 const ExpressionFunct meFunct
;
849 ParserContextSharedPtr mpContext
;
853 UnaryFunctionFunctor( const ExpressionFunct eFunct
, const ParserContextSharedPtr
& rContext
) :
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() );
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
879 Generator functor, to generate an ExpressionNode of
883 class BinaryFunctionFunctor
885 const ExpressionFunct meFunct
;
886 ParserContextSharedPtr mpContext
;
890 BinaryFunctionFunctor( const ExpressionFunct eFunct
, const ParserContextSharedPtr
& rContext
) :
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() );
906 ExpressionNodeSharedPtr
pFirstArg( rNodeStack
.top() );
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
);
921 ParserContextSharedPtr mpContext
;
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() );
939 ExpressionNodeSharedPtr
pSecondArg( rNodeStack
.top() );
941 ExpressionNodeSharedPtr
pFirstArg( rNodeStack
.top() );
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.
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'
988 function '(' additive_expression ')' |
989 '(' additive_expression ')'
992 '-' 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
>
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
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
;
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() ) ]
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()) ]
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()) ]
1061 (str_p( "if" ) >> '(' >> additiveExpression
>> ',' >> additiveExpression
>> ',' >> additiveExpression
>> ')' )[ IfFunctor( self
.getContext() ) ]
1065 lexeme_d
[ +( range_p('a','z') | range_p('A','Z') | range_p('0','9') ) ];
1068 (str_p( "?" ) >> funcRef_decl
)[ EnumFunctor( ENUM_FUNC_EQUATION
, self
.getContext() ) ];
1071 lexeme_d
[ +( range_p('0','9') ) ];
1074 (str_p( "$" ) >> modRef_decl
)[ EnumFunctor( ENUM_FUNC_ADJUSTMENT
, self
.getContext() ) ];
1077 real_parser
<double, custom_real_parser_policies
<double> >()[ DoubleConstantFunctor(self
.getContext()) ]
1084 | '(' >> additiveExpression
>> ')'
1088 ('-' >> basicExpression
)[ UnaryFunctionFunctor( UNARY_FUNC_NEG
, self
.getContext()) ]
1092 multiplicativeExpression
=
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
;
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
;
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
;
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();
1183 pContext
.reset( new ParserContext() );
1185 pContext
->mpCustoShape
= &rCustoShape
;
1187 ExpressionGrammar
aExpressionGrammer( pContext
);
1188 const ::boost::spirit::parse_info
<StringIteratorT
> aParseInfo(
1189 ::boost::spirit::parse( aStart
,
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();