From e7521b35416d8a9b034719281b4d26789964d20c Mon Sep 17 00:00:00 2001 From: Peter Soetens Date: Wed, 21 Apr 2010 10:28:46 +0000 Subject: [PATCH] Fix multi-threaded parser use bug. The parsers used some static/global variables that caused multi-threaded parsing to fail. This was solved for all cases, and a shared CommonParser object (on the stack) tracks eol skipping for each parser. From: Peter Soetens git-svn-id: https://svn.mech.kuleuven.be/repos/orocos/trunk/rtt@31663 ce417995-dfc9-0310-95a0-acdaff106893 --- src/scripting/CommandParser.cpp | 6 ++-- src/scripting/CommandParser.hpp | 4 +- src/scripting/CommonParser.cpp | 8 +----- src/scripting/CommonParser.hpp | 4 +++ src/scripting/ConditionParser.cpp | 4 +- src/scripting/ConditionParser.hpp | 4 +- src/scripting/ExpressionParser.cpp | 22 +++++++++++--------- src/scripting/ExpressionParser.hpp | 11 ++++++--- src/scripting/Parser.cpp | 22 +++++++++++++++----- src/scripting/PeerParser.cpp | 18 +++------------- src/scripting/PeerParser.hpp | 12 +++++++++- src/scripting/ProgramGraphParser.cpp | 27 ++++++++++++++----------- src/scripting/ProgramGraphParser.hpp | 4 +- src/scripting/ProgramGraphParser2.cpp | 4 +- src/scripting/PropertyParser.cpp | 34 +++++++++++--------------------- src/scripting/PropertyParser.hpp | 14 +++++++++++- src/scripting/StateGraphParser.cpp | 25 +++++++++++------------ src/scripting/StateGraphParser.hpp | 2 +- src/scripting/ValueChangeParser.cpp | 4 +- src/scripting/ValueChangeParser.hpp | 4 +- src/scripting/ValueParser.cpp | 4 +- src/scripting/ValueParser.hpp | 4 +- src/scripting/parser-types.hpp | 13 +++++------ tests/function_test.cpp | 4 +- tests/program_test.cpp | 4 +- tests/state_test.cpp | 16 +++++++------- tests/types_test.cpp | 10 ++++---- 27 files changed, 151 insertions(+), 137 deletions(-) diff --git a/src/scripting/CommandParser.cpp b/src/scripting/CommandParser.cpp index f27daa9..fd15963 100644 --- a/src/scripting/CommandParser.cpp +++ b/src/scripting/CommandParser.cpp @@ -60,11 +60,11 @@ namespace RTT assertion expect_methodname("Expected a method call on object."); assertion expect_args( "Expected method call arguments between ()." ); } - CommandParser::CommandParser( TaskContext* c, bool as_action) + CommandParser::CommandParser( TaskContext* c, CommonParser& cp, bool as_action) : mas_action( as_action ), dcom(0), retcommand( 0 ), - implicittermcondition( 0 ), peer(0), context( c ), - argsparser( 0 ), expressionparser( c ), peerparser( c, true ) + implicittermcondition( 0 ), peer(0), context( c ), commonparser(cp), + argsparser( 0 ), expressionparser( c, cp ), peerparser( c, cp, true ) { BOOST_SPIRIT_DEBUG_RULE( objectmethod ); BOOST_SPIRIT_DEBUG_RULE( callcommand ); diff --git a/src/scripting/CommandParser.hpp b/src/scripting/CommandParser.hpp index ce5271b..f28aa24 100644 --- a/src/scripting/CommandParser.hpp +++ b/src/scripting/CommandParser.hpp @@ -93,7 +93,7 @@ namespace RTT rule_t objectmethod, command, callcommand, nopcommand, arguments; TaskContext* context; - CommonParser commonparser; + CommonParser& commonparser; ArgumentsParser* argsparser; ExpressionParser expressionparser; PeerParser peerparser; @@ -104,7 +104,7 @@ namespace RTT * created DispatchInterface in an DispatchAction such that * execute() of the returned command does a DispatchInterface::dispatch(). */ - CommandParser( TaskContext* context, bool as_action ); + CommandParser( TaskContext* context, CommonParser& cp, bool as_action ); ~CommandParser(); bool foundObject() { diff --git a/src/scripting/CommonParser.cpp b/src/scripting/CommonParser.cpp index 33c6469..7a6409f 100644 --- a/src/scripting/CommonParser.cpp +++ b/src/scripting/CommonParser.cpp @@ -44,17 +44,13 @@ namespace RTT { using boost::bind; using namespace detail; - // see parser-types.hpp - functor_parser eol_skip_p; - - bool eol_skip_functor::skipeol = true; - namespace { assertion expect_eos("End of statement expected. Use a newline or ';' to separate statements."); } CommonParser::CommonParser() - : identchar( "a-zA-Z_0-9" ) + : identchar( "a-zA-Z_0-9" ), skipeol(true), + skipper( eol_skip_functor(skipeol) ) { // we reserve a few words keywords = diff --git a/src/scripting/CommonParser.hpp b/src/scripting/CommonParser.hpp index f1fd105..0744381 100644 --- a/src/scripting/CommonParser.hpp +++ b/src/scripting/CommonParser.hpp @@ -76,6 +76,10 @@ namespace RTT { namespace detail */ rule_t eos; lexeme_rule_t leos; + + //! Saves eol skipping state + bool skipeol; + functor_parser skipper; //@} CommonParser(); diff --git a/src/scripting/ConditionParser.cpp b/src/scripting/ConditionParser.cpp index 8e0fb1f..475be62 100644 --- a/src/scripting/ConditionParser.cpp +++ b/src/scripting/ConditionParser.cpp @@ -49,8 +49,8 @@ namespace RTT - ConditionParser::ConditionParser( TaskContext* c ) - : ds_bool( 0 ), context( c ), expressionparser( c ) + ConditionParser::ConditionParser( TaskContext* c, CommonParser& cp ) + : ds_bool( 0 ), context( c ), commonparser(cp), expressionparser( c, cp ) { BOOST_SPIRIT_DEBUG_RULE( condition ); diff --git a/src/scripting/ConditionParser.hpp b/src/scripting/ConditionParser.hpp index a35b6b1..a068499 100644 --- a/src/scripting/ConditionParser.hpp +++ b/src/scripting/ConditionParser.hpp @@ -68,11 +68,11 @@ namespace RTT { namespace detail rule_t condition; TaskContext* context; - CommonParser commonparser; + CommonParser& commonparser; ExpressionParser expressionparser; public: - ConditionParser( TaskContext* ); + ConditionParser( TaskContext*, CommonParser& cp ); ~ConditionParser(); rule_t& parser() diff --git a/src/scripting/ExpressionParser.cpp b/src/scripting/ExpressionParser.cpp index b34c325..f04d08d 100644 --- a/src/scripting/ExpressionParser.cpp +++ b/src/scripting/ExpressionParser.cpp @@ -46,12 +46,14 @@ #include #include +#include #include "../rtt-config.h" #include namespace RTT { using boost::bind; + using boost::ref; using namespace detail; using namespace std; @@ -71,8 +73,8 @@ namespace RTT - DataCallParser::DataCallParser( ExpressionParser& p, TaskContext* c ) - : expressionparser( p ), peerparser( c ) + DataCallParser::DataCallParser( ExpressionParser& p, CommonParser& cp, TaskContext* c ) + : commonparser(cp), expressionparser( p ), peerparser( c, cp ) { BOOST_SPIRIT_DEBUG_RULE( datacall ); BOOST_SPIRIT_DEBUG_RULE( arguments ); @@ -221,9 +223,10 @@ namespace RTT return error_status<>( error_status<>::rethrow ); } - ExpressionParser::ExpressionParser( TaskContext* pc ) - : datacallparser( *this, pc ), - valueparser( pc ), + ExpressionParser::ExpressionParser( TaskContext* pc, CommonParser& cp ) + : datacallparser( *this, cp, pc ), + commonparser( cp ), + valueparser( pc, cp ), _invert_time(false), opreg( OperatorRepository::Instance() ) { @@ -231,8 +234,7 @@ namespace RTT 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( div_or_mul ); BOOST_SPIRIT_DEBUG_RULE( modexp ); BOOST_SPIRIT_DEBUG_RULE( plusexp ); BOOST_SPIRIT_DEBUG_RULE( minusexp ); @@ -354,9 +356,9 @@ namespace RTT time_expression = (str_p("time")>>eps_p(~commonparser.identchar | eol_p | end_p ))[bind(&ExpressionParser::seentimeexpr, this)] | - ( (eps_p[boost::lambda::var(eol_skip_functor::skipeol) = false] >> uint_p[ bind( &ExpressionParser::seentimespec, this, _1 ) ] - >> (str_p( "s" ) | "ms" | "us" | "ns" )[boost::lambda::var(eol_skip_functor::skipeol) = true][bind( &ExpressionParser::seentimeunit, this, _1, _2 ) ]) - | (eps_p[boost::lambda::var(eol_skip_functor::skipeol) = true] >> nothing_p) // eps_p succeeds always, then fail. + ( (eps_p[boost::lambda::var(commonparser.skipeol) = false] >> uint_p[ bind( &ExpressionParser::seentimespec, this, _1 ) ] + >> (str_p( "s" ) | "ms" | "us" | "ns" )[boost::lambda::var(commonparser.skipeol) = true][bind( &ExpressionParser::seentimeunit, this, _1, _2 ) ]) + | (eps_p[boost::lambda::var(commonparser.skipeol) = true] >> nothing_p) // eps_p succeeds always, then fail. ) ; // enable skipeol. diff --git a/src/scripting/ExpressionParser.hpp b/src/scripting/ExpressionParser.hpp index cbc1fe2..b100e2f 100644 --- a/src/scripting/ExpressionParser.hpp +++ b/src/scripting/ExpressionParser.hpp @@ -78,12 +78,12 @@ namespace RTT { namespace detail void seendataname(); void seendatacall(); - CommonParser commonparser; + CommonParser& commonparser; ExpressionParser& expressionparser; PeerParser peerparser; std::stack argparsers; public: - DataCallParser( ExpressionParser& p, TaskContext* pc ); + DataCallParser( ExpressionParser& p, CommonParser& cp, TaskContext* pc ); ~DataCallParser(); rule_t& parser() @@ -142,12 +142,15 @@ namespace RTT { namespace detail void seentimeexpr(); DataCallParser datacallparser; - CommonParser commonparser; + /** + * The governing common parser. + */ + CommonParser& commonparser; ValueParser valueparser; bool _invert_time; OperatorRepository::shared_ptr opreg; public: - ExpressionParser( TaskContext* pc ); + ExpressionParser( TaskContext* pc, CommonParser& common_parser ); ~ExpressionParser(); rule_t& parser(); diff --git a/src/scripting/Parser.cpp b/src/scripting/Parser.cpp index 774f66f..bd104b7 100644 --- a/src/scripting/Parser.cpp +++ b/src/scripting/Parser.cpp @@ -62,7 +62,8 @@ namespace RTT our_pos_iter_t parsebegin( function.begin(), function.end(), filename ); our_pos_iter_t parseend( function.end(), function.end(), filename ); // The internal parser. - ProgramGraphParser gram( parsebegin, c ); + CommonParser cp; + ProgramGraphParser gram( parsebegin, c, cp ); ParsedFunctions ret = gram.parseFunction( parsebegin, parseend ); return ret; } @@ -74,7 +75,8 @@ namespace RTT our_pos_iter_t parseend( program.end(),program.end(),filename ); // The internal parser. - ProgramGraphParser gram( parsebegin, c ); + CommonParser cp; + ProgramGraphParser gram( parsebegin, c, cp ); ParsedPrograms ret = gram.parse( parsebegin, parseend ); return ret; @@ -110,7 +112,9 @@ namespace RTT our_pos_iter_t parsebegin( scopy.begin(), scopy.end(), "teststring" ); our_pos_iter_t parseend( scopy.end(), scopy.end(), "teststring" ); - ConditionParser parser( tc ); + CommonParser cp; + ConditionParser parser( tc, cp ); + bool skipref=true; try { parse( parsebegin, parseend, parser.parser(), SKIP_PARSER ); @@ -138,7 +142,9 @@ namespace RTT our_pos_iter_t parsebegin( s.begin(), s.end(), "teststring" ); our_pos_iter_t parseend( s.end(), s.end(), "teststring" ); - ExpressionParser parser( tc ); + CommonParser cp; + ExpressionParser parser( tc, cp ); + bool skipref=true; try { parse( parsebegin, parseend, parser.parser(), SKIP_PARSER ); @@ -167,7 +173,9 @@ namespace RTT our_pos_iter_t parsebegin( s.begin(), s.end(), "teststring" ); our_pos_iter_t parseend( s.end(), s.end(), "teststring" ); - ValueChangeParser parser( tc ); + CommonParser cp; + ValueChangeParser parser( tc, cp ); + bool skipref=true; try { parse( parsebegin, parseend, parser.variableChangeParser(), SKIP_PARSER ); @@ -200,7 +208,9 @@ namespace RTT our_pos_iter_t parsebegin( s.begin(), s.end(), "input" ); our_pos_iter_t parseend( s.end(), s.end(), "input" ); - CommandParser parser( tc, !dodispatch ); + CommonParser cp; + CommandParser parser( tc, cp, !dodispatch ); + bool skipref=true; try { boost_spirit::parse_info ret = parse( parsebegin, parseend, parser.parser(), SKIP_PARSER ); diff --git a/src/scripting/PeerParser.cpp b/src/scripting/PeerParser.cpp index 73fd8f0..7e96916 100644 --- a/src/scripting/PeerParser.cpp +++ b/src/scripting/PeerParser.cpp @@ -53,17 +53,7 @@ namespace RTT using namespace std; using namespace boost; - namespace { - enum PeerErrors { peer_not_found }; - guard my_guard; - - /** - * set by locatepeer, read by handle_no_peer - */ - static iterator_difference::type advance_on_error = 0; - } - - error_status<> handle_no_peer(scanner_t const& scan, parser_error&e ) + error_status<> PeerParser::handle_no_peer(scanner_t const& scan, parser_error&e ) { //std::cerr<<"Returning accept, advance "<> ".")[bind( &PeerParser::locatepeer, this, _1, _2 ) ])) - [ &handle_no_peer ]); + [ bind(&PeerParser::handle_no_peer, this, _1, _2) ]); } void PeerParser::reset() diff --git a/src/scripting/PeerParser.hpp b/src/scripting/PeerParser.hpp index b012917..40f2410 100644 --- a/src/scripting/PeerParser.hpp +++ b/src/scripting/PeerParser.hpp @@ -58,7 +58,7 @@ namespace RTT */ class RTT_API PeerParser { - CommonParser commonparser; + CommonParser& commonparser; rule_t peerpath, peerlocator; std::queue callqueue; OperationInterface* mcurobject; @@ -71,6 +71,14 @@ namespace RTT RTT_HIDE void seenobjectname( iter_t begin, iter_t end ); RTT_HIDE void locatepeer( iter_t begin, iter_t end ); + enum PeerErrors { peer_not_found }; + guard my_guard; + + /** + * set by locatepeer, read by handle_no_peer + */ + boost::iterator_difference::type advance_on_error; + RTT_HIDE error_status<> handle_no_peer(scanner_t const& scan, parser_error&e ); public: /** * Create a PeerParser which starts looking for peers from @@ -79,7 +87,7 @@ namespace RTT * @param fullpath Set to true if the parser() must * resolve the full path. */ - PeerParser(TaskContext* c, bool fullpath=false); + PeerParser(TaskContext* c, CommonParser& cp, bool fullpath=false); /** * After reset, peer() == current context and diff --git a/src/scripting/ProgramGraphParser.cpp b/src/scripting/ProgramGraphParser.cpp index ab4d807..355f0e0 100644 --- a/src/scripting/ProgramGraphParser.cpp +++ b/src/scripting/ProgramGraphParser.cpp @@ -71,16 +71,17 @@ namespace RTT } - ProgramGraphParser::ProgramGraphParser( iter_t& positer, TaskContext* t) + ProgramGraphParser::ProgramGraphParser( iter_t& positer, TaskContext* t, CommonParser& cp) : rootc( t ),context( 0 ), fcontext(0), mpositer( positer ), mcallfunc(), implcond(0), mcondition(0), try_cond(0), - conditionparser( rootc ), - commandparser( rootc, true ), // as_action == true - valuechangeparser( rootc ), - expressionparser( rootc ), + commonparser(cp), + conditionparser( rootc, commonparser ), + commandparser( rootc, commonparser, true ), // as_action == true + valuechangeparser( rootc, commonparser ), + expressionparser( rootc, commonparser ), argsparser(0), - peerparser(rootc), + peerparser(rootc, commonparser), program_builder( new FunctionGraphBuilder() ), for_init_command(0), for_incr_command(0), @@ -458,11 +459,11 @@ namespace RTT } void ProgramGraphParser::skip_eol() { - eol_skip_functor::skipeol = true; + commonparser.skipeol = true; } void ProgramGraphParser::noskip_eol() { - eol_skip_functor::skipeol = false; + commonparser.skipeol = false; } void ProgramGraphParser::startofnewstatement(const std::string& type) @@ -617,8 +618,9 @@ namespace RTT { // end is not used ! iter_t begin_copy = begin; - skip_parser_t skip_parser = SKIP_PARSER; - iter_pol_t iter_policy( skip_parser ); + //skip_parser_t skip_parser = SKIP_PARSER; + //iter_pol_t iter_policy( skip_parser ); + iter_pol_t iter_policy( ( comment_p( "#" ) | comment_p( "//" ) | comment_p( "/*", "*/" ) | (space_p - eol_p) | commonparser.skipper ) ); scanner_pol_t policies( iter_policy ); scanner_t scanner( begin, end, policies ); program_list.clear(); @@ -669,8 +671,9 @@ namespace RTT { // end is not used ! iter_t begin_copy = begin; - skip_parser_t skip_parser = SKIP_PARSER; - iter_pol_t iter_policy( skip_parser ); + //skip_parser_t skip_parser = SKIP_PARSER; + //iter_pol_t iter_policy( skip_parser ); + iter_pol_t iter_policy( ( comment_p( "#" ) | comment_p( "//" ) | comment_p( "/*", "*/" ) | (space_p - eol_p) | commonparser.skipper ) ); scanner_pol_t policies( iter_policy ); scanner_t scanner( begin, end, policies ); diff --git a/src/scripting/ProgramGraphParser.hpp b/src/scripting/ProgramGraphParser.hpp index a0cdfb2..b38994d 100644 --- a/src/scripting/ProgramGraphParser.hpp +++ b/src/scripting/ProgramGraphParser.hpp @@ -190,8 +190,8 @@ namespace RTT { namespace detail openbrace, closebrace, opencurly, closecurly, forstatement, semicolon, condition, catchpart, funcargs, functionarg, emitstatement ; + CommonParser& commonparser; ConditionParser conditionparser; - CommonParser commonparser; CommandParser commandparser; ValueChangeParser valuechangeparser; ExpressionParser expressionparser; @@ -207,7 +207,7 @@ namespace RTT { namespace detail bool exportf; int ln_offset; public: - ProgramGraphParser( iter_t& positer, TaskContext*); + ProgramGraphParser( iter_t& positer, TaskContext*, CommonParser&); /** * @brief Tries to parse programs, returns the generated programs on success. diff --git a/src/scripting/ProgramGraphParser2.cpp b/src/scripting/ProgramGraphParser2.cpp index fb6fbd6..d93123a 100644 --- a/src/scripting/ProgramGraphParser2.cpp +++ b/src/scripting/ProgramGraphParser2.cpp @@ -119,8 +119,8 @@ namespace RTT str_p( "if" ) >> condition >> expect_then( str_p("then") ) - >> (callpart | returnpart | continuepart)[lambda::var(eol_skip_functor::skipeol) = false] - >> commonparser.eos[lambda::var(eol_skip_functor::skipeol) = true]; + >> (callpart | returnpart | continuepart)[lambda::var(commonparser.skipeol) = false] + >> commonparser.eos[lambda::var(commonparser.skipeol) = true]; continuepart = str_p("continue")[ bind( &ProgramGraphParser::seencontinue, this)]; diff --git a/src/scripting/PropertyParser.cpp b/src/scripting/PropertyParser.cpp index 3340b27..8083ba9 100644 --- a/src/scripting/PropertyParser.cpp +++ b/src/scripting/PropertyParser.cpp @@ -54,34 +54,24 @@ namespace RTT using namespace boost; - namespace { - enum PropertyErrors { bag_not_found }; - guard my_guard; - - /** - * set by locateproperty, read by handle_no_property - */ - static iterator_difference::type advance_on_error = 0; - } - - error_status<> handle_no_property(scanner_t const& scan, parser_error&e ) + error_status<> PropertyParser::handle_no_property(scanner_t const& scan, parser_error&e ) { //std::cerr<<"Returning accept"<( error_status<>::accept, advance_on_error ); } - PropertyParser::PropertyParser() - : _bag(0), _property(0) - { - BOOST_SPIRIT_DEBUG_RULE( propertylocator ); - // find as far as possible a property without throwing an exception - // outside our interface - propertylocator = - !my_guard - ( +(commonparser.notassertingidentifier >> ".")[bind( &PropertyParser::locateproperty, this, _1, _2 ) ]) - [ &handle_no_property ]; - } + PropertyParser::PropertyParser(CommonParser& cp) + : commonparser(cp), _bag(0), _property(0) + { + BOOST_SPIRIT_DEBUG_RULE( propertylocator ); + // find as far as possible a property without throwing an exception + // outside our interface + propertylocator = + !my_guard + ( +(commonparser.notassertingidentifier >> ".")[bind( &PropertyParser::locateproperty, this, _1, _2 ) ]) + [ bind(&PropertyParser::handle_no_property, this, _1, _2) ]; + } void PropertyParser::setPropertyBag( PropertyBag* bg ) { diff --git a/src/scripting/PropertyParser.hpp b/src/scripting/PropertyParser.hpp index 4d56826..9bbd7e5 100644 --- a/src/scripting/PropertyParser.hpp +++ b/src/scripting/PropertyParser.hpp @@ -53,14 +53,24 @@ namespace RTT */ class PropertyParser { - CommonParser commonparser; + CommonParser& commonparser; rule_t propertylocator; PropertyBag* _bag; PropertyBase* _property; void locateproperty( iter_t begin, iter_t end ); + + enum PropertyErrors { bag_not_found }; + guard my_guard; + + /** + * set by locateproperty, read by handle_no_property + */ + boost::iterator_difference::type advance_on_error; + + error_status<> handle_no_property(scanner_t const& scan, parser_error&e ); public: - PropertyParser(); + PropertyParser(CommonParser& cp); /** * Change the bag we want to traverse. diff --git a/src/scripting/StateGraphParser.cpp b/src/scripting/StateGraphParser.cpp index 37dae00..308c927 100644 --- a/src/scripting/StateGraphParser.cpp +++ b/src/scripting/StateGraphParser.cpp @@ -119,12 +119,12 @@ namespace RTT isroot(false), selectln(0), evname(""), - conditionparser( new ConditionParser( context ) ), commonparser( new CommonParser ), - valuechangeparser( new ValueChangeParser(context) ), - expressionparser( new ExpressionParser(context) ), + conditionparser( new ConditionParser( context, *commonparser ) ), + valuechangeparser( new ValueChangeParser(context, *commonparser) ), + expressionparser( new ExpressionParser(context, *commonparser) ), argsparser(0), - peerparser( new PeerParser(context, true) ) // full-path peer parser for events. + peerparser( new PeerParser(context, *commonparser, true) ) // full-path peer parser for events. { BOOST_SPIRIT_DEBUG_RULE( production ); BOOST_SPIRIT_DEBUG_RULE( rootmachineinstantiation ); @@ -178,7 +178,7 @@ namespace RTT // Zero or more declarations and Zero or more states statemachinecontent = *( varline | state | transitions | transition); - varline = vardec[lambda::var(eol_skip_functor::skipeol) = false] >> commonparser->eos[lambda::var(eol_skip_functor::skipeol) = true]; + varline = vardec[lambda::var(commonparser->skipeol) = false] >> commonparser->eos[lambda::var(commonparser->skipeol) = true]; vardec = subMachinedecl | machinememvar | machineparam; @@ -229,7 +229,7 @@ namespace RTT | transitions | transition | exit - | (machinememvar[lambda::var(eol_skip_functor::skipeol) = false] >> commonparser->eos[lambda::var(eol_skip_functor::skipeol) = true]); + | (machinememvar[lambda::var(commonparser->skipeol) = false] >> commonparser->eos[lambda::var(commonparser->skipeol) = true]); precondition = str_p( "precondition") >> conditionparser->parser()[ bind( &StateGraphParser::seenprecondition, this)] ; @@ -304,8 +304,8 @@ namespace RTT selector = str_p( "select" ) >> expect_select_ident(( commonparser->identifier[ bind( &StateGraphParser::seenselect, this, _1, _2) ] >> *("or" >> commonparser->identifier[ bind( &StateGraphParser::seenselect, this, _1, _2) ]) - )[lambda::var(eol_skip_functor::skipeol) = false] - >> commonparser->eos[lambda::var(eol_skip_functor::skipeol) = true]); + )[lambda::var(commonparser->skipeol) = false] + >> commonparser->eos[lambda::var(commonparser->skipeol) = true]); } @@ -645,8 +645,7 @@ namespace RTT //skip_parser_t skip_parser = SKIP_PARSER; //iter_pol_t iter_policy( skip_parser ); //#define SKIP_PARSER - iter_pol_t iter_policy( ( comment_p( "#" ) | comment_p( "//" ) | \ - comment_p( "/*", "*/" ) | (space_p - eol_p) | eol_skip_p ) ); + iter_pol_t iter_policy( ( comment_p( "#" ) | comment_p( "//" ) | comment_p( "/*", "*/" ) | (space_p - eol_p) | commonparser->skipper ) ); scanner_pol_t policies( iter_policy ); scanner_t scanner( begin, end, policies ); @@ -719,8 +718,8 @@ namespace RTT valuechangeparser->reset(); // in case of corrupt file, skipeol could have remained on false, - // so make sure it is set correctly again (I hate this global variable approach, it should be a member of commonparser !) - eol_skip_functor::skipeol = true; + // so make sure it is set correctly again + commonparser->skipeol = true; selectln = 0; transProgram.reset(); elseProgram.reset(); @@ -787,7 +786,7 @@ namespace RTT // we pass the plain file positer such that parse errors are // refering to correct file line numbers. - progParser = new ProgramGraphParser(mpositer, context); + progParser = new ProgramGraphParser(mpositer, context, *commonparser); // set the 'type' name : curtemplate->setName( curmachinename, false ); diff --git a/src/scripting/StateGraphParser.hpp b/src/scripting/StateGraphParser.hpp index 2ec765e..56112bc 100644 --- a/src/scripting/StateGraphParser.hpp +++ b/src/scripting/StateGraphParser.hpp @@ -169,8 +169,8 @@ namespace RTT { namespace detail rule_t machinealias; rule_t subMachinevarchange; - ConditionParser* conditionparser; CommonParser* commonparser; + ConditionParser* conditionparser; ValueChangeParser* valuechangeparser; ExpressionParser* expressionparser; ArgumentsParser* argsparser; diff --git a/src/scripting/ValueChangeParser.cpp b/src/scripting/ValueChangeParser.cpp index 3f26e83..0d75121 100644 --- a/src/scripting/ValueChangeParser.cpp +++ b/src/scripting/ValueChangeParser.cpp @@ -69,9 +69,9 @@ namespace RTT } - ValueChangeParser::ValueChangeParser( TaskContext* pc, OperationInterface* storage ) + ValueChangeParser::ValueChangeParser( TaskContext* pc, CommonParser& cp, OperationInterface* storage ) : type( 0 ), context( pc ), mstore( storage ? storage : pc ), - expressionparser( pc ), peerparser( pc ), sizehint(-1), + expressionparser( pc, cp ), peerparser( pc, cp ), propparser(cp), commonparser(cp), sizehint(-1), typerepos( TypeInfoRepository::Instance() ) { BOOST_SPIRIT_DEBUG_RULE( constantdefinition ); diff --git a/src/scripting/ValueChangeParser.hpp b/src/scripting/ValueChangeParser.hpp index cc65bf1..a229fe1 100644 --- a/src/scripting/ValueChangeParser.hpp +++ b/src/scripting/ValueChangeParser.hpp @@ -108,7 +108,7 @@ namespace RTT { namespace detail ExpressionParser expressionparser; PeerParser peerparser; PropertyParser propparser; - CommonParser commonparser; + CommonParser& commonparser; DataSourceBase::shared_ptr index_ds; @@ -129,7 +129,7 @@ namespace RTT { namespace detail * If you want the new added values in a different \a storage, use * the second argument. Defaults to tc. */ - ValueChangeParser( TaskContext* tc, OperationInterface* storage= 0); + ValueChangeParser( TaskContext* tc, CommonParser& cp, OperationInterface* storage= 0 ); /** * Clear assignCommands(), definedValues() and diff --git a/src/scripting/ValueParser.cpp b/src/scripting/ValueParser.cpp index 909dd22..faa67c6 100644 --- a/src/scripting/ValueParser.cpp +++ b/src/scripting/ValueParser.cpp @@ -44,8 +44,8 @@ namespace RTT using boost::bind; using namespace detail; - ValueParser::ValueParser( TaskContext* tc) - : peerparser(tc), context(tc) + ValueParser::ValueParser( TaskContext* tc, CommonParser& cp) + : commonparser(cp), peerparser(tc,cp), propparser(cp), context(tc) { BOOST_SPIRIT_DEBUG_RULE( constant ); BOOST_SPIRIT_DEBUG_RULE( const_float ); diff --git a/src/scripting/ValueParser.hpp b/src/scripting/ValueParser.hpp index bff818a..6d23161 100644 --- a/src/scripting/ValueParser.hpp +++ b/src/scripting/ValueParser.hpp @@ -60,7 +60,7 @@ namespace RTT { rule_t constant, const_float, const_double, const_int, const_uint, const_bool, named_constant, const_string, const_char; - CommonParser commonparser; + CommonParser& commonparser; PeerParser peerparser; PropertyParser propparser; @@ -96,7 +96,7 @@ namespace RTT TaskContext* context; public: - ValueParser( TaskContext* tc ); + ValueParser( TaskContext* tc, CommonParser& cp ); ~ValueParser(); /** diff --git a/src/scripting/parser-types.hpp b/src/scripting/parser-types.hpp index f6ddaaf..057f81f 100644 --- a/src/scripting/parser-types.hpp +++ b/src/scripting/parser-types.hpp @@ -112,7 +112,9 @@ namespace RTT /** * By default, eol are skipped. */ - static bool skipeol; + eol_skip_functor(bool& skipref) : skipeol(skipref) {} + eol_skip_functor(eol_skip_functor const& orig) : skipeol( orig.skipeol ) {} + bool& skipeol; typedef nil_t result_t; template @@ -140,14 +142,11 @@ namespace RTT } }; - /** - * Use this global parser to skip newlines inside statements. - */ - extern functor_parser eol_skip_p; - + //! When using this macro, you must have a boolean variable skipref defined. + //! which is initialized to true. # define SKIP_PARSER \ ( comment_p( "#" ) | comment_p( "//" ) | \ - comment_p( "/*", "*/" ) | (space_p - eol_p) | eol_skip_p ) + comment_p( "/*", "*/" ) | (space_p - eol_p) | functor_parser( eol_skip_functor(skipref) ) ) // here are the typedef's for the scanner, and the rule types.. //typedef __typeof__ ( SKIP_PARSER ) skip_parser_t; diff --git a/tests/function_test.cpp b/tests/function_test.cpp index 9bfb036..9fa53a5 100644 --- a/tests/function_test.cpp +++ b/tests/function_test.cpp @@ -320,11 +320,11 @@ void FunctionTest::doFunction( const std::string& prog, TaskContext* tc, bool te } catch( const file_parse_exception& exc ) { - BOOST_CHECK_MESSAGE( false , exc.what() ); + BOOST_REQUIRE_MESSAGE( false , exc.what() ); } if ( pg_list.empty() ) { - BOOST_CHECK_MESSAGE(false , "No program parsed in test."); + BOOST_REQUIRE_MESSAGE(false , "No program parsed in test."); } ProgramProcessor* pp = tc->engine()->programs(); BOOST_CHECK( pp->loadProgram( *pg_list.begin() ) ); diff --git a/tests/program_test.cpp b/tests/program_test.cpp index eb35569..f8b4a62 100644 --- a/tests/program_test.cpp +++ b/tests/program_test.cpp @@ -394,11 +394,11 @@ void ProgramTest::doProgram( const std::string& prog, TaskContext* tc, bool test } catch( const file_parse_exception& exc ) { - BOOST_CHECK_MESSAGE( false, exc.what() ); + BOOST_REQUIRE_MESSAGE( false, exc.what() ); } if ( pg_list.empty() ) { - BOOST_CHECK( false ); + BOOST_REQUIRE( false ); } ProgramInterfacePtr pi = *pg_list.begin(); diff --git a/tests/state_test.cpp b/tests/state_test.cpp index 224f145..fe6a130 100644 --- a/tests/state_test.cpp +++ b/tests/state_test.cpp @@ -785,7 +785,7 @@ BOOST_AUTO_TEST_CASE( testStateEvents) + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n" + " do y1.requestState(\"INIT\")\n" + " do test.assert( y1.inState(\"INIT\") )\n" - + " do b_event(true)\n" + + " do b_event(true)\n" //20 + " do nothing\n" + " if ( !y1.inState(\"ISTRUE\") ) then\n" + " do test.assertMsg(false, y1.getState() )\n" @@ -795,7 +795,7 @@ BOOST_AUTO_TEST_CASE( testStateEvents) + " do b_event(false)\n" + " do nothing\n" + " if ( !y1.inState(\"ISFALSE\") ) then\n" - + " do test.assertMsg(false, y1.getState() )\n" + + " do test.assertMsg(false, y1.getState() )\n" // 30 + " do test.assert( y1.inState(\"ISFALSE\") )\n" + " do y1.requestState(\"INIT\")\n" + " do test.assert( y1.inState(\"INIT\") )\n" @@ -806,7 +806,7 @@ BOOST_AUTO_TEST_CASE( testStateEvents) + " do test.assert( !y1.inState(\"INIT\") )\n" + " do test.assert( !y1.inState(\"ISPOSITIVE\") )\n" + " do test.assert( !y1.inState(\"ISNEGATIVE\") )\n" - + " do test.assert( y1.inState(\"TESTSELF\") )\n" + + " do test.assert( y1.inState(\"TESTSELF\") )\n" //40 + " do test.assert( y1.eb == false )\n" + " do t_event()\n" + " do nothing\n" @@ -816,7 +816,7 @@ BOOST_AUTO_TEST_CASE( testStateEvents) + " do nothing\n" + " do test.assert( y1.inState(\"TESTSELF\") )\n" + " do test.assert( y1.eb == true )\n" - + " do y1.requestState(\"INIT\")\n" + + " do y1.requestState(\"INIT\")\n" // 50 + " do test.assert( y1.inState(\"INIT\") )\n" //+ " do y1.deactivate()\n" + " }\n" @@ -893,19 +893,19 @@ void StateTest::doState( const std::string& prog, TaskContext* tc, bool test ) } catch( const file_parse_exception& exc ) { - BOOST_CHECK_MESSAGE( false, exc.what() ); + BOOST_REQUIRE_MESSAGE( false, exc.what() ); } catch( const parse_exception& exc ) { - BOOST_CHECK_MESSAGE( false, exc.what() ); + BOOST_REQUIRE_MESSAGE( false, exc.what() ); } catch( const program_load_exception& e) { - BOOST_CHECK_MESSAGE( false, e.what() ); + BOOST_REQUIRE_MESSAGE( false, e.what() ); } catch( const std::exception& e ) { BOOST_CHECK_MESSAGE( false , e.what()); - BOOST_CHECK_MESSAGE( false, "Uncaught Processor load exception" ); + BOOST_REQUIRE_MESSAGE( false, "Uncaught Processor load exception" ); } BOOST_CHECK( gtask.start() ); StateMachinePtr sm = tc->engine()->states()->getStateMachine("x"); diff --git a/tests/types_test.cpp b/tests/types_test.cpp index 9dd475b..20492c6 100644 --- a/tests/types_test.cpp +++ b/tests/types_test.cpp @@ -316,7 +316,7 @@ BOOST_AUTO_TEST_CASE( testOperatorOrder ) "do test.assert( 3*(2+1) == 9 )\n" + "}"; // execute - executePrograms(prog); + executePrograms(prog); } BOOST_AUTO_TEST_SUITE_END() @@ -332,11 +332,11 @@ void TypesTest::executePrograms(const std::string& prog ) } catch( const file_parse_exception& exc ) { - BOOST_CHECK_MESSAGE( false , exc.what()); + BOOST_REQUIRE_MESSAGE( false , exc.what()); } if ( pg_list.empty() ) { - BOOST_CHECK( false ); + BOOST_REQUIRE( false ); } BOOST_CHECK( tc->engine()->programs()->loadProgram( *pg_list.begin() ) ); @@ -377,11 +377,11 @@ void TypesTest::executeStates(const std::string& state ) } catch( const file_parse_exception& exc ) { - BOOST_CHECK_MESSAGE( false , exc.what()); + BOOST_REQUIRE_MESSAGE( false , exc.what()); } if ( pg_list.empty() ) { - BOOST_CHECK( false ); + BOOST_REQUIRE_MESSAGE( false, "Parser returned no state machines to execute." ); } BOOST_CHECK( tc->engine()->states()->loadStateMachine( *pg_list.begin() ) ); -- 1.7.1