📄 expressionparser.cpp
字号:
/*************************************************************************** tag: Peter Soetens Mon May 10 19:10:37 CEST 2004 ExpressionParser.cxx ExpressionParser.cxx - description ------------------- begin : Mon May 10 2004 copyright : (C) 2004 Peter Soetens email : peter.soetens@mech.kuleuven.ac.be *************************************************************************** * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * 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. * * * * 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 * * * ***************************************************************************/#include "parser-debug.hpp"#include "parse_exception.hpp"#ifdef ORO_PRAGMA_INTERFACE#pragma implementation#endif#include "ExpressionParser.hpp"//#include "DumpObject.hpp"#include "ArgumentsParser.hpp"#include <Operators.hpp>#include <DataSourceCondition.hpp>#include "DataSourceTime.hpp"#include "TaskContext.hpp"#include "PeerParser.hpp"#include "Types.hpp"#include <boost/lambda/lambda.hpp>#include <boost/bind.hpp>#include "../rtt-config.h"#include <iostream>namespace RTT{ using boost::bind; using namespace detail; using namespace std; namespace { assertion<std::string> expect_open("Open brace expected."); assertion<std::string> expect_close("Closing brace expected ( or could not find out what this line means )."); assertion<std::string> expect_type("Unknown type. Please specify a type."); assertion<std::string> expect_expr("Expected a valid expression."); assertion<std::string> expect_ident("Expected a valid identifier."); assertion<std::string> expect_init("Expected an initialisation value of the value."); assertion<std::string> expect_comma("Expected the ',' separator after expression."); assertion<std::string> expect_timespec("Expected a time specification (e.g. > 10s or > varname ) after 'time' ."); guard<std::string> my_guard; } DataCallParser::DataCallParser( ExpressionParser& p, TaskContext* c ) : expressionparser( p ), peerparser( c ) { BOOST_SPIRIT_DEBUG_RULE( datacall ); BOOST_SPIRIT_DEBUG_RULE( arguments ); // this parser uses a neat boost.spirit trick to avoid keeping // loads of stacks for all parsing data ( this parser needs to be // reentrant because it can be called while parsing an argument of // a datacall, which has itself been called while parsing an // argument of a datacall... ). Boost.Spirit allows you to change // the parser that a rule points to at runtime, so we only create // the parser just before it's going to be used, when we know what // arguments we want.. See the ArgumentsParser doc for more // details.. datacall = ( peerparser.locator() >> !(commonparser.identifier >> ".") >> // just consume, peer locator already has object name expect_ident(commonparser.identifier)[bind( &DataCallParser::seenmethodname, this, _1, _2 ) ] [ bind( &DataCallParser::seendataname, this ) ] >> !arguments )[ bind( &DataCallParser::seendatacall, this ) ]; }; void DataCallParser::seendataname() { mobject = peerparser.object(); TaskContext* peer = peerparser.peer(); OperationInterface* ops = peerparser.taskObject(); peerparser.reset(); // Check if it is a constructor if ( mobject == "this" && TypeInfoRepository::Instance()->type( mmethod ) ) { // it is... } else { // it ain't... //cout << "DCP saw method "<< mmethod <<" of object "<<mobject<<" of peer "<<peer->getName()<<endl; // this is slightly different from CommandParser if ( ops == 0 ) { //DumpObject( peer ); throw_( iter_t(), std::string("Task '")+peer->getName()+"' has no object '"+mobject+"'." ); } if ( ops->methods()->hasMember(mmethod) == false ) { //DumpObject( peer ); if ( mobject != "this" ) throw parse_exception_no_such_method_on_component( "DataCall::"+mobject, mmethod ); else throw parse_exception_no_such_method_on_component( "DataCall::"+peer->getName(), mmethod ); } } // create an argument parser for the call.. // Store everything in the ArgumentsParser ! This DataCallParser instance is recursively called ! ArgumentsParser* argspar = new ArgumentsParser( expressionparser, peer, ops, mobject, mmethod ); // we no longer need these two.. mobject.clear(); mmethod.clear(); // keep hold of the argspar, we're still going to need it after // it's done its work.. ( in seendatacall(), that is.. ) argparsers.push( argspar ); // set the arguments parser to the parser provided by the // ArgumentsParser we just created.. arguments = argspar->parser(); } void DataCallParser::seendatacall() { ArgumentsParser* argspar = argparsers.top(); argparsers.pop(); std::string obj = argspar->objectname(); std::string meth = argspar->methodname(); std::vector<DataSourceBase::shared_ptr> args = argspar->result(); OperationInterface* peer = argspar->object(); delete argspar; // separate track if we are handling a constructor: if ( obj == "this" && TypeInfoRepository::Instance()->type( meth ) ) { log(Info) << "Looking for constructor "<<meth<<" with "<< args.size() << " Args."<<endlog(); ret = TypeInfoRepository::Instance()->type( meth )->construct( args ); if (!ret) { log(Error) << " no such constructor ! "<< endlog(); throw parse_exception_no_such_constructor( meth, args ); } } else { // plain method: OperationInterface* ops = peer; // we already checked for the existence of this object and method // in seendataname().. try { ret = ops->methods()->produce( meth, args ); } catch( const wrong_number_of_args_exception& e ) { throw parse_exception_wrong_number_of_arguments (obj, meth, e.wanted, e.received ); } catch( const wrong_types_of_args_exception& e ) { throw parse_exception_wrong_type_of_argument (obj, meth, e.whicharg, e.expected_, e.received_ ); } catch(...) { assert(false); } } assert( ret.get() ); } DataCallParser::~DataCallParser() { // if argparsers is not empty, then something went wrong during // the parsing ( someone threw an exception ), and we're // responsible for cleaning up the argparsers we created.. while ( ! argparsers.empty() ) { delete argparsers.top(); argparsers.pop(); }; }; error_status<> handle_no_value(scanner_t const& scan, parser_error<std::string, iter_t>& e ) { //std::cerr << "No value in EP : "<<e.descriptor<<std::endl; // retry if it is a datacall, thus fail this rule return error_status<>( error_status<>::fail ); } error_status<> handle_no_datacall(scanner_t const& scan, parser_error<std::string, iter_t>&e ) { // retry with a member : //std::cerr << "No DataCall in EP : "<<e.descriptor<<std::endl; return error_status<>( error_status<>::fail ); } error_status<> handle_no_member(scanner_t const& scan, parser_error<std::string, iter_t>&e ) { // if this rule also fails, throw semantic exception ( member not found ) throw parse_exception_semantic_error( e.descriptor ); // dough ! not reached : return error_status<>( error_status<>::rethrow ); } ExpressionParser::ExpressionParser( TaskContext* pc ) : datacallparser( *this, pc ), valueparser( pc ), _invert_time(false), opreg( OperatorRepository::Instance() ) { BOOST_SPIRIT_DEBUG_RULE( expression ); BOOST_SPIRIT_DEBUG_RULE( unarynotexp ); BOOST_SPIRIT_DEBUG_RULE( unaryminusexp ); BOOST_SPIRIT_DEBUG_RULE( unaryplusexp ); BOOST_SPIRIT_DEBUG_RULE( multexp ); BOOST_SPIRIT_DEBUG_RULE( divexp ); BOOST_SPIRIT_DEBUG_RULE( modexp ); BOOST_SPIRIT_DEBUG_RULE( plusexp ); BOOST_SPIRIT_DEBUG_RULE( minusexp ); BOOST_SPIRIT_DEBUG_RULE( smallereqexp ); BOOST_SPIRIT_DEBUG_RULE( smallerexp ); BOOST_SPIRIT_DEBUG_RULE( greatereqexp ); BOOST_SPIRIT_DEBUG_RULE( greaterexp ); BOOST_SPIRIT_DEBUG_RULE( equalexp ); BOOST_SPIRIT_DEBUG_RULE( notequalexp ); BOOST_SPIRIT_DEBUG_RULE( orexp ); BOOST_SPIRIT_DEBUG_RULE( andexp ); BOOST_SPIRIT_DEBUG_RULE( ifthenelseexp ); BOOST_SPIRIT_DEBUG_RULE( groupexp ); BOOST_SPIRIT_DEBUG_RULE( dotexp ); BOOST_SPIRIT_DEBUG_RULE( atomicexpression ); BOOST_SPIRIT_DEBUG_RULE( time_expression ); BOOST_SPIRIT_DEBUG_RULE( time_spec ); BOOST_SPIRIT_DEBUG_RULE( indexexp ); BOOST_SPIRIT_DEBUG_RULE( comma ); BOOST_SPIRIT_DEBUG_RULE( close_brace );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -