tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / svx / source / customshapes / EnhancedCustomShapeFunctionParser.cxx
blobdcec13c136a04624f2e5ac15f3eb7c6f9a2cc8a8
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 <sal/config.h>
22 #include <svx/EnhancedCustomShape2d.hxx>
23 #include <rtl/ustring.hxx>
24 #include <sal/log.hxx>
25 #include <tools/fract.hxx>
27 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
29 // Makes parser a static resource,
30 // we're synchronized externally.
31 // But watch out, the parser might have
32 // state not visible to this code!
34 #define BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
36 #if OSL_DEBUG_LEVEL >= 2 && defined(DBG_UTIL)
37 #define BOOST_SPIRIT_DEBUG
38 #endif
39 #include <boost/spirit/include/classic_core.hpp>
41 #include <functional>
42 #include <algorithm>
43 #include <stack>
44 #include <utility>
46 #include <math.h>
47 using namespace EnhancedCustomShape;
48 using namespace com::sun::star;
49 using namespace com::sun::star::drawing;
51 void EnhancedCustomShape::FillEquationParameter( const EnhancedCustomShapeParameter& rSource, const sal_Int32 nDestPara, EnhancedCustomShapeEquation& rDest )
53 sal_Int32 nValue = 0;
54 if ( rSource.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
56 double fValue(0.0);
57 if ( rSource.Value >>= fValue )
58 nValue = static_cast<sal_Int32>(fValue);
60 else
61 rSource.Value >>= nValue;
63 switch( rSource.Type )
65 case css::drawing::EnhancedCustomShapeParameterType::EQUATION :
67 if ( nValue & 0x40000000 )
69 nValue ^= 0x40000000;
70 rDest.nOperation |= 0x20000000 << nDestPara; // the bit is indicating that this value has to be adjusted later
72 nValue |= 0x400;
74 break;
75 case css::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT : nValue += DFF_Prop_adjustValue; break;
76 case css::drawing::EnhancedCustomShapeParameterType::BOTTOM : nValue = DFF_Prop_geoBottom; break;
77 case css::drawing::EnhancedCustomShapeParameterType::RIGHT : nValue = DFF_Prop_geoRight; break;
78 case css::drawing::EnhancedCustomShapeParameterType::TOP : nValue = DFF_Prop_geoTop; break;
79 case css::drawing::EnhancedCustomShapeParameterType::LEFT : nValue = DFF_Prop_geoLeft; break;
81 if ( rSource.Type != css::drawing::EnhancedCustomShapeParameterType::NORMAL )
82 rDest.nOperation |= ( 0x2000 << nDestPara );
83 rDest.nPara[ nDestPara ] = nValue;
86 ExpressionNode::~ExpressionNode()
89 namespace
93 // EXPRESSION NODES
96 class ConstantValueExpression : public ExpressionNode
98 double maValue;
100 public:
102 explicit ConstantValueExpression( double rValue ) :
103 maValue( rValue )
106 virtual double operator()() const override
108 return maValue;
110 virtual bool isConstant() const override
112 return true;
114 virtual ExpressionFunct getType() const override
116 return ExpressionFunct::Const;
118 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /* pOptionalArg */, sal_uInt32 /* nFlags */ ) override
120 EnhancedCustomShapeParameter aRet;
121 Fraction aFract( maValue );
122 if ( aFract.GetDenominator() == 1 )
124 aRet.Type = EnhancedCustomShapeParameterType::NORMAL;
125 aRet.Value <<= aFract.GetNumerator();
127 else
129 EnhancedCustomShapeEquation aEquation;
130 aEquation.nOperation = 1;
131 aEquation.nPara[ 0 ] = 1;
132 aEquation.nPara[ 1 ] = static_cast<sal_Int16>(aFract.GetNumerator());
133 aEquation.nPara[ 2 ] = static_cast<sal_Int16>(aFract.GetDenominator());
134 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
135 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
136 rEquations.push_back( aEquation );
138 return aRet;
142 class AdjustmentExpression : public ExpressionNode
144 sal_Int32 mnIndex;
145 const EnhancedCustomShape2d& mrCustoShape;
147 public:
149 AdjustmentExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex )
150 : mnIndex ( nIndex )
151 , mrCustoShape( rCustoShape )
155 virtual double operator()() const override
157 SAL_INFO(
158 "svx",
159 "$" << mnIndex << " --> "
160 << mrCustoShape.GetAdjustValueAsDouble(mnIndex) << " (angle: "
161 << 180.0*mrCustoShape.GetAdjustValueAsDouble(mnIndex)/10800000.0
162 << ")");
163 return mrCustoShape.GetAdjustValueAsDouble( mnIndex );
165 virtual bool isConstant() const override
167 return false;
169 virtual ExpressionFunct getType() const override
171 return ExpressionFunct::EnumAdjustment;
173 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ ) override
175 EnhancedCustomShapeParameter aRet;
176 aRet.Type = EnhancedCustomShapeParameterType::ADJUSTMENT;
177 aRet.Value <<= mnIndex;
178 return aRet;
182 class EquationExpression : public ExpressionNode
184 const sal_Int32 mnIndex;
185 const EnhancedCustomShape2d& mrCustoShape;
186 mutable bool mbGettingValueGuard;
188 public:
190 EquationExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex )
191 : mnIndex ( nIndex )
192 , mrCustoShape( rCustoShape )
193 , mbGettingValueGuard(false)
196 virtual double operator()() const override
198 if (mbGettingValueGuard)
199 throw ParseError("Loop in Expression");
200 mbGettingValueGuard = true;
201 double fRet = mrCustoShape.GetEquationValueAsDouble(mnIndex);
202 mbGettingValueGuard = false;
203 return fRet;
205 virtual bool isConstant() const override
207 return false;
209 virtual ExpressionFunct getType() const override
211 return ExpressionFunct::EnumEquation;
213 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ ) override
215 EnhancedCustomShapeParameter aRet;
216 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
217 aRet.Value <<= mnIndex | 0x40000000; // the bit is indicating that this equation needs to be adjusted later
218 return aRet;
222 class EnumValueExpression : public ExpressionNode
224 const ExpressionFunct meFunct;
225 const EnhancedCustomShape2d& mrCustoShape;
227 public:
229 EnumValueExpression( const EnhancedCustomShape2d& rCustoShape, const ExpressionFunct eFunct )
230 : meFunct ( eFunct )
231 , mrCustoShape ( rCustoShape )
234 virtual double operator()() const override
236 SAL_INFO("svx", meFunct << " --> " << mrCustoShape.GetEnumFunc(meFunct) << "(angle: " <<
237 180.0 * mrCustoShape.GetEnumFunc(meFunct) / 10800000.0 << ")");
239 return mrCustoShape.GetEnumFunc( meFunct );
241 virtual bool isConstant() const override
243 return false;
245 virtual ExpressionFunct getType() const override
247 return meFunct;
249 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags ) override
251 EnhancedCustomShapeParameter aRet;
253 aRet.Value <<= sal_Int32(1);
255 switch( meFunct )
257 case ExpressionFunct::EnumWidth : // TODO: do not use this as constant value
258 case ExpressionFunct::EnumHeight :
259 case ExpressionFunct::EnumLogWidth :
260 case ExpressionFunct::EnumLogHeight :
261 case ExpressionFunct::EnumPi :
263 ConstantValueExpression aConstantValue( mrCustoShape.GetEnumFunc( meFunct ) );
264 aRet = aConstantValue.fillNode( rEquations, nullptr, nFlags );
266 break;
267 case ExpressionFunct::EnumLeft : aRet.Type = EnhancedCustomShapeParameterType::LEFT; break;
268 case ExpressionFunct::EnumTop : aRet.Type = EnhancedCustomShapeParameterType::TOP; break;
269 case ExpressionFunct::EnumRight : aRet.Type = EnhancedCustomShapeParameterType::RIGHT; break;
270 case ExpressionFunct::EnumBottom : aRet.Type = EnhancedCustomShapeParameterType::BOTTOM; break;
272 // not implemented so far
273 case ExpressionFunct::EnumXStretch :
274 case ExpressionFunct::EnumYStretch :
275 case ExpressionFunct::EnumHasStroke :
276 case ExpressionFunct::EnumHasFill : aRet.Type = EnhancedCustomShapeParameterType::NORMAL; break;
278 default:
279 break;
281 return aRet;
285 /** ExpressionNode implementation for unary
286 function over one ExpressionNode
288 class UnaryFunctionExpression : public ExpressionNode
290 const ExpressionFunct meFunct;
291 std::shared_ptr<ExpressionNode> mpArg;
293 public:
294 UnaryFunctionExpression( const ExpressionFunct eFunct, std::shared_ptr<ExpressionNode> aArg ) :
295 meFunct( eFunct ),
296 mpArg(std::move( aArg ))
299 static double getValue( const ExpressionFunct eFunct, const std::shared_ptr<ExpressionNode>& rArg )
301 double fRet = 0;
302 switch( eFunct )
304 case ExpressionFunct::UnaryAbs : fRet = fabs( (*rArg)() ); break;
305 case ExpressionFunct::UnarySqrt: fRet = sqrt( (*rArg)() ); break;
306 case ExpressionFunct::UnarySin : fRet = sin( (*rArg)() ); break;
307 case ExpressionFunct::UnaryCos : fRet = cos( (*rArg)() ); break;
308 case ExpressionFunct::UnaryTan : fRet = tan( (*rArg)() ); break;
309 case ExpressionFunct::UnaryAtan: fRet = atan( (*rArg)() ); break;
310 case ExpressionFunct::UnaryNeg : fRet = ::std::negate<double>()( (*rArg)() ); break;
311 default:
312 break;
314 return fRet;
316 virtual double operator()() const override
318 return getValue( meFunct, mpArg );
320 virtual bool isConstant() const override
322 return mpArg->isConstant();
324 virtual ExpressionFunct getType() const override
326 return meFunct;
328 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* pOptionalArg, sal_uInt32 nFlags ) override
330 EnhancedCustomShapeParameter aRet;
331 switch( meFunct )
333 case ExpressionFunct::UnaryAbs :
335 EnhancedCustomShapeEquation aEquation;
336 aEquation.nOperation |= 3;
337 FillEquationParameter( mpArg->fillNode( rEquations, nullptr, nFlags ), 0, aEquation );
338 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
339 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
340 rEquations.push_back( aEquation );
342 break;
343 case ExpressionFunct::UnarySqrt:
345 EnhancedCustomShapeEquation aEquation;
346 aEquation.nOperation |= 13;
347 FillEquationParameter( mpArg->fillNode( rEquations, nullptr, nFlags ), 0, aEquation );
348 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
349 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
350 rEquations.push_back( aEquation );
352 break;
353 case ExpressionFunct::UnarySin :
355 EnhancedCustomShapeEquation aEquation;
356 aEquation.nOperation |= 9;
357 if ( pOptionalArg )
358 FillEquationParameter( pOptionalArg->fillNode( rEquations, nullptr, nFlags ), 0, aEquation );
359 else
360 aEquation.nPara[ 0 ] = 1;
362 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, nullptr, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
363 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
364 { // sumangle needed :-(
365 EnhancedCustomShapeEquation _aEquation;
366 _aEquation.nOperation |= 0xe; // sumangle
367 FillEquationParameter( aSource, 1, _aEquation );
368 aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
369 aSource.Value <<= static_cast<sal_Int32>(rEquations.size());
370 rEquations.push_back( _aEquation );
372 FillEquationParameter( aSource, 1, aEquation );
373 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
374 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
375 rEquations.push_back( aEquation );
377 break;
378 case ExpressionFunct::UnaryCos :
380 EnhancedCustomShapeEquation aEquation;
381 aEquation.nOperation |= 10;
382 if ( pOptionalArg )
383 FillEquationParameter( pOptionalArg->fillNode( rEquations, nullptr, nFlags ), 0, aEquation );
384 else
385 aEquation.nPara[ 0 ] = 1;
387 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, nullptr, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
388 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
389 { // sumangle needed :-(
390 EnhancedCustomShapeEquation aTmpEquation;
391 aTmpEquation.nOperation |= 0xe; // sumangle
392 FillEquationParameter( aSource, 1, aTmpEquation );
393 aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
394 aSource.Value <<= static_cast<sal_Int32>(rEquations.size());
395 rEquations.push_back( aTmpEquation );
397 FillEquationParameter( aSource, 1, aEquation );
398 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
399 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
400 rEquations.push_back( aEquation );
402 break;
403 case ExpressionFunct::UnaryTan :
405 EnhancedCustomShapeEquation aEquation;
406 aEquation.nOperation |= 16;
407 if ( pOptionalArg )
408 FillEquationParameter( pOptionalArg->fillNode( rEquations, nullptr, nFlags ), 0, aEquation );
409 else
410 aEquation.nPara[ 0 ] = 1;
412 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, nullptr, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
413 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
414 { // sumangle needed :-(
415 EnhancedCustomShapeEquation aTmpEquation;
416 aTmpEquation.nOperation |= 0xe; // sumangle
417 FillEquationParameter( aSource, 1, aTmpEquation );
418 aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
419 aSource.Value <<= static_cast<sal_Int32>(rEquations.size());
420 rEquations.push_back( aTmpEquation );
422 FillEquationParameter( aSource, 1, aEquation );
423 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
424 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
425 rEquations.push_back( aEquation );
427 break;
428 case ExpressionFunct::UnaryAtan:
430 // TODO:
431 aRet.Type = EnhancedCustomShapeParameterType::NORMAL;
433 break;
434 case ExpressionFunct::UnaryNeg:
436 EnhancedCustomShapeEquation aEquation;
437 aEquation.nOperation |= 1;
438 aEquation.nPara[ 1 ] = -1;
439 aEquation.nPara[ 2 ] = 1;
440 FillEquationParameter( mpArg->fillNode( rEquations, nullptr, nFlags ), 0, aEquation );
441 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
442 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
443 rEquations.push_back( aEquation );
445 break;
446 default:
447 break;
449 return aRet;
453 /** ExpressionNode implementation for unary
454 function over two ExpressionNodes
456 class BinaryFunctionExpression : public ExpressionNode
458 const ExpressionFunct meFunct;
459 std::shared_ptr<ExpressionNode> mpFirstArg;
460 std::shared_ptr<ExpressionNode> mpSecondArg;
462 public:
464 BinaryFunctionExpression( const ExpressionFunct eFunct, std::shared_ptr<ExpressionNode> xFirstArg, std::shared_ptr<ExpressionNode> xSecondArg ) :
465 meFunct( eFunct ),
466 mpFirstArg(std::move( xFirstArg )),
467 mpSecondArg(std::move( xSecondArg ))
470 #if defined(__clang__) || defined (__GNUC__)
471 //GetEquationValueAsDouble calls isFinite on the result
472 __attribute__((no_sanitize("float-divide-by-zero")))
473 #endif
474 static double getValue( const ExpressionFunct eFunct, const std::shared_ptr<ExpressionNode>& rFirstArg, const std::shared_ptr<ExpressionNode>& rSecondArg )
476 double fRet = 0;
477 switch( eFunct )
479 case ExpressionFunct::BinaryPlus : fRet = (*rFirstArg)() + (*rSecondArg)(); break;
480 case ExpressionFunct::BinaryMinus: fRet = (*rFirstArg)() - (*rSecondArg)(); break;
481 case ExpressionFunct::BinaryMul : fRet = (*rFirstArg)() * (*rSecondArg)(); break;
482 case ExpressionFunct::BinaryDiv : fRet = (*rFirstArg)() / (*rSecondArg)(); break;
483 case ExpressionFunct::BinaryMin : fRet = ::std::min( (*rFirstArg)(), (*rSecondArg)() ); break;
484 case ExpressionFunct::BinaryMax : fRet = ::std::max( (*rFirstArg)(), (*rSecondArg)() ); break;
485 case ExpressionFunct::BinaryAtan2: fRet = atan2( (*rFirstArg)(), (*rSecondArg)() ); break;
486 default:
487 break;
489 return fRet;
491 virtual double operator()() const override
493 return getValue( meFunct, mpFirstArg, mpSecondArg );
495 virtual bool isConstant() const override
497 return mpFirstArg->isConstant() && mpSecondArg->isConstant();
499 virtual ExpressionFunct getType() const override
501 return meFunct;
503 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags ) override
505 EnhancedCustomShapeParameter aRet;
506 switch( meFunct )
508 case ExpressionFunct::BinaryPlus :
510 if ( nFlags & EXPRESSION_FLAG_SUMANGLE_MODE )
512 if ( mpFirstArg->getType() == ExpressionFunct::EnumAdjustment )
514 EnhancedCustomShapeEquation aEquation;
515 aEquation.nOperation |= 0xe; // sumangle
516 FillEquationParameter( mpFirstArg->fillNode( rEquations, nullptr, nFlags ), 0, aEquation );
517 FillEquationParameter( mpSecondArg->fillNode( rEquations, nullptr, nFlags ), 1, aEquation );
518 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
519 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
520 rEquations.push_back( aEquation );
522 else if ( mpSecondArg->getType() == ExpressionFunct::EnumAdjustment )
524 EnhancedCustomShapeEquation aEquation;
525 aEquation.nOperation |= 0xe; // sumangle
526 FillEquationParameter( mpSecondArg->fillNode( rEquations, nullptr, nFlags ), 0, aEquation );
527 FillEquationParameter( mpFirstArg->fillNode( rEquations, nullptr, nFlags ), 1, aEquation );
528 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
529 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
530 rEquations.push_back( aEquation );
532 else
534 EnhancedCustomShapeEquation aSumangle1;
535 aSumangle1.nOperation |= 0xe; // sumangle
536 FillEquationParameter( mpFirstArg->fillNode( rEquations, nullptr, nFlags &~EXPRESSION_FLAG_SUMANGLE_MODE ), 1, aSumangle1 );
537 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
538 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
539 rEquations.push_back( aSumangle1 );
541 EnhancedCustomShapeEquation aSumangle2;
542 aSumangle2.nOperation |= 0xe; // sumangle
543 FillEquationParameter( mpSecondArg->fillNode( rEquations, nullptr, nFlags &~EXPRESSION_FLAG_SUMANGLE_MODE ), 1, aSumangle2 );
544 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
545 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
546 rEquations.push_back( aSumangle2 );
548 EnhancedCustomShapeEquation aEquation;
549 aEquation.nOperation |= 0;
550 aEquation.nPara[ 0 ] = ( rEquations.size() - 2 ) | 0x400;
551 aEquation.nPara[ 1 ] = ( rEquations.size() - 1 ) | 0x400;
552 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
553 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
554 rEquations.push_back( aEquation );
557 else
559 bool bFirstIsEmpty = mpFirstArg->isConstant() && ( (*mpFirstArg)() == 0 );
560 bool bSecondIsEmpty = mpSecondArg->isConstant() && ( (*mpSecondArg)() == 0 );
562 if ( bFirstIsEmpty )
563 aRet = mpSecondArg->fillNode( rEquations, nullptr, nFlags );
564 else if ( bSecondIsEmpty )
565 aRet = mpFirstArg->fillNode( rEquations, nullptr, nFlags );
566 else
568 EnhancedCustomShapeEquation aEquation;
569 aEquation.nOperation |= 0;
570 FillEquationParameter( mpFirstArg->fillNode( rEquations, nullptr, nFlags ), 0, aEquation );
571 FillEquationParameter( mpSecondArg->fillNode( rEquations, nullptr, nFlags ), 1, aEquation );
572 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
573 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
574 rEquations.push_back( aEquation );
578 break;
579 case ExpressionFunct::BinaryMinus:
581 EnhancedCustomShapeEquation aEquation;
582 aEquation.nOperation |= 0;
583 FillEquationParameter( mpFirstArg->fillNode( rEquations, nullptr, nFlags ), 0, aEquation );
584 FillEquationParameter( mpSecondArg->fillNode( rEquations, nullptr, nFlags ), 2, aEquation );
585 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
586 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
587 rEquations.push_back( aEquation );
589 break;
590 case ExpressionFunct::BinaryMul :
592 // in the dest. format the cos function is using integer as result :-(
593 // so we can't use the generic algorithm
594 if ( ( mpFirstArg->getType() == ExpressionFunct::UnarySin ) || ( mpFirstArg->getType() == ExpressionFunct::UnaryCos ) || ( mpFirstArg->getType() == ExpressionFunct::UnaryTan ) )
595 aRet = mpFirstArg->fillNode( rEquations, mpSecondArg.get(), nFlags );
596 else if ( ( mpSecondArg->getType() == ExpressionFunct::UnarySin ) || ( mpSecondArg->getType() == ExpressionFunct::UnaryCos ) || ( mpSecondArg->getType() == ExpressionFunct::UnaryTan ) )
597 aRet = mpSecondArg->fillNode( rEquations, mpFirstArg.get(), nFlags );
598 else
600 if ( mpFirstArg->isConstant() && (*mpFirstArg)() == 1 )
601 aRet = mpSecondArg->fillNode( rEquations, nullptr, nFlags );
602 else if ( mpSecondArg->isConstant() && (*mpSecondArg)() == 1 )
603 aRet = mpFirstArg->fillNode( rEquations, nullptr, nFlags );
604 else if ( ( mpFirstArg->getType() == ExpressionFunct::BinaryDiv ) // don't care of (pi/180)
605 && ( static_cast<BinaryFunctionExpression*>(mpFirstArg.get())->mpFirstArg->getType() == ExpressionFunct::EnumPi )
606 && ( static_cast<BinaryFunctionExpression*>(mpFirstArg.get())->mpSecondArg->getType() == ExpressionFunct::Const ) )
608 aRet = mpSecondArg->fillNode( rEquations, nullptr, nFlags );
610 else if ( ( mpSecondArg->getType() == ExpressionFunct::BinaryDiv ) // don't care of (pi/180)
611 && ( static_cast<BinaryFunctionExpression*>(mpSecondArg.get())->mpFirstArg->getType() == ExpressionFunct::EnumPi )
612 && ( static_cast<BinaryFunctionExpression*>(mpSecondArg.get())->mpSecondArg->getType() == ExpressionFunct::Const ) )
614 aRet = mpFirstArg->fillNode( rEquations, nullptr, nFlags );
616 else
618 EnhancedCustomShapeEquation aEquation;
619 aEquation.nOperation |= 1;
620 FillEquationParameter( mpFirstArg->fillNode( rEquations, nullptr, nFlags ), 0, aEquation );
621 FillEquationParameter( mpSecondArg->fillNode( rEquations, nullptr, nFlags ), 1, aEquation );
622 aEquation.nPara[ 2 ] = 1;
623 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
624 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
625 rEquations.push_back( aEquation );
629 break;
630 case ExpressionFunct::BinaryDiv :
632 EnhancedCustomShapeEquation aEquation;
633 aEquation.nOperation |= 1;
634 FillEquationParameter( mpFirstArg->fillNode( rEquations, nullptr, nFlags ), 0, aEquation );
635 aEquation.nPara[ 1 ] = 1;
636 FillEquationParameter( mpSecondArg->fillNode( rEquations, nullptr, nFlags ), 2, aEquation );
637 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
638 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
639 rEquations.push_back( aEquation );
641 break;
642 case ExpressionFunct::BinaryMin :
644 EnhancedCustomShapeEquation aEquation;
645 aEquation.nOperation |= 4;
646 FillEquationParameter( mpFirstArg->fillNode( rEquations, nullptr, nFlags ), 0, aEquation );
647 FillEquationParameter( mpSecondArg->fillNode( rEquations, nullptr, nFlags ), 1, aEquation );
648 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
649 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
650 rEquations.push_back( aEquation );
652 break;
653 case ExpressionFunct::BinaryMax :
655 EnhancedCustomShapeEquation aEquation;
656 aEquation.nOperation |= 5;
657 FillEquationParameter( mpFirstArg->fillNode( rEquations, nullptr, nFlags ), 0, aEquation );
658 FillEquationParameter( mpSecondArg->fillNode( rEquations, nullptr, nFlags ), 1, aEquation );
659 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
660 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
661 rEquations.push_back( aEquation );
663 break;
664 case ExpressionFunct::BinaryAtan2:
666 EnhancedCustomShapeEquation aEquation;
667 aEquation.nOperation |= 8;
668 FillEquationParameter( mpSecondArg->fillNode( rEquations, nullptr, nFlags ), 0, aEquation );
669 FillEquationParameter( mpFirstArg->fillNode( rEquations, nullptr, nFlags ), 1, aEquation );
670 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
671 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
672 rEquations.push_back( aEquation );
674 break;
675 default:
676 break;
678 return aRet;
682 class IfExpression : public ExpressionNode
684 std::shared_ptr<ExpressionNode> mpFirstArg;
685 std::shared_ptr<ExpressionNode> mpSecondArg;
686 std::shared_ptr<ExpressionNode> mpThirdArg;
688 public:
690 IfExpression( std::shared_ptr<ExpressionNode> xFirstArg,
691 std::shared_ptr<ExpressionNode> xSecondArg,
692 std::shared_ptr<ExpressionNode> xThirdArg ) :
693 mpFirstArg(std::move( xFirstArg )),
694 mpSecondArg(std::move(xSecondArg )),
695 mpThirdArg(std::move( xThirdArg ))
698 virtual bool isConstant() const override
700 return
701 mpFirstArg->isConstant() &&
702 mpSecondArg->isConstant() &&
703 mpThirdArg->isConstant();
705 virtual double operator()() const override
707 return (*mpFirstArg)() > 0 ? (*mpSecondArg)() : (*mpThirdArg)();
709 virtual ExpressionFunct getType() const override
711 return ExpressionFunct::TernaryIf;
713 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags ) override
715 EnhancedCustomShapeParameter aRet;
716 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
717 aRet.Value <<= static_cast<sal_Int32>(rEquations.size());
719 EnhancedCustomShapeEquation aEquation;
720 aEquation.nOperation |= 6;
721 FillEquationParameter( mpFirstArg->fillNode( rEquations, nullptr, nFlags ), 0, aEquation );
722 FillEquationParameter( mpSecondArg->fillNode( rEquations, nullptr, nFlags ), 1, aEquation );
723 FillEquationParameter( mpThirdArg->fillNode( rEquations, nullptr, nFlags ), 2, aEquation );
724 rEquations.push_back( aEquation );
726 return aRet;
731 // FUNCTION PARSER
734 typedef const char* StringIteratorT;
736 struct ParserContext
738 typedef ::std::stack< std::shared_ptr<ExpressionNode> > OperandStack;
740 // stores a stack of not-yet-evaluated operands. This is used
741 // by the operators (i.e. '+', '*', 'sin' etc.) to pop their
742 // arguments from. If all arguments to an operator are constant,
743 // the operator pushes a precalculated result on the stack, and
744 // a composite ExpressionNode otherwise.
745 OperandStack maOperandStack;
747 const EnhancedCustomShape2d* mpCustoShape;
751 typedef std::shared_ptr< ParserContext > ParserContextSharedPtr;
753 /** Generate parse-dependent-but-then-constant value
755 class DoubleConstantFunctor
757 ParserContextSharedPtr mxContext;
759 public:
760 explicit DoubleConstantFunctor( ParserContextSharedPtr xContext ) :
761 mxContext(std::move( xContext ))
764 void operator()( double n ) const
766 mxContext->maOperandStack.push( std::make_shared<ConstantValueExpression>( n ) );
770 class EnumFunctor
772 const ExpressionFunct meFunct;
773 ParserContextSharedPtr mxContext;
775 public:
777 EnumFunctor( const ExpressionFunct eFunct, ParserContextSharedPtr xContext )
778 : meFunct( eFunct )
779 , mxContext(std::move( xContext ))
782 void operator()( StringIteratorT rFirst, StringIteratorT rSecond ) const
784 /*double nVal = mnValue;*/
785 switch( meFunct )
787 case ExpressionFunct::EnumAdjustment :
789 OUString aVal( rFirst + 1, rSecond - rFirst, RTL_TEXTENCODING_UTF8 );
790 mxContext->maOperandStack.push( std::make_shared<AdjustmentExpression>( *mxContext->mpCustoShape, aVal.toInt32() ) );
792 break;
793 case ExpressionFunct::EnumEquation :
795 OUString aVal( rFirst + 1, rSecond - rFirst, RTL_TEXTENCODING_UTF8 );
796 mxContext->maOperandStack.push( std::make_shared<EquationExpression>( *mxContext->mpCustoShape, aVal.toInt32() ) );
798 break;
799 default:
800 mxContext->maOperandStack.push( std::make_shared<EnumValueExpression>( *mxContext->mpCustoShape, meFunct ) );
805 class UnaryFunctionFunctor
807 const ExpressionFunct meFunct;
808 ParserContextSharedPtr mxContext;
810 public:
812 UnaryFunctionFunctor( const ExpressionFunct eFunct, ParserContextSharedPtr xContext ) :
813 meFunct( eFunct ),
814 mxContext(std::move( xContext ))
817 void operator()( StringIteratorT, StringIteratorT ) const
819 ParserContext::OperandStack& rNodeStack( mxContext->maOperandStack );
821 if( rNodeStack.empty() )
822 throw ParseError( "Not enough arguments for unary operator" );
824 // retrieve arguments
825 std::shared_ptr<ExpressionNode> pArg( std::move(rNodeStack.top()) );
826 rNodeStack.pop();
828 if( pArg->isConstant() ) // check for constness
829 rNodeStack.push( std::make_shared<ConstantValueExpression>( UnaryFunctionExpression::getValue( meFunct, pArg ) ) );
830 else // push complex node, that calcs the value on demand
831 rNodeStack.push( std::make_shared<UnaryFunctionExpression>( meFunct, pArg ) );
835 /** Implements a binary function over two ExpressionNodes
837 @tpl Generator
838 Generator functor, to generate an ExpressionNode of
839 appropriate type
842 class BinaryFunctionFunctor
844 const ExpressionFunct meFunct;
845 ParserContextSharedPtr mxContext;
847 public:
849 BinaryFunctionFunctor( const ExpressionFunct eFunct, ParserContextSharedPtr xContext ) :
850 meFunct( eFunct ),
851 mxContext(std::move( xContext ))
855 void operator()( StringIteratorT, StringIteratorT ) const
857 ParserContext::OperandStack& rNodeStack( mxContext->maOperandStack );
859 if( rNodeStack.size() < 2 )
860 throw ParseError( "Not enough arguments for binary operator" );
862 // retrieve arguments
863 std::shared_ptr<ExpressionNode> pSecondArg( std::move(rNodeStack.top()) );
864 rNodeStack.pop();
865 std::shared_ptr<ExpressionNode> pFirstArg( std::move(rNodeStack.top()) );
866 rNodeStack.pop();
868 assert(pSecondArg && pFirstArg && "count of arg checked before we get here");
870 // create combined ExpressionNode
871 auto pNode = std::make_shared<BinaryFunctionExpression>( meFunct, pFirstArg, pSecondArg );
872 // check for constness
873 if( pFirstArg->isConstant() && pSecondArg->isConstant() ) // call the operator() at pNode, store result in constant value ExpressionNode.
874 rNodeStack.push( std::make_shared<ConstantValueExpression>( (*pNode)() ) );
875 else // push complex node, that calcs the value on demand
876 rNodeStack.push( pNode );
880 class IfFunctor
882 ParserContextSharedPtr mxContext;
884 public:
886 explicit IfFunctor( ParserContextSharedPtr xContext ) :
887 mxContext(std::move( xContext ))
890 void operator()( StringIteratorT, StringIteratorT ) const
892 ParserContext::OperandStack& rNodeStack( mxContext->maOperandStack );
894 if( rNodeStack.size() < 3 )
895 throw ParseError( "Not enough arguments for ternary operator" );
897 // retrieve arguments
898 std::shared_ptr<ExpressionNode> pThirdArg( std::move(rNodeStack.top()) );
899 rNodeStack.pop();
900 std::shared_ptr<ExpressionNode> pSecondArg( std::move(rNodeStack.top()) );
901 rNodeStack.pop();
902 std::shared_ptr<ExpressionNode> pFirstArg( std::move(rNodeStack.top()) );
903 rNodeStack.pop();
905 assert(pThirdArg && pSecondArg && pFirstArg);
907 // create combined ExpressionNode
908 auto pNode = std::make_shared<IfExpression>( pFirstArg, pSecondArg, pThirdArg );
909 // check for constness
910 if( pFirstArg->isConstant() && pSecondArg->isConstant() && pThirdArg->isConstant() )
911 rNodeStack.push( std::make_shared<ConstantValueExpression>( (*pNode)() ) ); // call the operator() at pNode, store result in constant value ExpressionNode.
912 else
913 rNodeStack.push( pNode ); // push complex node, that calcs the value on demand
917 // Workaround for MSVC compiler anomaly (stack trashing)
919 // The default ureal_parser_policies implementation of parse_exp
920 // triggers a really weird error in MSVC7 (Version 13.00.9466), in
921 // that the real_parser_impl::parse_main() call of parse_exp()
922 // overwrites the frame pointer _on the stack_ (EBP of the calling
923 // function gets overwritten while lying on the stack).
925 // For the time being, our parser thus can only read the 1.0E10
926 // notation, not the 1.0e10 one.
928 // TODO(F1): Also handle the 1.0e10 case here.
929 template< typename T > struct custom_real_parser_policies : public ::boost::spirit::classic::ureal_parser_policies<T>
931 template< typename ScannerT >
932 static typename ::boost::spirit::classic::parser_result< ::boost::spirit::classic::chlit<>, ScannerT >::type
933 parse_exp(ScannerT& scan)
935 // as_lower_d somehow breaks MSVC7
936 return ::boost::spirit::classic::ch_p('E').parse(scan);
940 /* This class implements the following grammar (more or
941 less literally written down below, only slightly
942 obfuscated by the parser actions):
944 identifier = '$'|'pi'|'e'|'X'|'Y'|'Width'|'Height'
946 function = 'abs'|'sqrt'|'sin'|'cos'|'tan'|'atan'|'acos'|'asin'|'exp'|'log'
948 basic_expression =
949 number |
950 identifier |
951 function '(' additive_expression ')' |
952 '(' additive_expression ')'
954 unary_expression =
955 '-' basic_expression |
956 basic_expression
958 multiplicative_expression =
959 unary_expression ( ( '*' unary_expression )* |
960 ( '/' unary_expression )* )
962 additive_expression =
963 multiplicative_expression ( ( '+' multiplicative_expression )* |
964 ( '-' multiplicative_expression )* )
968 class ExpressionGrammar : public ::boost::spirit::classic::grammar< ExpressionGrammar >
970 public:
971 /** Create an arithmetic expression grammar
973 @param rParserContext
974 Contains context info for the parser
976 explicit ExpressionGrammar( ParserContextSharedPtr xParserContext ) :
977 mpParserContext(std::move( xParserContext ))
981 template< typename ScannerT > class definition
983 public:
984 // grammar definition
985 explicit definition( const ExpressionGrammar& self )
987 using ::boost::spirit::classic::str_p;
988 using ::boost::spirit::classic::range_p;
989 using ::boost::spirit::classic::lexeme_d;
990 using ::boost::spirit::classic::real_parser;
992 identifier =
993 str_p( "pi" )[ EnumFunctor(ExpressionFunct::EnumPi, self.getContext() ) ]
994 | str_p( "left" )[ EnumFunctor(ExpressionFunct::EnumLeft, self.getContext() ) ]
995 | str_p( "top" )[ EnumFunctor(ExpressionFunct::EnumTop, self.getContext() ) ]
996 | str_p( "right" )[ EnumFunctor(ExpressionFunct::EnumRight, self.getContext() ) ]
997 | str_p( "bottom" )[ EnumFunctor(ExpressionFunct::EnumBottom, self.getContext() ) ]
998 | str_p( "xstretch" )[ EnumFunctor(ExpressionFunct::EnumXStretch, self.getContext() ) ]
999 | str_p( "ystretch" )[ EnumFunctor(ExpressionFunct::EnumYStretch, self.getContext() ) ]
1000 | str_p( "hasstroke" )[ EnumFunctor(ExpressionFunct::EnumHasStroke, self.getContext() ) ]
1001 | str_p( "hasfill" )[ EnumFunctor(ExpressionFunct::EnumHasFill, self.getContext() ) ]
1002 | str_p( "width" )[ EnumFunctor(ExpressionFunct::EnumWidth, self.getContext() ) ]
1003 | str_p( "height" )[ EnumFunctor(ExpressionFunct::EnumHeight, self.getContext() ) ]
1004 | str_p( "logwidth" )[ EnumFunctor(ExpressionFunct::EnumLogWidth, self.getContext() ) ]
1005 | str_p( "logheight" )[ EnumFunctor(ExpressionFunct::EnumLogHeight, self.getContext() ) ]
1008 unaryFunction =
1009 (str_p( "abs" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( ExpressionFunct::UnaryAbs, self.getContext()) ]
1010 | (str_p( "sqrt" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( ExpressionFunct::UnarySqrt, self.getContext()) ]
1011 | (str_p( "sin" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( ExpressionFunct::UnarySin, self.getContext()) ]
1012 | (str_p( "cos" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( ExpressionFunct::UnaryCos, self.getContext()) ]
1013 | (str_p( "tan" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( ExpressionFunct::UnaryTan, self.getContext()) ]
1014 | (str_p( "atan" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( ExpressionFunct::UnaryAtan, self.getContext()) ]
1017 binaryFunction =
1018 (str_p( "min" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( ExpressionFunct::BinaryMin, self.getContext()) ]
1019 | (str_p( "max" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( ExpressionFunct::BinaryMax, self.getContext()) ]
1020 | (str_p( "atan2") >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( ExpressionFunct::BinaryAtan2,self.getContext()) ]
1023 ternaryFunction =
1024 (str_p( "if" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ IfFunctor( self.getContext() ) ]
1027 funcRef_decl =
1028 lexeme_d[ +( range_p('a','z') | range_p('A','Z') | range_p('0','9') ) ];
1030 functionReference =
1031 (str_p( "?" ) >> funcRef_decl )[ EnumFunctor( ExpressionFunct::EnumEquation, self.getContext() ) ];
1033 modRef_decl =
1034 lexeme_d[ +( range_p('0','9') ) ];
1036 modifierReference =
1037 (str_p( "$" ) >> modRef_decl )[ EnumFunctor( ExpressionFunct::EnumAdjustment, self.getContext() ) ];
1039 basicExpression =
1040 real_parser<double, custom_real_parser_policies<double> >()[ DoubleConstantFunctor(self.getContext()) ]
1041 | identifier
1042 | functionReference
1043 | modifierReference
1044 | unaryFunction
1045 | binaryFunction
1046 | ternaryFunction
1047 | '(' >> additiveExpression >> ')'
1050 unaryExpression =
1051 ('-' >> basicExpression)[ UnaryFunctionFunctor( ExpressionFunct::UnaryNeg, self.getContext()) ]
1052 | basicExpression
1055 multiplicativeExpression =
1056 unaryExpression
1057 >> *( ('*' >> unaryExpression)[ BinaryFunctionFunctor( ExpressionFunct::BinaryMul, self.getContext()) ]
1058 | ('/' >> unaryExpression)[ BinaryFunctionFunctor( ExpressionFunct::BinaryDiv, self.getContext()) ]
1062 additiveExpression =
1063 multiplicativeExpression
1064 >> *( ('+' >> multiplicativeExpression)[ BinaryFunctionFunctor( ExpressionFunct::BinaryPlus, self.getContext()) ]
1065 | ('-' >> multiplicativeExpression)[ BinaryFunctionFunctor( ExpressionFunct::BinaryMinus, self.getContext()) ]
1069 BOOST_SPIRIT_DEBUG_RULE(additiveExpression);
1070 BOOST_SPIRIT_DEBUG_RULE(multiplicativeExpression);
1071 BOOST_SPIRIT_DEBUG_RULE(unaryExpression);
1072 BOOST_SPIRIT_DEBUG_RULE(basicExpression);
1073 BOOST_SPIRIT_DEBUG_RULE(unaryFunction);
1074 BOOST_SPIRIT_DEBUG_RULE(binaryFunction);
1075 BOOST_SPIRIT_DEBUG_RULE(ternaryFunction);
1076 BOOST_SPIRIT_DEBUG_RULE(identifier);
1079 const ::boost::spirit::classic::rule< ScannerT >& start() const
1081 return additiveExpression;
1084 private:
1085 // the constituents of the Spirit arithmetic expression grammar.
1086 // For the sake of readability, without 'ma' prefix.
1087 ::boost::spirit::classic::rule< ScannerT > additiveExpression;
1088 ::boost::spirit::classic::rule< ScannerT > multiplicativeExpression;
1089 ::boost::spirit::classic::rule< ScannerT > unaryExpression;
1090 ::boost::spirit::classic::rule< ScannerT > basicExpression;
1091 ::boost::spirit::classic::rule< ScannerT > unaryFunction;
1092 ::boost::spirit::classic::rule< ScannerT > binaryFunction;
1093 ::boost::spirit::classic::rule< ScannerT > ternaryFunction;
1094 ::boost::spirit::classic::rule< ScannerT > funcRef_decl;
1095 ::boost::spirit::classic::rule< ScannerT > functionReference;
1096 ::boost::spirit::classic::rule< ScannerT > modRef_decl;
1097 ::boost::spirit::classic::rule< ScannerT > modifierReference;
1098 ::boost::spirit::classic::rule< ScannerT > identifier;
1101 const ParserContextSharedPtr& getContext() const
1103 return mpParserContext;
1106 private:
1107 ParserContextSharedPtr mpParserContext; // might get modified during parsing
1110 const ParserContextSharedPtr& getParserContext()
1112 static ParserContextSharedPtr lcl_parserContext = std::make_shared<ParserContext>();
1114 // clear node stack (since we reuse the static object, that's
1115 // the whole point here)
1116 while( !lcl_parserContext->maOperandStack.empty() )
1117 lcl_parserContext->maOperandStack.pop();
1119 return lcl_parserContext;
1124 namespace EnhancedCustomShape {
1127 std::shared_ptr<ExpressionNode> const & FunctionParser::parseFunction( std::u16string_view rFunction, const EnhancedCustomShape2d& rCustoShape )
1129 // TODO(Q1): Check if a combination of the RTL_UNICODETOTEXT_FLAGS_*
1130 // gives better conversion robustness here (we might want to map space
1131 // etc. to ASCII space here)
1132 const OString aAsciiFunction(
1133 OUStringToOString( rFunction, RTL_TEXTENCODING_ASCII_US ) );
1135 StringIteratorT aStart( aAsciiFunction.getStr() );
1136 StringIteratorT aEnd( aAsciiFunction.getStr()+aAsciiFunction.getLength() );
1138 // static parser context, because the actual
1139 // Spirit parser is also a static object
1140 const ParserContextSharedPtr& pContext = getParserContext();
1141 pContext->mpCustoShape = &rCustoShape;
1143 ExpressionGrammar aExpressionGrammer( pContext );
1144 const ::boost::spirit::classic::parse_info<StringIteratorT> aParseInfo(
1145 ::boost::spirit::classic::parse( aStart,
1146 aEnd,
1147 aExpressionGrammer >> ::boost::spirit::classic::end_p,
1148 ::boost::spirit::classic::space_p ) );
1150 // input fully congested by the parser?
1151 if( !aParseInfo.full )
1152 throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): string not fully parseable" );
1154 // parser's state stack now must contain exactly _one_ ExpressionNode,
1155 // which represents our formula.
1156 if( pContext->maOperandStack.size() != 1 )
1157 throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): incomplete or empty expression" );
1160 return pContext->maOperandStack.top();
1165 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */