diff --git a/rtt/scripting/CommonParser.cpp b/rtt/scripting/CommonParser.cpp index 608700384..9f4d0f599 100644 --- a/rtt/scripting/CommonParser.cpp +++ b/rtt/scripting/CommonParser.cpp @@ -105,6 +105,7 @@ namespace RTT { BOOST_SPIRIT_DEBUG_RULE( notassertingidentifier ); BOOST_SPIRIT_DEBUG_RULE( lexeme_identifier ); BOOST_SPIRIT_DEBUG_RULE( lexeme_notassertingidentifier ); + BOOST_SPIRIT_DEBUG_RULE( type_name ); // an identifier is a word which can be used to identify a // label, or be the name of an object or method. it is required @@ -140,6 +141,9 @@ namespace RTT { eos = expect_eos( notassertingeos ); // detect } as eos, but do not consume. notassertingeos = eol_p | ch_p(';') | eps_p(ch_p('}')); // detect } as eos, but do not consume. leos = *(space_p - eol_p) >> (eol_p | ch_p(';') | eps_p(ch_p('}'))); + + chset<> t_identchar( "a-zA-Z-_0-9/<>." ); + type_name = lexeme_d[ alpha_p >> *t_identchar ] - keyword; } void CommonParser::seenillegalidentifier() diff --git a/rtt/scripting/CommonParser.hpp b/rtt/scripting/CommonParser.hpp index 944da12af..45ab98760 100644 --- a/rtt/scripting/CommonParser.hpp +++ b/rtt/scripting/CommonParser.hpp @@ -71,7 +71,7 @@ namespace RTT { namespace scripting rule_t notassertingidentifier; //! plain 'C' identifier. Does not throw if keyword is parsed. lexeme_rule_t lexeme_identifier; //! See identifier, but in lexeme parsing mode. lexeme_rule_t lexeme_notassertingidentifier; //! See notassertingidentifier, but in lexeme parsing mode. - + rule_t type_name; //@{ /** * End Of Statement Parser. Identifies the end of a statement diff --git a/rtt/scripting/ExpressionParser.cpp b/rtt/scripting/ExpressionParser.cpp index 1bce0d687..05fe8d4ae 100644 --- a/rtt/scripting/ExpressionParser.cpp +++ b/rtt/scripting/ExpressionParser.cpp @@ -100,7 +100,7 @@ namespace RTT method= ( commonparser.keyword | expect_ident(commonparser.tidentifier))[boost::bind( &DataCallParser::seenmethodname, this, _1, _2 ) ]; // may be send, call or method name. datacall = ( peerpath >> !object >> method[ boost::bind( &DataCallParser::seendataname, this ) ] >> !arguments)[ boost::bind( &DataCallParser::seendatacall, this ) ]; - }; + } void DataCallParser::seensend() { mis_send = true; @@ -134,12 +134,7 @@ namespace RTT Service::shared_ptr ops = peerparser.taskObject(); peerparser.reset(); // cout << "seendataname "<< mobject << "." << mmethod<type( mmethod )) - || - (TypeInfoRepository::Instance()->type( mobject + "." + mmethod )) ) { - // it is... - } else { + if (true) { // it ain't... // set the proper object name again in case of a send() if (mis_send && ops) @@ -197,17 +192,7 @@ namespace RTT assert(peer && "peer may never be null."); // cout << "seendatacall "<< mobject << "." << mmethod<type( meth )) || - (TypeInfoRepository::Instance()->type( obj + "." + meth) ) ) { - if (obj == "this") - ret = TypeInfoRepository::Instance()->type( meth )->construct( args ); - else - ret = TypeInfoRepository::Instance()->type( obj +"."+ meth )->construct( args ); - if (!ret) { - throw parse_exception_no_such_constructor( meth, args ); - } - } else { + if ( true ) { // plain method or collect/collectIfDone Service::shared_ptr ops = peer; @@ -267,30 +252,81 @@ namespace RTT delete argparsers.top(); argparsers.pop(); }; - }; + } - /** @cond */ - static error_status<> handle_no_value(scanner_t const& scan, parser_error& e ) - { - //std::cerr << "No value in EP : "<( error_status<>::fail ); - } + ConstructorParser::ConstructorParser( ExpressionParser& p, CommonParser& cp) + : commonparser(cp), expressionparser( p ) + { + BOOST_SPIRIT_DEBUG_RULE( type_name ); + BOOST_SPIRIT_DEBUG_RULE( arguments ); + + type_name = + ( commonparser.type_name[ boost::bind( &ConstructorParser::seen_type_name, this, _1, _2 ) ] >> !arguments)[ boost::bind( &ConstructorParser::seen_constructor, this ) ]; + } - static error_status<> handle_no_datacall(scanner_t const& scan, parser_error&e ) + ConstructorParser::~ConstructorParser() + { + // 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() ) { - //retry with a member : - //std::cerr << "No DataCall in EP : "<( error_status<>::fail ); + delete argparsers.top(); + argparsers.pop(); + }; + } + + + void ConstructorParser::seen_type_name( iter_t begin, iter_t end ) + { + std::string name( begin, end ); + TypeInfo* type = Types()->type( name ); + if ( type == 0 ) + throw_(iter_t(), "\"" + name + "\" is an unknown type..."); + + ArgumentsParser* argspar = + new ArgumentsParser( expressionparser, 0, Service::shared_ptr(), name, "" ); + + // keep hold of the argspar, we're still going to need it after + // it's done its work.. ( in seen_constructor(), that is.. ) + argparsers.push( argspar ); + + // set the arguments parser to the parser provided by the + // ArgumentsParser we just created.. + arguments = argspar->parser(); + + } + + void ConstructorParser::seen_constructor( void ) + { + ArgumentsParser* argspar = argparsers.top(); + argparsers.pop(); + std::string obj = argspar->objectname(); + std::vector args = argspar->result(); + delete argspar; + + ret = TypeInfoRepository::Instance()->type( obj )->construct( args ); + + if (!ret) { + throw parse_exception_no_such_constructor( obj, args ); } + } + + /** @cond */ static void abort_rule(const string& reason) { throw_(iter_t(), reason); } + + static error_status<> fail_rule(scanner_t const& scan, parser_error&e ) + { + return error_status<>( error_status<>::fail ); + } /** @endcond */ ExpressionParser::ExpressionParser( TaskContext* pc, ExecutionEngine* caller, CommonParser& cp ) : datacallparser( *this, cp, pc, caller ), + constrparser(*this, cp), commonparser( cp ), valueparser( pc, cp ), _invert_time(false), @@ -323,6 +359,7 @@ namespace RTT BOOST_SPIRIT_DEBUG_RULE( close_brace ); BOOST_SPIRIT_DEBUG_RULE( value_expression ); BOOST_SPIRIT_DEBUG_RULE( call_expression ); + BOOST_SPIRIT_DEBUG_RULE( constructor_expression ); comma = expect_comma( ch_p(',') ); close_brace = expect_close( ch_p(')') ); @@ -405,14 +442,17 @@ namespace RTT | time_expression // or a constant or user-defined value.. | value_expression + | constructor_expression | call_expression // or an index or dot expression ) >> *( dotexp | indexexp); + constructor_expression = my_guard( constrparser.parser()[ boost::bind(&ExpressionParser::seenconstructor, this)])[&fail_rule]; + // if it's value.keyword then pass it on to the call_expression. - value_expression = my_guard( valueparser.parser() >> !('.' >> commonparser.keyword[boost::bind(&abort_rule,"Rule must be handled by datacallparser.")]))[ &handle_no_value ] + value_expression = my_guard( valueparser.parser() >> !('.' >> commonparser.keyword[boost::bind(&abort_rule,"Rule must be handled by datacallparser.")]))[ &fail_rule ] [ bind( &ExpressionParser::seenvalue, this ) ]; - call_expression = my_guard( datacallparser.parser() )[&handle_no_datacall] + call_expression = my_guard( datacallparser.parser() )[&fail_rule] [bind( &ExpressionParser::seendatacall, this ) ]; // take index of an atomicexpression indexexp = @@ -515,6 +555,12 @@ namespace RTT mhandle = datacallparser.getParseHandle(); } + void ExpressionParser::seenconstructor() + { + DataSourceBase::shared_ptr n( constrparser.getParseResult() ); + parsestack.push( n ); + } + ExpressionParser::~ExpressionParser() { // if parsestack is not empty, then something went wrong, someone @@ -550,7 +596,7 @@ namespace RTT throw parse_exception_fatal_semantic_error( "Cannot apply unary operator \"" + op + "\" to " + arg->getType() +"." ); parsestack.push( ret ); - }; + } void ExpressionParser::seen_dotmember( iter_t s, iter_t f ) { @@ -563,7 +609,7 @@ namespace RTT throw parse_exception_fatal_semantic_error( arg->getType() + " does not have member \"" + member + "\"." ); parsestack.push( ret ); - }; + } void ExpressionParser::seen_binary( const std::string& op ) { @@ -580,7 +626,7 @@ namespace RTT throw parse_exception_fatal_semantic_error( "Cannot apply binary operation "+ arg2->getType() +" " + op + " "+arg1->getType() +"." ); parsestack.push( ret ); - }; + } void ExpressionParser::seen_assign() { @@ -625,7 +671,7 @@ namespace RTT ret = new DataSourceCommand( act ); // fall back into the old behavior of returning a boolean. } parsestack.push( ret ); - }; + } void ExpressionParser::seen_index() { @@ -641,7 +687,7 @@ namespace RTT throw parse_exception_fatal_semantic_error( "Illegal use of []: "+ arg2->getType() +"[ " +arg1->getType() +" ]." ); parsestack.push( ret ); - }; + } void ExpressionParser::dropResult() { diff --git a/rtt/scripting/ExpressionParser.hpp b/rtt/scripting/ExpressionParser.hpp index b894162bf..bd6e14bda 100644 --- a/rtt/scripting/ExpressionParser.hpp +++ b/rtt/scripting/ExpressionParser.hpp @@ -89,16 +89,45 @@ namespace RTT { namespace scripting rule_t& parser() { return datacall; - }; + } base::DataSourceBase* getParseResult() { return ret.get(); - }; + } boost::shared_ptr getParseHandle() { return mhandle; - }; + } + }; + + /** + * Parses type constructor syntax + */ + class ConstructorParser + { + base::DataSourceBase::shared_ptr ret; + rule_t type_name, arguments; + + CommonParser& commonparser; + ExpressionParser& expressionparser; + std::stack argparsers; + public: + ConstructorParser( ExpressionParser& p, CommonParser& cp); + ~ConstructorParser(); + + void seen_type_name( iter_t begin, iter_t end ); + void seen_constructor( void ); + + rule_t& parser() + { + return type_name; + } + + base::DataSourceBase* getParseResult() + { + return ret.get(); + } }; /** @@ -115,7 +144,7 @@ namespace RTT { namespace scripting greatereqexp, greaterexp, equalexp, notequalexp, orexp, andexp, ifthenelseexp, dotexp, groupexp, atomicexpression, time_expression, time_spec, indexexp, comma, close_brace, - value_expression, call_expression, assignexp; + value_expression, call_expression, assignexp, constructor_expression; /** * The parse stack.. see the comment for this class ( scroll up @@ -148,12 +177,14 @@ namespace RTT { namespace scripting void seen_dotmember( iter_t begin, iter_t end ); void seenvalue(); void seendatacall(); + void seenconstructor(); void seentimespec( int n ); void seentimeunit( iter_t begin, iter_t end ); void inverttime(); void seentimeexpr(); DataCallParser datacallparser; + ConstructorParser constrparser; /** * The governing common parser. */