fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / svx / source / customshapes / EnhancedCustomShapeFunctionParser.cxx
bloba8c9cadc06a4053036bcd370fb8eb62d6e8063d4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "svx/EnhancedCustomShape2d.hxx"
21 #include <rtl/ustring.hxx>
22 #include <tools/fract.hxx>
24 // Makes parser a static resource,
25 // we're synchronized externally.
26 // But watch out, the parser might have
27 // state not visible to this code!
29 #define BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
30 #if OSL_DEBUG_LEVEL >= 2 && defined(DBG_UTIL)
31 #include <typeinfo>
32 #define BOOST_SPIRIT_DEBUG
33 #endif
34 #include <boost/spirit/include/classic_core.hpp>
36 #if (OSL_DEBUG_LEVEL > 0)
37 #include <iostream>
38 #endif
39 #include <functional>
40 #include <algorithm>
41 #include <stack>
43 #include <math.h> // fabs, sqrt, sin, cos, tan, atan, atan2
44 using namespace EnhancedCustomShape;
45 using namespace com::sun::star;
46 using namespace com::sun::star::drawing;
48 void EnhancedCustomShape::FillEquationParameter( const EnhancedCustomShapeParameter& rSource, const sal_Int32 nDestPara, EnhancedCustomShapeEquation& rDest )
50 sal_Int32 nValue = 0;
51 if ( rSource.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
53 double fValue(0.0);
54 if ( rSource.Value >>= fValue )
55 nValue = (sal_Int32)fValue;
57 else
58 rSource.Value >>= nValue;
60 switch( rSource.Type )
62 case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION :
64 if ( nValue & 0x40000000 )
66 nValue ^= 0x40000000;
67 rDest.nOperation |= 0x20000000 << nDestPara; // the bit is indicating that this value has to be adjusted later
69 nValue |= 0x400;
71 break;
72 case com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT : nValue += DFF_Prop_adjustValue; break;
73 case com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM : nValue = DFF_Prop_geoBottom; break;
74 case com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT : nValue = DFF_Prop_geoRight; break;
75 case com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP : nValue = DFF_Prop_geoTop; break;
76 case com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT : nValue = DFF_Prop_geoLeft; break;
78 if ( rSource.Type != com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL )
79 rDest.nOperation |= ( 0x2000 << nDestPara );
80 rDest.nPara[ nDestPara ] = nValue;
83 ExpressionNode::~ExpressionNode()
86 namespace
89 //////////////////////
90 //////////////////////
91 // EXPRESSION NODES
92 //////////////////////
93 //////////////////////
94 class ConstantValueExpression : public ExpressionNode
96 double maValue;
98 public:
100 ConstantValueExpression( double rValue ) :
101 maValue( rValue )
104 virtual double operator()() const
106 return maValue;
108 virtual bool isConstant() const
110 return true;
112 virtual ExpressionFunct getType() const
114 return FUNC_CONST;
116 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /* pOptionalArg */, sal_uInt32 /* nFlags */ )
118 EnhancedCustomShapeParameter aRet;
119 Fraction aFract( maValue );
120 if ( aFract.GetDenominator() == 1 )
122 aRet.Type = EnhancedCustomShapeParameterType::NORMAL;
123 aRet.Value <<= (sal_Int32)aFract.GetNumerator();
125 else
127 EnhancedCustomShapeEquation aEquation;
128 aEquation.nOperation = 1;
129 aEquation.nPara[ 0 ] = 1;
130 aEquation.nPara[ 1 ] = (sal_Int16)aFract.GetNumerator();
131 aEquation.nPara[ 2 ] = (sal_Int16)aFract.GetDenominator();
132 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
133 aRet.Value <<= (sal_Int32)rEquations.size();
134 rEquations.push_back( aEquation );
136 return aRet;
140 class AdjustmentExpression : public ExpressionNode
142 sal_Int32 mnIndex;
143 const EnhancedCustomShape2d& mrCustoShape;
145 public:
147 AdjustmentExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex )
148 : mnIndex ( nIndex )
149 , mrCustoShape( rCustoShape )
153 virtual double operator()() const
155 OSL_TRACE(" $%d --> %f (angle: %f)", mnIndex, mrCustoShape.GetAdjustValueAsDouble( mnIndex ), 180.0*mrCustoShape.GetAdjustValueAsDouble( mnIndex )/10800000.0);
156 return mrCustoShape.GetAdjustValueAsDouble( mnIndex );
158 virtual bool isConstant() const
160 return false;
162 virtual ExpressionFunct getType() const
164 return ENUM_FUNC_ADJUSTMENT;
166 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ )
168 EnhancedCustomShapeParameter aRet;
169 aRet.Type = EnhancedCustomShapeParameterType::ADJUSTMENT;
170 aRet.Value <<= mnIndex;
171 return aRet;
175 class EquationExpression : public ExpressionNode
177 sal_Int32 mnIndex;
178 const EnhancedCustomShape2d& mrCustoShape;
180 public:
182 EquationExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex )
183 : mnIndex ( nIndex )
184 , mrCustoShape( rCustoShape )
187 virtual double operator()() const
189 return mrCustoShape.GetEquationValueAsDouble( mnIndex );
191 virtual bool isConstant() const
193 return false;
195 virtual ExpressionFunct getType() const
197 return ENUM_FUNC_EQUATION;
199 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ )
201 EnhancedCustomShapeParameter aRet;
202 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
203 aRet.Value <<= mnIndex | 0x40000000; // the bit is indicating that this equation needs to be adjusted later
204 return aRet;
208 class EnumValueExpression : public ExpressionNode
210 const ExpressionFunct meFunct;
211 const EnhancedCustomShape2d& mrCustoShape;
213 public:
215 EnumValueExpression( const EnhancedCustomShape2d& rCustoShape, const ExpressionFunct eFunct )
216 : meFunct ( eFunct )
217 , mrCustoShape ( rCustoShape )
220 static double getValue( const EnhancedCustomShape2d& rCustoShape, const ExpressionFunct eFunc )
222 EnhancedCustomShape2d::EnumFunc eF;
223 switch( eFunc )
225 case ENUM_FUNC_PI : eF = EnhancedCustomShape2d::ENUM_FUNC_PI; break;
226 case ENUM_FUNC_LEFT : eF = EnhancedCustomShape2d::ENUM_FUNC_LEFT; break;
227 case ENUM_FUNC_TOP : eF = EnhancedCustomShape2d::ENUM_FUNC_TOP; break;
228 case ENUM_FUNC_RIGHT : eF = EnhancedCustomShape2d::ENUM_FUNC_RIGHT; break;
229 case ENUM_FUNC_BOTTOM : eF = EnhancedCustomShape2d::ENUM_FUNC_BOTTOM; break;
230 case ENUM_FUNC_XSTRETCH : eF = EnhancedCustomShape2d::ENUM_FUNC_XSTRETCH; break;
231 case ENUM_FUNC_YSTRETCH : eF = EnhancedCustomShape2d::ENUM_FUNC_YSTRETCH; break;
232 case ENUM_FUNC_HASSTROKE : eF = EnhancedCustomShape2d::ENUM_FUNC_HASSTROKE; break;
233 case ENUM_FUNC_HASFILL : eF = EnhancedCustomShape2d::ENUM_FUNC_HASFILL; break;
234 case ENUM_FUNC_WIDTH : eF = EnhancedCustomShape2d::ENUM_FUNC_WIDTH; break;
235 case ENUM_FUNC_HEIGHT : eF = EnhancedCustomShape2d::ENUM_FUNC_HEIGHT; break;
236 case ENUM_FUNC_LOGWIDTH : eF = EnhancedCustomShape2d::ENUM_FUNC_LOGWIDTH; break;
237 case ENUM_FUNC_LOGHEIGHT : eF = EnhancedCustomShape2d::ENUM_FUNC_LOGHEIGHT; break;
239 default :
240 return 0.0;
242 return rCustoShape.GetEnumFunc( eF );
244 virtual double operator()() const
246 #if OSL_DEBUG_LEVEL > 1
247 const char *funcName;
249 switch (meFunct) {
250 case ENUM_FUNC_PI : funcName = "pi"; break;
251 case ENUM_FUNC_LEFT : funcName = "left"; break;
252 case ENUM_FUNC_TOP : funcName = "top"; break;
253 case ENUM_FUNC_RIGHT : funcName = "right"; break;
254 case ENUM_FUNC_BOTTOM : funcName = "bottom"; break;
255 case ENUM_FUNC_XSTRETCH : funcName = "xstretch"; break;
256 case ENUM_FUNC_YSTRETCH : funcName = "ystretch"; break;
257 case ENUM_FUNC_HASSTROKE : funcName = "hasstroke"; break;
258 case ENUM_FUNC_HASFILL : funcName = "hasfill"; break;
259 case ENUM_FUNC_WIDTH : funcName = "width"; break;
260 case ENUM_FUNC_HEIGHT : funcName = "height"; break;
261 case ENUM_FUNC_LOGWIDTH : funcName = "logwidth"; break;
262 case ENUM_FUNC_LOGHEIGHT : funcName = "logheight"; break;
263 default: funcName = "???"; break;
266 OSL_TRACE(" %s --> %f (angle: %f)", funcName, getValue( mrCustoShape, meFunct ), 180.0*getValue( mrCustoShape, meFunct )/10800000.0);
267 #endif
269 return getValue( mrCustoShape, meFunct );
271 virtual bool isConstant() const
273 return false;
275 virtual ExpressionFunct getType() const
277 return meFunct;
279 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags )
281 EnhancedCustomShapeParameter aRet;
283 sal_Int32 nDummy = 1;
284 aRet.Value <<= nDummy;
286 switch( meFunct )
288 case ENUM_FUNC_WIDTH : // TODO: do not use this as constant value
289 case ENUM_FUNC_HEIGHT :
290 case ENUM_FUNC_LOGWIDTH :
291 case ENUM_FUNC_LOGHEIGHT :
292 case ENUM_FUNC_PI :
294 ConstantValueExpression aConstantValue( getValue( mrCustoShape, meFunct ) );
295 aRet = aConstantValue.fillNode( rEquations, NULL, nFlags );
297 break;
298 case ENUM_FUNC_LEFT : aRet.Type = EnhancedCustomShapeParameterType::LEFT; break;
299 case ENUM_FUNC_TOP : aRet.Type = EnhancedCustomShapeParameterType::TOP; break;
300 case ENUM_FUNC_RIGHT : aRet.Type = EnhancedCustomShapeParameterType::RIGHT; break;
301 case ENUM_FUNC_BOTTOM : aRet.Type = EnhancedCustomShapeParameterType::BOTTOM; break;
303 // not implemented so far
304 case ENUM_FUNC_XSTRETCH :
305 case ENUM_FUNC_YSTRETCH :
306 case ENUM_FUNC_HASSTROKE :
307 case ENUM_FUNC_HASFILL : aRet.Type = EnhancedCustomShapeParameterType::NORMAL; break;
309 default:
310 break;
312 return aRet;
316 /** ExpressionNode implementation for unary
317 function over one ExpressionNode
319 class UnaryFunctionExpression : public ExpressionNode
321 const ExpressionFunct meFunct;
322 ExpressionNodeSharedPtr mpArg;
324 public:
325 UnaryFunctionExpression( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rArg ) :
326 meFunct( eFunct ),
327 mpArg( rArg )
330 static double getValue( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rArg )
332 double fRet = 0;
333 switch( eFunct )
335 case UNARY_FUNC_ABS : fRet = fabs( (*rArg)() ); break;
336 case UNARY_FUNC_SQRT: fRet = sqrt( (*rArg)() ); break;
337 case UNARY_FUNC_SIN : fRet = sin( (*rArg)() ); break;
338 case UNARY_FUNC_COS : fRet = cos( (*rArg)() ); break;
339 case UNARY_FUNC_TAN : fRet = tan( (*rArg)() ); break;
340 case UNARY_FUNC_ATAN: fRet = atan( (*rArg)() ); break;
341 case UNARY_FUNC_NEG : fRet = ::std::negate<double>()( (*rArg)() ); break;
342 default:
343 break;
345 return fRet;
347 virtual double operator()() const
349 return getValue( meFunct, mpArg );
351 virtual bool isConstant() const
353 return mpArg->isConstant();
355 virtual ExpressionFunct getType() const
357 return meFunct;
359 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* pOptionalArg, sal_uInt32 nFlags )
361 EnhancedCustomShapeParameter aRet;
362 switch( meFunct )
364 case UNARY_FUNC_ABS :
366 EnhancedCustomShapeEquation aEquation;
367 aEquation.nOperation |= 3;
368 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
369 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
370 aRet.Value <<= (sal_Int32)rEquations.size();
371 rEquations.push_back( aEquation );
373 break;
374 case UNARY_FUNC_SQRT:
376 EnhancedCustomShapeEquation aEquation;
377 aEquation.nOperation |= 13;
378 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
379 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
380 aRet.Value <<= (sal_Int32)rEquations.size();
381 rEquations.push_back( aEquation );
383 break;
384 case UNARY_FUNC_SIN :
386 EnhancedCustomShapeEquation aEquation;
387 aEquation.nOperation |= 9;
388 if ( pOptionalArg )
389 FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
390 else
391 aEquation.nPara[ 0 ] = 1;
393 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
394 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
395 { // sumangle needed :-(
396 EnhancedCustomShapeEquation _aEquation;
397 _aEquation.nOperation |= 0xe; // sumangle
398 FillEquationParameter( aSource, 1, _aEquation );
399 aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
400 aSource.Value <<= (sal_Int32)rEquations.size();
401 rEquations.push_back( _aEquation );
403 FillEquationParameter( aSource, 1, aEquation );
404 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
405 aRet.Value <<= (sal_Int32)rEquations.size();
406 rEquations.push_back( aEquation );
408 break;
409 case UNARY_FUNC_COS :
411 EnhancedCustomShapeEquation aEquation;
412 aEquation.nOperation |= 10;
413 if ( pOptionalArg )
414 FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
415 else
416 aEquation.nPara[ 0 ] = 1;
418 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
419 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
420 { // sumangle needed :-(
421 EnhancedCustomShapeEquation aTmpEquation;
422 aTmpEquation.nOperation |= 0xe; // sumangle
423 FillEquationParameter( aSource, 1, aTmpEquation );
424 aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
425 aSource.Value <<= (sal_Int32)rEquations.size();
426 rEquations.push_back( aTmpEquation );
428 FillEquationParameter( aSource, 1, aEquation );
429 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
430 aRet.Value <<= (sal_Int32)rEquations.size();
431 rEquations.push_back( aEquation );
433 break;
434 case UNARY_FUNC_TAN :
436 EnhancedCustomShapeEquation aEquation;
437 aEquation.nOperation |= 16;
438 if ( pOptionalArg )
439 FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
440 else
441 aEquation.nPara[ 0 ] = 1;
443 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
444 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
445 { // sumangle needed :-(
446 EnhancedCustomShapeEquation aTmpEquation;
447 aTmpEquation.nOperation |= 0xe; // sumangle
448 FillEquationParameter( aSource, 1, aTmpEquation );
449 aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
450 aSource.Value <<= (sal_Int32)rEquations.size();
451 rEquations.push_back( aTmpEquation );
453 FillEquationParameter( aSource, 1, aEquation );
454 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
455 aRet.Value <<= (sal_Int32)rEquations.size();
456 rEquations.push_back( aEquation );
458 break;
459 case UNARY_FUNC_ATAN:
461 // TODO:
462 aRet.Type = EnhancedCustomShapeParameterType::NORMAL;
464 break;
465 case UNARY_FUNC_NEG:
467 EnhancedCustomShapeEquation aEquation;
468 aEquation.nOperation |= 1;
469 aEquation.nPara[ 1 ] = -1;
470 aEquation.nPara[ 2 ] = 1;
471 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
472 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
473 aRet.Value <<= (sal_Int32)rEquations.size();
474 rEquations.push_back( aEquation );
476 break;
477 default:
478 break;
480 return aRet;
484 /** ExpressionNode implementation for unary
485 function over two ExpressionNodes
487 class BinaryFunctionExpression : public ExpressionNode
489 const ExpressionFunct meFunct;
490 ExpressionNodeSharedPtr mpFirstArg;
491 ExpressionNodeSharedPtr mpSecondArg;
493 public:
495 BinaryFunctionExpression( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rFirstArg, const ExpressionNodeSharedPtr& rSecondArg ) :
496 meFunct( eFunct ),
497 mpFirstArg( rFirstArg ),
498 mpSecondArg( rSecondArg )
501 static double getValue( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rFirstArg, const ExpressionNodeSharedPtr& rSecondArg )
503 double fRet = 0;
504 switch( eFunct )
506 case BINARY_FUNC_PLUS : fRet = (*rFirstArg)() + (*rSecondArg)(); break;
507 case BINARY_FUNC_MINUS: fRet = (*rFirstArg)() - (*rSecondArg)(); break;
508 case BINARY_FUNC_MUL : fRet = (*rFirstArg)() * (*rSecondArg)(); break;
509 case BINARY_FUNC_DIV : fRet = (*rFirstArg)() / (*rSecondArg)(); break;
510 case BINARY_FUNC_MIN : fRet = ::std::min( (*rFirstArg)(), (*rSecondArg)() ); break;
511 case BINARY_FUNC_MAX : fRet = ::std::max( (*rFirstArg)(), (*rSecondArg)() ); break;
512 case BINARY_FUNC_ATAN2: fRet = atan2( (*rFirstArg)(), (*rSecondArg)() ); break;
513 default:
514 break;
516 return fRet;
518 virtual double operator()() const
520 return getValue( meFunct, mpFirstArg, mpSecondArg );
522 virtual bool isConstant() const
524 return mpFirstArg->isConstant() && mpSecondArg->isConstant();
526 virtual ExpressionFunct getType() const
528 return meFunct;
530 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags )
532 EnhancedCustomShapeParameter aRet;
533 switch( meFunct )
535 case BINARY_FUNC_PLUS :
537 if ( nFlags & EXPRESSION_FLAG_SUMANGLE_MODE )
539 if ( mpFirstArg->getType() == ENUM_FUNC_ADJUSTMENT )
541 EnhancedCustomShapeEquation aEquation;
542 aEquation.nOperation |= 0xe; // sumangle
543 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
544 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
545 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
546 aRet.Value <<= (sal_Int32)rEquations.size();
547 rEquations.push_back( aEquation );
549 else if ( mpSecondArg->getType() == ENUM_FUNC_ADJUSTMENT )
551 EnhancedCustomShapeEquation aEquation;
552 aEquation.nOperation |= 0xe; // sumangle
553 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
554 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
555 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
556 aRet.Value <<= (sal_Int32)rEquations.size();
557 rEquations.push_back( aEquation );
559 else
561 EnhancedCustomShapeEquation aSumangle1;
562 aSumangle1.nOperation |= 0xe; // sumangle
563 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags &~EXPRESSION_FLAG_SUMANGLE_MODE ), 1, aSumangle1 );
564 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
565 aRet.Value <<= (sal_Int32)rEquations.size();
566 rEquations.push_back( aSumangle1 );
568 EnhancedCustomShapeEquation aSumangle2;
569 aSumangle2.nOperation |= 0xe; // sumangle
570 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags &~EXPRESSION_FLAG_SUMANGLE_MODE ), 1, aSumangle2 );
571 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
572 aRet.Value <<= (sal_Int32)rEquations.size();
573 rEquations.push_back( aSumangle2 );
575 EnhancedCustomShapeEquation aEquation;
576 aEquation.nOperation |= 0;
577 aEquation.nPara[ 0 ] = ( rEquations.size() - 2 ) | 0x400;
578 aEquation.nPara[ 1 ] = ( rEquations.size() - 1 ) | 0x400;
579 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
580 aRet.Value <<= (sal_Int32)rEquations.size();
581 rEquations.push_back( aEquation );
584 else
586 bool bFirstIsEmpty = mpFirstArg->isConstant() && ( (*mpFirstArg)() == 0 );
587 bool bSecondIsEmpty = mpSecondArg->isConstant() && ( (*mpSecondArg)() == 0 );
589 if ( bFirstIsEmpty )
590 aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
591 else if ( bSecondIsEmpty )
592 aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
593 else
595 EnhancedCustomShapeEquation aEquation;
596 aEquation.nOperation |= 0;
597 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
598 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
599 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
600 aRet.Value <<= (sal_Int32)rEquations.size();
601 rEquations.push_back( aEquation );
605 break;
606 case BINARY_FUNC_MINUS:
608 EnhancedCustomShapeEquation aEquation;
609 aEquation.nOperation |= 0;
610 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
611 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
612 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
613 aRet.Value <<= (sal_Int32)rEquations.size();
614 rEquations.push_back( aEquation );
616 break;
617 case BINARY_FUNC_MUL :
619 // in the dest. format the cos function is using integer as result :-(
620 // so we can't use the generic algorithm
621 if ( ( mpFirstArg->getType() == UNARY_FUNC_SIN ) || ( mpFirstArg->getType() == UNARY_FUNC_COS ) || ( mpFirstArg->getType() == UNARY_FUNC_TAN ) )
622 aRet = mpFirstArg->fillNode( rEquations, mpSecondArg.get(), nFlags );
623 else if ( ( mpSecondArg->getType() == UNARY_FUNC_SIN ) || ( mpSecondArg->getType() == UNARY_FUNC_COS ) || ( mpSecondArg->getType() == UNARY_FUNC_TAN ) )
624 aRet = mpSecondArg->fillNode( rEquations, mpFirstArg.get(), nFlags );
625 else
627 if ( mpFirstArg->isConstant() && (*mpFirstArg)() == 1 )
628 aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
629 else if ( mpSecondArg->isConstant() && (*mpSecondArg)() == 1 )
630 aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
631 else if ( ( mpFirstArg->getType() == BINARY_FUNC_DIV ) // don't care of (pi/180)
632 && ( ((BinaryFunctionExpression*)((BinaryFunctionExpression*)mpFirstArg.get())->mpFirstArg.get())->getType() == ENUM_FUNC_PI )
633 && ( ((BinaryFunctionExpression*)((BinaryFunctionExpression*)mpFirstArg.get())->mpSecondArg.get())->getType() == FUNC_CONST ) )
635 aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
637 else if ( ( mpSecondArg->getType() == BINARY_FUNC_DIV ) // don't care of (pi/180)
638 && ( ((BinaryFunctionExpression*)((BinaryFunctionExpression*)mpSecondArg.get())->mpFirstArg.get())->getType() == ENUM_FUNC_PI )
639 && ( ((BinaryFunctionExpression*)((BinaryFunctionExpression*)mpSecondArg.get())->mpSecondArg.get())->getType() == FUNC_CONST ) )
641 aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
643 else
645 EnhancedCustomShapeEquation aEquation;
646 aEquation.nOperation |= 1;
647 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
648 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
649 aEquation.nPara[ 2 ] = 1;
650 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
651 aRet.Value <<= (sal_Int32)rEquations.size();
652 rEquations.push_back( aEquation );
656 break;
657 case BINARY_FUNC_DIV :
659 EnhancedCustomShapeEquation aEquation;
660 aEquation.nOperation |= 1;
661 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
662 aEquation.nPara[ 1 ] = 1;
663 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
664 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
665 aRet.Value <<= (sal_Int32)rEquations.size();
666 rEquations.push_back( aEquation );
668 break;
669 case BINARY_FUNC_MIN :
671 EnhancedCustomShapeEquation aEquation;
672 aEquation.nOperation |= 4;
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_MAX :
682 EnhancedCustomShapeEquation aEquation;
683 aEquation.nOperation |= 5;
684 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
685 FillEquationParameter( mpSecondArg->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 case BINARY_FUNC_ATAN2:
693 EnhancedCustomShapeEquation aEquation;
694 aEquation.nOperation |= 8;
695 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
696 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
697 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
698 aRet.Value <<= (sal_Int32)rEquations.size();
699 rEquations.push_back( aEquation );
701 break;
702 default:
703 break;
705 return aRet;
709 class IfExpression : public ExpressionNode
711 ExpressionNodeSharedPtr mpFirstArg;
712 ExpressionNodeSharedPtr mpSecondArg;
713 ExpressionNodeSharedPtr mpThirdArg;
715 public:
717 IfExpression( const ExpressionNodeSharedPtr& rFirstArg,
718 const ExpressionNodeSharedPtr& rSecondArg,
719 const ExpressionNodeSharedPtr& rThirdArg ) :
720 mpFirstArg( rFirstArg ),
721 mpSecondArg( rSecondArg ),
722 mpThirdArg( rThirdArg )
725 virtual bool isConstant() const
727 return
728 mpFirstArg->isConstant() &&
729 mpSecondArg->isConstant() &&
730 mpThirdArg->isConstant();
732 virtual double operator()() const
734 return (*mpFirstArg)() > 0 ? (*mpSecondArg)() : (*mpThirdArg)();
736 virtual ExpressionFunct getType() const
738 return TERNARY_FUNC_IF;
740 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags )
742 EnhancedCustomShapeParameter aRet;
743 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
744 aRet.Value <<= (sal_Int32)rEquations.size();
746 EnhancedCustomShapeEquation aEquation;
747 aEquation.nOperation |= 6;
748 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
749 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
750 FillEquationParameter( mpThirdArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
751 rEquations.push_back( aEquation );
753 return aRet;
757 ////////////////////////
758 ////////////////////////
759 // FUNCTION PARSER
760 ////////////////////////
761 ////////////////////////
763 typedef const sal_Char* StringIteratorT;
765 struct ParserContext
767 typedef ::std::stack< ExpressionNodeSharedPtr > OperandStack;
769 // stores a stack of not-yet-evaluated operands. This is used
770 // by the operators (i.e. '+', '*', 'sin' etc.) to pop their
771 // arguments from. If all arguments to an operator are constant,
772 // the operator pushes a precalculated result on the stack, and
773 // a composite ExpressionNode otherwise.
774 OperandStack maOperandStack;
776 const EnhancedCustomShape2d* mpCustoShape;
780 typedef ::boost::shared_ptr< ParserContext > ParserContextSharedPtr;
782 /** Generate apriori constant value
785 class ConstantFunctor
787 const double mnValue;
788 ParserContextSharedPtr mpContext;
790 public:
792 ConstantFunctor( double rValue, const ParserContextSharedPtr& rContext ) :
793 mnValue( rValue ),
794 mpContext( rContext )
797 void operator()( StringIteratorT /*rFirst*/, StringIteratorT /*rSecond*/ ) const
799 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( mnValue ) ) );
803 /** Generate parse-dependent-but-then-constant value
805 class DoubleConstantFunctor
807 ParserContextSharedPtr mpContext;
809 public:
810 DoubleConstantFunctor( const ParserContextSharedPtr& rContext ) :
811 mpContext( rContext )
814 void operator()( double n ) const
816 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( n ) ) );
820 class EnumFunctor
822 const ExpressionFunct meFunct;
823 double mnValue;
824 ParserContextSharedPtr mpContext;
826 public:
828 EnumFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext )
829 : meFunct( eFunct )
830 , mnValue( 0 )
831 , mpContext( rContext )
834 void operator()( StringIteratorT rFirst, StringIteratorT rSecond ) const
836 /*double nVal = mnValue;*/
837 switch( meFunct )
839 case ENUM_FUNC_ADJUSTMENT :
841 OUString aVal( rFirst + 1, rSecond - rFirst, RTL_TEXTENCODING_UTF8 );
842 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new AdjustmentExpression( *mpContext->mpCustoShape, aVal.toInt32() ) ) );
844 break;
845 case ENUM_FUNC_EQUATION :
847 OUString aVal( rFirst + 1, rSecond - rFirst, RTL_TEXTENCODING_UTF8 );
848 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new EquationExpression( *mpContext->mpCustoShape, aVal.toInt32() ) ) );
850 break;
851 default:
852 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new EnumValueExpression( *mpContext->mpCustoShape, meFunct ) ) );
857 class UnaryFunctionFunctor
859 const ExpressionFunct meFunct;
860 ParserContextSharedPtr mpContext;
862 public :
864 UnaryFunctionFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) :
865 meFunct( eFunct ),
866 mpContext( rContext )
869 void operator()( StringIteratorT, StringIteratorT ) const
871 ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
873 if( rNodeStack.size() < 1 )
874 throw ParseError( "Not enough arguments for unary operator" );
876 // retrieve arguments
877 ExpressionNodeSharedPtr pArg( rNodeStack.top() );
878 rNodeStack.pop();
880 if( pArg->isConstant() ) // check for constness
881 rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( UnaryFunctionExpression::getValue( meFunct, pArg ) ) ) );
882 else // push complex node, that calcs the value on demand
883 rNodeStack.push( ExpressionNodeSharedPtr( new UnaryFunctionExpression( meFunct, pArg ) ) );
887 /** Implements a binary function over two ExpressionNodes
889 @tpl Generator
890 Generator functor, to generate an ExpressionNode of
891 appropriate type
894 class BinaryFunctionFunctor
896 const ExpressionFunct meFunct;
897 ParserContextSharedPtr mpContext;
899 public:
901 BinaryFunctionFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) :
902 meFunct( eFunct ),
903 mpContext( rContext )
907 void operator()( StringIteratorT, StringIteratorT ) const
909 ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
911 if( rNodeStack.size() < 2 )
912 throw ParseError( "Not enough arguments for binary operator" );
914 // retrieve arguments
915 ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() );
916 rNodeStack.pop();
917 ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() );
918 rNodeStack.pop();
920 // create combined ExpressionNode
921 ExpressionNodeSharedPtr pNode = ExpressionNodeSharedPtr( new BinaryFunctionExpression( meFunct, pFirstArg, pSecondArg ) );
922 // check for constness
923 if( pFirstArg->isConstant() && pSecondArg->isConstant() ) // call the operator() at pNode, store result in constant value ExpressionNode.
924 rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode)() ) ) );
925 else // push complex node, that calcs the value on demand
926 rNodeStack.push( pNode );
930 class IfFunctor
932 ParserContextSharedPtr mpContext;
934 public :
936 IfFunctor( const ParserContextSharedPtr& rContext ) :
937 mpContext( rContext )
940 void operator()( StringIteratorT, StringIteratorT ) const
942 ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
944 if( rNodeStack.size() < 3 )
945 throw ParseError( "Not enough arguments for ternary operator" );
947 // retrieve arguments
948 ExpressionNodeSharedPtr pThirdArg( rNodeStack.top() );
949 rNodeStack.pop();
950 ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() );
951 rNodeStack.pop();
952 ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() );
953 rNodeStack.pop();
955 // create combined ExpressionNode
956 ExpressionNodeSharedPtr pNode( new IfExpression( pFirstArg, pSecondArg, pThirdArg ) );
957 // check for constness
958 if( pFirstArg->isConstant() && pSecondArg->isConstant() && pThirdArg->isConstant() )
959 rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode)() ) ) ); // call the operator() at pNode, store result in constant value ExpressionNode.
960 else
961 rNodeStack.push( pNode ); // push complex node, that calcs the value on demand
965 // Workaround for MSVC compiler anomaly (stack trashing)
967 // The default ureal_parser_policies implementation of parse_exp
968 // triggers a really weird error in MSVC7 (Version 13.00.9466), in
969 // that the real_parser_impl::parse_main() call of parse_exp()
970 // overwrites the frame pointer _on the stack_ (EBP of the calling
971 // function gets overwritten while lying on the stack).
973 // For the time being, our parser thus can only read the 1.0E10
974 // notation, not the 1.0e10 one.
976 // TODO(F1): Also handle the 1.0e10 case here.
977 template< typename T > struct custom_real_parser_policies : public ::boost::spirit::ureal_parser_policies<T>
979 template< typename ScannerT >
980 static typename ::boost::spirit::parser_result< ::boost::spirit::chlit<>, ScannerT >::type
981 parse_exp(ScannerT& scan)
983 // as_lower_d somehow breaks MSVC7
984 return ::boost::spirit::ch_p('E').parse(scan);
988 /* This class implements the following grammar (more or
989 less literally written down below, only slightly
990 obfuscated by the parser actions):
992 identifier = '$'|'pi'|'e'|'X'|'Y'|'Width'|'Height'
994 function = 'abs'|'sqrt'|'sin'|'cos'|'tan'|'atan'|'acos'|'asin'|'exp'|'log'
996 basic_expression =
997 number |
998 identifier |
999 function '(' additive_expression ')' |
1000 '(' additive_expression ')'
1002 unary_expression =
1003 '-' basic_expression |
1004 basic_expression
1006 multiplicative_expression =
1007 unary_expression ( ( '*' unary_expression )* |
1008 ( '/' unary_expression )* )
1010 additive_expression =
1011 multiplicative_expression ( ( '+' multiplicative_expression )* |
1012 ( '-' multiplicative_expression )* )
1016 class ExpressionGrammar : public ::boost::spirit::grammar< ExpressionGrammar >
1018 public:
1019 /** Create an arithmetic expression grammar
1021 @param rParserContext
1022 Contains context info for the parser
1024 ExpressionGrammar( const ParserContextSharedPtr& rParserContext ) :
1025 mpParserContext( rParserContext )
1029 template< typename ScannerT > class definition
1031 public:
1032 // grammar definition
1033 definition( const ExpressionGrammar& self )
1035 using ::boost::spirit::str_p;
1036 using ::boost::spirit::range_p;
1037 using ::boost::spirit::lexeme_d;
1038 using ::boost::spirit::real_parser;
1039 using ::boost::spirit::chseq_p;
1041 identifier =
1042 str_p( "pi" )[ EnumFunctor(ENUM_FUNC_PI, self.getContext() ) ]
1043 | str_p( "left" )[ EnumFunctor(ENUM_FUNC_LEFT, self.getContext() ) ]
1044 | str_p( "top" )[ EnumFunctor(ENUM_FUNC_TOP, self.getContext() ) ]
1045 | str_p( "right" )[ EnumFunctor(ENUM_FUNC_RIGHT, self.getContext() ) ]
1046 | str_p( "bottom" )[ EnumFunctor(ENUM_FUNC_BOTTOM, self.getContext() ) ]
1047 | str_p( "xstretch" )[ EnumFunctor(ENUM_FUNC_XSTRETCH, self.getContext() ) ]
1048 | str_p( "ystretch" )[ EnumFunctor(ENUM_FUNC_YSTRETCH, self.getContext() ) ]
1049 | str_p( "hasstroke" )[ EnumFunctor(ENUM_FUNC_HASSTROKE, self.getContext() ) ]
1050 | str_p( "hasfill" )[ EnumFunctor(ENUM_FUNC_HASFILL, self.getContext() ) ]
1051 | str_p( "width" )[ EnumFunctor(ENUM_FUNC_WIDTH, self.getContext() ) ]
1052 | str_p( "height" )[ EnumFunctor(ENUM_FUNC_HEIGHT, self.getContext() ) ]
1053 | str_p( "logwidth" )[ EnumFunctor(ENUM_FUNC_LOGWIDTH, self.getContext() ) ]
1054 | str_p( "logheight" )[ EnumFunctor(ENUM_FUNC_LOGHEIGHT, self.getContext() ) ]
1057 unaryFunction =
1058 (str_p( "abs" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ABS, self.getContext()) ]
1059 | (str_p( "sqrt" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SQRT, self.getContext()) ]
1060 | (str_p( "sin" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SIN, self.getContext()) ]
1061 | (str_p( "cos" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_COS, self.getContext()) ]
1062 | (str_p( "tan" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_TAN, self.getContext()) ]
1063 | (str_p( "atan" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ATAN, self.getContext()) ]
1066 binaryFunction =
1067 (str_p( "min" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MIN, self.getContext()) ]
1068 | (str_p( "max" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MAX, self.getContext()) ]
1069 | (str_p( "atan2") >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_ATAN2,self.getContext()) ]
1072 ternaryFunction =
1073 (str_p( "if" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ IfFunctor( self.getContext() ) ]
1076 funcRef_decl =
1077 lexeme_d[ +( range_p('a','z') | range_p('A','Z') | range_p('0','9') ) ];
1079 functionReference =
1080 (str_p( "?" ) >> funcRef_decl )[ EnumFunctor( ENUM_FUNC_EQUATION, self.getContext() ) ];
1082 modRef_decl =
1083 lexeme_d[ +( range_p('0','9') ) ];
1085 modifierReference =
1086 (str_p( "$" ) >> modRef_decl )[ EnumFunctor( ENUM_FUNC_ADJUSTMENT, self.getContext() ) ];
1088 basicExpression =
1089 real_parser<double, custom_real_parser_policies<double> >()[ DoubleConstantFunctor(self.getContext()) ]
1090 | identifier
1091 | functionReference
1092 | modifierReference
1093 | unaryFunction
1094 | binaryFunction
1095 | ternaryFunction
1096 | '(' >> additiveExpression >> ')'
1099 unaryExpression =
1100 ('-' >> basicExpression)[ UnaryFunctionFunctor( UNARY_FUNC_NEG, self.getContext()) ]
1101 | basicExpression
1104 multiplicativeExpression =
1105 unaryExpression
1106 >> *( ('*' >> unaryExpression)[ BinaryFunctionFunctor( BINARY_FUNC_MUL, self.getContext()) ]
1107 | ('/' >> unaryExpression)[ BinaryFunctionFunctor( BINARY_FUNC_DIV, self.getContext()) ]
1111 additiveExpression =
1112 multiplicativeExpression
1113 >> *( ('+' >> multiplicativeExpression)[ BinaryFunctionFunctor( BINARY_FUNC_PLUS, self.getContext()) ]
1114 | ('-' >> multiplicativeExpression)[ BinaryFunctionFunctor( BINARY_FUNC_MINUS, self.getContext()) ]
1118 BOOST_SPIRIT_DEBUG_RULE(additiveExpression);
1119 BOOST_SPIRIT_DEBUG_RULE(multiplicativeExpression);
1120 BOOST_SPIRIT_DEBUG_RULE(unaryExpression);
1121 BOOST_SPIRIT_DEBUG_RULE(basicExpression);
1122 BOOST_SPIRIT_DEBUG_RULE(unaryFunction);
1123 BOOST_SPIRIT_DEBUG_RULE(binaryFunction);
1124 BOOST_SPIRIT_DEBUG_RULE(ternaryFunction);
1125 BOOST_SPIRIT_DEBUG_RULE(identifier);
1128 const ::boost::spirit::rule< ScannerT >& start() const
1130 return additiveExpression;
1133 private:
1134 // the constituents of the Spirit arithmetic expression grammar.
1135 // For the sake of readability, without 'ma' prefix.
1136 ::boost::spirit::rule< ScannerT > additiveExpression;
1137 ::boost::spirit::rule< ScannerT > multiplicativeExpression;
1138 ::boost::spirit::rule< ScannerT > unaryExpression;
1139 ::boost::spirit::rule< ScannerT > basicExpression;
1140 ::boost::spirit::rule< ScannerT > unaryFunction;
1141 ::boost::spirit::rule< ScannerT > binaryFunction;
1142 ::boost::spirit::rule< ScannerT > ternaryFunction;
1143 ::boost::spirit::rule< ScannerT > funcRef_decl;
1144 ::boost::spirit::rule< ScannerT > functionReference;
1145 ::boost::spirit::rule< ScannerT > modRef_decl;
1146 ::boost::spirit::rule< ScannerT > modifierReference;
1147 ::boost::spirit::rule< ScannerT > identifier;
1150 const ParserContextSharedPtr& getContext() const
1152 return mpParserContext;
1155 private:
1156 ParserContextSharedPtr mpParserContext; // might get modified during parsing
1159 #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
1160 const ParserContextSharedPtr& getParserContext()
1162 static ParserContextSharedPtr lcl_parserContext( new ParserContext() );
1164 // clear node stack (since we reuse the static object, that's
1165 // the whole point here)
1166 while( !lcl_parserContext->maOperandStack.empty() )
1167 lcl_parserContext->maOperandStack.pop();
1169 return lcl_parserContext;
1171 #endif
1175 namespace EnhancedCustomShape {
1179 ExpressionNodeSharedPtr FunctionParser::parseFunction( const OUString& rFunction, const EnhancedCustomShape2d& rCustoShape )
1181 // TODO(Q1): Check if a combination of the RTL_UNICODETOTEXT_FLAGS_*
1182 // gives better conversion robustness here (we might want to map space
1183 // etc. to ASCII space here)
1184 const OString& rAsciiFunction(
1185 OUStringToOString( rFunction, RTL_TEXTENCODING_ASCII_US ) );
1187 StringIteratorT aStart( rAsciiFunction.getStr() );
1188 StringIteratorT aEnd( rAsciiFunction.getStr()+rAsciiFunction.getLength() );
1190 ParserContextSharedPtr pContext;
1192 #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
1193 // static parser context, because the actual
1194 // Spirit parser is also a static object
1195 pContext = getParserContext();
1196 #else
1197 pContext.reset( new ParserContext() );
1198 #endif
1199 pContext->mpCustoShape = &rCustoShape;
1201 ExpressionGrammar aExpressionGrammer( pContext );
1202 const ::boost::spirit::parse_info<StringIteratorT> aParseInfo(
1203 ::boost::spirit::parse( aStart,
1204 aEnd,
1205 aExpressionGrammer >> ::boost::spirit::end_p,
1206 ::boost::spirit::space_p ) );
1207 OSL_DEBUG_ONLY(::std::cout.flush()); // needed to keep stdout and cout in sync
1211 // input fully congested by the parser?
1212 if( !aParseInfo.full )
1213 throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): string not fully parseable" );
1215 // parser's state stack now must contain exactly _one_ ExpressionNode,
1216 // which represents our formula.
1217 if( pContext->maOperandStack.size() != 1 )
1218 throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): incomplete or empty expression" );
1221 return pContext->maOperandStack.top();
1227 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */