diff options
Diffstat (limited to 'connectivity/source/commontools/RowFunctionParser.cxx')
-rw-r--r-- | connectivity/source/commontools/RowFunctionParser.cxx | 501 |
1 files changed, 0 insertions, 501 deletions
diff --git a/connectivity/source/commontools/RowFunctionParser.cxx b/connectivity/source/commontools/RowFunctionParser.cxx deleted file mode 100644 index 590cfb6489..0000000000 --- a/connectivity/source/commontools/RowFunctionParser.cxx +++ /dev/null @@ -1,501 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org 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 version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_connectivity.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> -#include "RowFunctionParser.hxx" -#include <rtl/ustring.hxx> -#include <tools/fract.hxx> - - - -#if (OSL_DEBUG_LEVEL > 0) -#include <iostream> -#endif -#include <functional> -#include <algorithm> -#include <stack> - -namespace connectivity -{ -using namespace com::sun::star; - -namespace -{ -////////////////////// -////////////////////// -// EXPRESSION NODES -////////////////////// -////////////////////// -class ConstantValueExpression : public ExpressionNode -{ - ORowSetValueDecoratorRef maValue; - -public: - - ConstantValueExpression( ORowSetValueDecoratorRef rValue ) : - maValue( rValue ) - { - } - virtual ORowSetValueDecoratorRef evaluate(const ODatabaseMetaDataResultSet::ORow& /*_aRow*/ ) const - { - return maValue; - } - virtual void fill(const ODatabaseMetaDataResultSet::ORow& /*_aRow*/ ) const - { - } - virtual ExpressionFunct getType() const - { - return FUNC_CONST; - } - virtual ODatabaseMetaDataResultSet::ORow fillNode( std::vector< RowEquation >& /*rEquations*/, ExpressionNode* /* pOptionalArg */, sal_uInt32 /* nFlags */ ) - { - ODatabaseMetaDataResultSet::ORow aRet; - 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 ) - { - } - virtual ORowSetValueDecoratorRef evaluate(const ODatabaseMetaDataResultSet::ORow& _aRow ) const - { - ORowSetValueDecoratorRef aRet; - switch(meFunct) - { - case ENUM_FUNC_EQUATION: - aRet = new ORowSetValueDecorator(sal_Bool(mpFirstArg->evaluate(_aRow )->getValue() == mpSecondArg->evaluate(_aRow )->getValue()) ); - break; - case ENUM_FUNC_AND: - aRet = new ORowSetValueDecorator( sal_Bool(mpFirstArg->evaluate(_aRow )->getValue().getBool() && mpSecondArg->evaluate(_aRow )->getValue().getBool()) ); - break; - case ENUM_FUNC_OR: - aRet = new ORowSetValueDecorator( sal_Bool(mpFirstArg->evaluate(_aRow )->getValue().getBool() || mpSecondArg->evaluate(_aRow )->getValue().getBool()) ); - break; - default: - break; - } - return aRet; - } - virtual void fill(const ODatabaseMetaDataResultSet::ORow& _aRow ) const - { - switch(meFunct) - { - case ENUM_FUNC_EQUATION: - (*mpFirstArg->evaluate(_aRow )) = mpSecondArg->evaluate(_aRow )->getValue(); - break; - default: - break; - } - } - virtual ExpressionFunct getType() const - { - return meFunct; - } - virtual ODatabaseMetaDataResultSet::ORow fillNode( std::vector< RowEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ ) - { - ODatabaseMetaDataResultSet::ORow aRet; - 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; -}; - -typedef ::boost::shared_ptr< ParserContext > ParserContextSharedPtr; - -/** Generate apriori constant value - */ - -class ConstantFunctor -{ - ParserContextSharedPtr mpContext; - -public: - - ConstantFunctor( const ParserContextSharedPtr& rContext ) : - mpContext( rContext ) - { - } - void operator()( StringIteratorT rFirst,StringIteratorT rSecond) const - { - rtl::OUString sVal( rFirst, rSecond - rFirst, RTL_TEXTENCODING_UTF8 ); - mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( new ORowSetValueDecorator( sVal ) ) ) ); - } -}; - -/** Generate parse-dependent-but-then-constant value - */ -class IntConstantFunctor -{ - ParserContextSharedPtr mpContext; - -public: - IntConstantFunctor( const ParserContextSharedPtr& rContext ) : - mpContext( rContext ) - { - } - void operator()( sal_Int32 n ) const - { - mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( new ORowSetValueDecorator( n ) ) ) ); - } - void operator()( StringIteratorT rFirst,StringIteratorT rSecond) const - { - rtl::OUString sVal( rFirst, rSecond - rFirst, RTL_TEXTENCODING_UTF8 ); - (void)sVal; - } -}; - -/** 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 - rNodeStack.push( pNode ); - } -}; -/** 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 ) - { - } - virtual ORowSetValueDecoratorRef evaluate(const ODatabaseMetaDataResultSet::ORow& _aRow ) const - { - return _aRow[mpArg->evaluate(_aRow )->getValue().getInt32()]; - } - virtual void fill(const ODatabaseMetaDataResultSet::ORow& /*_aRow*/ ) const - { - } - virtual ExpressionFunct getType() const - { - return meFunct; - } - virtual ODatabaseMetaDataResultSet::ORow fillNode( std::vector< RowEquation >& /*rEquations*/, ExpressionNode* /* pOptionalArg */, sal_uInt32 /* nFlags */ ) - { - ODatabaseMetaDataResultSet::ORow aRet; - return aRet; - } -}; - -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(); - - rNodeStack.push( ExpressionNodeSharedPtr( new UnaryFunctionExpression( meFunct, pArg ) ) ); - } -}; - -/* This class implements the following grammar (more or - less literally written down below, only slightly - obfuscated by the parser actions): - - basic_expression = - number | - '(' additive_expression ')' - - unary_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::space_p; - using ::boost::spirit::range_p; - using ::boost::spirit::lexeme_d; - using ::boost::spirit::real_parser; - using ::boost::spirit::chseq_p; - using ::boost::spirit::ch_p; - using ::boost::spirit::int_p; - using ::boost::spirit::as_lower_d; - using ::boost::spirit::strlit; - using ::boost::spirit::inhibit_case; - - - typedef inhibit_case<strlit<> > token_t; - token_t COLUMN = as_lower_d[ "column" ]; - token_t OR_ = as_lower_d[ "or" ]; - token_t AND_ = as_lower_d[ "and" ]; - - integer = - int_p - [IntConstantFunctor(self.getContext())]; - - argument = - integer - | lexeme_d[ +( range_p('a','z') | range_p('A','Z') | range_p('0','9') ) ] - [ ConstantFunctor(self.getContext()) ] - ; - - unaryFunction = - (COLUMN >> '(' >> integer >> ')' ) - [ UnaryFunctionFunctor( UNARY_FUNC_COLUMN, self.getContext()) ] - ; - - assignment = - unaryFunction >> ch_p('=') >> argument - [ BinaryFunctionFunctor( ENUM_FUNC_EQUATION, self.getContext()) ] - ; - - andExpression = - assignment - | ( '(' >> orExpression >> ')' ) - | ( assignment >> AND_ >> assignment ) [ BinaryFunctionFunctor( ENUM_FUNC_AND, self.getContext()) ] - ; - - orExpression = - andExpression - | ( orExpression >> OR_ >> andExpression ) [ BinaryFunctionFunctor( ENUM_FUNC_OR, self.getContext()) ] - ; - - basicExpression = - orExpression - ; - - BOOST_SPIRIT_DEBUG_RULE(basicExpression); - BOOST_SPIRIT_DEBUG_RULE(unaryFunction); - BOOST_SPIRIT_DEBUG_RULE(assignment); - BOOST_SPIRIT_DEBUG_RULE(argument); - BOOST_SPIRIT_DEBUG_RULE(integer); - BOOST_SPIRIT_DEBUG_RULE(orExpression); - BOOST_SPIRIT_DEBUG_RULE(andExpression); - } - - const ::boost::spirit::rule< ScannerT >& start() const - { - return basicExpression; - } - - private: - // the constituents of the Spirit arithmetic expression grammar. - // For the sake of readability, without 'ma' prefix. - ::boost::spirit::rule< ScannerT > basicExpression; - ::boost::spirit::rule< ScannerT > unaryFunction; - ::boost::spirit::rule< ScannerT > assignment; - ::boost::spirit::rule< ScannerT > integer,argument; - ::boost::spirit::rule< ScannerT > orExpression,andExpression; - }; - - 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 -} - -ExpressionNodeSharedPtr FunctionParser::parseFunction( const ::rtl::OUString& _sFunction) -{ - // 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( _sFunction, 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 - - 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( "RowFunctionParser::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( "RowFunctionParser::parseFunction(): incomplete or empty expression" ); - - return pContext->maOperandStack.top(); -} -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |