2004-11-26 13:26:43 +00:00
/*************************************************************************
*
2005-09-08 19:26:28 +00:00
* OpenOffice . org - a multi - platform office productivity suite
2004-11-26 13:26:43 +00:00
*
2005-09-08 19:26:28 +00:00
* $ RCSfile : EnhancedCustomShapeFunctionParser . cxx , v $
2004-11-26 13:26:43 +00:00
*
2006-10-24 12:42:15 +00:00
* $ Revision : 1.10 $
2004-11-26 13:26:43 +00:00
*
2006-10-24 12:42:15 +00:00
* last change : $ Author : hr $ $ Date : 2006 - 10 - 24 13 : 42 : 15 $
2004-11-26 13:26:43 +00:00
*
2005-09-08 19:26:28 +00:00
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1 .
2004-11-26 13:26:43 +00:00
*
*
2005-09-08 19:26:28 +00:00
* GNU Lesser General Public License Version 2.1
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* Copyright 2005 by Sun Microsystems , Inc .
* 901 San Antonio Road , Palo Alto , CA 94303 , USA
2004-11-26 13:26:43 +00:00
*
2005-09-08 19:26:28 +00:00
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 , as published by the Free Software Foundation .
2004-11-26 13:26:43 +00:00
*
2005-09-08 19:26:28 +00:00
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
2004-11-26 13:26:43 +00:00
*
2005-09-08 19:26:28 +00:00
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston ,
* MA 02111 - 1307 USA
2004-11-26 13:26:43 +00:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-09-17 03:07:08 +00:00
// MARKER(update_precomp.py): autogen include statement, do not remove
# include "precompiled_svx.hxx"
2006-07-10 10:26:54 +00:00
# ifndef _ENHANCEDCUSTOMSHAPEFUNCTIONPARSER_HXX
# include "EnhancedCustomShapeFunctionParser.hxx"
# endif
2004-11-26 13:26:43 +00:00
# ifndef _ENHANCEDCUSTOMSHAPE2D_HXX
# include "EnhancedCustomShape2d.hxx"
# endif
# ifndef _RTL_USTRING_HXX_
# include <rtl/ustring.hxx>
# endif
# ifndef _FRACT_HXX
# include <tools/fract.hxx>
# endif
// Makes parser a static resource,
// we're synchronized externally.
// But watch out, the parser might have
// state not visible to this code!
# define BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
# if defined(VERBOSE) && defined(DBG_UTIL)
# include <typeinfo>
# define BOOST_SPIRIT_DEBUG
# endif
# include <boost/spirit/core.hpp>
2006-10-24 12:42:15 +00:00
# if (OSL_DEBUG_LEVEL > 0)
2004-11-26 13:26:43 +00:00
# include <iostream>
2006-10-24 12:42:15 +00:00
# endif
2004-11-26 13:26:43 +00:00
# include <functional>
# include <algorithm>
# include <stack>
2006-07-10 10:26:54 +00:00
using namespace EnhancedCustomShape ;
2004-11-26 13:26:43 +00:00
using namespace com : : sun : : star ;
2005-03-01 18:05:47 +00:00
using namespace com : : sun : : star : : drawing ;
2004-11-26 13:26:43 +00:00
2006-07-10 10:26:54 +00:00
void EnhancedCustomShape : : FillEquationParameter ( const EnhancedCustomShapeParameter & rSource , const sal_Int32 nDestPara , EnhancedCustomShapeEquation & rDest )
2004-11-26 13:26:43 +00:00
{
sal_Int32 nValue = 0 ;
if ( rSource . Value . getValueTypeClass ( ) = = uno : : TypeClass_DOUBLE )
{
double fValue ;
if ( rSource . Value > > = fValue )
nValue = ( sal_Int32 ) fValue ;
}
else
rSource . Value > > = nValue ;
switch ( rSource . Type )
{
2005-03-01 18:05:47 +00:00
case com : : sun : : star : : drawing : : EnhancedCustomShapeParameterType : : EQUATION :
2004-11-26 13:26:43 +00:00
{
if ( nValue & 0x40000000 )
{
nValue ^ = 0x40000000 ;
rDest . nOperation | = 0x20000000 < < nDestPara ; // the bit is indicating that this value has to be adjusted later
}
nValue | = 0x400 ;
}
break ;
2005-03-01 18:05:47 +00:00
case com : : sun : : star : : drawing : : EnhancedCustomShapeParameterType : : ADJUSTMENT : nValue + = DFF_Prop_adjustValue ; break ;
case com : : sun : : star : : drawing : : EnhancedCustomShapeParameterType : : BOTTOM : nValue = DFF_Prop_geoBottom ; break ;
case com : : sun : : star : : drawing : : EnhancedCustomShapeParameterType : : RIGHT : nValue = DFF_Prop_geoRight ; break ;
case com : : sun : : star : : drawing : : EnhancedCustomShapeParameterType : : TOP : nValue = DFF_Prop_geoTop ; break ;
case com : : sun : : star : : drawing : : EnhancedCustomShapeParameterType : : LEFT : nValue = DFF_Prop_geoLeft ; break ;
2004-11-26 13:26:43 +00:00
}
2005-03-01 18:05:47 +00:00
if ( rSource . Type ! = com : : sun : : star : : drawing : : EnhancedCustomShapeParameterType : : NORMAL )
2004-11-26 13:26:43 +00:00
rDest . nOperation | = ( 0x2000 < < nDestPara ) ;
rDest . nPara [ nDestPara ] = nValue ;
}
2006-10-12 11:02:31 +00:00
ExpressionNode : : ~ ExpressionNode ( )
{ }
2004-11-26 13:26:43 +00:00
namespace
{
//////////////////////
//////////////////////
// EXPRESSION NODES
//////////////////////
//////////////////////
class ConstantValueExpression : public ExpressionNode
{
double maValue ;
public :
ConstantValueExpression ( double rValue ) :
maValue ( rValue )
{
}
virtual double operator ( ) ( ) const
{
return maValue ;
}
virtual bool isConstant ( ) const
{
return true ;
}
virtual ExpressionFunct getType ( ) const
{
return FUNC_CONST ;
}
2006-06-19 13:57:06 +00:00
virtual EnhancedCustomShapeParameter fillNode ( std : : vector < EnhancedCustomShapeEquation > & rEquations , ExpressionNode * /* pOptionalArg */ , sal_uInt32 /* nFlags */ )
2004-11-26 13:26:43 +00:00
{
EnhancedCustomShapeParameter aRet ;
Fraction aFract ( maValue ) ;
if ( aFract . GetDenominator ( ) = = 1 )
{
aRet . Type = EnhancedCustomShapeParameterType : : NORMAL ;
aRet . Value < < = ( sal_Int32 ) aFract . GetNumerator ( ) ;
}
else
{
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation = 1 ;
aEquation . nPara [ 0 ] = 1 ;
aEquation . nPara [ 1 ] = ( sal_Int16 ) aFract . GetNumerator ( ) ;
aEquation . nPara [ 2 ] = ( sal_Int16 ) aFract . GetDenominator ( ) ;
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
}
return aRet ;
}
} ;
class AdjustmentExpression : public ExpressionNode
{
sal_Int32 mnIndex ;
const EnhancedCustomShape2d & mrCustoShape ;
public :
2006-06-19 13:57:06 +00:00
AdjustmentExpression ( const EnhancedCustomShape2d & rCustoShape , sal_Int32 nIndex )
: mnIndex ( nIndex )
, mrCustoShape ( rCustoShape )
2004-11-26 13:26:43 +00:00
{
}
virtual double operator ( ) ( ) const
{
return mrCustoShape . GetAdjustValueAsDouble ( mnIndex ) ;
}
virtual bool isConstant ( ) const
{
return false ;
}
virtual ExpressionFunct getType ( ) const
{
return ENUM_FUNC_ADJUSTMENT ;
}
2006-06-19 13:57:06 +00:00
virtual EnhancedCustomShapeParameter fillNode ( std : : vector < EnhancedCustomShapeEquation > & /*rEquations*/ , ExpressionNode * /*pOptionalArg*/ , sal_uInt32 /*nFlags*/ )
2004-11-26 13:26:43 +00:00
{
EnhancedCustomShapeParameter aRet ;
aRet . Type = EnhancedCustomShapeParameterType : : ADJUSTMENT ;
aRet . Value < < = mnIndex ;
return aRet ;
}
} ;
class EquationExpression : public ExpressionNode
{
sal_Int32 mnIndex ;
const EnhancedCustomShape2d & mrCustoShape ;
public :
2006-06-19 13:57:06 +00:00
EquationExpression ( const EnhancedCustomShape2d & rCustoShape , sal_Int32 nIndex )
: mnIndex ( nIndex )
, mrCustoShape ( rCustoShape )
2004-11-26 13:26:43 +00:00
{
}
virtual double operator ( ) ( ) const
{
return mrCustoShape . GetEquationValueAsDouble ( mnIndex ) ;
}
virtual bool isConstant ( ) const
{
return false ;
}
virtual ExpressionFunct getType ( ) const
{
return ENUM_FUNC_EQUATION ;
}
2006-06-19 13:57:06 +00:00
virtual EnhancedCustomShapeParameter fillNode ( std : : vector < EnhancedCustomShapeEquation > & /*rEquations*/ , ExpressionNode * /*pOptionalArg*/ , sal_uInt32 /*nFlags*/ )
2004-11-26 13:26:43 +00:00
{
EnhancedCustomShapeParameter aRet ;
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = mnIndex | 0x40000000 ; // the bit is indicating that this equation needs to be adjusted later
return aRet ;
}
} ;
class EnumValueExpression : public ExpressionNode
{
const ExpressionFunct meFunct ;
const EnhancedCustomShape2d & mrCustoShape ;
public :
2006-06-19 13:57:06 +00:00
EnumValueExpression ( const EnhancedCustomShape2d & rCustoShape , const ExpressionFunct eFunct )
: meFunct ( eFunct )
, mrCustoShape ( rCustoShape )
2004-11-26 13:26:43 +00:00
{
}
static double getValue ( const EnhancedCustomShape2d & rCustoShape , const ExpressionFunct eFunc )
{
EnhancedCustomShape2d : : EnumFunc eF ;
switch ( eFunc )
{
case ENUM_FUNC_PI : eF = EnhancedCustomShape2d : : ENUM_FUNC_PI ; break ;
case ENUM_FUNC_LEFT : eF = EnhancedCustomShape2d : : ENUM_FUNC_LEFT ; break ;
case ENUM_FUNC_TOP : eF = EnhancedCustomShape2d : : ENUM_FUNC_TOP ; break ;
case ENUM_FUNC_RIGHT : eF = EnhancedCustomShape2d : : ENUM_FUNC_RIGHT ; break ;
case ENUM_FUNC_BOTTOM : eF = EnhancedCustomShape2d : : ENUM_FUNC_BOTTOM ; break ;
case ENUM_FUNC_XSTRETCH : eF = EnhancedCustomShape2d : : ENUM_FUNC_XSTRETCH ; break ;
case ENUM_FUNC_YSTRETCH : eF = EnhancedCustomShape2d : : ENUM_FUNC_YSTRETCH ; break ;
case ENUM_FUNC_HASSTROKE : eF = EnhancedCustomShape2d : : ENUM_FUNC_HASSTROKE ; break ;
case ENUM_FUNC_HASFILL : eF = EnhancedCustomShape2d : : ENUM_FUNC_HASFILL ; break ;
case ENUM_FUNC_WIDTH : eF = EnhancedCustomShape2d : : ENUM_FUNC_WIDTH ; break ;
case ENUM_FUNC_HEIGHT : eF = EnhancedCustomShape2d : : ENUM_FUNC_HEIGHT ; break ;
case ENUM_FUNC_LOGWIDTH : eF = EnhancedCustomShape2d : : ENUM_FUNC_LOGWIDTH ; break ;
case ENUM_FUNC_LOGHEIGHT : eF = EnhancedCustomShape2d : : ENUM_FUNC_LOGHEIGHT ; break ;
default :
return 0.0 ;
}
return rCustoShape . GetEnumFunc ( eF ) ;
}
virtual double operator ( ) ( ) const
{
return getValue ( mrCustoShape , meFunct ) ;
}
virtual bool isConstant ( ) const
{
return false ;
}
virtual ExpressionFunct getType ( ) const
{
return meFunct ;
}
2006-06-19 13:57:06 +00:00
virtual EnhancedCustomShapeParameter fillNode ( std : : vector < EnhancedCustomShapeEquation > & rEquations , ExpressionNode * /*pOptionalArg*/ , sal_uInt32 nFlags )
2004-11-26 13:26:43 +00:00
{
EnhancedCustomShapeParameter aRet ;
sal_Int32 nDummy = 1 ;
aRet . Value < < = nDummy ;
switch ( meFunct )
{
case ENUM_FUNC_WIDTH : // TODO: do not use this as constant value
case ENUM_FUNC_HEIGHT :
case ENUM_FUNC_LOGWIDTH :
case ENUM_FUNC_LOGHEIGHT :
case ENUM_FUNC_PI :
{
ConstantValueExpression aConstantValue ( getValue ( mrCustoShape , meFunct ) ) ;
2005-01-07 08:23:03 +00:00
aRet = aConstantValue . fillNode ( rEquations , NULL , nFlags ) ;
2004-11-26 13:26:43 +00:00
}
break ;
case ENUM_FUNC_LEFT : aRet . Type = EnhancedCustomShapeParameterType : : LEFT ; break ;
case ENUM_FUNC_TOP : aRet . Type = EnhancedCustomShapeParameterType : : TOP ; break ;
case ENUM_FUNC_RIGHT : aRet . Type = EnhancedCustomShapeParameterType : : RIGHT ; break ;
case ENUM_FUNC_BOTTOM : aRet . Type = EnhancedCustomShapeParameterType : : BOTTOM ; break ;
// not implemented so far
case ENUM_FUNC_XSTRETCH :
case ENUM_FUNC_YSTRETCH :
case ENUM_FUNC_HASSTROKE :
case ENUM_FUNC_HASFILL : aRet . Type = EnhancedCustomShapeParameterType : : NORMAL ; break ;
2006-10-12 11:02:31 +00:00
default :
break ;
2004-11-26 13:26:43 +00:00
}
return aRet ;
}
} ;
/** ExpressionNode implementation for unary
function over one ExpressionNode
*/
class UnaryFunctionExpression : public ExpressionNode
{
const ExpressionFunct meFunct ;
ExpressionNodeSharedPtr mpArg ;
public :
UnaryFunctionExpression ( const ExpressionFunct eFunct , const ExpressionNodeSharedPtr & rArg ) :
meFunct ( eFunct ) ,
mpArg ( rArg )
{
}
static double getValue ( const ExpressionFunct eFunct , const ExpressionNodeSharedPtr & rArg )
{
double fRet = 0 ;
switch ( eFunct )
{
case UNARY_FUNC_ABS : fRet = fabs ( ( * rArg ) ( ) ) ; break ;
case UNARY_FUNC_SQRT : fRet = sqrt ( ( * rArg ) ( ) ) ; break ;
case UNARY_FUNC_SIN : fRet = sin ( ( * rArg ) ( ) ) ; break ;
case UNARY_FUNC_COS : fRet = cos ( ( * rArg ) ( ) ) ; break ;
case UNARY_FUNC_TAN : fRet = tan ( ( * rArg ) ( ) ) ; break ;
case UNARY_FUNC_ATAN : fRet = atan ( ( * rArg ) ( ) ) ; break ;
case UNARY_FUNC_NEG : fRet = : : std : : negate < double > ( ) ( ( * rArg ) ( ) ) ; break ;
2006-10-12 11:02:31 +00:00
default :
break ;
2004-11-26 13:26:43 +00:00
}
return fRet ;
}
virtual double operator ( ) ( ) const
{
return getValue ( meFunct , mpArg ) ;
}
virtual bool isConstant ( ) const
{
return mpArg - > isConstant ( ) ;
}
virtual ExpressionFunct getType ( ) const
{
return meFunct ;
}
2005-01-07 08:23:03 +00:00
virtual EnhancedCustomShapeParameter fillNode ( std : : vector < EnhancedCustomShapeEquation > & rEquations , ExpressionNode * pOptionalArg , sal_uInt32 nFlags )
2004-11-26 13:26:43 +00:00
{
EnhancedCustomShapeParameter aRet ;
switch ( meFunct )
{
case UNARY_FUNC_ABS :
{
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation | = 3 ;
2005-01-07 08:23:03 +00:00
FillEquationParameter ( mpArg - > fillNode ( rEquations , NULL , nFlags ) , 0 , aEquation ) ;
2004-11-26 13:26:43 +00:00
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
}
break ;
case UNARY_FUNC_SQRT :
{
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation | = 13 ;
2005-01-07 08:23:03 +00:00
FillEquationParameter ( mpArg - > fillNode ( rEquations , NULL , nFlags ) , 0 , aEquation ) ;
2004-11-26 13:26:43 +00:00
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
}
break ;
case UNARY_FUNC_SIN :
{
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation | = 9 ;
2005-01-07 08:23:03 +00:00
if ( pOptionalArg )
FillEquationParameter ( pOptionalArg - > fillNode ( rEquations , NULL , nFlags ) , 0 , aEquation ) ;
2004-11-26 13:26:43 +00:00
else
aEquation . nPara [ 0 ] = 1 ;
2005-01-07 08:23:03 +00:00
EnhancedCustomShapeParameter aSource ( mpArg - > fillNode ( rEquations , NULL , nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) ) ;
if ( aSource . Type = = EnhancedCustomShapeParameterType : : NORMAL )
{ // sumangle needed :-(
2006-06-19 13:57:06 +00:00
EnhancedCustomShapeEquation _aEquation ;
_aEquation . nOperation | = 0xe ; // sumangle
FillEquationParameter ( aSource , 1 , _aEquation ) ;
2005-01-07 08:23:03 +00:00
aSource . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aSource . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
2006-06-19 13:57:06 +00:00
rEquations . push_back ( _aEquation ) ;
2005-01-07 08:23:03 +00:00
}
FillEquationParameter ( aSource , 1 , aEquation ) ;
2004-11-26 13:26:43 +00:00
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
}
break ;
case UNARY_FUNC_COS :
{
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation | = 10 ;
2005-01-07 08:23:03 +00:00
if ( pOptionalArg )
FillEquationParameter ( pOptionalArg - > fillNode ( rEquations , NULL , nFlags ) , 0 , aEquation ) ;
2004-11-26 13:26:43 +00:00
else
aEquation . nPara [ 0 ] = 1 ;
2005-01-07 08:23:03 +00:00
EnhancedCustomShapeParameter aSource ( mpArg - > fillNode ( rEquations , NULL , nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) ) ;
if ( aSource . Type = = EnhancedCustomShapeParameterType : : NORMAL )
{ // sumangle needed :-(
2006-10-12 11:02:31 +00:00
EnhancedCustomShapeEquation aTmpEquation ;
aTmpEquation . nOperation | = 0xe ; // sumangle
FillEquationParameter ( aSource , 1 , aTmpEquation ) ;
2005-01-07 08:23:03 +00:00
aSource . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aSource . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
2006-10-12 11:02:31 +00:00
rEquations . push_back ( aTmpEquation ) ;
2005-01-07 08:23:03 +00:00
}
FillEquationParameter ( aSource , 1 , aEquation ) ;
2004-11-26 13:26:43 +00:00
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
}
break ;
case UNARY_FUNC_TAN :
{
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation | = 16 ;
2005-01-07 08:23:03 +00:00
if ( pOptionalArg )
FillEquationParameter ( pOptionalArg - > fillNode ( rEquations , NULL , nFlags ) , 0 , aEquation ) ;
2004-11-26 13:26:43 +00:00
else
aEquation . nPara [ 0 ] = 1 ;
2005-01-07 08:23:03 +00:00
EnhancedCustomShapeParameter aSource ( mpArg - > fillNode ( rEquations , NULL , nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) ) ;
if ( aSource . Type = = EnhancedCustomShapeParameterType : : NORMAL )
{ // sumangle needed :-(
2006-10-12 11:02:31 +00:00
EnhancedCustomShapeEquation aTmpEquation ;
aTmpEquation . nOperation | = 0xe ; // sumangle
FillEquationParameter ( aSource , 1 , aTmpEquation ) ;
2005-01-07 08:23:03 +00:00
aSource . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aSource . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
2006-10-12 11:02:31 +00:00
rEquations . push_back ( aTmpEquation ) ;
2005-01-07 08:23:03 +00:00
}
FillEquationParameter ( aSource , 1 , aEquation ) ;
2004-11-26 13:26:43 +00:00
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
}
break ;
case UNARY_FUNC_ATAN :
{
// TODO:
aRet . Type = EnhancedCustomShapeParameterType : : NORMAL ;
}
break ;
case UNARY_FUNC_NEG :
{
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation | = 1 ;
aEquation . nPara [ 1 ] = - 1 ;
aEquation . nPara [ 2 ] = 1 ;
2005-01-07 08:23:03 +00:00
FillEquationParameter ( mpArg - > fillNode ( rEquations , NULL , nFlags ) , 0 , aEquation ) ;
2004-11-26 13:26:43 +00:00
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
}
break ;
2006-10-12 11:02:31 +00:00
default :
break ;
2004-11-26 13:26:43 +00:00
}
return aRet ;
}
} ;
/** ExpressionNode implementation for unary
function over two ExpressionNodes
*/
class BinaryFunctionExpression : public ExpressionNode
{
const ExpressionFunct meFunct ;
ExpressionNodeSharedPtr mpFirstArg ;
ExpressionNodeSharedPtr mpSecondArg ;
public :
BinaryFunctionExpression ( const ExpressionFunct eFunct , const ExpressionNodeSharedPtr & rFirstArg , const ExpressionNodeSharedPtr & rSecondArg ) :
meFunct ( eFunct ) ,
mpFirstArg ( rFirstArg ) ,
mpSecondArg ( rSecondArg )
{
}
static double getValue ( const ExpressionFunct eFunct , const ExpressionNodeSharedPtr & rFirstArg , const ExpressionNodeSharedPtr & rSecondArg )
{
double fRet = 0 ;
switch ( eFunct )
{
case BINARY_FUNC_PLUS : fRet = ( * rFirstArg ) ( ) + ( * rSecondArg ) ( ) ; break ;
case BINARY_FUNC_MINUS : fRet = ( * rFirstArg ) ( ) - ( * rSecondArg ) ( ) ; break ;
case BINARY_FUNC_MUL : fRet = ( * rFirstArg ) ( ) * ( * rSecondArg ) ( ) ; break ;
case BINARY_FUNC_DIV : fRet = ( * rFirstArg ) ( ) / ( * rSecondArg ) ( ) ; break ;
case BINARY_FUNC_MIN : fRet = : : std : : min ( ( * rFirstArg ) ( ) , ( * rSecondArg ) ( ) ) ; break ;
case BINARY_FUNC_MAX : fRet = : : std : : max ( ( * rFirstArg ) ( ) , ( * rSecondArg ) ( ) ) ; break ;
case BINARY_FUNC_ATAN2 : fRet = atan2 ( ( * rFirstArg ) ( ) , ( * rSecondArg ) ( ) ) ; break ;
2006-10-12 11:02:31 +00:00
default :
break ;
2004-11-26 13:26:43 +00:00
}
return fRet ;
}
virtual double operator ( ) ( ) const
{
return getValue ( meFunct , mpFirstArg , mpSecondArg ) ;
}
virtual bool isConstant ( ) const
{
return mpFirstArg - > isConstant ( ) & & mpSecondArg - > isConstant ( ) ;
}
virtual ExpressionFunct getType ( ) const
{
return meFunct ;
}
2006-06-19 13:57:06 +00:00
virtual EnhancedCustomShapeParameter fillNode ( std : : vector < EnhancedCustomShapeEquation > & rEquations , ExpressionNode * /*pOptionalArg*/ , sal_uInt32 nFlags )
2004-11-26 13:26:43 +00:00
{
EnhancedCustomShapeParameter aRet ;
switch ( meFunct )
{
case BINARY_FUNC_PLUS :
{
2005-01-07 08:23:03 +00:00
if ( nFlags & EXPRESSION_FLAG_SUMANGLE_MODE )
{
if ( mpFirstArg - > getType ( ) = = ENUM_FUNC_ADJUSTMENT )
{
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation | = 0xe ; // sumangle
FillEquationParameter ( mpFirstArg - > fillNode ( rEquations , NULL , nFlags ) , 0 , aEquation ) ;
FillEquationParameter ( mpSecondArg - > fillNode ( rEquations , NULL , nFlags ) , 1 , aEquation ) ;
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
}
else if ( mpSecondArg - > getType ( ) = = ENUM_FUNC_ADJUSTMENT )
{
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation | = 0xe ; // sumangle
FillEquationParameter ( mpSecondArg - > fillNode ( rEquations , NULL , nFlags ) , 0 , aEquation ) ;
FillEquationParameter ( mpFirstArg - > fillNode ( rEquations , NULL , nFlags ) , 1 , aEquation ) ;
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
}
else
{
EnhancedCustomShapeEquation aSumangle1 ;
aSumangle1 . nOperation | = 0xe ; // sumangle
FillEquationParameter ( mpFirstArg - > fillNode ( rEquations , NULL , nFlags & ~ EXPRESSION_FLAG_SUMANGLE_MODE ) , 1 , aSumangle1 ) ;
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aSumangle1 ) ;
EnhancedCustomShapeEquation aSumangle2 ;
aSumangle2 . nOperation | = 0xe ; // sumangle
FillEquationParameter ( mpSecondArg - > fillNode ( rEquations , NULL , nFlags & ~ EXPRESSION_FLAG_SUMANGLE_MODE ) , 1 , aSumangle2 ) ;
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aSumangle2 ) ;
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation | = 0 ;
aEquation . nPara [ 0 ] = ( rEquations . size ( ) - 2 ) | 0x400 ;
aEquation . nPara [ 1 ] = ( rEquations . size ( ) - 1 ) | 0x400 ;
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
}
}
2004-11-26 13:26:43 +00:00
else
{
2005-01-07 08:23:03 +00:00
sal_Bool bFirstIsEmpty = mpFirstArg - > isConstant ( ) & & ( ( * mpFirstArg ) ( ) = = 0 ) ;
sal_Bool bSecondIsEmpty = mpSecondArg - > isConstant ( ) & & ( ( * mpSecondArg ) ( ) = = 0 ) ;
if ( bFirstIsEmpty )
aRet = mpSecondArg - > fillNode ( rEquations , NULL , nFlags ) ;
else if ( bSecondIsEmpty )
aRet = mpFirstArg - > fillNode ( rEquations , NULL , nFlags ) ;
else
{
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation | = 0 ;
FillEquationParameter ( mpFirstArg - > fillNode ( rEquations , NULL , nFlags ) , 0 , aEquation ) ;
FillEquationParameter ( mpSecondArg - > fillNode ( rEquations , NULL , nFlags ) , 1 , aEquation ) ;
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
}
2004-11-26 13:26:43 +00:00
}
}
break ;
case BINARY_FUNC_MINUS :
{
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation | = 0 ;
2005-01-07 08:23:03 +00:00
FillEquationParameter ( mpFirstArg - > fillNode ( rEquations , NULL , nFlags ) , 0 , aEquation ) ;
FillEquationParameter ( mpSecondArg - > fillNode ( rEquations , NULL , nFlags ) , 2 , aEquation ) ;
2004-11-26 13:26:43 +00:00
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
}
break ;
case BINARY_FUNC_MUL :
{
// in the dest. format the cos function is using integer as result :-(
// so we can't use the generic algorithm
if ( ( mpFirstArg - > getType ( ) = = UNARY_FUNC_SIN ) | | ( mpFirstArg - > getType ( ) = = UNARY_FUNC_COS ) | | ( mpFirstArg - > getType ( ) = = UNARY_FUNC_TAN ) )
2005-01-07 08:23:03 +00:00
aRet = mpFirstArg - > fillNode ( rEquations , mpSecondArg . get ( ) , nFlags ) ;
2004-11-26 13:26:43 +00:00
else if ( ( mpSecondArg - > getType ( ) = = UNARY_FUNC_SIN ) | | ( mpSecondArg - > getType ( ) = = UNARY_FUNC_COS ) | | ( mpSecondArg - > getType ( ) = = UNARY_FUNC_TAN ) )
2005-01-07 08:23:03 +00:00
aRet = mpSecondArg - > fillNode ( rEquations , mpFirstArg . get ( ) , nFlags ) ;
2004-11-26 13:26:43 +00:00
else
{
2005-01-07 08:23:03 +00:00
if ( mpFirstArg - > isConstant ( ) & & ( * mpFirstArg ) ( ) = = 1 )
aRet = mpSecondArg - > fillNode ( rEquations , NULL , nFlags ) ;
else if ( mpSecondArg - > isConstant ( ) & & ( * mpSecondArg ) ( ) = = 1 )
aRet = mpFirstArg - > fillNode ( rEquations , NULL , nFlags ) ;
else if ( ( mpFirstArg - > getType ( ) = = BINARY_FUNC_DIV ) // don't care of (pi/180)
& & ( ( ( BinaryFunctionExpression * ) ( ( BinaryFunctionExpression * ) mpFirstArg . get ( ) ) - > mpFirstArg . get ( ) ) - > getType ( ) = = ENUM_FUNC_PI )
& & ( ( ( BinaryFunctionExpression * ) ( ( BinaryFunctionExpression * ) mpFirstArg . get ( ) ) - > mpSecondArg . get ( ) ) - > getType ( ) = = FUNC_CONST ) )
{
aRet = mpSecondArg - > fillNode ( rEquations , NULL , nFlags ) ;
}
else if ( ( mpSecondArg - > getType ( ) = = BINARY_FUNC_DIV ) // don't care of (pi/180)
& & ( ( ( BinaryFunctionExpression * ) ( ( BinaryFunctionExpression * ) mpSecondArg . get ( ) ) - > mpFirstArg . get ( ) ) - > getType ( ) = = ENUM_FUNC_PI )
& & ( ( ( BinaryFunctionExpression * ) ( ( BinaryFunctionExpression * ) mpSecondArg . get ( ) ) - > mpSecondArg . get ( ) ) - > getType ( ) = = FUNC_CONST ) )
{
aRet = mpFirstArg - > fillNode ( rEquations , NULL , nFlags ) ;
}
else
{
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation | = 1 ;
FillEquationParameter ( mpFirstArg - > fillNode ( rEquations , NULL , nFlags ) , 0 , aEquation ) ;
FillEquationParameter ( mpSecondArg - > fillNode ( rEquations , NULL , nFlags ) , 1 , aEquation ) ;
aEquation . nPara [ 2 ] = 1 ;
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
}
2004-11-26 13:26:43 +00:00
}
}
break ;
case BINARY_FUNC_DIV :
{
EnhancedCustomShapeEquation aEquation ;
2005-01-07 08:23:03 +00:00
aEquation . nOperation | = 1 ;
FillEquationParameter ( mpFirstArg - > fillNode ( rEquations , NULL , nFlags ) , 0 , aEquation ) ;
aEquation . nPara [ 1 ] = 1 ;
FillEquationParameter ( mpSecondArg - > fillNode ( rEquations , NULL , nFlags ) , 2 , aEquation ) ;
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
2004-11-26 13:26:43 +00:00
}
break ;
case BINARY_FUNC_MIN :
{
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation | = 4 ;
2005-01-07 08:23:03 +00:00
FillEquationParameter ( mpFirstArg - > fillNode ( rEquations , NULL , nFlags ) , 0 , aEquation ) ;
FillEquationParameter ( mpSecondArg - > fillNode ( rEquations , NULL , nFlags ) , 1 , aEquation ) ;
2004-11-26 13:26:43 +00:00
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
}
break ;
case BINARY_FUNC_MAX :
{
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation | = 5 ;
2005-01-07 08:23:03 +00:00
FillEquationParameter ( mpFirstArg - > fillNode ( rEquations , NULL , nFlags ) , 0 , aEquation ) ;
FillEquationParameter ( mpSecondArg - > fillNode ( rEquations , NULL , nFlags ) , 1 , aEquation ) ;
2004-11-26 13:26:43 +00:00
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
}
break ;
case BINARY_FUNC_ATAN2 :
{
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation | = 8 ;
2005-01-07 08:23:03 +00:00
FillEquationParameter ( mpSecondArg - > fillNode ( rEquations , NULL , nFlags ) , 0 , aEquation ) ;
FillEquationParameter ( mpFirstArg - > fillNode ( rEquations , NULL , nFlags ) , 1 , aEquation ) ;
2004-11-26 13:26:43 +00:00
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
rEquations . push_back ( aEquation ) ;
}
break ;
2006-10-12 11:02:31 +00:00
default :
break ;
2004-11-26 13:26:43 +00:00
}
return aRet ;
}
} ;
class IfExpression : public ExpressionNode
{
ExpressionNodeSharedPtr mpFirstArg ;
ExpressionNodeSharedPtr mpSecondArg ;
ExpressionNodeSharedPtr mpThirdArg ;
public :
IfExpression ( const ExpressionNodeSharedPtr & rFirstArg ,
const ExpressionNodeSharedPtr & rSecondArg ,
const ExpressionNodeSharedPtr & rThirdArg ) :
mpFirstArg ( rFirstArg ) ,
mpSecondArg ( rSecondArg ) ,
mpThirdArg ( rThirdArg )
{
}
virtual bool isConstant ( ) const
{
return
mpFirstArg - > isConstant ( ) & &
mpSecondArg - > isConstant ( ) & &
mpThirdArg - > isConstant ( ) ;
}
virtual double operator ( ) ( ) const
{
return ( * mpFirstArg ) ( ) > 0 ? ( * mpSecondArg ) ( ) : ( * mpThirdArg ) ( ) ;
}
virtual ExpressionFunct getType ( ) const
{
return TERNARY_FUNC_IF ;
}
2006-06-19 13:57:06 +00:00
virtual EnhancedCustomShapeParameter fillNode ( std : : vector < EnhancedCustomShapeEquation > & rEquations , ExpressionNode * /*pOptionalArg*/ , sal_uInt32 nFlags )
2004-11-26 13:26:43 +00:00
{
EnhancedCustomShapeParameter aRet ;
aRet . Type = EnhancedCustomShapeParameterType : : EQUATION ;
aRet . Value < < = ( sal_Int32 ) rEquations . size ( ) ;
{
EnhancedCustomShapeEquation aEquation ;
aEquation . nOperation | = 6 ;
2005-01-07 08:23:03 +00:00
FillEquationParameter ( mpFirstArg - > fillNode ( rEquations , NULL , nFlags ) , 0 , aEquation ) ;
FillEquationParameter ( mpSecondArg - > fillNode ( rEquations , NULL , nFlags ) , 1 , aEquation ) ;
FillEquationParameter ( mpThirdArg - > fillNode ( rEquations , NULL , nFlags ) , 2 , aEquation ) ;
2004-11-26 13:26:43 +00:00
rEquations . push_back ( aEquation ) ;
}
return aRet ;
}
} ;
////////////////////////
////////////////////////
// FUNCTION PARSER
////////////////////////
////////////////////////
typedef const sal_Char * StringIteratorT ;
struct ParserContext
{
typedef : : std : : stack < ExpressionNodeSharedPtr > OperandStack ;
// stores a stack of not-yet-evaluated operands. This is used
// by the operators (i.e. '+', '*', 'sin' etc.) to pop their
// arguments from. If all arguments to an operator are constant,
// the operator pushes a precalculated result on the stack, and
// a composite ExpressionNode otherwise.
OperandStack maOperandStack ;
const EnhancedCustomShape2d * mpCustoShape ;
} ;
typedef : : boost : : shared_ptr < ParserContext > ParserContextSharedPtr ;
/** Generate apriori constant value
*/
class ConstantFunctor
{
const double mnValue ;
ParserContextSharedPtr mpContext ;
public :
ConstantFunctor ( double rValue , const ParserContextSharedPtr & rContext ) :
mnValue ( rValue ) ,
mpContext ( rContext )
{
}
2006-06-19 13:57:06 +00:00
void operator ( ) ( StringIteratorT /*rFirst*/ , StringIteratorT /*rSecond*/ ) const
2004-11-26 13:26:43 +00:00
{
mpContext - > maOperandStack . push ( ExpressionNodeSharedPtr ( new ConstantValueExpression ( mnValue ) ) ) ;
}
} ;
/** Generate parse-dependent-but-then-constant value
*/
class DoubleConstantFunctor
{
ParserContextSharedPtr mpContext ;
public :
DoubleConstantFunctor ( const ParserContextSharedPtr & rContext ) :
mpContext ( rContext )
{
}
void operator ( ) ( double n ) const
{
mpContext - > maOperandStack . push ( ExpressionNodeSharedPtr ( new ConstantValueExpression ( n ) ) ) ;
}
} ;
class EnumFunctor
{
const ExpressionFunct meFunct ;
double mnValue ;
ParserContextSharedPtr mpContext ;
public :
2006-06-19 13:57:06 +00:00
EnumFunctor ( const ExpressionFunct eFunct , const ParserContextSharedPtr & rContext )
: meFunct ( eFunct )
, mnValue ( 0 )
, mpContext ( rContext )
2004-11-26 13:26:43 +00:00
{
}
void operator ( ) ( StringIteratorT rFirst , StringIteratorT rSecond ) const
{
2006-06-19 13:57:06 +00:00
/*double nVal = mnValue;*/
2004-11-26 13:26:43 +00:00
switch ( meFunct )
{
case ENUM_FUNC_ADJUSTMENT :
{
rtl : : OUString aVal ( rFirst + 1 , rSecond - rFirst , RTL_TEXTENCODING_UTF8 ) ;
mpContext - > maOperandStack . push ( ExpressionNodeSharedPtr ( new AdjustmentExpression ( * mpContext - > mpCustoShape , aVal . toInt32 ( ) ) ) ) ;
}
break ;
case ENUM_FUNC_EQUATION :
{
rtl : : OUString aVal ( rFirst + 1 , rSecond - rFirst , RTL_TEXTENCODING_UTF8 ) ;
mpContext - > maOperandStack . push ( ExpressionNodeSharedPtr ( new EquationExpression ( * mpContext - > mpCustoShape , aVal . toInt32 ( ) ) ) ) ;
}
break ;
default :
mpContext - > maOperandStack . push ( ExpressionNodeSharedPtr ( new EnumValueExpression ( * mpContext - > mpCustoShape , meFunct ) ) ) ;
}
}
} ;
class UnaryFunctionFunctor
{
const ExpressionFunct meFunct ;
ParserContextSharedPtr mpContext ;
public :
UnaryFunctionFunctor ( const ExpressionFunct eFunct , const ParserContextSharedPtr & rContext ) :
meFunct ( eFunct ) ,
mpContext ( rContext )
{
}
void operator ( ) ( StringIteratorT , StringIteratorT ) const
{
ParserContext : : OperandStack & rNodeStack ( mpContext - > maOperandStack ) ;
if ( rNodeStack . size ( ) < 1 )
throw ParseError ( " Not enough arguments for unary operator " ) ;
// retrieve arguments
ExpressionNodeSharedPtr pArg ( rNodeStack . top ( ) ) ;
rNodeStack . pop ( ) ;
if ( pArg - > isConstant ( ) ) // check for constness
rNodeStack . push ( ExpressionNodeSharedPtr ( new ConstantValueExpression ( UnaryFunctionExpression : : getValue ( meFunct , pArg ) ) ) ) ;
else // push complex node, that calcs the value on demand
rNodeStack . push ( ExpressionNodeSharedPtr ( new UnaryFunctionExpression ( meFunct , pArg ) ) ) ;
}
} ;
/** Implements a binary function over two ExpressionNodes
@ tpl Generator
Generator functor , to generate an ExpressionNode of
appropriate type
*/
class BinaryFunctionFunctor
{
const ExpressionFunct meFunct ;
ParserContextSharedPtr mpContext ;
public :
BinaryFunctionFunctor ( const ExpressionFunct eFunct , const ParserContextSharedPtr & rContext ) :
meFunct ( eFunct ) ,
mpContext ( rContext )
{
}
void operator ( ) ( StringIteratorT , StringIteratorT ) const
{
ParserContext : : OperandStack & rNodeStack ( mpContext - > maOperandStack ) ;
if ( rNodeStack . size ( ) < 2 )
throw ParseError ( " Not enough arguments for binary operator " ) ;
// retrieve arguments
ExpressionNodeSharedPtr pSecondArg ( rNodeStack . top ( ) ) ;
rNodeStack . pop ( ) ;
ExpressionNodeSharedPtr pFirstArg ( rNodeStack . top ( ) ) ;
rNodeStack . pop ( ) ;
// create combined ExpressionNode
ExpressionNodeSharedPtr pNode = ExpressionNodeSharedPtr ( new BinaryFunctionExpression ( meFunct , pFirstArg , pSecondArg ) ) ;
// check for constness
if ( pFirstArg - > isConstant ( ) & & pSecondArg - > isConstant ( ) ) // call the operator() at pNode, store result in constant value ExpressionNode.
rNodeStack . push ( ExpressionNodeSharedPtr ( new ConstantValueExpression ( ( * pNode ) ( ) ) ) ) ;
else // push complex node, that calcs the value on demand
rNodeStack . push ( pNode ) ;
}
} ;
class IfFunctor
{
ParserContextSharedPtr mpContext ;
public :
IfFunctor ( const ParserContextSharedPtr & rContext ) :
mpContext ( rContext )
{
}
void operator ( ) ( StringIteratorT , StringIteratorT ) const
{
ParserContext : : OperandStack & rNodeStack ( mpContext - > maOperandStack ) ;
if ( rNodeStack . size ( ) < 3 )
throw ParseError ( " Not enough arguments for ternary operator " ) ;
// retrieve arguments
ExpressionNodeSharedPtr pThirdArg ( rNodeStack . top ( ) ) ;
rNodeStack . pop ( ) ;
ExpressionNodeSharedPtr pSecondArg ( rNodeStack . top ( ) ) ;
rNodeStack . pop ( ) ;
ExpressionNodeSharedPtr pFirstArg ( rNodeStack . top ( ) ) ;
rNodeStack . pop ( ) ;
// create combined ExpressionNode
ExpressionNodeSharedPtr pNode ( new IfExpression ( pFirstArg , pSecondArg , pThirdArg ) ) ;
// check for constness
if ( pFirstArg - > isConstant ( ) & & pSecondArg - > isConstant ( ) & & pThirdArg - > isConstant ( ) )
rNodeStack . push ( ExpressionNodeSharedPtr ( new ConstantValueExpression ( ( * pNode ) ( ) ) ) ) ; // call the operator() at pNode, store result in constant value ExpressionNode.
else
rNodeStack . push ( pNode ) ; // push complex node, that calcs the value on demand
}
} ;
// Workaround for MSVC compiler anomaly (stack trashing)
//
// The default ureal_parser_policies implementation of parse_exp
// triggers a really weird error in MSVC7 (Version 13.00.9466), in
// that the real_parser_impl::parse_main() call of parse_exp()
// overwrites the frame pointer _on the stack_ (EBP of the calling
// function gets overwritten while lying on the stack).
//
// For the time being, our parser thus can only read the 1.0E10
// notation, not the 1.0e10 one.
//
// TODO(F1): Also handle the 1.0e10 case here.
template < typename T > struct custom_real_parser_policies : public : : boost : : spirit : : ureal_parser_policies < T >
{
template < typename ScannerT >
static typename : : boost : : spirit : : parser_result < : : boost : : spirit : : chlit < > , ScannerT > : : type
parse_exp ( ScannerT & scan )
{
// as_lower_d somehow breaks MSVC7
return : : boost : : spirit : : ch_p ( ' E ' ) . parse ( scan ) ;
}
} ;
/* This class implements the following grammar (more or
less literally written down below , only slightly
obfuscated by the parser actions ) :
identifier = ' $ ' | ' pi ' | ' e ' | ' X ' | ' Y ' | ' Width ' | ' Height '
function = ' abs ' | ' sqrt ' | ' sin ' | ' cos ' | ' tan ' | ' atan ' | ' acos ' | ' asin ' | ' exp ' | ' log '
basic_expression =
number |
identifier |
function ' ( ' additive_expression ' ) ' |
' ( ' additive_expression ' ) '
unary_expression =
' - ' basic_expression |
basic_expression
multiplicative_expression =
unary_expression ( ( ' * ' unary_expression ) * |
( ' / ' unary_expression ) * )
additive_expression =
multiplicative_expression ( ( ' + ' multiplicative_expression ) * |
( ' - ' multiplicative_expression ) * )
*/
class ExpressionGrammar : public : : boost : : spirit : : grammar < ExpressionGrammar >
{
public :
/** Create an arithmetic expression grammar
@ param rParserContext
Contains context info for the parser
*/
ExpressionGrammar ( const ParserContextSharedPtr & rParserContext ) :
mpParserContext ( rParserContext )
{
}
template < typename ScannerT > class definition
{
public :
// grammar definition
definition ( const ExpressionGrammar & self )
{
using : : boost : : spirit : : str_p ;
using : : boost : : spirit : : range_p ;
using : : boost : : spirit : : lexeme_d ;
using : : boost : : spirit : : real_parser ;
using : : boost : : spirit : : chseq_p ;
identifier =
str_p ( " pi " ) [ EnumFunctor ( ENUM_FUNC_PI , self . getContext ( ) ) ]
| str_p ( " left " ) [ EnumFunctor ( ENUM_FUNC_LEFT , self . getContext ( ) ) ]
| str_p ( " top " ) [ EnumFunctor ( ENUM_FUNC_TOP , self . getContext ( ) ) ]
| str_p ( " right " ) [ EnumFunctor ( ENUM_FUNC_RIGHT , self . getContext ( ) ) ]
| str_p ( " bottom " ) [ EnumFunctor ( ENUM_FUNC_BOTTOM , self . getContext ( ) ) ]
| str_p ( " xstretch " ) [ EnumFunctor ( ENUM_FUNC_XSTRETCH , self . getContext ( ) ) ]
| str_p ( " ystretch " ) [ EnumFunctor ( ENUM_FUNC_YSTRETCH , self . getContext ( ) ) ]
| str_p ( " hasstroke " ) [ EnumFunctor ( ENUM_FUNC_HASSTROKE , self . getContext ( ) ) ]
| str_p ( " hasfill " ) [ EnumFunctor ( ENUM_FUNC_HASFILL , self . getContext ( ) ) ]
| str_p ( " width " ) [ EnumFunctor ( ENUM_FUNC_WIDTH , self . getContext ( ) ) ]
| str_p ( " height " ) [ EnumFunctor ( ENUM_FUNC_HEIGHT , self . getContext ( ) ) ]
| str_p ( " logwidth " ) [ EnumFunctor ( ENUM_FUNC_LOGWIDTH , self . getContext ( ) ) ]
| str_p ( " logheight " ) [ EnumFunctor ( ENUM_FUNC_LOGHEIGHT , self . getContext ( ) ) ]
;
unaryFunction =
( str_p ( " abs " ) > > ' ( ' > > additiveExpression > > ' ) ' ) [ UnaryFunctionFunctor ( UNARY_FUNC_ABS , self . getContext ( ) ) ]
| ( str_p ( " sqrt " ) > > ' ( ' > > additiveExpression > > ' ) ' ) [ UnaryFunctionFunctor ( UNARY_FUNC_SQRT , self . getContext ( ) ) ]
| ( str_p ( " sin " ) > > ' ( ' > > additiveExpression > > ' ) ' ) [ UnaryFunctionFunctor ( UNARY_FUNC_SIN , self . getContext ( ) ) ]
| ( str_p ( " cos " ) > > ' ( ' > > additiveExpression > > ' ) ' ) [ UnaryFunctionFunctor ( UNARY_FUNC_COS , self . getContext ( ) ) ]
| ( str_p ( " tan " ) > > ' ( ' > > additiveExpression > > ' ) ' ) [ UnaryFunctionFunctor ( UNARY_FUNC_TAN , self . getContext ( ) ) ]
| ( str_p ( " atan " ) > > ' ( ' > > additiveExpression > > ' ) ' ) [ UnaryFunctionFunctor ( UNARY_FUNC_ATAN , self . getContext ( ) ) ]
;
binaryFunction =
( str_p ( " min " ) > > ' ( ' > > additiveExpression > > ' , ' > > additiveExpression > > ' ) ' ) [ BinaryFunctionFunctor ( BINARY_FUNC_MIN , self . getContext ( ) ) ]
| ( str_p ( " max " ) > > ' ( ' > > additiveExpression > > ' , ' > > additiveExpression > > ' ) ' ) [ BinaryFunctionFunctor ( BINARY_FUNC_MAX , self . getContext ( ) ) ]
| ( str_p ( " atan2 " ) > > ' ( ' > > additiveExpression > > ' , ' > > additiveExpression > > ' ) ' ) [ BinaryFunctionFunctor ( BINARY_FUNC_ATAN2 , self . getContext ( ) ) ]
;
ternaryFunction =
( str_p ( " if " ) > > ' ( ' > > additiveExpression > > ' , ' > > additiveExpression > > ' , ' > > additiveExpression > > ' ) ' ) [ IfFunctor ( self . getContext ( ) ) ]
;
funcRef_decl =
lexeme_d [ + ( range_p ( ' a ' , ' z ' ) | range_p ( ' A ' , ' Z ' ) | range_p ( ' 0 ' , ' 9 ' ) ) ] ;
functionReference =
( str_p ( " ? " ) > > funcRef_decl ) [ EnumFunctor ( ENUM_FUNC_EQUATION , self . getContext ( ) ) ] ;
modRef_decl =
lexeme_d [ + ( range_p ( ' 0 ' , ' 9 ' ) ) ] ;
modifierReference =
( str_p ( " $ " ) > > modRef_decl ) [ EnumFunctor ( ENUM_FUNC_ADJUSTMENT , self . getContext ( ) ) ] ;
basicExpression =
real_parser < double , custom_real_parser_policies < double > > ( ) [ DoubleConstantFunctor ( self . getContext ( ) ) ]
| identifier
| functionReference
| modifierReference
| unaryFunction
| binaryFunction
| ternaryFunction
| ' ( ' > > additiveExpression > > ' ) '
;
unaryExpression =
( ' - ' > > basicExpression ) [ UnaryFunctionFunctor ( UNARY_FUNC_NEG , self . getContext ( ) ) ]
| basicExpression
;
multiplicativeExpression =
unaryExpression
> > * ( ( ' * ' > > unaryExpression ) [ BinaryFunctionFunctor ( BINARY_FUNC_MUL , self . getContext ( ) ) ]
| ( ' / ' > > unaryExpression ) [ BinaryFunctionFunctor ( BINARY_FUNC_DIV , self . getContext ( ) ) ]
)
;
additiveExpression =
multiplicativeExpression
> > * ( ( ' + ' > > multiplicativeExpression ) [ BinaryFunctionFunctor ( BINARY_FUNC_PLUS , self . getContext ( ) ) ]
| ( ' - ' > > multiplicativeExpression ) [ BinaryFunctionFunctor ( BINARY_FUNC_MINUS , self . getContext ( ) ) ]
)
;
BOOST_SPIRIT_DEBUG_RULE ( additiveExpression ) ;
BOOST_SPIRIT_DEBUG_RULE ( multiplicativeExpression ) ;
BOOST_SPIRIT_DEBUG_RULE ( unaryExpression ) ;
BOOST_SPIRIT_DEBUG_RULE ( basicExpression ) ;
BOOST_SPIRIT_DEBUG_RULE ( unaryFunction ) ;
BOOST_SPIRIT_DEBUG_RULE ( binaryFunction ) ;
BOOST_SPIRIT_DEBUG_RULE ( ternaryFunction ) ;
BOOST_SPIRIT_DEBUG_RULE ( identifier ) ;
}
const : : boost : : spirit : : rule < ScannerT > & start ( ) const
{
return additiveExpression ;
}
private :
// the constituents of the Spirit arithmetic expression grammar.
// For the sake of readability, without 'ma' prefix.
: : boost : : spirit : : rule < ScannerT > additiveExpression ;
: : boost : : spirit : : rule < ScannerT > multiplicativeExpression ;
: : boost : : spirit : : rule < ScannerT > unaryExpression ;
: : boost : : spirit : : rule < ScannerT > basicExpression ;
: : boost : : spirit : : rule < ScannerT > unaryFunction ;
: : boost : : spirit : : rule < ScannerT > binaryFunction ;
: : boost : : spirit : : rule < ScannerT > ternaryFunction ;
: : boost : : spirit : : rule < ScannerT > funcRef_decl ;
: : boost : : spirit : : rule < ScannerT > functionReference ;
: : boost : : spirit : : rule < ScannerT > modRef_decl ;
: : boost : : spirit : : rule < ScannerT > modifierReference ;
: : boost : : spirit : : rule < ScannerT > identifier ;
} ;
const ParserContextSharedPtr & getContext ( ) const
{
return mpParserContext ;
}
private :
ParserContextSharedPtr mpParserContext ; // might get modified during parsing
} ;
# ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
const ParserContextSharedPtr & getParserContext ( )
{
static ParserContextSharedPtr lcl_parserContext ( new ParserContext ( ) ) ;
// clear node stack (since we reuse the static object, that's
// the whole point here)
while ( ! lcl_parserContext - > maOperandStack . empty ( ) )
lcl_parserContext - > maOperandStack . pop ( ) ;
return lcl_parserContext ;
}
# endif
2006-10-12 11:02:31 +00:00
}
2004-11-26 13:26:43 +00:00
2006-07-10 10:26:54 +00:00
namespace EnhancedCustomShape {
ExpressionNodeSharedPtr FunctionParser : : parseFunction ( const : : rtl : : OUString & rFunction , const EnhancedCustomShape2d & rCustoShape )
2004-11-26 13:26:43 +00:00
{
// TODO(Q1): Check if a combination of the RTL_UNICODETOTEXT_FLAGS_*
// gives better conversion robustness here (we might want to map space
// etc. to ASCII space here)
const : : rtl : : OString & rAsciiFunction (
rtl : : OUStringToOString ( rFunction , RTL_TEXTENCODING_ASCII_US ) ) ;
StringIteratorT aStart ( rAsciiFunction . getStr ( ) ) ;
StringIteratorT aEnd ( rAsciiFunction . getStr ( ) + rAsciiFunction . getLength ( ) ) ;
ParserContextSharedPtr pContext ;
# ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
// static parser context, because the actual
// Spirit parser is also a static object
pContext = getParserContext ( ) ;
# else
pContext . reset ( new ParserContext ( ) ) ;
# endif
pContext - > mpCustoShape = & rCustoShape ;
ExpressionGrammar aExpressionGrammer ( pContext ) ;
const : : boost : : spirit : : parse_info < StringIteratorT > aParseInfo (
: : boost : : spirit : : parse ( aStart ,
aEnd ,
aExpressionGrammer ,
: : boost : : spirit : : space_p ) ) ;
OSL_DEBUG_ONLY ( : : std : : cout . flush ( ) ) ; // needed to keep stdout and cout in sync
// input fully congested by the parser?
if ( ! aParseInfo . full )
throw ParseError ( " EnhancedCustomShapeFunctionParser::parseFunction() : string not fully parseable " ) ;
// parser's state stack now must contain exactly _one_ ExpressionNode,
// which represents our formula.
if ( pContext - > maOperandStack . size ( ) ! = 1 )
throw ParseError ( " EnhancedCustomShapeFunctionParser::parseFunction() : incomplete or empty expression " ) ;
return pContext - > maOperandStack . top ( ) ;
}
2006-07-10 10:26:54 +00:00
}