00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "parser-debug.hpp"
00029 #include "parse_exception.hpp"
00030
00031 #ifdef ORO_PRAGMA_INTERFACE
00032 #pragma implementation
00033 #endif
00034 #include "ExpressionParser.hpp"
00035
00036
00037 #include "ArgumentsParser.hpp"
00038 #include "../types/Operators.hpp"
00039 #include "DataSourceCondition.hpp"
00040 #include "../internal/DataSourceCommand.hpp"
00041 #include "../internal/GlobalService.hpp"
00042
00043 #include "DataSourceTime.hpp"
00044 #include "../TaskContext.hpp"
00045 #include "PeerParser.hpp"
00046 #include "../types/Types.hpp"
00047 #include "SendHandleAlias.hpp"
00048
00049 #include <boost/lambda/lambda.hpp>
00050
00051 #include <boost/bind.hpp>
00052 #include <boost/ref.hpp>
00053 #include "rtt-scripting-config.h"
00054 #include <iostream>
00055
00056 namespace RTT
00057 {
00058 using boost::bind;
00059 using boost::ref;
00060
00061 using namespace detail;
00062 using namespace std;
00063
00064 namespace {
00065 boost::spirit::classic::assertion<std::string> expect_open("Open brace expected.");
00066 boost::spirit::classic::assertion<std::string> expect_close("Closing brace expected ( or could not find out what this line means ).");
00067 boost::spirit::classic::assertion<std::string> expect_type("Unknown type. Please specify a type.");
00068 boost::spirit::classic::assertion<std::string> expect_expr("Expected a valid expression.");
00069 boost::spirit::classic::assertion<std::string> expect_ident("Expected a valid identifier.");
00070 boost::spirit::classic::assertion<std::string> expect_init("Expected an initialisation value of the value.");
00071 boost::spirit::classic::assertion<std::string> expect_comma("Expected the ',' separator after expression.");
00072 boost::spirit::classic::assertion<std::string> expect_timespec("Expected a time specification (e.g. > 10s or > varname ) after 'time' .");
00073
00074 guard<std::string> my_guard;
00075 }
00076
00077
00078
00079 DataCallParser::DataCallParser( ExpressionParser& p, CommonParser& cp, TaskContext* c, ExecutionEngine* caller )
00080 : mcaller( caller ? caller : c->engine()), mis_send(false), commonparser(cp), expressionparser( p ),
00081 peerparser( c, cp, false )
00082 {
00083 BOOST_SPIRIT_DEBUG_RULE( datacall );
00084 BOOST_SPIRIT_DEBUG_RULE( arguments );
00085 BOOST_SPIRIT_DEBUG_RULE( peerpath );
00086 BOOST_SPIRIT_DEBUG_RULE( object );
00087 BOOST_SPIRIT_DEBUG_RULE( method );
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 peerpath = peerparser.locator();
00099 object= (commonparser.identifier >> ".")[boost::bind(&DataCallParser::seenobjectname, this, _1, _2)];
00100 method= ( commonparser.keyword | expect_ident(commonparser.tidentifier))[boost::bind( &DataCallParser::seenmethodname, this, _1, _2 ) ];
00101 datacall =
00102 ( peerpath >> !object >> method[ boost::bind( &DataCallParser::seendataname, this ) ] >> !arguments)[ boost::bind( &DataCallParser::seendatacall, this ) ];
00103 }
00104
00105 void DataCallParser::seensend() {
00106 mis_send = true;
00107 }
00108
00109 void DataCallParser::seenobjectname( iter_t begin, iter_t end )
00110 {
00111 std::string name( begin, end );
00112 mobject = name.substr(0, name.length() - 1);
00113 };
00114
00115 void DataCallParser::seenmethodname( iter_t begin, iter_t end )
00116 {
00117 std::string name( begin, end );
00118 if ( name == "send") {
00119 mis_send = true;
00120 mmethod = mobject;
00121 mobject.clear();
00122 } else {
00123 mis_send = false;
00124 mmethod = name;
00125 }
00126
00127 };
00128
00129 void DataCallParser::seendataname()
00130 {
00131
00132 mobject = peerparser.object();
00133 TaskContext* peer = peerparser.peer();
00134 Service::shared_ptr ops = peerparser.taskObject();
00135 peerparser.reset();
00136
00137 if (true) {
00138
00139
00140 if (mis_send && ops)
00141 mobject = ops->getName();
00142
00143
00144 if (mmethod != "collect" && mmethod != "collectIfDone" ) {
00145 if ( ops == 0 || (mobject != "this" && ops->getName() != mobject ) ) {
00146 throw parse_exception_no_such_component( peer->getName(), mobject);
00147 }
00148
00149 if ( ops->hasMember(mmethod) == false ) {
00150
00151 if ( ops == peerparser.taskObject() && GlobalService::Instance()->hasMember(mmethod) ) {
00152 mobject = "GlobalService";
00153 ops = GlobalService::Instance();
00154 } else {
00155
00156 if ( mobject != "this" )
00157 throw parse_exception_no_such_method_on_component( mobject, mmethod );
00158 else
00159 throw parse_exception_no_such_method_on_component( peer->getName(), mmethod );
00160 }
00161 }
00162 }
00163 }
00164
00165
00166
00167 ArgumentsParser* argspar =
00168 new ArgumentsParser( expressionparser, peer, ops,
00169 mobject, mmethod );
00170
00171 mobject.clear();
00172 mmethod.clear();
00173
00174
00175
00176 argparsers.push( argspar );
00177
00178
00179
00180 arguments = argspar->parser();
00181 }
00182
00183 void DataCallParser::seendatacall()
00184 {
00185 ArgumentsParser* argspar = argparsers.top();
00186 argparsers.pop();
00187 std::string obj = argspar->objectname();
00188 std::string meth = argspar->methodname();
00189 std::vector<DataSourceBase::shared_ptr> args = argspar->result();
00190 Service::shared_ptr peer = argspar->object();
00191 delete argspar;
00192 assert(peer && "peer may never be null.");
00193
00194
00195 if ( true ) {
00196
00197
00198 Service::shared_ptr ops = peer;
00199
00200
00201 peerparser.reset();
00202
00203 try {
00204 if ( (meth == "collect" || meth == "collectIfDone") && !ops->hasMember(mmethod) ) {
00205 if ( ops->hasAttribute(obj) ) {
00206 SendHandleAlias* sha = dynamic_cast<SendHandleAlias*>( peer->getValue(obj) );
00207 if (sha) {
00208
00209 args.insert( args.begin(), sha->getDataSource() );
00210 if (meth == "collect")
00211 ret = sha->getFactory()->produceCollect(args, new ValueDataSource<bool>(true) );
00212 else
00213 ret = sha->getFactory()->produceCollect(args, new ValueDataSource<bool>(false) );
00214 return;
00215 }
00216 }
00217 throw parse_exception_fatal_semantic_error( obj + "."+meth +": "+ obj +" is not a valid SendHandle object.");
00218 }
00219 if (!mis_send) {
00220 ret = ops->produce( meth, args, mcaller );
00221 mhandle.reset();
00222 } else {
00223 ret = ops->produceSend( meth, args, mcaller );
00224 mhandle.reset( new SendHandleAlias( meth, ops->produceHandle(meth), ops->getPart(meth)) );
00225 }
00226 }
00227 catch( const wrong_number_of_args_exception& e )
00228 {
00229 throw parse_exception_wrong_number_of_arguments
00230 (obj, meth, e.wanted, e.received );
00231 }
00232 catch( const wrong_types_of_args_exception& e )
00233 {
00234 throw parse_exception_wrong_type_of_argument
00235 (obj, meth, e.whicharg, e.expected_, e.received_ );
00236 }
00237 catch( const std::exception& e)
00238 {
00239 throw parse_exception_fatal_semantic_error("While calling "+obj+"."+meth+": "+e.what());
00240 }
00241 }
00242 assert( ret.get() );
00243 }
00244
00245 DataCallParser::~DataCallParser()
00246 {
00247
00248
00249
00250 while ( ! argparsers.empty() )
00251 {
00252 delete argparsers.top();
00253 argparsers.pop();
00254 };
00255 }
00256
00257 ConstructorParser::ConstructorParser( ExpressionParser& p, CommonParser& cp)
00258 : commonparser(cp), expressionparser( p )
00259 {
00260 BOOST_SPIRIT_DEBUG_RULE( type_name );
00261 BOOST_SPIRIT_DEBUG_RULE( arguments );
00262
00263 type_name =
00264 ( commonparser.type_name[ boost::bind( &ConstructorParser::seen_type_name, this, _1, _2 ) ] >> !arguments)[ boost::bind( &ConstructorParser::seen_constructor, this ) ];
00265 }
00266
00267 ConstructorParser::~ConstructorParser()
00268 {
00269
00270
00271
00272 while ( ! argparsers.empty() )
00273 {
00274 delete argparsers.top();
00275 argparsers.pop();
00276 };
00277 }
00278
00279
00280 void ConstructorParser::seen_type_name( iter_t begin, iter_t end )
00281 {
00282 std::string name( begin, end );
00283 TypeInfo* type = Types()->type( name );
00284 if ( type == 0 )
00285 throw_(iter_t(), "\"" + name + "\" is an unknown type...");
00286
00287 ArgumentsParser* argspar =
00288 new ArgumentsParser( expressionparser, 0, Service::shared_ptr(), name, "" );
00289
00290
00291
00292 argparsers.push( argspar );
00293
00294
00295
00296 arguments = argspar->parser();
00297
00298 }
00299
00300 void ConstructorParser::seen_constructor( void )
00301 {
00302 ArgumentsParser* argspar = argparsers.top();
00303 argparsers.pop();
00304 std::string obj = argspar->objectname();
00305 std::vector<DataSourceBase::shared_ptr> args = argspar->result();
00306 delete argspar;
00307
00308 ret = TypeInfoRepository::Instance()->type( obj )->construct( args );
00309
00310 if (!ret) {
00311 throw parse_exception_no_such_constructor( obj, args );
00312 }
00313
00314 }
00315
00317 static void abort_rule(const string& reason) {
00318 throw_(iter_t(), reason);
00319 }
00320
00321 static error_status<> fail_rule(scanner_t const& scan, parser_error<std::string, iter_t>&e )
00322 {
00323 return error_status<>( error_status<>::fail );
00324 }
00327 ExpressionParser::ExpressionParser( TaskContext* pc, ExecutionEngine* caller, CommonParser& cp )
00328 : datacallparser( *this, cp, pc, caller ),
00329 constrparser(*this, cp),
00330 commonparser( cp ),
00331 valueparser( pc, cp ),
00332 _invert_time(false),
00333 opreg( OperatorRepository::Instance() ),
00334 context(pc)
00335 {
00336 BOOST_SPIRIT_DEBUG_RULE( expression );
00337 BOOST_SPIRIT_DEBUG_RULE( unarynotexp );
00338 BOOST_SPIRIT_DEBUG_RULE( unaryminusexp );
00339 BOOST_SPIRIT_DEBUG_RULE( unaryplusexp );
00340 BOOST_SPIRIT_DEBUG_RULE( div_or_mul );
00341 BOOST_SPIRIT_DEBUG_RULE( modexp );
00342 BOOST_SPIRIT_DEBUG_RULE( plus_or_min );
00343 BOOST_SPIRIT_DEBUG_RULE( smallereqexp );
00344 BOOST_SPIRIT_DEBUG_RULE( smallerexp );
00345 BOOST_SPIRIT_DEBUG_RULE( greatereqexp );
00346 BOOST_SPIRIT_DEBUG_RULE( greaterexp );
00347 BOOST_SPIRIT_DEBUG_RULE( equalexp );
00348 BOOST_SPIRIT_DEBUG_RULE( notequalexp );
00349 BOOST_SPIRIT_DEBUG_RULE( orexp );
00350 BOOST_SPIRIT_DEBUG_RULE( andexp );
00351 BOOST_SPIRIT_DEBUG_RULE( ifthenelseexp );
00352 BOOST_SPIRIT_DEBUG_RULE( groupexp );
00353 BOOST_SPIRIT_DEBUG_RULE( dotexp );
00354 BOOST_SPIRIT_DEBUG_RULE( atomicexpression );
00355 BOOST_SPIRIT_DEBUG_RULE( time_expression );
00356 BOOST_SPIRIT_DEBUG_RULE( time_spec );
00357 BOOST_SPIRIT_DEBUG_RULE( indexexp );
00358 BOOST_SPIRIT_DEBUG_RULE( comma );
00359 BOOST_SPIRIT_DEBUG_RULE( close_brace );
00360 BOOST_SPIRIT_DEBUG_RULE( value_expression );
00361 BOOST_SPIRIT_DEBUG_RULE( call_expression );
00362 BOOST_SPIRIT_DEBUG_RULE( constructor_expression );
00363
00364 comma = expect_comma( ch_p(',') );
00365 close_brace = expect_close( ch_p(')') );
00366 expression = assignexp;
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 assignexp = andexp >> *( ch_p( '=' ) >> eps_p(~ch_p( '=' ))
00377 >> assignexp)[ bind( &ExpressionParser::seen_assign, this)];
00378 andexp =
00379 orexp >> *( ( str_p( "&&" ) ) >> orexp[
00380 boost::bind( &ExpressionParser::seen_binary, this, "&&" ) ] );
00381 orexp =
00382 notequalexp >> *( ( str_p( "||" ) ) >> notequalexp[
00383 boost::bind( &ExpressionParser::seen_binary, this, "||" ) ] );
00384 notequalexp =
00385 equalexp >> *( "!=" >> equalexp[
00386 boost::bind( &ExpressionParser::seen_binary, this, "!=" ) ] );
00387 equalexp =
00388 greatereqexp
00389 >> *( "==" >> greatereqexp[
00390 boost::bind( &ExpressionParser::seen_binary, this, "==" ) ] );
00391 greatereqexp =
00392 greaterexp
00393 >> *( ">=" >> greaterexp[
00394 boost::bind( &ExpressionParser::seen_binary, this, ">=" ) ] );
00395 greaterexp =
00396 smallereqexp
00397 >> *( '>' >> smallereqexp[
00398 boost::bind( &ExpressionParser::seen_binary, this, ">" ) ] );
00399 smallereqexp =
00400 smallerexp
00401 >> *( "<=" >> smallerexp[
00402 boost::bind( &ExpressionParser::seen_binary, this, "<=" ) ] );
00403 smallerexp =
00404 plus_or_min >> *( '<' >> plus_or_min[
00405 boost::bind( &ExpressionParser::seen_binary, this, "<" ) ] );
00406
00407 plus_or_min =
00408 modexp >> *( ('-' >> modexp[
00409 boost::bind( &ExpressionParser::seen_binary, this, "-" ) ] )
00410 | ('+' >> modexp[
00411 boost::bind( &ExpressionParser::seen_binary, this, "+" ) ] ) );
00412
00413 modexp =
00414 div_or_mul >> *( '%' >> div_or_mul[
00415 boost::bind( &ExpressionParser::seen_binary, this, "%" ) ] );
00416 div_or_mul =
00417 unaryplusexp >> *( ('/' >> unaryplusexp[
00418 boost::bind( &ExpressionParser::seen_binary, this, "/" ) ] )
00419 | ('*' >> unaryplusexp[
00420 boost::bind( &ExpressionParser::seen_binary, this, "*" ) ] ) );
00421
00422 unaryplusexp =
00423 '+' >> unaryminusexp[
00424 boost::bind( &ExpressionParser::seen_unary, this, "+" ) ]
00425 | unaryminusexp;
00426 unaryminusexp =
00427 '-' >> unarynotexp[
00428 boost::bind( &ExpressionParser::seen_unary, this, "-" ) ]
00429 | unarynotexp;
00430 unarynotexp =
00431 ch_p('!') >> atomicexpression[
00432 boost::bind( &ExpressionParser::seen_unary, this, "!" ) ]
00433 | atomicexpression;
00434
00435
00436
00437
00438 atomicexpression = (
00439
00440 groupexp
00441
00442 | time_expression
00443
00444 | value_expression
00445 | constructor_expression
00446 | call_expression
00447
00448 ) >> *( dotexp | indexexp);
00449
00450 constructor_expression = my_guard( constrparser.parser()[ boost::bind(&ExpressionParser::seenconstructor, this)])[&fail_rule];
00451
00452
00453 value_expression = my_guard( valueparser.parser() >> !('.' >> commonparser.keyword[boost::bind(&abort_rule,"Rule must be handled by datacallparser.")]))[ &fail_rule ]
00454 [ bind( &ExpressionParser::seenvalue, this ) ];
00455 call_expression = my_guard( datacallparser.parser() )[&fail_rule]
00456 [bind( &ExpressionParser::seendatacall, this ) ];
00457
00458 indexexp =
00459 (ch_p('[') >> expression[bind(&ExpressionParser::seen_index, this)] >> expect_close( ch_p( ']') ) );
00460
00461 dotexp =
00462 ( ch_p('.') >> commonparser.identifier[ boost::bind(&ExpressionParser::seen_dotmember, this, _1, _2)]);
00463
00464
00465
00466 groupexp = '(' >> expression >> close_brace;
00467
00468
00469
00470 time_expression =
00471 (str_p("time")>>eps_p(~commonparser.identchar | eol_p | end_p ))[bind(&ExpressionParser::seentimeexpr, this)]
00472 |
00473 ( (eps_p[boost::lambda::var(commonparser.skipeol) = false] >> uint_p[ bind( &ExpressionParser::seentimespec, this, _1 ) ]
00474 >> (str_p( "s" ) | "ms" | "us" | "ns" )[boost::lambda::var(commonparser.skipeol) = true][boost::bind( &ExpressionParser::seentimeunit, this, _1, _2 ) ])
00475 | (eps_p[boost::lambda::var(commonparser.skipeol) = true] >> nothing_p)
00476 )
00477 ;
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 };
00491
00492 void ExpressionParser::inverttime()
00493 {
00494 _invert_time = true;
00495 }
00496
00497 void ExpressionParser::seentimeexpr()
00498 {
00499 parsestack.push( new DataSourceTime() );
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 }
00510
00511 void ExpressionParser::seentimeunit( iter_t begin, iter_t end)
00512 {
00513
00514
00515
00516 TimeService::Seconds total = 0;
00517 switch( *begin )
00518 {
00519 case 's': total = TimeService::Seconds(tsecs);
00520 break;
00521 case 'm': total = tsecs / 1000.0;
00522 break;
00523 case 'u': total = tsecs / 1000000.0;
00524 break;
00525 case 'n': total = tsecs / 1000000000.0;
00526 break;
00527 default:
00528 std::string arg(begin, end);
00529 throw parse_exception_semantic_error("Expected time expression 's', 'ms', 'us' or 'ns' after integer value, got "+arg);
00530 };
00531
00532 parsestack.push( new ConstantDataSource<double>( total ) );
00533
00534
00535
00536
00537
00538 }
00539
00540 void ExpressionParser::seentimespec( int n )
00541 {
00542 tsecs = n;
00543 }
00544
00545 void ExpressionParser::seenvalue()
00546 {
00547 DataSourceBase::shared_ptr ds = valueparser.lastParsed();
00548 parsestack.push( ds );
00549 }
00550
00551 void ExpressionParser::seendatacall()
00552 {
00553 DataSourceBase::shared_ptr n( datacallparser.getParseResult() );
00554 parsestack.push( n );
00555 mhandle = datacallparser.getParseHandle();
00556 }
00557
00558 void ExpressionParser::seenconstructor()
00559 {
00560 DataSourceBase::shared_ptr n( constrparser.getParseResult() );
00561 parsestack.push( n );
00562 }
00563
00564 ExpressionParser::~ExpressionParser()
00565 {
00566
00567
00568 while ( !parsestack.empty() )
00569 parsestack.pop();
00570 }
00571
00572 rule_t& ExpressionParser::parser()
00573 {
00574 return expression;
00575 }
00576
00577 DataSourceBase::shared_ptr ExpressionParser::getResult()
00578 {
00579 assert( !parsestack.empty() );
00580 return parsestack.top();
00581 }
00582
00583 boost::shared_ptr<AttributeBase> ExpressionParser::getHandle()
00584 {
00585 assert( !parsestack.empty() );
00586 return mhandle;
00587 }
00588
00589 void ExpressionParser::seen_unary( const std::string& op )
00590 {
00591 DataSourceBase::shared_ptr arg( parsestack.top() );
00592 parsestack.pop();
00593 DataSourceBase::shared_ptr ret =
00594 opreg->applyUnary( op, arg.get() );
00595 if ( ! ret )
00596 throw parse_exception_fatal_semantic_error( "Cannot apply unary operator \"" + op +
00597 "\" to " + arg->getType() +"." );
00598 parsestack.push( ret );
00599 }
00600
00601 void ExpressionParser::seen_dotmember( iter_t s, iter_t f )
00602 {
00603 std::string member(s,f);
00604
00605 DataSourceBase::shared_ptr arg( parsestack.top() );
00606 parsestack.pop();
00607 DataSourceBase::shared_ptr ret = arg->getMember(member);
00608 if ( ! ret )
00609 throw parse_exception_fatal_semantic_error( arg->getType() + " does not have member \"" + member +
00610 "\"." );
00611 parsestack.push( ret );
00612 }
00613
00614 void ExpressionParser::seen_binary( const std::string& op )
00615 {
00616 DataSourceBase::shared_ptr arg1( parsestack.top() );
00617 parsestack.pop();
00618 DataSourceBase::shared_ptr arg2( parsestack.top() );
00619 parsestack.pop();
00620
00621
00622
00623 DataSourceBase::shared_ptr ret =
00624 opreg->applyBinary( op, arg2.get(), arg1.get() );
00625 if ( ! ret )
00626 throw parse_exception_fatal_semantic_error( "Cannot apply binary operation "+ arg2->getType() +" " + op +
00627 " "+arg1->getType() +"." );
00628 parsestack.push( ret );
00629 }
00630
00631 void ExpressionParser::seen_assign()
00632 {
00633 DataSourceBase::shared_ptr arg1( parsestack.top() );
00634 parsestack.pop();
00635 DataSourceBase::shared_ptr arg2( parsestack.top() );
00636 parsestack.pop();
00637
00638
00639 if (arg2->getTypeName() == "SendHandle" && mhandle) {
00640
00641 ConfigurationInterface::AttributeObjects attrs = context->attributes()->getValues();
00642 for( ConfigurationInterface::AttributeObjects::iterator it = attrs.begin(); it != attrs.end(); ++it) {
00643 if ( (*it)->getDataSource() == arg2 ) {
00644
00645 string name = (*it)->getName();
00646 context->attributes()->removeAttribute(name);
00647 AttributeBase* var = mhandle->clone();
00648 var->setName( name );
00649 context->attributes()->setValue( var );
00650 arg2 = var->getDataSource();
00651 break;
00652 }
00653 }
00654 }
00655
00656 DataSourceBase::shared_ptr ret;
00657 ActionInterface* act = 0;
00658 try {
00659 act = arg2->updateAction( arg1.get() );
00660 } catch(...) {
00661 throw parse_exception_fatal_semantic_error( "Incompatible types. Cannot assign: "+ arg2->getType() +" = " +
00662 " "+arg1->getType() +"." );
00663 }
00664 if (!act)
00665 throw parse_exception_fatal_semantic_error( "2:Cannot assign constant (or returned) variable of types: "+ arg2->getType() +" = " +
00666 " "+arg1->getType() );
00667
00668 if (arg2->getTypeInfo()->getTypeName() != "unknown_t")
00669 ret = arg2->getTypeInfo()->buildActionAlias(act, arg2);
00670 if (!ret) {
00671 ret = new DataSourceCommand( act );
00672 }
00673 parsestack.push( ret );
00674 }
00675
00676 void ExpressionParser::seen_index()
00677 {
00678 DataSourceBase::shared_ptr arg1( parsestack.top() );
00679 parsestack.pop();
00680 DataSourceBase::shared_ptr arg2( parsestack.top() );
00681 parsestack.pop();
00682
00683
00684
00685 DataSourceBase::shared_ptr ret = arg2->getMember( arg1, 0 );
00686 if ( ! ret )
00687 throw parse_exception_fatal_semantic_error( "Illegal use of []: "+ arg2->getType() +"[ "
00688 +arg1->getType() +" ]." );
00689 parsestack.push( ret );
00690 }
00691
00692 void ExpressionParser::dropResult()
00693 {
00694 parsestack.pop();
00695 }
00696 }