27#include <rtl/ustring.hxx>
34#define BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
37#define BOOST_SPIRIT_DEBUG
39#include <boost/spirit/include/classic_core.hpp>
54 typedef const char* StringIteratorT;
58 typedef ::std::stack< std::shared_ptr<ExpressionNode> > OperandStack;
75 typedef ::std::shared_ptr< ParserContext > ParserContextSharedPtr;
78 template<
typename Generator >
class ShapeBoundsFunctor
81 ShapeBoundsFunctor( Generator aGenerator,
82 ParserContextSharedPtr xContext ) :
87 "ShapeBoundsFunctor::ShapeBoundsFunctor(): Invalid context" );
90 void operator()( StringIteratorT, StringIteratorT )
const
102 template<
typename Generator > ShapeBoundsFunctor< Generator >
103 makeShapeBoundsFunctor(
const Generator& rGenerator,
104 const ParserContextSharedPtr& rContext )
106 return ShapeBoundsFunctor<Generator>(rGenerator, rContext);
111 class ConstantFunctor
114 ConstantFunctor(
double rValue,
115 ParserContextSharedPtr xContext ) :
120 "ConstantFunctor::ConstantFunctor(): Invalid context" );
123 void operator()( StringIteratorT, StringIteratorT )
const
136 class DoubleConstantFunctor
139 explicit DoubleConstantFunctor( ParserContextSharedPtr xContext ) :
143 "DoubleConstantFunctor::DoubleConstantFunctor(): Invalid context" );
146 void operator()(
double n )
const
162 explicit ValueTFunctor( ParserContextSharedPtr xContext ) :
166 "ValueTFunctor::ValueTFunctor(): Invalid context" );
169 void operator()( StringIteratorT, StringIteratorT )
const
171 if( !
mpContext->mbParseAnimationFunction )
173 SAL_WARN(
"slideshow",
"ValueTFunctor::operator(): variable encountered, but we're not parsing a function here" );
186 template<
typename Functor >
class UnaryFunctionFunctor
192 class UnaryFunctionExpression :
public ExpressionNode
195 UnaryFunctionExpression(
const Functor& rFunctor,
196 std::shared_ptr<ExpressionNode> xArg ) :
202 virtual double operator()(
double t )
const override
207 virtual bool isConstant()
const override
209 return mpArg->isConstant();
214 std::shared_ptr<ExpressionNode>
mpArg;
218 UnaryFunctionFunctor(
const Functor& rFunctor,
219 ParserContextSharedPtr xContext ) :
224 "UnaryFunctionFunctor::UnaryFunctionFunctor(): Invalid context" );
227 void operator()( StringIteratorT, StringIteratorT )
const
229 ParserContext::OperandStack& rNodeStack(
mpContext->maOperandStack );
231 if( rNodeStack.empty() )
232 throw ParseError(
"Not enough arguments for unary operator" );
235 std::shared_ptr<ExpressionNode> pArg( std::move(rNodeStack.top()) );
239 if( pArg->isConstant() )
249 std::make_shared<UnaryFunctionExpression>(
265 template<
typename Functor > UnaryFunctionFunctor<Functor>
266 makeUnaryFunctionFunctor(
const Functor& rFunctor,
267 const ParserContextSharedPtr& rContext )
269 return UnaryFunctionFunctor<Functor>( rFunctor, rContext );
275 UnaryFunctionFunctor< double (*)(double) >
276 makeUnaryFunctionFunctor(
double (*pFunc)(double),
277 const ParserContextSharedPtr& rContext )
279 return UnaryFunctionFunctor< double (*)(double) >( pFunc, rContext );
289 template<
class Generator >
class BinaryFunctionFunctor
292 BinaryFunctionFunctor(
const Generator& rGenerator,
293 ParserContextSharedPtr xContext ) :
298 "BinaryFunctionFunctor::BinaryFunctionFunctor(): Invalid context" );
301 void operator()( StringIteratorT, StringIteratorT )
const
303 ParserContext::OperandStack& rNodeStack(
mpContext->maOperandStack );
305 if( rNodeStack.size() < 2 )
306 throw ParseError(
"Not enough arguments for binary operator" );
309 std::shared_ptr<ExpressionNode> pSecondArg( std::move(rNodeStack.top()) );
311 std::shared_ptr<ExpressionNode> pFirstArg( std::move(rNodeStack.top()) );
315 std::shared_ptr<ExpressionNode> pNode(
maGenerator( pFirstArg,
318 assert(pSecondArg && pFirstArg);
321 if (pFirstArg->isConstant() && pSecondArg->isConstant())
332 rNodeStack.push( pNode );
341 template<
typename Generator > BinaryFunctionFunctor<Generator>
342 makeBinaryFunctionFunctor(
const Generator& rGenerator,
343 const ParserContextSharedPtr& rContext )
345 return BinaryFunctionFunctor<Generator>( rGenerator, rContext );
361 template<
typename T >
struct custom_real_parser_policies :
public ::boost::spirit::classic::ureal_parser_policies<T>
363 template<
typename ScannerT >
364 static typename ::boost::spirit::classic::parser_result< ::boost::spirit::classic::chlit<>, ScannerT >::type
365 parse_exp(ScannerT& scan)
368 return ::boost::spirit::classic::ch_p(
'E').parse(scan);
399 class ExpressionGrammar :
public ::boost::spirit::classic::grammar< ExpressionGrammar >
407 explicit ExpressionGrammar( ParserContextSharedPtr xParserContext ) :
412 template<
typename ScannerT >
class definition
416 explicit definition(
const ExpressionGrammar& self )
418 using ::boost::spirit::classic::str_p;
419 using ::boost::spirit::classic::real_parser;
422 str_p(
"$" )[ ValueTFunctor( self.getContext()) ]
423 | str_p(
"pi" )[ ConstantFunctor(M_PI, self.getContext()) ]
424 | str_p(
"e" )[ ConstantFunctor(M_E, self.getContext()) ]
432 (str_p(
"abs" ) >>
'(' >>
additiveExpression >>
')' )[ makeUnaryFunctionFunctor(&fabs, self.getContext()) ]
433 | (str_p(
"sqrt" ) >>
'(' >>
additiveExpression >>
')' )[ makeUnaryFunctionFunctor(&sqrt, self.getContext()) ]
434 | (str_p(
"sin" ) >>
'(' >>
additiveExpression >>
')' )[ makeUnaryFunctionFunctor(&sin, self.getContext()) ]
435 | (str_p(
"cos" ) >>
'(' >>
additiveExpression >>
')' )[ makeUnaryFunctionFunctor(&cos, self.getContext()) ]
436 | (str_p(
"tan" ) >>
'(' >>
additiveExpression >>
')' )[ makeUnaryFunctionFunctor(&tan, self.getContext()) ]
437 | (str_p(
"atan" ) >>
'(' >>
additiveExpression >>
')' )[ makeUnaryFunctionFunctor(&atan, self.getContext()) ]
438 | (str_p(
"acos" ) >>
'(' >>
additiveExpression >>
')' )[ makeUnaryFunctionFunctor(&acos, self.getContext()) ]
439 | (str_p(
"asin" ) >>
'(' >>
additiveExpression >>
')' )[ makeUnaryFunctionFunctor(&asin, self.getContext()) ]
440 | (str_p(
"exp" ) >>
'(' >>
additiveExpression >>
')' )[ makeUnaryFunctionFunctor(&exp, self.getContext()) ]
441 | (str_p(
"log" ) >>
'(' >>
additiveExpression >>
')' )[ makeUnaryFunctionFunctor(&log, self.getContext()) ]
450 real_parser<double, custom_real_parser_policies<double> >()[ DoubleConstantFunctor(self.getContext()) ]
458 (
'-' >>
basicExpression)[ makeUnaryFunctionFunctor(::std::negate<double>(), self.getContext()) ]
485 const ::boost::spirit::classic::rule< ScannerT >&
start()
const
502 const ParserContextSharedPtr& getContext()
const
511 const ParserContextSharedPtr& getParserContext()
513 static ParserContextSharedPtr lcl_parserContext = std::make_shared<ParserContext>();
517 while( !lcl_parserContext->maOperandStack.empty() )
518 lcl_parserContext->maOperandStack.pop();
520 return lcl_parserContext;
525 const ::basegfx::B2DRectangle& rRelativeShapeBounds )
530 const OString& rAsciiSmilValue(
533 StringIteratorT aStart( rAsciiSmilValue.getStr() );
534 StringIteratorT aEnd( rAsciiSmilValue.getStr()+rAsciiSmilValue.getLength() );
538 ParserContextSharedPtr pContext = getParserContext();
540 pContext->maShapeBounds = rRelativeShapeBounds;
541 pContext->mbParseAnimationFunction =
false;
544 ExpressionGrammar aExpressionGrammer( pContext );
545 const ::boost::spirit::classic::parse_info<StringIteratorT> aParseInfo(
546 ::boost::spirit::classic::parse( aStart,
549 ::boost::spirit::classic::space_p ) );
551#if OSL_DEBUG_LEVEL > 0
556 if( !aParseInfo.full )
557 throw ParseError(
"SmilFunctionParser::parseSmilValue(): string not fully parseable" );
561 if( pContext->maOperandStack.size() != 1 )
562 throw ParseError(
"SmilFunctionParser::parseSmilValue(): incomplete or empty expression" );
564 return pContext->maOperandStack.top();
568 const ::basegfx::B2DRectangle& rRelativeShapeBounds )
573 const OString& rAsciiSmilFunction(
576 StringIteratorT aStart( rAsciiSmilFunction.getStr() );
577 StringIteratorT aEnd( rAsciiSmilFunction.getStr()+rAsciiSmilFunction.getLength() );
581 ParserContextSharedPtr pContext = getParserContext();
583 pContext->maShapeBounds = rRelativeShapeBounds;
584 pContext->mbParseAnimationFunction =
true;
587 ExpressionGrammar aExpressionGrammer( pContext );
588 const ::boost::spirit::classic::parse_info<StringIteratorT> aParseInfo(
589 ::boost::spirit::classic::parse( aStart,
591 aExpressionGrammer >> ::boost::spirit::classic::end_p,
592 ::boost::spirit::classic::space_p ) );
594#if OSL_DEBUG_LEVEL > 0
598 if( !aParseInfo.full )
599 throw ParseError(
"SmilFunctionParser::parseSmilFunction(): string not fully parseable" );
603 if( pContext->maOperandStack.size() != 1 )
604 throw ParseError(
"SmilFunctionParser::parseSmilFunction(): incomplete or empty expression" );
606 return pContext->maOperandStack.top();
610#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
617void sp_scalar_constructor_hook(
void *)
621void sp_scalar_destructor_hook(
void *)
double getCenterX() const
double getCenterY() const
static std::shared_ptr< ExpressionNode > createMultipliesExpression(const std::shared_ptr< ExpressionNode > &rLHS, const std::shared_ptr< ExpressionNode > &rRHS)
static std::shared_ptr< ExpressionNode > createConstantValueExpression(double rConstantValue)
static std::shared_ptr< ExpressionNode > createPlusExpression(const std::shared_ptr< ExpressionNode > &rLHS, const std::shared_ptr< ExpressionNode > &rRHS)
static std::shared_ptr< ExpressionNode > createMinExpression(const std::shared_ptr< ExpressionNode > &rOuterFunction, const std::shared_ptr< ExpressionNode > &rInnerFunction)
Composes two ExpressionNode function.
static std::shared_ptr< ExpressionNode > createValueTExpression()
static std::shared_ptr< ExpressionNode > createMaxExpression(const std::shared_ptr< ExpressionNode > &rOuterFunction, const std::shared_ptr< ExpressionNode > &rInnerFunction)
static std::shared_ptr< ExpressionNode > createDividesExpression(const std::shared_ptr< ExpressionNode > &rLHS, const std::shared_ptr< ExpressionNode > &rRHS)
static std::shared_ptr< ExpressionNode > createMinusExpression(const std::shared_ptr< ExpressionNode > &rLHS, const std::shared_ptr< ExpressionNode > &rRHS)
static std::shared_ptr< ExpressionNode > const & parseSmilValue(const OUString &rSmilValue, const ::basegfx::B2DRectangle &rRelativeShapeBounds)
Parse a string containing a SMIL value.
static std::shared_ptr< ExpressionNode > const & parseSmilFunction(const OUString &rSmilFunction, const ::basegfx::B2DRectangle &rRelativeShapeBounds)
Parse a string containing a SMIL function.
#define ENSURE_OR_THROW(c, m)
#define SAL_WARN(area, stream)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
::boost::spirit::classic::rule< ScannerT > unaryExpression
bool mbParseAnimationFunction
::boost::spirit::classic::rule< ScannerT > additiveExpression
ParserContextSharedPtr mpParserContext
::basegfx::B2DRectangle maShapeBounds
OperandStack maOperandStack
::boost::spirit::classic::rule< ScannerT > binaryFunction
ParserContextSharedPtr mpContext
::boost::spirit::classic::rule< ScannerT > multiplicativeExpression
std::shared_ptr< ExpressionNode > mpArg
::boost::spirit::classic::rule< ScannerT > basicExpression
::boost::spirit::classic::rule< ScannerT > identifier
::boost::spirit::classic::rule< ScannerT > unaryFunction
This exception is thrown, when the SMIL arithmetic expression parser failed to parse a string.