/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"
#include "svx/EnhancedCustomShape2d.hxx"
#include <rtl/ustring.hxx>
#include <tools/fract.hxx>

// 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/include/classic_core.hpp>

#if (OSL_DEBUG_LEVEL > 0)
#include <iostream>
#endif
#include <functional>
#include <algorithm>
#include <stack>

#include <math.h> // fabs, sqrt, sin, cos, tan, atan, atan2
using namespace EnhancedCustomShape;
using namespace com::sun::star;
using namespace com::sun::star::drawing;

void EnhancedCustomShape::FillEquationParameter( const EnhancedCustomShapeParameter& rSource, const sal_Int32 nDestPara, EnhancedCustomShapeEquation& rDest )
{
	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 )
	{
		case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION :
		{
			if ( nValue & 0x40000000 )
			{
				nValue ^= 0x40000000;
				rDest.nOperation |= 0x20000000 << nDestPara;	// the bit is indicating that this value has to be adjusted later
			}
			nValue |= 0x400;
		}
		break;
		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;
	}
	if ( rSource.Type != com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL )
		rDest.nOperation |= ( 0x2000 << nDestPara );
	rDest.nPara[ nDestPara ] = nValue;
}

ExpressionNode::~ExpressionNode()
{}

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;
	}
	virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /* pOptionalArg */, sal_uInt32 /* nFlags */ )
	{
		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:

	AdjustmentExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex )
	: mnIndex		( nIndex )
	, mrCustoShape( rCustoShape )

    {
    }
    virtual double operator()() const
    {
		return mrCustoShape.GetAdjustValueAsDouble( mnIndex );
    }
    virtual bool isConstant() const
    {
        return false;
    }
	virtual ExpressionFunct getType() const
	{
		return ENUM_FUNC_ADJUSTMENT;
	}
	virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ )
	{
		EnhancedCustomShapeParameter aRet;
		aRet.Type = EnhancedCustomShapeParameterType::ADJUSTMENT;
		aRet.Value <<= mnIndex;
		return aRet;
	}
};

class EquationExpression : public ExpressionNode
{
    sal_Int32						mnIndex;
	const EnhancedCustomShape2d&	mrCustoShape;

public:

	EquationExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex )
		: mnIndex		( nIndex )
        , mrCustoShape( rCustoShape )
    {
    }
    virtual double operator()() const
    {
		return mrCustoShape.GetEquationValueAsDouble( mnIndex );
    }
    virtual bool isConstant() const
    {
        return false;
    }
	virtual ExpressionFunct getType() const
	{
		return ENUM_FUNC_EQUATION;
	}
	virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ )
	{
		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:

	EnumValueExpression( const EnhancedCustomShape2d& rCustoShape, const ExpressionFunct eFunct )
		: meFunct		( eFunct )
		, mrCustoShape	( rCustoShape )
    {
    }
	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;
	}
	virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags )
	{
		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 ) );
				aRet = aConstantValue.fillNode( rEquations, NULL, nFlags );
			}
			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;

			default:
				break;
		}
		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;
			default:
				break;
		}
		return fRet;
	}
    virtual double operator()() const
    {
		return getValue( meFunct, mpArg );
    }
    virtual bool isConstant() const
    {
        return mpArg->isConstant();
    }
	virtual ExpressionFunct getType() const
	{
		return meFunct;
	}
	virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* pOptionalArg, sal_uInt32 nFlags )
	{
		EnhancedCustomShapeParameter aRet;
		switch( meFunct )
		{
			case UNARY_FUNC_ABS :
			{
				EnhancedCustomShapeEquation	aEquation;
				aEquation.nOperation |= 3;
				FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
				aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
				aRet.Value <<= (sal_Int32)rEquations.size();
				rEquations.push_back( aEquation );
			}
			break;
			case UNARY_FUNC_SQRT:
			{
				EnhancedCustomShapeEquation	aEquation;
				aEquation.nOperation |= 13;
				FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
				aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
				aRet.Value <<= (sal_Int32)rEquations.size();
				rEquations.push_back( aEquation );
			}
			break;
			case UNARY_FUNC_SIN :
			{
				EnhancedCustomShapeEquation	aEquation;
				aEquation.nOperation |= 9;
				if ( pOptionalArg )
					FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
				else
					aEquation.nPara[ 0 ] = 1;

				EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
				if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
				{	// sumangle needed :-(
					EnhancedCustomShapeEquation	_aEquation;
					_aEquation.nOperation |= 0xe;	// sumangle
					FillEquationParameter( aSource, 1, _aEquation );
					aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
					aSource.Value <<= (sal_Int32)rEquations.size();
					rEquations.push_back( _aEquation );
				}
				FillEquationParameter( aSource, 1, aEquation );
				aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
				aRet.Value <<= (sal_Int32)rEquations.size();
				rEquations.push_back( aEquation );
			}
			break;
			case UNARY_FUNC_COS :
			{
				EnhancedCustomShapeEquation	aEquation;
				aEquation.nOperation |= 10;
				if ( pOptionalArg )
					FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
				else
					aEquation.nPara[ 0 ] = 1;

				EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
				if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
				{	// sumangle needed :-(
					EnhancedCustomShapeEquation	aTmpEquation;
					aTmpEquation.nOperation |= 0xe;	// sumangle
					FillEquationParameter( aSource, 1, aTmpEquation );
					aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
					aSource.Value <<= (sal_Int32)rEquations.size();
					rEquations.push_back( aTmpEquation );
				}
				FillEquationParameter( aSource, 1, aEquation );
				aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
				aRet.Value <<= (sal_Int32)rEquations.size();
				rEquations.push_back( aEquation );
			}
			break;
			case UNARY_FUNC_TAN :
			{
				EnhancedCustomShapeEquation	aEquation;
				aEquation.nOperation |= 16;
				if ( pOptionalArg )
					FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
				else
					aEquation.nPara[ 0 ] = 1;

				EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
				if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
				{	// sumangle needed :-(
					EnhancedCustomShapeEquation	aTmpEquation;
					aTmpEquation.nOperation |= 0xe;	// sumangle
					FillEquationParameter( aSource, 1, aTmpEquation );
					aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
					aSource.Value <<= (sal_Int32)rEquations.size();
					rEquations.push_back( aTmpEquation );
				}
				FillEquationParameter( aSource, 1, aEquation );
				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;
				FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
				aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
				aRet.Value <<= (sal_Int32)rEquations.size();
				rEquations.push_back( aEquation );
			}
			break;
			default:
				break;
		}
		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;
			default:
				break;
		}
		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;
	}
	virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags )
	{
		EnhancedCustomShapeParameter aRet;
		switch( meFunct )
		{
			case BINARY_FUNC_PLUS :
			{
				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 );
					}
				}
				else
				{
					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 );
					}
				}
			}
			break;
			case BINARY_FUNC_MINUS:
			{
				EnhancedCustomShapeEquation	aEquation;
				aEquation.nOperation |= 0;
				FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
				FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
				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 ) )
					aRet = mpFirstArg->fillNode( rEquations, mpSecondArg.get(), nFlags );
				else if ( ( mpSecondArg->getType() == UNARY_FUNC_SIN ) || ( mpSecondArg->getType() == UNARY_FUNC_COS ) || ( mpSecondArg->getType() == UNARY_FUNC_TAN ) )
					aRet = mpSecondArg->fillNode( rEquations, mpFirstArg.get(), nFlags );
				else
				{
					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 );
					}
				}
			}
			break;
			case BINARY_FUNC_DIV :
			{
				EnhancedCustomShapeEquation	aEquation;
				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 );
			}
			break;
			case BINARY_FUNC_MIN :
			{
				EnhancedCustomShapeEquation	aEquation;
				aEquation.nOperation |= 4;
				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 );
			}
			break;
			case BINARY_FUNC_MAX :
			{
				EnhancedCustomShapeEquation	aEquation;
				aEquation.nOperation |= 5;
				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 );
			}
			break;
			case BINARY_FUNC_ATAN2:
			{
				EnhancedCustomShapeEquation	aEquation;
				aEquation.nOperation |= 8;
				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 );
			}
			break;
			default:
				break;
		}
		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;
	}
	virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags )
	{
		EnhancedCustomShapeParameter aRet;
		aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
		aRet.Value <<= (sal_Int32)rEquations.size();
		{
			EnhancedCustomShapeEquation	aEquation;
			aEquation.nOperation |= 6;
			FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
			FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags  ), 1, aEquation );
			FillEquationParameter( mpThirdArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
			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 )
	{
	}
    void operator()( StringIteratorT /*rFirst*/, StringIteratorT /*rSecond*/ ) const
    {
        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:

	EnumFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext )
	: meFunct( eFunct )
	, mnValue( 0 )
	, mpContext( rContext )
	{
	}
    void operator()( StringIteratorT rFirst, StringIteratorT rSecond ) const
    {
		/*double nVal = mnValue;*/
		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

}

namespace EnhancedCustomShape  {



ExpressionNodeSharedPtr FunctionParser::parseFunction( const ::rtl::OUString& rFunction, const EnhancedCustomShape2d& rCustoShape )
{
    // 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::end_p,
                                    ::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();
}


}
