1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_svx.hxx" 26 #include "svx/EnhancedCustomShape2d.hxx" 27 #include <rtl/ustring.hxx> 28 #include <tools/fract.hxx> 29 30 // Makes parser a static resource, 31 // we're synchronized externally. 32 // But watch out, the parser might have 33 // state not visible to this code! 34 35 #define BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE 36 #if defined(VERBOSE) && defined(DBG_UTIL) 37 #include <typeinfo> 38 #define BOOST_SPIRIT_DEBUG 39 #endif 40 #include <boost/spirit/include/classic_core.hpp> 41 42 #if (OSL_DEBUG_LEVEL > 0) 43 #include <iostream> 44 #endif 45 #include <functional> 46 #include <algorithm> 47 #include <stack> 48 49 #include <math.h> // fabs, sqrt, sin, cos, tan, atan, atan2 50 using namespace EnhancedCustomShape; 51 using namespace com::sun::star; 52 using namespace com::sun::star::drawing; 53 54 void EnhancedCustomShape::FillEquationParameter( const EnhancedCustomShapeParameter& rSource, const sal_Int32 nDestPara, EnhancedCustomShapeEquation& rDest ) 55 { 56 sal_Int32 nValue = 0; 57 if ( rSource.Value.getValueTypeClass() == uno::TypeClass_DOUBLE ) 58 { 59 double fValue; 60 if ( rSource.Value >>= fValue ) 61 nValue = (sal_Int32)fValue; 62 } 63 else 64 rSource.Value >>= nValue; 65 66 switch( rSource.Type ) 67 { 68 case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION : 69 { 70 if ( nValue & 0x40000000 ) 71 { 72 nValue ^= 0x40000000; 73 rDest.nOperation |= 0x20000000 << nDestPara; // the bit is indicating that this value has to be adjusted later 74 } 75 nValue |= 0x400; 76 } 77 break; 78 case com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT : nValue += DFF_Prop_adjustValue; break; 79 case com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM : nValue = DFF_Prop_geoBottom; break; 80 case com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT : nValue = DFF_Prop_geoRight; break; 81 case com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP : nValue = DFF_Prop_geoTop; break; 82 case com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT : nValue = DFF_Prop_geoLeft; break; 83 } 84 if ( rSource.Type != com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL ) 85 rDest.nOperation |= ( 0x2000 << nDestPara ); 86 rDest.nPara[ nDestPara ] = nValue; 87 } 88 89 ExpressionNode::~ExpressionNode() 90 {} 91 92 namespace 93 { 94 95 ////////////////////// 96 ////////////////////// 97 // EXPRESSION NODES 98 ////////////////////// 99 ////////////////////// 100 class ConstantValueExpression : public ExpressionNode 101 { 102 double maValue; 103 104 public: 105 106 ConstantValueExpression( double rValue ) : 107 maValue( rValue ) 108 { 109 } 110 virtual double operator()() const 111 { 112 return maValue; 113 } 114 virtual bool isConstant() const 115 { 116 return true; 117 } 118 virtual ExpressionFunct getType() const 119 { 120 return FUNC_CONST; 121 } 122 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /* pOptionalArg */, sal_uInt32 /* nFlags */ ) 123 { 124 EnhancedCustomShapeParameter aRet; 125 Fraction aFract( maValue ); 126 if ( aFract.GetDenominator() == 1 ) 127 { 128 aRet.Type = EnhancedCustomShapeParameterType::NORMAL; 129 aRet.Value <<= (sal_Int32)aFract.GetNumerator(); 130 } 131 else 132 { 133 EnhancedCustomShapeEquation aEquation; 134 aEquation.nOperation = 1; 135 aEquation.nPara[ 0 ] = 1; 136 aEquation.nPara[ 1 ] = (sal_Int16)aFract.GetNumerator(); 137 aEquation.nPara[ 2 ] = (sal_Int16)aFract.GetDenominator(); 138 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 139 aRet.Value <<= (sal_Int32)rEquations.size(); 140 rEquations.push_back( aEquation ); 141 } 142 return aRet; 143 } 144 }; 145 146 class AdjustmentExpression : public ExpressionNode 147 { 148 sal_Int32 mnIndex; 149 const EnhancedCustomShape2d& mrCustoShape; 150 151 public: 152 153 AdjustmentExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex ) 154 : mnIndex ( nIndex ) 155 , mrCustoShape( rCustoShape ) 156 157 { 158 } 159 virtual double operator()() const 160 { 161 return mrCustoShape.GetAdjustValueAsDouble( mnIndex ); 162 } 163 virtual bool isConstant() const 164 { 165 return false; 166 } 167 virtual ExpressionFunct getType() const 168 { 169 return ENUM_FUNC_ADJUSTMENT; 170 } 171 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ ) 172 { 173 EnhancedCustomShapeParameter aRet; 174 aRet.Type = EnhancedCustomShapeParameterType::ADJUSTMENT; 175 aRet.Value <<= mnIndex; 176 return aRet; 177 } 178 }; 179 180 class EquationExpression : public ExpressionNode 181 { 182 sal_Int32 mnIndex; 183 const EnhancedCustomShape2d& mrCustoShape; 184 185 public: 186 187 EquationExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex ) 188 : mnIndex ( nIndex ) 189 , mrCustoShape( rCustoShape ) 190 { 191 } 192 virtual double operator()() const 193 { 194 return mrCustoShape.GetEquationValueAsDouble( mnIndex ); 195 } 196 virtual bool isConstant() const 197 { 198 return false; 199 } 200 virtual ExpressionFunct getType() const 201 { 202 return ENUM_FUNC_EQUATION; 203 } 204 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ ) 205 { 206 EnhancedCustomShapeParameter aRet; 207 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 208 aRet.Value <<= mnIndex | 0x40000000; // the bit is indicating that this equation needs to be adjusted later 209 return aRet; 210 } 211 }; 212 213 class EnumValueExpression : public ExpressionNode 214 { 215 const ExpressionFunct meFunct; 216 const EnhancedCustomShape2d& mrCustoShape; 217 218 public: 219 220 EnumValueExpression( const EnhancedCustomShape2d& rCustoShape, const ExpressionFunct eFunct ) 221 : meFunct ( eFunct ) 222 , mrCustoShape ( rCustoShape ) 223 { 224 } 225 static double getValue( const EnhancedCustomShape2d& rCustoShape, const ExpressionFunct eFunc ) 226 { 227 EnhancedCustomShape2d::EnumFunc eF; 228 switch( eFunc ) 229 { 230 case ENUM_FUNC_PI : eF = EnhancedCustomShape2d::ENUM_FUNC_PI; break; 231 case ENUM_FUNC_LEFT : eF = EnhancedCustomShape2d::ENUM_FUNC_LEFT; break; 232 case ENUM_FUNC_TOP : eF = EnhancedCustomShape2d::ENUM_FUNC_TOP; break; 233 case ENUM_FUNC_RIGHT : eF = EnhancedCustomShape2d::ENUM_FUNC_RIGHT; break; 234 case ENUM_FUNC_BOTTOM : eF = EnhancedCustomShape2d::ENUM_FUNC_BOTTOM; break; 235 case ENUM_FUNC_XSTRETCH : eF = EnhancedCustomShape2d::ENUM_FUNC_XSTRETCH; break; 236 case ENUM_FUNC_YSTRETCH : eF = EnhancedCustomShape2d::ENUM_FUNC_YSTRETCH; break; 237 case ENUM_FUNC_HASSTROKE : eF = EnhancedCustomShape2d::ENUM_FUNC_HASSTROKE; break; 238 case ENUM_FUNC_HASFILL : eF = EnhancedCustomShape2d::ENUM_FUNC_HASFILL; break; 239 case ENUM_FUNC_WIDTH : eF = EnhancedCustomShape2d::ENUM_FUNC_WIDTH; break; 240 case ENUM_FUNC_HEIGHT : eF = EnhancedCustomShape2d::ENUM_FUNC_HEIGHT; break; 241 case ENUM_FUNC_LOGWIDTH : eF = EnhancedCustomShape2d::ENUM_FUNC_LOGWIDTH; break; 242 case ENUM_FUNC_LOGHEIGHT : eF = EnhancedCustomShape2d::ENUM_FUNC_LOGHEIGHT; break; 243 244 default : 245 return 0.0; 246 } 247 return rCustoShape.GetEnumFunc( eF ); 248 } 249 virtual double operator()() const 250 { 251 return getValue( mrCustoShape, meFunct ); 252 } 253 virtual bool isConstant() const 254 { 255 return false; 256 } 257 virtual ExpressionFunct getType() const 258 { 259 return meFunct; 260 } 261 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags ) 262 { 263 EnhancedCustomShapeParameter aRet; 264 265 sal_Int32 nDummy = 1; 266 aRet.Value <<= nDummy; 267 268 switch( meFunct ) 269 { 270 case ENUM_FUNC_WIDTH : // TODO: do not use this as constant value 271 case ENUM_FUNC_HEIGHT : 272 case ENUM_FUNC_LOGWIDTH : 273 case ENUM_FUNC_LOGHEIGHT : 274 case ENUM_FUNC_PI : 275 { 276 ConstantValueExpression aConstantValue( getValue( mrCustoShape, meFunct ) ); 277 aRet = aConstantValue.fillNode( rEquations, NULL, nFlags ); 278 } 279 break; 280 case ENUM_FUNC_LEFT : aRet.Type = EnhancedCustomShapeParameterType::LEFT; break; 281 case ENUM_FUNC_TOP : aRet.Type = EnhancedCustomShapeParameterType::TOP; break; 282 case ENUM_FUNC_RIGHT : aRet.Type = EnhancedCustomShapeParameterType::RIGHT; break; 283 case ENUM_FUNC_BOTTOM : aRet.Type = EnhancedCustomShapeParameterType::BOTTOM; break; 284 285 // not implemented so far 286 case ENUM_FUNC_XSTRETCH : 287 case ENUM_FUNC_YSTRETCH : 288 case ENUM_FUNC_HASSTROKE : 289 case ENUM_FUNC_HASFILL : aRet.Type = EnhancedCustomShapeParameterType::NORMAL; break; 290 291 default: 292 break; 293 } 294 return aRet; 295 } 296 }; 297 298 /** ExpressionNode implementation for unary 299 function over one ExpressionNode 300 */ 301 class UnaryFunctionExpression : public ExpressionNode 302 { 303 const ExpressionFunct meFunct; 304 ExpressionNodeSharedPtr mpArg; 305 306 public: 307 UnaryFunctionExpression( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rArg ) : 308 meFunct( eFunct ), 309 mpArg( rArg ) 310 { 311 } 312 static double getValue( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rArg ) 313 { 314 double fRet = 0; 315 switch( eFunct ) 316 { 317 case UNARY_FUNC_ABS : fRet = fabs( (*rArg)() ); break; 318 case UNARY_FUNC_SQRT: fRet = sqrt( (*rArg)() ); break; 319 case UNARY_FUNC_SIN : fRet = sin( (*rArg)() ); break; 320 case UNARY_FUNC_COS : fRet = cos( (*rArg)() ); break; 321 case UNARY_FUNC_TAN : fRet = tan( (*rArg)() ); break; 322 case UNARY_FUNC_ATAN: fRet = atan( (*rArg)() ); break; 323 case UNARY_FUNC_NEG : fRet = ::std::negate<double>()( (*rArg)() ); break; 324 default: 325 break; 326 } 327 return fRet; 328 } 329 virtual double operator()() const 330 { 331 return getValue( meFunct, mpArg ); 332 } 333 virtual bool isConstant() const 334 { 335 return mpArg->isConstant(); 336 } 337 virtual ExpressionFunct getType() const 338 { 339 return meFunct; 340 } 341 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* pOptionalArg, sal_uInt32 nFlags ) 342 { 343 EnhancedCustomShapeParameter aRet; 344 switch( meFunct ) 345 { 346 case UNARY_FUNC_ABS : 347 { 348 EnhancedCustomShapeEquation aEquation; 349 aEquation.nOperation |= 3; 350 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation ); 351 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 352 aRet.Value <<= (sal_Int32)rEquations.size(); 353 rEquations.push_back( aEquation ); 354 } 355 break; 356 case UNARY_FUNC_SQRT: 357 { 358 EnhancedCustomShapeEquation aEquation; 359 aEquation.nOperation |= 13; 360 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation ); 361 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 362 aRet.Value <<= (sal_Int32)rEquations.size(); 363 rEquations.push_back( aEquation ); 364 } 365 break; 366 case UNARY_FUNC_SIN : 367 { 368 EnhancedCustomShapeEquation aEquation; 369 aEquation.nOperation |= 9; 370 if ( pOptionalArg ) 371 FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation ); 372 else 373 aEquation.nPara[ 0 ] = 1; 374 375 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) ); 376 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL ) 377 { // sumangle needed :-( 378 EnhancedCustomShapeEquation _aEquation; 379 _aEquation.nOperation |= 0xe; // sumangle 380 FillEquationParameter( aSource, 1, _aEquation ); 381 aSource.Type = EnhancedCustomShapeParameterType::EQUATION; 382 aSource.Value <<= (sal_Int32)rEquations.size(); 383 rEquations.push_back( _aEquation ); 384 } 385 FillEquationParameter( aSource, 1, aEquation ); 386 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 387 aRet.Value <<= (sal_Int32)rEquations.size(); 388 rEquations.push_back( aEquation ); 389 } 390 break; 391 case UNARY_FUNC_COS : 392 { 393 EnhancedCustomShapeEquation aEquation; 394 aEquation.nOperation |= 10; 395 if ( pOptionalArg ) 396 FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation ); 397 else 398 aEquation.nPara[ 0 ] = 1; 399 400 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) ); 401 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL ) 402 { // sumangle needed :-( 403 EnhancedCustomShapeEquation aTmpEquation; 404 aTmpEquation.nOperation |= 0xe; // sumangle 405 FillEquationParameter( aSource, 1, aTmpEquation ); 406 aSource.Type = EnhancedCustomShapeParameterType::EQUATION; 407 aSource.Value <<= (sal_Int32)rEquations.size(); 408 rEquations.push_back( aTmpEquation ); 409 } 410 FillEquationParameter( aSource, 1, aEquation ); 411 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 412 aRet.Value <<= (sal_Int32)rEquations.size(); 413 rEquations.push_back( aEquation ); 414 } 415 break; 416 case UNARY_FUNC_TAN : 417 { 418 EnhancedCustomShapeEquation aEquation; 419 aEquation.nOperation |= 16; 420 if ( pOptionalArg ) 421 FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation ); 422 else 423 aEquation.nPara[ 0 ] = 1; 424 425 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) ); 426 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL ) 427 { // sumangle needed :-( 428 EnhancedCustomShapeEquation aTmpEquation; 429 aTmpEquation.nOperation |= 0xe; // sumangle 430 FillEquationParameter( aSource, 1, aTmpEquation ); 431 aSource.Type = EnhancedCustomShapeParameterType::EQUATION; 432 aSource.Value <<= (sal_Int32)rEquations.size(); 433 rEquations.push_back( aTmpEquation ); 434 } 435 FillEquationParameter( aSource, 1, aEquation ); 436 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 437 aRet.Value <<= (sal_Int32)rEquations.size(); 438 rEquations.push_back( aEquation ); 439 } 440 break; 441 case UNARY_FUNC_ATAN: 442 { 443 // TODO: 444 aRet.Type = EnhancedCustomShapeParameterType::NORMAL; 445 } 446 break; 447 case UNARY_FUNC_NEG: 448 { 449 EnhancedCustomShapeEquation aEquation; 450 aEquation.nOperation |= 1; 451 aEquation.nPara[ 1 ] = -1; 452 aEquation.nPara[ 2 ] = 1; 453 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation ); 454 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 455 aRet.Value <<= (sal_Int32)rEquations.size(); 456 rEquations.push_back( aEquation ); 457 } 458 break; 459 default: 460 break; 461 } 462 return aRet; 463 } 464 }; 465 466 /** ExpressionNode implementation for unary 467 function over two ExpressionNodes 468 */ 469 class BinaryFunctionExpression : public ExpressionNode 470 { 471 const ExpressionFunct meFunct; 472 ExpressionNodeSharedPtr mpFirstArg; 473 ExpressionNodeSharedPtr mpSecondArg; 474 475 public: 476 477 BinaryFunctionExpression( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rFirstArg, const ExpressionNodeSharedPtr& rSecondArg ) : 478 meFunct( eFunct ), 479 mpFirstArg( rFirstArg ), 480 mpSecondArg( rSecondArg ) 481 { 482 } 483 static double getValue( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rFirstArg, const ExpressionNodeSharedPtr& rSecondArg ) 484 { 485 double fRet = 0; 486 switch( eFunct ) 487 { 488 case BINARY_FUNC_PLUS : fRet = (*rFirstArg)() + (*rSecondArg)(); break; 489 case BINARY_FUNC_MINUS: fRet = (*rFirstArg)() - (*rSecondArg)(); break; 490 case BINARY_FUNC_MUL : fRet = (*rFirstArg)() * (*rSecondArg)(); break; 491 case BINARY_FUNC_DIV : fRet = (*rFirstArg)() / (*rSecondArg)(); break; 492 case BINARY_FUNC_MIN : fRet = ::std::min( (*rFirstArg)(), (*rSecondArg)() ); break; 493 case BINARY_FUNC_MAX : fRet = ::std::max( (*rFirstArg)(), (*rSecondArg)() ); break; 494 case BINARY_FUNC_ATAN2: fRet = atan2( (*rFirstArg)(), (*rSecondArg)() ); break; 495 default: 496 break; 497 } 498 return fRet; 499 } 500 virtual double operator()() const 501 { 502 return getValue( meFunct, mpFirstArg, mpSecondArg ); 503 } 504 virtual bool isConstant() const 505 { 506 return mpFirstArg->isConstant() && mpSecondArg->isConstant(); 507 } 508 virtual ExpressionFunct getType() const 509 { 510 return meFunct; 511 } 512 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags ) 513 { 514 EnhancedCustomShapeParameter aRet; 515 switch( meFunct ) 516 { 517 case BINARY_FUNC_PLUS : 518 { 519 if ( nFlags & EXPRESSION_FLAG_SUMANGLE_MODE ) 520 { 521 if ( mpFirstArg->getType() == ENUM_FUNC_ADJUSTMENT ) 522 { 523 EnhancedCustomShapeEquation aEquation; 524 aEquation.nOperation |= 0xe; // sumangle 525 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation ); 526 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation ); 527 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 528 aRet.Value <<= (sal_Int32)rEquations.size(); 529 rEquations.push_back( aEquation ); 530 } 531 else if ( mpSecondArg->getType() == ENUM_FUNC_ADJUSTMENT ) 532 { 533 EnhancedCustomShapeEquation aEquation; 534 aEquation.nOperation |= 0xe; // sumangle 535 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation ); 536 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation ); 537 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 538 aRet.Value <<= (sal_Int32)rEquations.size(); 539 rEquations.push_back( aEquation ); 540 } 541 else 542 { 543 EnhancedCustomShapeEquation aSumangle1; 544 aSumangle1.nOperation |= 0xe; // sumangle 545 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags &~EXPRESSION_FLAG_SUMANGLE_MODE ), 1, aSumangle1 ); 546 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 547 aRet.Value <<= (sal_Int32)rEquations.size(); 548 rEquations.push_back( aSumangle1 ); 549 550 EnhancedCustomShapeEquation aSumangle2; 551 aSumangle2.nOperation |= 0xe; // sumangle 552 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags &~EXPRESSION_FLAG_SUMANGLE_MODE ), 1, aSumangle2 ); 553 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 554 aRet.Value <<= (sal_Int32)rEquations.size(); 555 rEquations.push_back( aSumangle2 ); 556 557 EnhancedCustomShapeEquation aEquation; 558 aEquation.nOperation |= 0; 559 aEquation.nPara[ 0 ] = ( rEquations.size() - 2 ) | 0x400; 560 aEquation.nPara[ 1 ] = ( rEquations.size() - 1 ) | 0x400; 561 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 562 aRet.Value <<= (sal_Int32)rEquations.size(); 563 rEquations.push_back( aEquation ); 564 } 565 } 566 else 567 { 568 sal_Bool bFirstIsEmpty = mpFirstArg->isConstant() && ( (*mpFirstArg)() == 0 ); 569 sal_Bool bSecondIsEmpty = mpSecondArg->isConstant() && ( (*mpSecondArg)() == 0 ); 570 571 if ( bFirstIsEmpty ) 572 aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags ); 573 else if ( bSecondIsEmpty ) 574 aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags ); 575 else 576 { 577 EnhancedCustomShapeEquation aEquation; 578 aEquation.nOperation |= 0; 579 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation ); 580 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation ); 581 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 582 aRet.Value <<= (sal_Int32)rEquations.size(); 583 rEquations.push_back( aEquation ); 584 } 585 } 586 } 587 break; 588 case BINARY_FUNC_MINUS: 589 { 590 EnhancedCustomShapeEquation aEquation; 591 aEquation.nOperation |= 0; 592 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation ); 593 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation ); 594 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 595 aRet.Value <<= (sal_Int32)rEquations.size(); 596 rEquations.push_back( aEquation ); 597 } 598 break; 599 case BINARY_FUNC_MUL : 600 { 601 // in the dest. format the cos function is using integer as result :-( 602 // so we can't use the generic algorithm 603 if ( ( mpFirstArg->getType() == UNARY_FUNC_SIN ) || ( mpFirstArg->getType() == UNARY_FUNC_COS ) || ( mpFirstArg->getType() == UNARY_FUNC_TAN ) ) 604 aRet = mpFirstArg->fillNode( rEquations, mpSecondArg.get(), nFlags ); 605 else if ( ( mpSecondArg->getType() == UNARY_FUNC_SIN ) || ( mpSecondArg->getType() == UNARY_FUNC_COS ) || ( mpSecondArg->getType() == UNARY_FUNC_TAN ) ) 606 aRet = mpSecondArg->fillNode( rEquations, mpFirstArg.get(), nFlags ); 607 else 608 { 609 if ( mpFirstArg->isConstant() && (*mpFirstArg)() == 1 ) 610 aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags ); 611 else if ( mpSecondArg->isConstant() && (*mpSecondArg)() == 1 ) 612 aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags ); 613 else if ( ( mpFirstArg->getType() == BINARY_FUNC_DIV ) // don't care of (pi/180) 614 && ( ((BinaryFunctionExpression*)((BinaryFunctionExpression*)mpFirstArg.get())->mpFirstArg.get())->getType() == ENUM_FUNC_PI ) 615 && ( ((BinaryFunctionExpression*)((BinaryFunctionExpression*)mpFirstArg.get())->mpSecondArg.get())->getType() == FUNC_CONST ) ) 616 { 617 aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags ); 618 } 619 else if ( ( mpSecondArg->getType() == BINARY_FUNC_DIV ) // don't care of (pi/180) 620 && ( ((BinaryFunctionExpression*)((BinaryFunctionExpression*)mpSecondArg.get())->mpFirstArg.get())->getType() == ENUM_FUNC_PI ) 621 && ( ((BinaryFunctionExpression*)((BinaryFunctionExpression*)mpSecondArg.get())->mpSecondArg.get())->getType() == FUNC_CONST ) ) 622 { 623 aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags ); 624 } 625 else 626 { 627 EnhancedCustomShapeEquation aEquation; 628 aEquation.nOperation |= 1; 629 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation ); 630 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation ); 631 aEquation.nPara[ 2 ] = 1; 632 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 633 aRet.Value <<= (sal_Int32)rEquations.size(); 634 rEquations.push_back( aEquation ); 635 } 636 } 637 } 638 break; 639 case BINARY_FUNC_DIV : 640 { 641 EnhancedCustomShapeEquation aEquation; 642 aEquation.nOperation |= 1; 643 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation ); 644 aEquation.nPara[ 1 ] = 1; 645 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation ); 646 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 647 aRet.Value <<= (sal_Int32)rEquations.size(); 648 rEquations.push_back( aEquation ); 649 } 650 break; 651 case BINARY_FUNC_MIN : 652 { 653 EnhancedCustomShapeEquation aEquation; 654 aEquation.nOperation |= 4; 655 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation ); 656 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation ); 657 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 658 aRet.Value <<= (sal_Int32)rEquations.size(); 659 rEquations.push_back( aEquation ); 660 } 661 break; 662 case BINARY_FUNC_MAX : 663 { 664 EnhancedCustomShapeEquation aEquation; 665 aEquation.nOperation |= 5; 666 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation ); 667 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation ); 668 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 669 aRet.Value <<= (sal_Int32)rEquations.size(); 670 rEquations.push_back( aEquation ); 671 } 672 break; 673 case BINARY_FUNC_ATAN2: 674 { 675 EnhancedCustomShapeEquation aEquation; 676 aEquation.nOperation |= 8; 677 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation ); 678 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation ); 679 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 680 aRet.Value <<= (sal_Int32)rEquations.size(); 681 rEquations.push_back( aEquation ); 682 } 683 break; 684 default: 685 break; 686 } 687 return aRet; 688 } 689 }; 690 691 class IfExpression : public ExpressionNode 692 { 693 ExpressionNodeSharedPtr mpFirstArg; 694 ExpressionNodeSharedPtr mpSecondArg; 695 ExpressionNodeSharedPtr mpThirdArg; 696 697 public: 698 699 IfExpression( const ExpressionNodeSharedPtr& rFirstArg, 700 const ExpressionNodeSharedPtr& rSecondArg, 701 const ExpressionNodeSharedPtr& rThirdArg ) : 702 mpFirstArg( rFirstArg ), 703 mpSecondArg( rSecondArg ), 704 mpThirdArg( rThirdArg ) 705 { 706 } 707 virtual bool isConstant() const 708 { 709 return 710 mpFirstArg->isConstant() && 711 mpSecondArg->isConstant() && 712 mpThirdArg->isConstant(); 713 } 714 virtual double operator()() const 715 { 716 return (*mpFirstArg)() > 0 ? (*mpSecondArg)() : (*mpThirdArg)(); 717 } 718 virtual ExpressionFunct getType() const 719 { 720 return TERNARY_FUNC_IF; 721 } 722 virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags ) 723 { 724 EnhancedCustomShapeParameter aRet; 725 aRet.Type = EnhancedCustomShapeParameterType::EQUATION; 726 aRet.Value <<= (sal_Int32)rEquations.size(); 727 { 728 EnhancedCustomShapeEquation aEquation; 729 aEquation.nOperation |= 6; 730 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation ); 731 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation ); 732 FillEquationParameter( mpThirdArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation ); 733 rEquations.push_back( aEquation ); 734 } 735 return aRet; 736 } 737 }; 738 739 //////////////////////// 740 //////////////////////// 741 // FUNCTION PARSER 742 //////////////////////// 743 //////////////////////// 744 745 typedef const sal_Char* StringIteratorT; 746 747 struct ParserContext 748 { 749 typedef ::std::stack< ExpressionNodeSharedPtr > OperandStack; 750 751 // stores a stack of not-yet-evaluated operands. This is used 752 // by the operators (i.e. '+', '*', 'sin' etc.) to pop their 753 // arguments from. If all arguments to an operator are constant, 754 // the operator pushes a precalculated result on the stack, and 755 // a composite ExpressionNode otherwise. 756 OperandStack maOperandStack; 757 758 const EnhancedCustomShape2d* mpCustoShape; 759 760 }; 761 762 typedef ::boost::shared_ptr< ParserContext > ParserContextSharedPtr; 763 764 /** Generate apriori constant value 765 */ 766 767 class ConstantFunctor 768 { 769 const double mnValue; 770 ParserContextSharedPtr mpContext; 771 772 public: 773 774 ConstantFunctor( double rValue, const ParserContextSharedPtr& rContext ) : 775 mnValue( rValue ), 776 mpContext( rContext ) 777 { 778 } 779 void operator()( StringIteratorT /*rFirst*/, StringIteratorT /*rSecond*/ ) const 780 { 781 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( mnValue ) ) ); 782 } 783 }; 784 785 /** Generate parse-dependent-but-then-constant value 786 */ 787 class DoubleConstantFunctor 788 { 789 ParserContextSharedPtr mpContext; 790 791 public: 792 DoubleConstantFunctor( const ParserContextSharedPtr& rContext ) : 793 mpContext( rContext ) 794 { 795 } 796 void operator()( double n ) const 797 { 798 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( n ) ) ); 799 } 800 }; 801 802 class EnumFunctor 803 { 804 const ExpressionFunct meFunct; 805 double mnValue; 806 ParserContextSharedPtr mpContext; 807 808 public: 809 810 EnumFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) 811 : meFunct( eFunct ) 812 , mnValue( 0 ) 813 , mpContext( rContext ) 814 { 815 } 816 void operator()( StringIteratorT rFirst, StringIteratorT rSecond ) const 817 { 818 /*double nVal = mnValue;*/ 819 switch( meFunct ) 820 { 821 case ENUM_FUNC_ADJUSTMENT : 822 { 823 rtl::OUString aVal( rFirst + 1, rSecond - rFirst, RTL_TEXTENCODING_UTF8 ); 824 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new AdjustmentExpression( *mpContext->mpCustoShape, aVal.toInt32() ) ) ); 825 } 826 break; 827 case ENUM_FUNC_EQUATION : 828 { 829 rtl::OUString aVal( rFirst + 1, rSecond - rFirst, RTL_TEXTENCODING_UTF8 ); 830 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new EquationExpression( *mpContext->mpCustoShape, aVal.toInt32() ) ) ); 831 } 832 break; 833 default: 834 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new EnumValueExpression( *mpContext->mpCustoShape, meFunct ) ) ); 835 } 836 } 837 }; 838 839 class UnaryFunctionFunctor 840 { 841 const ExpressionFunct meFunct; 842 ParserContextSharedPtr mpContext; 843 844 public : 845 846 UnaryFunctionFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) : 847 meFunct( eFunct ), 848 mpContext( rContext ) 849 { 850 } 851 void operator()( StringIteratorT, StringIteratorT ) const 852 { 853 ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack ); 854 855 if( rNodeStack.size() < 1 ) 856 throw ParseError( "Not enough arguments for unary operator" ); 857 858 // retrieve arguments 859 ExpressionNodeSharedPtr pArg( rNodeStack.top() ); 860 rNodeStack.pop(); 861 862 if( pArg->isConstant() ) // check for constness 863 rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( UnaryFunctionExpression::getValue( meFunct, pArg ) ) ) ); 864 else // push complex node, that calcs the value on demand 865 rNodeStack.push( ExpressionNodeSharedPtr( new UnaryFunctionExpression( meFunct, pArg ) ) ); 866 } 867 }; 868 869 /** Implements a binary function over two ExpressionNodes 870 871 @tpl Generator 872 Generator functor, to generate an ExpressionNode of 873 appropriate type 874 875 */ 876 class BinaryFunctionFunctor 877 { 878 const ExpressionFunct meFunct; 879 ParserContextSharedPtr mpContext; 880 881 public: 882 883 BinaryFunctionFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) : 884 meFunct( eFunct ), 885 mpContext( rContext ) 886 { 887 } 888 889 void operator()( StringIteratorT, StringIteratorT ) const 890 { 891 ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack ); 892 893 if( rNodeStack.size() < 2 ) 894 throw ParseError( "Not enough arguments for binary operator" ); 895 896 // retrieve arguments 897 ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() ); 898 rNodeStack.pop(); 899 ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() ); 900 rNodeStack.pop(); 901 902 // create combined ExpressionNode 903 ExpressionNodeSharedPtr pNode = ExpressionNodeSharedPtr( new BinaryFunctionExpression( meFunct, pFirstArg, pSecondArg ) ); 904 // check for constness 905 if( pFirstArg->isConstant() && pSecondArg->isConstant() ) // call the operator() at pNode, store result in constant value ExpressionNode. 906 rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode)() ) ) ); 907 else // push complex node, that calcs the value on demand 908 rNodeStack.push( pNode ); 909 } 910 }; 911 912 class IfFunctor 913 { 914 ParserContextSharedPtr mpContext; 915 916 public : 917 918 IfFunctor( const ParserContextSharedPtr& rContext ) : 919 mpContext( rContext ) 920 { 921 } 922 void operator()( StringIteratorT, StringIteratorT ) const 923 { 924 ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack ); 925 926 if( rNodeStack.size() < 3 ) 927 throw ParseError( "Not enough arguments for ternary operator" ); 928 929 // retrieve arguments 930 ExpressionNodeSharedPtr pThirdArg( rNodeStack.top() ); 931 rNodeStack.pop(); 932 ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() ); 933 rNodeStack.pop(); 934 ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() ); 935 rNodeStack.pop(); 936 937 // create combined ExpressionNode 938 ExpressionNodeSharedPtr pNode( new IfExpression( pFirstArg, pSecondArg, pThirdArg ) ); 939 // check for constness 940 if( pFirstArg->isConstant() && pSecondArg->isConstant() && pThirdArg->isConstant() ) 941 rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode)() ) ) ); // call the operator() at pNode, store result in constant value ExpressionNode. 942 else 943 rNodeStack.push( pNode ); // push complex node, that calcs the value on demand 944 } 945 }; 946 947 // Workaround for MSVC compiler anomaly (stack trashing) 948 // 949 // The default ureal_parser_policies implementation of parse_exp 950 // triggers a really weird error in MSVC7 (Version 13.00.9466), in 951 // that the real_parser_impl::parse_main() call of parse_exp() 952 // overwrites the frame pointer _on the stack_ (EBP of the calling 953 // function gets overwritten while lying on the stack). 954 // 955 // For the time being, our parser thus can only read the 1.0E10 956 // notation, not the 1.0e10 one. 957 // 958 // TODO(F1): Also handle the 1.0e10 case here. 959 template< typename T > struct custom_real_parser_policies : public ::boost::spirit::ureal_parser_policies<T> 960 { 961 template< typename ScannerT > 962 static typename ::boost::spirit::parser_result< ::boost::spirit::chlit<>, ScannerT >::type 963 parse_exp(ScannerT& scan) 964 { 965 // as_lower_d somehow breaks MSVC7 966 return ::boost::spirit::ch_p('E').parse(scan); 967 } 968 }; 969 970 /* This class implements the following grammar (more or 971 less literally written down below, only slightly 972 obfuscated by the parser actions): 973 974 identifier = '$'|'pi'|'e'|'X'|'Y'|'Width'|'Height' 975 976 function = 'abs'|'sqrt'|'sin'|'cos'|'tan'|'atan'|'acos'|'asin'|'exp'|'log' 977 978 basic_expression = 979 number | 980 identifier | 981 function '(' additive_expression ')' | 982 '(' additive_expression ')' 983 984 unary_expression = 985 '-' basic_expression | 986 basic_expression 987 988 multiplicative_expression = 989 unary_expression ( ( '*' unary_expression )* | 990 ( '/' unary_expression )* ) 991 992 additive_expression = 993 multiplicative_expression ( ( '+' multiplicative_expression )* | 994 ( '-' multiplicative_expression )* ) 995 996 */ 997 998 class ExpressionGrammar : public ::boost::spirit::grammar< ExpressionGrammar > 999 { 1000 public: 1001 /** Create an arithmetic expression grammar 1002 1003 @param rParserContext 1004 Contains context info for the parser 1005 */ 1006 ExpressionGrammar( const ParserContextSharedPtr& rParserContext ) : 1007 mpParserContext( rParserContext ) 1008 { 1009 } 1010 1011 template< typename ScannerT > class definition 1012 { 1013 public: 1014 // grammar definition 1015 definition( const ExpressionGrammar& self ) 1016 { 1017 using ::boost::spirit::str_p; 1018 using ::boost::spirit::range_p; 1019 using ::boost::spirit::lexeme_d; 1020 using ::boost::spirit::real_parser; 1021 using ::boost::spirit::chseq_p; 1022 1023 identifier = 1024 str_p( "pi" )[ EnumFunctor(ENUM_FUNC_PI, self.getContext() ) ] 1025 | str_p( "left" )[ EnumFunctor(ENUM_FUNC_LEFT, self.getContext() ) ] 1026 | str_p( "top" )[ EnumFunctor(ENUM_FUNC_TOP, self.getContext() ) ] 1027 | str_p( "right" )[ EnumFunctor(ENUM_FUNC_RIGHT, self.getContext() ) ] 1028 | str_p( "bottom" )[ EnumFunctor(ENUM_FUNC_BOTTOM, self.getContext() ) ] 1029 | str_p( "xstretch" )[ EnumFunctor(ENUM_FUNC_XSTRETCH, self.getContext() ) ] 1030 | str_p( "ystretch" )[ EnumFunctor(ENUM_FUNC_YSTRETCH, self.getContext() ) ] 1031 | str_p( "hasstroke" )[ EnumFunctor(ENUM_FUNC_HASSTROKE, self.getContext() ) ] 1032 | str_p( "hasfill" )[ EnumFunctor(ENUM_FUNC_HASFILL, self.getContext() ) ] 1033 | str_p( "width" )[ EnumFunctor(ENUM_FUNC_WIDTH, self.getContext() ) ] 1034 | str_p( "height" )[ EnumFunctor(ENUM_FUNC_HEIGHT, self.getContext() ) ] 1035 | str_p( "logwidth" )[ EnumFunctor(ENUM_FUNC_LOGWIDTH, self.getContext() ) ] 1036 | str_p( "logheight" )[ EnumFunctor(ENUM_FUNC_LOGHEIGHT, self.getContext() ) ] 1037 ; 1038 1039 unaryFunction = 1040 (str_p( "abs" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ABS, self.getContext()) ] 1041 | (str_p( "sqrt" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SQRT, self.getContext()) ] 1042 | (str_p( "sin" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SIN, self.getContext()) ] 1043 | (str_p( "cos" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_COS, self.getContext()) ] 1044 | (str_p( "tan" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_TAN, self.getContext()) ] 1045 | (str_p( "atan" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ATAN, self.getContext()) ] 1046 ; 1047 1048 binaryFunction = 1049 (str_p( "min" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MIN, self.getContext()) ] 1050 | (str_p( "max" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MAX, self.getContext()) ] 1051 | (str_p( "atan2") >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_ATAN2,self.getContext()) ] 1052 ; 1053 1054 ternaryFunction = 1055 (str_p( "if" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ IfFunctor( self.getContext() ) ] 1056 ; 1057 1058 funcRef_decl = 1059 lexeme_d[ +( range_p('a','z') | range_p('A','Z') | range_p('0','9') ) ]; 1060 1061 functionReference = 1062 (str_p( "?" ) >> funcRef_decl )[ EnumFunctor( ENUM_FUNC_EQUATION, self.getContext() ) ]; 1063 1064 modRef_decl = 1065 lexeme_d[ +( range_p('0','9') ) ]; 1066 1067 modifierReference = 1068 (str_p( "$" ) >> modRef_decl )[ EnumFunctor( ENUM_FUNC_ADJUSTMENT, self.getContext() ) ]; 1069 1070 basicExpression = 1071 real_parser<double, custom_real_parser_policies<double> >()[ DoubleConstantFunctor(self.getContext()) ] 1072 | identifier 1073 | functionReference 1074 | modifierReference 1075 | unaryFunction 1076 | binaryFunction 1077 | ternaryFunction 1078 | '(' >> additiveExpression >> ')' 1079 ; 1080 1081 unaryExpression = 1082 ('-' >> basicExpression)[ UnaryFunctionFunctor( UNARY_FUNC_NEG, self.getContext()) ] 1083 | basicExpression 1084 ; 1085 1086 multiplicativeExpression = 1087 unaryExpression 1088 >> *( ('*' >> unaryExpression)[ BinaryFunctionFunctor( BINARY_FUNC_MUL, self.getContext()) ] 1089 | ('/' >> unaryExpression)[ BinaryFunctionFunctor( BINARY_FUNC_DIV, self.getContext()) ] 1090 ) 1091 ; 1092 1093 additiveExpression = 1094 multiplicativeExpression 1095 >> *( ('+' >> multiplicativeExpression)[ BinaryFunctionFunctor( BINARY_FUNC_PLUS, self.getContext()) ] 1096 | ('-' >> multiplicativeExpression)[ BinaryFunctionFunctor( BINARY_FUNC_MINUS, self.getContext()) ] 1097 ) 1098 ; 1099 1100 BOOST_SPIRIT_DEBUG_RULE(additiveExpression); 1101 BOOST_SPIRIT_DEBUG_RULE(multiplicativeExpression); 1102 BOOST_SPIRIT_DEBUG_RULE(unaryExpression); 1103 BOOST_SPIRIT_DEBUG_RULE(basicExpression); 1104 BOOST_SPIRIT_DEBUG_RULE(unaryFunction); 1105 BOOST_SPIRIT_DEBUG_RULE(binaryFunction); 1106 BOOST_SPIRIT_DEBUG_RULE(ternaryFunction); 1107 BOOST_SPIRIT_DEBUG_RULE(identifier); 1108 } 1109 1110 const ::boost::spirit::rule< ScannerT >& start() const 1111 { 1112 return additiveExpression; 1113 } 1114 1115 private: 1116 // the constituents of the Spirit arithmetic expression grammar. 1117 // For the sake of readability, without 'ma' prefix. 1118 ::boost::spirit::rule< ScannerT > additiveExpression; 1119 ::boost::spirit::rule< ScannerT > multiplicativeExpression; 1120 ::boost::spirit::rule< ScannerT > unaryExpression; 1121 ::boost::spirit::rule< ScannerT > basicExpression; 1122 ::boost::spirit::rule< ScannerT > unaryFunction; 1123 ::boost::spirit::rule< ScannerT > binaryFunction; 1124 ::boost::spirit::rule< ScannerT > ternaryFunction; 1125 ::boost::spirit::rule< ScannerT > funcRef_decl; 1126 ::boost::spirit::rule< ScannerT > functionReference; 1127 ::boost::spirit::rule< ScannerT > modRef_decl; 1128 ::boost::spirit::rule< ScannerT > modifierReference; 1129 ::boost::spirit::rule< ScannerT > identifier; 1130 }; 1131 1132 const ParserContextSharedPtr& getContext() const 1133 { 1134 return mpParserContext; 1135 } 1136 1137 private: 1138 ParserContextSharedPtr mpParserContext; // might get modified during parsing 1139 }; 1140 1141 #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE 1142 const ParserContextSharedPtr& getParserContext() 1143 { 1144 static ParserContextSharedPtr lcl_parserContext( new ParserContext() ); 1145 1146 // clear node stack (since we reuse the static object, that's 1147 // the whole point here) 1148 while( !lcl_parserContext->maOperandStack.empty() ) 1149 lcl_parserContext->maOperandStack.pop(); 1150 1151 return lcl_parserContext; 1152 } 1153 #endif 1154 1155 } 1156 1157 namespace EnhancedCustomShape { 1158 1159 1160 1161 ExpressionNodeSharedPtr FunctionParser::parseFunction( const ::rtl::OUString& rFunction, const EnhancedCustomShape2d& rCustoShape ) 1162 { 1163 // TODO(Q1): Check if a combination of the RTL_UNICODETOTEXT_FLAGS_* 1164 // gives better conversion robustness here (we might want to map space 1165 // etc. to ASCII space here) 1166 const ::rtl::OString& rAsciiFunction( 1167 rtl::OUStringToOString( rFunction, RTL_TEXTENCODING_ASCII_US ) ); 1168 1169 StringIteratorT aStart( rAsciiFunction.getStr() ); 1170 StringIteratorT aEnd( rAsciiFunction.getStr()+rAsciiFunction.getLength() ); 1171 1172 ParserContextSharedPtr pContext; 1173 1174 #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE 1175 // static parser context, because the actual 1176 // Spirit parser is also a static object 1177 pContext = getParserContext(); 1178 #else 1179 pContext.reset( new ParserContext() ); 1180 #endif 1181 pContext->mpCustoShape = &rCustoShape; 1182 1183 ExpressionGrammar aExpressionGrammer( pContext ); 1184 const ::boost::spirit::parse_info<StringIteratorT> aParseInfo( 1185 ::boost::spirit::parse( aStart, 1186 aEnd, 1187 aExpressionGrammer >> ::boost::spirit::end_p, 1188 ::boost::spirit::space_p ) ); 1189 OSL_DEBUG_ONLY(::std::cout.flush()); // needed to keep stdout and cout in sync 1190 1191 1192 1193 // input fully congested by the parser? 1194 if( !aParseInfo.full ) 1195 throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): string not fully parseable" ); 1196 1197 // parser's state stack now must contain exactly _one_ ExpressionNode, 1198 // which represents our formula. 1199 if( pContext->maOperandStack.size() != 1 ) 1200 throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): incomplete or empty expression" ); 1201 1202 1203 return pContext->maOperandStack.top(); 1204 } 1205 1206 1207 } 1208 1209