bump product version to 5.0.4.1
[LibreOffice.git] / svx / source / customshapes / EnhancedCustomShapeFunctionParser.cxx
blobf3656a30d5c1beef849da54e7f72222db1e9b4ac
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 <osl/diagnose.h>
23 #include <tools/fract.hxx>
25 // Makes parser a static resource,
26 // we're synchronized externally.
27 // But watch out, the parser might have
28 // state not visible to this code!
30 #define BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
31 #if OSL_DEBUG_LEVEL >= 2 && defined(DBG_UTIL)
32 #include <typeinfo>
33 #define BOOST_SPIRIT_DEBUG
34 #endif
35 #include <boost/spirit/include/classic_core.hpp>
37 #if (OSL_DEBUG_LEVEL > 0)
38 #include <iostream>
39 #endif
40 #include <functional>
41 #include <algorithm>
42 #include <stack>
44 #include <math.h>
45 using namespace EnhancedCustomShape;
46 using namespace com::sun::star;
47 using namespace com::sun::star::drawing;
49 void EnhancedCustomShape::FillEquationParameter( const EnhancedCustomShapeParameter& rSource, const sal_Int32 nDestPara, EnhancedCustomShapeEquation& rDest )
51 sal_Int32 nValue = 0;
52 if ( rSource.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
54 double fValue(0.0);
55 if ( rSource.Value >>= fValue )
56 nValue = (sal_Int32)fValue;
58 else
59 rSource.Value >>= nValue;
61 switch( rSource.Type )
63 case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION :
65 if ( nValue & 0x40000000 )
67 nValue ^= 0x40000000;
68 rDest.nOperation |= 0x20000000 << nDestPara; // the bit is indicating that this value has to be adjusted later
70 nValue |= 0x400;
72 break;
73 case com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT : nValue += DFF_Prop_adjustValue; break;
74 case com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM : nValue = DFF_Prop_geoBottom; break;
75 case com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT : nValue = DFF_Prop_geoRight; break;
76 case com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP : nValue = DFF_Prop_geoTop; break;
77 case com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT : nValue = DFF_Prop_geoLeft; break;
79 if ( rSource.Type != com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL )
80 rDest.nOperation |= ( 0x2000 << nDestPara );
81 rDest.nPara[ nDestPara ] = nValue;
84 ExpressionNode::~ExpressionNode()
87 namespace
92 // EXPRESSION NODES
95 class ConstantValueExpression : public ExpressionNode
97 double maValue;
99 public:
101 ConstantValueExpression( double rValue ) :
102 maValue( rValue )
105 virtual double operator()() const SAL_OVERRIDE
107 return maValue;
109 virtual bool isConstant() const SAL_OVERRIDE
111 return true;
113 virtual ExpressionFunct getType() const SAL_OVERRIDE
115 return FUNC_CONST;
117 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /* pOptionalArg */, sal_uInt32 /* nFlags */ ) SAL_OVERRIDE
119 EnhancedCustomShapeParameter aRet;
120 Fraction aFract( maValue );
121 if ( aFract.GetDenominator() == 1 )
123 aRet.Type = EnhancedCustomShapeParameterType::NORMAL;
124 aRet.Value <<= (sal_Int32)aFract.GetNumerator();
126 else
128 EnhancedCustomShapeEquation aEquation;
129 aEquation.nOperation = 1;
130 aEquation.nPara[ 0 ] = 1;
131 aEquation.nPara[ 1 ] = (sal_Int16)aFract.GetNumerator();
132 aEquation.nPara[ 2 ] = (sal_Int16)aFract.GetDenominator();
133 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
134 aRet.Value <<= (sal_Int32)rEquations.size();
135 rEquations.push_back( aEquation );
137 return aRet;
141 class AdjustmentExpression : public ExpressionNode
143 sal_Int32 mnIndex;
144 const EnhancedCustomShape2d& mrCustoShape;
146 public:
148 AdjustmentExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex )
149 : mnIndex ( nIndex )
150 , mrCustoShape( rCustoShape )
154 virtual double operator()() const SAL_OVERRIDE
156 SAL_INFO(
157 "svx",
158 "$" << mnIndex << " --> "
159 << mrCustoShape.GetAdjustValueAsDouble(mnIndex) << " (angle: "
160 << 180.0*mrCustoShape.GetAdjustValueAsDouble(mnIndex)/10800000.0
161 << ")");
162 return mrCustoShape.GetAdjustValueAsDouble( mnIndex );
164 virtual bool isConstant() const SAL_OVERRIDE
166 return false;
168 virtual ExpressionFunct getType() const SAL_OVERRIDE
170 return ENUM_FUNC_ADJUSTMENT;
172 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ ) SAL_OVERRIDE
174 EnhancedCustomShapeParameter aRet;
175 aRet.Type = EnhancedCustomShapeParameterType::ADJUSTMENT;
176 aRet.Value <<= mnIndex;
177 return aRet;
181 class EquationExpression : public ExpressionNode
183 sal_Int32 mnIndex;
184 const EnhancedCustomShape2d& mrCustoShape;
186 public:
188 EquationExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex )
189 : mnIndex ( nIndex )
190 , mrCustoShape( rCustoShape )
193 virtual double operator()() const SAL_OVERRIDE
195 return mrCustoShape.GetEquationValueAsDouble( mnIndex );
197 virtual bool isConstant() const SAL_OVERRIDE
199 return false;
201 virtual ExpressionFunct getType() const SAL_OVERRIDE
203 return ENUM_FUNC_EQUATION;
205 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ ) SAL_OVERRIDE
207 EnhancedCustomShapeParameter aRet;
208 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
209 aRet.Value <<= mnIndex | 0x40000000; // the bit is indicating that this equation needs to be adjusted later
210 return aRet;
214 class EnumValueExpression : public ExpressionNode
216 const ExpressionFunct meFunct;
217 const EnhancedCustomShape2d& mrCustoShape;
219 public:
221 EnumValueExpression( const EnhancedCustomShape2d& rCustoShape, const ExpressionFunct eFunct )
222 : meFunct ( eFunct )
223 , mrCustoShape ( rCustoShape )
226 static double getValue( const EnhancedCustomShape2d& rCustoShape, const ExpressionFunct eFunc )
228 EnhancedCustomShape2d::EnumFunc eF;
229 switch( eFunc )
231 case ENUM_FUNC_PI : eF = EnhancedCustomShape2d::ENUM_FUNC_PI; break;
232 case ENUM_FUNC_LEFT : eF = EnhancedCustomShape2d::ENUM_FUNC_LEFT; break;
233 case ENUM_FUNC_TOP : eF = EnhancedCustomShape2d::ENUM_FUNC_TOP; break;
234 case ENUM_FUNC_RIGHT : eF = EnhancedCustomShape2d::ENUM_FUNC_RIGHT; break;
235 case ENUM_FUNC_BOTTOM : eF = EnhancedCustomShape2d::ENUM_FUNC_BOTTOM; break;
236 case ENUM_FUNC_XSTRETCH : eF = EnhancedCustomShape2d::ENUM_FUNC_XSTRETCH; break;
237 case ENUM_FUNC_YSTRETCH : eF = EnhancedCustomShape2d::ENUM_FUNC_YSTRETCH; break;
238 case ENUM_FUNC_HASSTROKE : eF = EnhancedCustomShape2d::ENUM_FUNC_HASSTROKE; break;
239 case ENUM_FUNC_HASFILL : eF = EnhancedCustomShape2d::ENUM_FUNC_HASFILL; break;
240 case ENUM_FUNC_WIDTH : eF = EnhancedCustomShape2d::ENUM_FUNC_WIDTH; break;
241 case ENUM_FUNC_HEIGHT : eF = EnhancedCustomShape2d::ENUM_FUNC_HEIGHT; break;
242 case ENUM_FUNC_LOGWIDTH : eF = EnhancedCustomShape2d::ENUM_FUNC_LOGWIDTH; break;
243 case ENUM_FUNC_LOGHEIGHT : eF = EnhancedCustomShape2d::ENUM_FUNC_LOGHEIGHT; break;
245 default :
246 return 0.0;
248 return rCustoShape.GetEnumFunc( eF );
250 virtual double operator()() const SAL_OVERRIDE
252 #if OSL_DEBUG_LEVEL > 1
253 const char *funcName;
255 switch (meFunct) {
256 case ENUM_FUNC_PI : funcName = "pi"; break;
257 case ENUM_FUNC_LEFT : funcName = "left"; break;
258 case ENUM_FUNC_TOP : funcName = "top"; break;
259 case ENUM_FUNC_RIGHT : funcName = "right"; break;
260 case ENUM_FUNC_BOTTOM : funcName = "bottom"; break;
261 case ENUM_FUNC_XSTRETCH : funcName = "xstretch"; break;
262 case ENUM_FUNC_YSTRETCH : funcName = "ystretch"; break;
263 case ENUM_FUNC_HASSTROKE : funcName = "hasstroke"; break;
264 case ENUM_FUNC_HASFILL : funcName = "hasfill"; break;
265 case ENUM_FUNC_WIDTH : funcName = "width"; break;
266 case ENUM_FUNC_HEIGHT : funcName = "height"; break;
267 case ENUM_FUNC_LOGWIDTH : funcName = "logwidth"; break;
268 case ENUM_FUNC_LOGHEIGHT : funcName = "logheight"; break;
269 default: funcName = "???"; break;
272 OSL_TRACE(" %s --> %f (angle: %f)", funcName, getValue( mrCustoShape, meFunct ), 180.0*getValue( mrCustoShape, meFunct )/10800000.0);
273 #endif
275 return getValue( mrCustoShape, meFunct );
277 virtual bool isConstant() const SAL_OVERRIDE
279 return false;
281 virtual ExpressionFunct getType() const SAL_OVERRIDE
283 return meFunct;
285 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags ) SAL_OVERRIDE
287 EnhancedCustomShapeParameter aRet;
289 sal_Int32 nDummy = 1;
290 aRet.Value <<= nDummy;
292 switch( meFunct )
294 case ENUM_FUNC_WIDTH : // TODO: do not use this as constant value
295 case ENUM_FUNC_HEIGHT :
296 case ENUM_FUNC_LOGWIDTH :
297 case ENUM_FUNC_LOGHEIGHT :
298 case ENUM_FUNC_PI :
300 ConstantValueExpression aConstantValue( getValue( mrCustoShape, meFunct ) );
301 aRet = aConstantValue.fillNode( rEquations, NULL, nFlags );
303 break;
304 case ENUM_FUNC_LEFT : aRet.Type = EnhancedCustomShapeParameterType::LEFT; break;
305 case ENUM_FUNC_TOP : aRet.Type = EnhancedCustomShapeParameterType::TOP; break;
306 case ENUM_FUNC_RIGHT : aRet.Type = EnhancedCustomShapeParameterType::RIGHT; break;
307 case ENUM_FUNC_BOTTOM : aRet.Type = EnhancedCustomShapeParameterType::BOTTOM; break;
309 // not implemented so far
310 case ENUM_FUNC_XSTRETCH :
311 case ENUM_FUNC_YSTRETCH :
312 case ENUM_FUNC_HASSTROKE :
313 case ENUM_FUNC_HASFILL : aRet.Type = EnhancedCustomShapeParameterType::NORMAL; break;
315 default:
316 break;
318 return aRet;
322 /** ExpressionNode implementation for unary
323 function over one ExpressionNode
325 class UnaryFunctionExpression : public ExpressionNode
327 const ExpressionFunct meFunct;
328 ExpressionNodeSharedPtr mpArg;
330 public:
331 UnaryFunctionExpression( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rArg ) :
332 meFunct( eFunct ),
333 mpArg( rArg )
336 static double getValue( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rArg )
338 double fRet = 0;
339 switch( eFunct )
341 case UNARY_FUNC_ABS : fRet = fabs( (*rArg)() ); break;
342 case UNARY_FUNC_SQRT: fRet = sqrt( (*rArg)() ); break;
343 case UNARY_FUNC_SIN : fRet = sin( (*rArg)() ); break;
344 case UNARY_FUNC_COS : fRet = cos( (*rArg)() ); break;
345 case UNARY_FUNC_TAN : fRet = tan( (*rArg)() ); break;
346 case UNARY_FUNC_ATAN: fRet = atan( (*rArg)() ); break;
347 case UNARY_FUNC_NEG : fRet = ::std::negate<double>()( (*rArg)() ); break;
348 default:
349 break;
351 return fRet;
353 virtual double operator()() const SAL_OVERRIDE
355 return getValue( meFunct, mpArg );
357 virtual bool isConstant() const SAL_OVERRIDE
359 return mpArg->isConstant();
361 virtual ExpressionFunct getType() const SAL_OVERRIDE
363 return meFunct;
365 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* pOptionalArg, sal_uInt32 nFlags ) SAL_OVERRIDE
367 EnhancedCustomShapeParameter aRet;
368 switch( meFunct )
370 case UNARY_FUNC_ABS :
372 EnhancedCustomShapeEquation aEquation;
373 aEquation.nOperation |= 3;
374 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
375 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
376 aRet.Value <<= (sal_Int32)rEquations.size();
377 rEquations.push_back( aEquation );
379 break;
380 case UNARY_FUNC_SQRT:
382 EnhancedCustomShapeEquation aEquation;
383 aEquation.nOperation |= 13;
384 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
385 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
386 aRet.Value <<= (sal_Int32)rEquations.size();
387 rEquations.push_back( aEquation );
389 break;
390 case UNARY_FUNC_SIN :
392 EnhancedCustomShapeEquation aEquation;
393 aEquation.nOperation |= 9;
394 if ( pOptionalArg )
395 FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
396 else
397 aEquation.nPara[ 0 ] = 1;
399 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
400 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
401 { // sumangle needed :-(
402 EnhancedCustomShapeEquation _aEquation;
403 _aEquation.nOperation |= 0xe; // sumangle
404 FillEquationParameter( aSource, 1, _aEquation );
405 aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
406 aSource.Value <<= (sal_Int32)rEquations.size();
407 rEquations.push_back( _aEquation );
409 FillEquationParameter( aSource, 1, aEquation );
410 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
411 aRet.Value <<= (sal_Int32)rEquations.size();
412 rEquations.push_back( aEquation );
414 break;
415 case UNARY_FUNC_COS :
417 EnhancedCustomShapeEquation aEquation;
418 aEquation.nOperation |= 10;
419 if ( pOptionalArg )
420 FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
421 else
422 aEquation.nPara[ 0 ] = 1;
424 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
425 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
426 { // sumangle needed :-(
427 EnhancedCustomShapeEquation aTmpEquation;
428 aTmpEquation.nOperation |= 0xe; // sumangle
429 FillEquationParameter( aSource, 1, aTmpEquation );
430 aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
431 aSource.Value <<= (sal_Int32)rEquations.size();
432 rEquations.push_back( aTmpEquation );
434 FillEquationParameter( aSource, 1, aEquation );
435 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
436 aRet.Value <<= (sal_Int32)rEquations.size();
437 rEquations.push_back( aEquation );
439 break;
440 case UNARY_FUNC_TAN :
442 EnhancedCustomShapeEquation aEquation;
443 aEquation.nOperation |= 16;
444 if ( pOptionalArg )
445 FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
446 else
447 aEquation.nPara[ 0 ] = 1;
449 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
450 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
451 { // sumangle needed :-(
452 EnhancedCustomShapeEquation aTmpEquation;
453 aTmpEquation.nOperation |= 0xe; // sumangle
454 FillEquationParameter( aSource, 1, aTmpEquation );
455 aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
456 aSource.Value <<= (sal_Int32)rEquations.size();
457 rEquations.push_back( aTmpEquation );
459 FillEquationParameter( aSource, 1, aEquation );
460 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
461 aRet.Value <<= (sal_Int32)rEquations.size();
462 rEquations.push_back( aEquation );
464 break;
465 case UNARY_FUNC_ATAN:
467 // TODO:
468 aRet.Type = EnhancedCustomShapeParameterType::NORMAL;
470 break;
471 case UNARY_FUNC_NEG:
473 EnhancedCustomShapeEquation aEquation;
474 aEquation.nOperation |= 1;
475 aEquation.nPara[ 1 ] = -1;
476 aEquation.nPara[ 2 ] = 1;
477 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
478 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
479 aRet.Value <<= (sal_Int32)rEquations.size();
480 rEquations.push_back( aEquation );
482 break;
483 default:
484 break;
486 return aRet;
490 /** ExpressionNode implementation for unary
491 function over two ExpressionNodes
493 class BinaryFunctionExpression : public ExpressionNode
495 const ExpressionFunct meFunct;
496 ExpressionNodeSharedPtr mpFirstArg;
497 ExpressionNodeSharedPtr mpSecondArg;
499 public:
501 BinaryFunctionExpression( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rFirstArg, const ExpressionNodeSharedPtr& rSecondArg ) :
502 meFunct( eFunct ),
503 mpFirstArg( rFirstArg ),
504 mpSecondArg( rSecondArg )
507 static double getValue( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rFirstArg, const ExpressionNodeSharedPtr& rSecondArg )
509 double fRet = 0;
510 switch( eFunct )
512 case BINARY_FUNC_PLUS : fRet = (*rFirstArg)() + (*rSecondArg)(); break;
513 case BINARY_FUNC_MINUS: fRet = (*rFirstArg)() - (*rSecondArg)(); break;
514 case BINARY_FUNC_MUL : fRet = (*rFirstArg)() * (*rSecondArg)(); break;
515 case BINARY_FUNC_DIV : fRet = (*rFirstArg)() / (*rSecondArg)(); break;
516 case BINARY_FUNC_MIN : fRet = ::std::min( (*rFirstArg)(), (*rSecondArg)() ); break;
517 case BINARY_FUNC_MAX : fRet = ::std::max( (*rFirstArg)(), (*rSecondArg)() ); break;
518 case BINARY_FUNC_ATAN2: fRet = atan2( (*rFirstArg)(), (*rSecondArg)() ); break;
519 default:
520 break;
522 return fRet;
524 virtual double operator()() const SAL_OVERRIDE
526 return getValue( meFunct, mpFirstArg, mpSecondArg );
528 virtual bool isConstant() const SAL_OVERRIDE
530 return mpFirstArg->isConstant() && mpSecondArg->isConstant();
532 virtual ExpressionFunct getType() const SAL_OVERRIDE
534 return meFunct;
536 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags ) SAL_OVERRIDE
538 EnhancedCustomShapeParameter aRet;
539 switch( meFunct )
541 case BINARY_FUNC_PLUS :
543 if ( nFlags & EXPRESSION_FLAG_SUMANGLE_MODE )
545 if ( mpFirstArg->getType() == ENUM_FUNC_ADJUSTMENT )
547 EnhancedCustomShapeEquation aEquation;
548 aEquation.nOperation |= 0xe; // sumangle
549 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
550 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
551 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
552 aRet.Value <<= (sal_Int32)rEquations.size();
553 rEquations.push_back( aEquation );
555 else if ( mpSecondArg->getType() == ENUM_FUNC_ADJUSTMENT )
557 EnhancedCustomShapeEquation aEquation;
558 aEquation.nOperation |= 0xe; // sumangle
559 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
560 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
561 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
562 aRet.Value <<= (sal_Int32)rEquations.size();
563 rEquations.push_back( aEquation );
565 else
567 EnhancedCustomShapeEquation aSumangle1;
568 aSumangle1.nOperation |= 0xe; // sumangle
569 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags &~EXPRESSION_FLAG_SUMANGLE_MODE ), 1, aSumangle1 );
570 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
571 aRet.Value <<= (sal_Int32)rEquations.size();
572 rEquations.push_back( aSumangle1 );
574 EnhancedCustomShapeEquation aSumangle2;
575 aSumangle2.nOperation |= 0xe; // sumangle
576 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags &~EXPRESSION_FLAG_SUMANGLE_MODE ), 1, aSumangle2 );
577 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
578 aRet.Value <<= (sal_Int32)rEquations.size();
579 rEquations.push_back( aSumangle2 );
581 EnhancedCustomShapeEquation aEquation;
582 aEquation.nOperation |= 0;
583 aEquation.nPara[ 0 ] = ( rEquations.size() - 2 ) | 0x400;
584 aEquation.nPara[ 1 ] = ( rEquations.size() - 1 ) | 0x400;
585 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
586 aRet.Value <<= (sal_Int32)rEquations.size();
587 rEquations.push_back( aEquation );
590 else
592 bool bFirstIsEmpty = mpFirstArg->isConstant() && ( (*mpFirstArg)() == 0 );
593 bool bSecondIsEmpty = mpSecondArg->isConstant() && ( (*mpSecondArg)() == 0 );
595 if ( bFirstIsEmpty )
596 aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
597 else if ( bSecondIsEmpty )
598 aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
599 else
601 EnhancedCustomShapeEquation aEquation;
602 aEquation.nOperation |= 0;
603 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
604 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
605 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
606 aRet.Value <<= (sal_Int32)rEquations.size();
607 rEquations.push_back( aEquation );
611 break;
612 case BINARY_FUNC_MINUS:
614 EnhancedCustomShapeEquation aEquation;
615 aEquation.nOperation |= 0;
616 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
617 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
618 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
619 aRet.Value <<= (sal_Int32)rEquations.size();
620 rEquations.push_back( aEquation );
622 break;
623 case BINARY_FUNC_MUL :
625 // in the dest. format the cos function is using integer as result :-(
626 // so we can't use the generic algorithm
627 if ( ( mpFirstArg->getType() == UNARY_FUNC_SIN ) || ( mpFirstArg->getType() == UNARY_FUNC_COS ) || ( mpFirstArg->getType() == UNARY_FUNC_TAN ) )
628 aRet = mpFirstArg->fillNode( rEquations, mpSecondArg.get(), nFlags );
629 else if ( ( mpSecondArg->getType() == UNARY_FUNC_SIN ) || ( mpSecondArg->getType() == UNARY_FUNC_COS ) || ( mpSecondArg->getType() == UNARY_FUNC_TAN ) )
630 aRet = mpSecondArg->fillNode( rEquations, mpFirstArg.get(), nFlags );
631 else
633 if ( mpFirstArg->isConstant() && (*mpFirstArg)() == 1 )
634 aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
635 else if ( mpSecondArg->isConstant() && (*mpSecondArg)() == 1 )
636 aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
637 else if ( ( mpFirstArg->getType() == BINARY_FUNC_DIV ) // don't care of (pi/180)
638 && ( static_cast<BinaryFunctionExpression*>(mpFirstArg.get())->mpFirstArg.get()->getType() == ENUM_FUNC_PI )
639 && ( static_cast<BinaryFunctionExpression*>(mpFirstArg.get())->mpSecondArg.get()->getType() == FUNC_CONST ) )
641 aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
643 else if ( ( mpSecondArg->getType() == BINARY_FUNC_DIV ) // don't care of (pi/180)
644 && ( static_cast<BinaryFunctionExpression*>(mpSecondArg.get())->mpFirstArg.get()->getType() == ENUM_FUNC_PI )
645 && ( static_cast<BinaryFunctionExpression*>(mpSecondArg.get())->mpSecondArg.get()->getType() == FUNC_CONST ) )
647 aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
649 else
651 EnhancedCustomShapeEquation aEquation;
652 aEquation.nOperation |= 1;
653 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
654 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
655 aEquation.nPara[ 2 ] = 1;
656 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
657 aRet.Value <<= (sal_Int32)rEquations.size();
658 rEquations.push_back( aEquation );
662 break;
663 case BINARY_FUNC_DIV :
665 EnhancedCustomShapeEquation aEquation;
666 aEquation.nOperation |= 1;
667 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
668 aEquation.nPara[ 1 ] = 1;
669 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
670 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
671 aRet.Value <<= (sal_Int32)rEquations.size();
672 rEquations.push_back( aEquation );
674 break;
675 case BINARY_FUNC_MIN :
677 EnhancedCustomShapeEquation aEquation;
678 aEquation.nOperation |= 4;
679 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
680 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
681 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
682 aRet.Value <<= (sal_Int32)rEquations.size();
683 rEquations.push_back( aEquation );
685 break;
686 case BINARY_FUNC_MAX :
688 EnhancedCustomShapeEquation aEquation;
689 aEquation.nOperation |= 5;
690 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
691 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
692 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
693 aRet.Value <<= (sal_Int32)rEquations.size();
694 rEquations.push_back( aEquation );
696 break;
697 case BINARY_FUNC_ATAN2:
699 EnhancedCustomShapeEquation aEquation;
700 aEquation.nOperation |= 8;
701 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
702 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
703 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
704 aRet.Value <<= (sal_Int32)rEquations.size();
705 rEquations.push_back( aEquation );
707 break;
708 default:
709 break;
711 return aRet;
715 class IfExpression : public ExpressionNode
717 ExpressionNodeSharedPtr mpFirstArg;
718 ExpressionNodeSharedPtr mpSecondArg;
719 ExpressionNodeSharedPtr mpThirdArg;
721 public:
723 IfExpression( const ExpressionNodeSharedPtr& rFirstArg,
724 const ExpressionNodeSharedPtr& rSecondArg,
725 const ExpressionNodeSharedPtr& rThirdArg ) :
726 mpFirstArg( rFirstArg ),
727 mpSecondArg( rSecondArg ),
728 mpThirdArg( rThirdArg )
731 virtual bool isConstant() const SAL_OVERRIDE
733 return
734 mpFirstArg->isConstant() &&
735 mpSecondArg->isConstant() &&
736 mpThirdArg->isConstant();
738 virtual double operator()() const SAL_OVERRIDE
740 return (*mpFirstArg)() > 0 ? (*mpSecondArg)() : (*mpThirdArg)();
742 virtual ExpressionFunct getType() const SAL_OVERRIDE
744 return TERNARY_FUNC_IF;
746 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags ) SAL_OVERRIDE
748 EnhancedCustomShapeParameter aRet;
749 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
750 aRet.Value <<= (sal_Int32)rEquations.size();
752 EnhancedCustomShapeEquation aEquation;
753 aEquation.nOperation |= 6;
754 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
755 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
756 FillEquationParameter( mpThirdArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
757 rEquations.push_back( aEquation );
759 return aRet;
765 // FUNCTION PARSER
769 typedef const sal_Char* StringIteratorT;
771 struct ParserContext
773 typedef ::std::stack< ExpressionNodeSharedPtr > OperandStack;
775 // stores a stack of not-yet-evaluated operands. This is used
776 // by the operators (i.e. '+', '*', 'sin' etc.) to pop their
777 // arguments from. If all arguments to an operator are constant,
778 // the operator pushes a precalculated result on the stack, and
779 // a composite ExpressionNode otherwise.
780 OperandStack maOperandStack;
782 const EnhancedCustomShape2d* mpCustoShape;
786 typedef std::shared_ptr< ParserContext > ParserContextSharedPtr;
788 /** Generate parse-dependent-but-then-constant value
790 class DoubleConstantFunctor
792 ParserContextSharedPtr mxContext;
794 public:
795 DoubleConstantFunctor( const ParserContextSharedPtr& rContext ) :
796 mxContext( rContext )
799 void operator()( double n ) const
801 mxContext->maOperandStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( n ) ) );
805 class EnumFunctor
807 const ExpressionFunct meFunct;
808 double mnValue;
809 ParserContextSharedPtr mxContext;
811 public:
813 EnumFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext )
814 : meFunct( eFunct )
815 , mnValue( 0 )
816 , mxContext( rContext )
819 void operator()( StringIteratorT rFirst, StringIteratorT rSecond ) const
821 /*double nVal = mnValue;*/
822 switch( meFunct )
824 case ENUM_FUNC_ADJUSTMENT :
826 OUString aVal( rFirst + 1, rSecond - rFirst, RTL_TEXTENCODING_UTF8 );
827 mxContext->maOperandStack.push( ExpressionNodeSharedPtr( new AdjustmentExpression( *mxContext->mpCustoShape, aVal.toInt32() ) ) );
829 break;
830 case ENUM_FUNC_EQUATION :
832 OUString aVal( rFirst + 1, rSecond - rFirst, RTL_TEXTENCODING_UTF8 );
833 mxContext->maOperandStack.push( ExpressionNodeSharedPtr( new EquationExpression( *mxContext->mpCustoShape, aVal.toInt32() ) ) );
835 break;
836 default:
837 mxContext->maOperandStack.push( ExpressionNodeSharedPtr( new EnumValueExpression( *mxContext->mpCustoShape, meFunct ) ) );
842 class UnaryFunctionFunctor
844 const ExpressionFunct meFunct;
845 ParserContextSharedPtr mxContext;
847 public :
849 UnaryFunctionFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) :
850 meFunct( eFunct ),
851 mxContext( rContext )
854 void operator()( StringIteratorT, StringIteratorT ) const
856 ParserContext::OperandStack& rNodeStack( mxContext->maOperandStack );
858 if( rNodeStack.size() < 1 )
859 throw ParseError( "Not enough arguments for unary operator" );
861 // retrieve arguments
862 ExpressionNodeSharedPtr pArg( rNodeStack.top() );
863 rNodeStack.pop();
865 if( pArg->isConstant() ) // check for constness
866 rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( UnaryFunctionExpression::getValue( meFunct, pArg ) ) ) );
867 else // push complex node, that calcs the value on demand
868 rNodeStack.push( ExpressionNodeSharedPtr( new UnaryFunctionExpression( meFunct, pArg ) ) );
872 /** Implements a binary function over two ExpressionNodes
874 @tpl Generator
875 Generator functor, to generate an ExpressionNode of
876 appropriate type
879 class BinaryFunctionFunctor
881 const ExpressionFunct meFunct;
882 ParserContextSharedPtr mxContext;
884 public:
886 BinaryFunctionFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) :
887 meFunct( eFunct ),
888 mxContext( rContext )
892 void operator()( StringIteratorT, StringIteratorT ) const
894 ParserContext::OperandStack& rNodeStack( mxContext->maOperandStack );
896 if( rNodeStack.size() < 2 )
897 throw ParseError( "Not enough arguments for binary operator" );
899 // retrieve arguments
900 ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() );
901 rNodeStack.pop();
902 ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() );
903 rNodeStack.pop();
905 // create combined ExpressionNode
906 ExpressionNodeSharedPtr pNode = ExpressionNodeSharedPtr( new BinaryFunctionExpression( meFunct, pFirstArg, pSecondArg ) );
907 // check for constness
908 if( pFirstArg->isConstant() && pSecondArg->isConstant() ) // call the operator() at pNode, store result in constant value ExpressionNode.
909 rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode)() ) ) );
910 else // push complex node, that calcs the value on demand
911 rNodeStack.push( pNode );
915 class IfFunctor
917 ParserContextSharedPtr mxContext;
919 public :
921 IfFunctor( const ParserContextSharedPtr& rContext ) :
922 mxContext( rContext )
925 void operator()( StringIteratorT, StringIteratorT ) const
927 ParserContext::OperandStack& rNodeStack( mxContext->maOperandStack );
929 if( rNodeStack.size() < 3 )
930 throw ParseError( "Not enough arguments for ternary operator" );
932 // retrieve arguments
933 ExpressionNodeSharedPtr pThirdArg( rNodeStack.top() );
934 rNodeStack.pop();
935 ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() );
936 rNodeStack.pop();
937 ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() );
938 rNodeStack.pop();
940 // create combined ExpressionNode
941 ExpressionNodeSharedPtr pNode( new IfExpression( pFirstArg, pSecondArg, pThirdArg ) );
942 // check for constness
943 if( pFirstArg->isConstant() && pSecondArg->isConstant() && pThirdArg->isConstant() )
944 rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode)() ) ) ); // call the operator() at pNode, store result in constant value ExpressionNode.
945 else
946 rNodeStack.push( pNode ); // push complex node, that calcs the value on demand
950 // Workaround for MSVC compiler anomaly (stack trashing)
952 // The default ureal_parser_policies implementation of parse_exp
953 // triggers a really weird error in MSVC7 (Version 13.00.9466), in
954 // that the real_parser_impl::parse_main() call of parse_exp()
955 // overwrites the frame pointer _on the stack_ (EBP of the calling
956 // function gets overwritten while lying on the stack).
958 // For the time being, our parser thus can only read the 1.0E10
959 // notation, not the 1.0e10 one.
961 // TODO(F1): Also handle the 1.0e10 case here.
962 template< typename T > struct custom_real_parser_policies : public ::boost::spirit::ureal_parser_policies<T>
964 template< typename ScannerT >
965 static typename ::boost::spirit::parser_result< ::boost::spirit::chlit<>, ScannerT >::type
966 parse_exp(ScannerT& scan)
968 // as_lower_d somehow breaks MSVC7
969 return ::boost::spirit::ch_p('E').parse(scan);
973 /* This class implements the following grammar (more or
974 less literally written down below, only slightly
975 obfuscated by the parser actions):
977 identifier = '$'|'pi'|'e'|'X'|'Y'|'Width'|'Height'
979 function = 'abs'|'sqrt'|'sin'|'cos'|'tan'|'atan'|'acos'|'asin'|'exp'|'log'
981 basic_expression =
982 number |
983 identifier |
984 function '(' additive_expression ')' |
985 '(' additive_expression ')'
987 unary_expression =
988 '-' basic_expression |
989 basic_expression
991 multiplicative_expression =
992 unary_expression ( ( '*' unary_expression )* |
993 ( '/' unary_expression )* )
995 additive_expression =
996 multiplicative_expression ( ( '+' multiplicative_expression )* |
997 ( '-' multiplicative_expression )* )
1001 class ExpressionGrammar : public ::boost::spirit::grammar< ExpressionGrammar >
1003 public:
1004 /** Create an arithmetic expression grammar
1006 @param rParserContext
1007 Contains context info for the parser
1009 ExpressionGrammar( const ParserContextSharedPtr& rParserContext ) :
1010 mpParserContext( rParserContext )
1014 template< typename ScannerT > class definition
1016 public:
1017 // grammar definition
1018 definition( const ExpressionGrammar& self )
1020 using ::boost::spirit::str_p;
1021 using ::boost::spirit::range_p;
1022 using ::boost::spirit::lexeme_d;
1023 using ::boost::spirit::real_parser;
1024 using ::boost::spirit::chseq_p;
1026 identifier =
1027 str_p( "pi" )[ EnumFunctor(ENUM_FUNC_PI, self.getContext() ) ]
1028 | str_p( "left" )[ EnumFunctor(ENUM_FUNC_LEFT, self.getContext() ) ]
1029 | str_p( "top" )[ EnumFunctor(ENUM_FUNC_TOP, self.getContext() ) ]
1030 | str_p( "right" )[ EnumFunctor(ENUM_FUNC_RIGHT, self.getContext() ) ]
1031 | str_p( "bottom" )[ EnumFunctor(ENUM_FUNC_BOTTOM, self.getContext() ) ]
1032 | str_p( "xstretch" )[ EnumFunctor(ENUM_FUNC_XSTRETCH, self.getContext() ) ]
1033 | str_p( "ystretch" )[ EnumFunctor(ENUM_FUNC_YSTRETCH, self.getContext() ) ]
1034 | str_p( "hasstroke" )[ EnumFunctor(ENUM_FUNC_HASSTROKE, self.getContext() ) ]
1035 | str_p( "hasfill" )[ EnumFunctor(ENUM_FUNC_HASFILL, self.getContext() ) ]
1036 | str_p( "width" )[ EnumFunctor(ENUM_FUNC_WIDTH, self.getContext() ) ]
1037 | str_p( "height" )[ EnumFunctor(ENUM_FUNC_HEIGHT, self.getContext() ) ]
1038 | str_p( "logwidth" )[ EnumFunctor(ENUM_FUNC_LOGWIDTH, self.getContext() ) ]
1039 | str_p( "logheight" )[ EnumFunctor(ENUM_FUNC_LOGHEIGHT, self.getContext() ) ]
1042 unaryFunction =
1043 (str_p( "abs" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ABS, self.getContext()) ]
1044 | (str_p( "sqrt" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SQRT, self.getContext()) ]
1045 | (str_p( "sin" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SIN, self.getContext()) ]
1046 | (str_p( "cos" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_COS, self.getContext()) ]
1047 | (str_p( "tan" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_TAN, self.getContext()) ]
1048 | (str_p( "atan" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ATAN, self.getContext()) ]
1051 binaryFunction =
1052 (str_p( "min" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MIN, self.getContext()) ]
1053 | (str_p( "max" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MAX, self.getContext()) ]
1054 | (str_p( "atan2") >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_ATAN2,self.getContext()) ]
1057 ternaryFunction =
1058 (str_p( "if" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ IfFunctor( self.getContext() ) ]
1061 funcRef_decl =
1062 lexeme_d[ +( range_p('a','z') | range_p('A','Z') | range_p('0','9') ) ];
1064 functionReference =
1065 (str_p( "?" ) >> funcRef_decl )[ EnumFunctor( ENUM_FUNC_EQUATION, self.getContext() ) ];
1067 modRef_decl =
1068 lexeme_d[ +( range_p('0','9') ) ];
1070 modifierReference =
1071 (str_p( "$" ) >> modRef_decl )[ EnumFunctor( ENUM_FUNC_ADJUSTMENT, self.getContext() ) ];
1073 basicExpression =
1074 real_parser<double, custom_real_parser_policies<double> >()[ DoubleConstantFunctor(self.getContext()) ]
1075 | identifier
1076 | functionReference
1077 | modifierReference
1078 | unaryFunction
1079 | binaryFunction
1080 | ternaryFunction
1081 | '(' >> additiveExpression >> ')'
1084 unaryExpression =
1085 ('-' >> basicExpression)[ UnaryFunctionFunctor( UNARY_FUNC_NEG, self.getContext()) ]
1086 | basicExpression
1089 multiplicativeExpression =
1090 unaryExpression
1091 >> *( ('*' >> unaryExpression)[ BinaryFunctionFunctor( BINARY_FUNC_MUL, self.getContext()) ]
1092 | ('/' >> unaryExpression)[ BinaryFunctionFunctor( BINARY_FUNC_DIV, self.getContext()) ]
1096 additiveExpression =
1097 multiplicativeExpression
1098 >> *( ('+' >> multiplicativeExpression)[ BinaryFunctionFunctor( BINARY_FUNC_PLUS, self.getContext()) ]
1099 | ('-' >> multiplicativeExpression)[ BinaryFunctionFunctor( BINARY_FUNC_MINUS, self.getContext()) ]
1103 BOOST_SPIRIT_DEBUG_RULE(additiveExpression);
1104 BOOST_SPIRIT_DEBUG_RULE(multiplicativeExpression);
1105 BOOST_SPIRIT_DEBUG_RULE(unaryExpression);
1106 BOOST_SPIRIT_DEBUG_RULE(basicExpression);
1107 BOOST_SPIRIT_DEBUG_RULE(unaryFunction);
1108 BOOST_SPIRIT_DEBUG_RULE(binaryFunction);
1109 BOOST_SPIRIT_DEBUG_RULE(ternaryFunction);
1110 BOOST_SPIRIT_DEBUG_RULE(identifier);
1113 const ::boost::spirit::rule< ScannerT >& start() const
1115 return additiveExpression;
1118 private:
1119 // the constituents of the Spirit arithmetic expression grammar.
1120 // For the sake of readability, without 'ma' prefix.
1121 ::boost::spirit::rule< ScannerT > additiveExpression;
1122 ::boost::spirit::rule< ScannerT > multiplicativeExpression;
1123 ::boost::spirit::rule< ScannerT > unaryExpression;
1124 ::boost::spirit::rule< ScannerT > basicExpression;
1125 ::boost::spirit::rule< ScannerT > unaryFunction;
1126 ::boost::spirit::rule< ScannerT > binaryFunction;
1127 ::boost::spirit::rule< ScannerT > ternaryFunction;
1128 ::boost::spirit::rule< ScannerT > funcRef_decl;
1129 ::boost::spirit::rule< ScannerT > functionReference;
1130 ::boost::spirit::rule< ScannerT > modRef_decl;
1131 ::boost::spirit::rule< ScannerT > modifierReference;
1132 ::boost::spirit::rule< ScannerT > identifier;
1135 const ParserContextSharedPtr& getContext() const
1137 return mpParserContext;
1140 private:
1141 ParserContextSharedPtr mpParserContext; // might get modified during parsing
1144 #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
1145 const ParserContextSharedPtr& getParserContext()
1147 static ParserContextSharedPtr lcl_parserContext( new ParserContext() );
1149 // clear node stack (since we reuse the static object, that's
1150 // the whole point here)
1151 while( !lcl_parserContext->maOperandStack.empty() )
1152 lcl_parserContext->maOperandStack.pop();
1154 return lcl_parserContext;
1156 #endif
1160 namespace EnhancedCustomShape {
1164 ExpressionNodeSharedPtr FunctionParser::parseFunction( const OUString& rFunction, const EnhancedCustomShape2d& rCustoShape )
1166 // TODO(Q1): Check if a combination of the RTL_UNICODETOTEXT_FLAGS_*
1167 // gives better conversion robustness here (we might want to map space
1168 // etc. to ASCII space here)
1169 const OString& rAsciiFunction(
1170 OUStringToOString( rFunction, RTL_TEXTENCODING_ASCII_US ) );
1172 StringIteratorT aStart( rAsciiFunction.getStr() );
1173 StringIteratorT aEnd( rAsciiFunction.getStr()+rAsciiFunction.getLength() );
1175 ParserContextSharedPtr pContext;
1177 #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
1178 // static parser context, because the actual
1179 // Spirit parser is also a static object
1180 pContext = getParserContext();
1181 #else
1182 pContext.reset( new ParserContext() );
1183 #endif
1184 pContext->mpCustoShape = &rCustoShape;
1186 ExpressionGrammar aExpressionGrammer( pContext );
1187 const ::boost::spirit::parse_info<StringIteratorT> aParseInfo(
1188 ::boost::spirit::parse( aStart,
1189 aEnd,
1190 aExpressionGrammer >> ::boost::spirit::end_p,
1191 ::boost::spirit::space_p ) );
1193 #if (OSL_DEBUG_LEVEL > 0)
1194 ::std::cout.flush(); // needed to keep stdout and cout in sync
1195 #endif
1197 // input fully congested by the parser?
1198 if( !aParseInfo.full )
1199 throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): string not fully parseable" );
1201 // parser's state stack now must contain exactly _one_ ExpressionNode,
1202 // which represents our formula.
1203 if( pContext->maOperandStack.size() != 1 )
1204 throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): incomplete or empty expression" );
1207 return pContext->maOperandStack.top();
1213 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */