From e7521b35416d8a9b034719281b4d26789964d20c Mon Sep 17 00:00:00 2001
From: Peter Soetens <peter@thesourceworks.com>
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 <peter@thesourceworks.com>

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<std::string> expect_methodname("Expected a method call on object.");
         assertion<std::string> 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_functor> eol_skip_p;
-
-    bool eol_skip_functor::skipeol = true;
-
     namespace {
         assertion<std::string> 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<eol_skip_functor> 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 <boost/lambda/lambda.hpp>
 
 #include <boost/bind.hpp>
+#include <boost/ref.hpp>
 #include "../rtt-config.h"
 #include <iostream>
 
 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<ArgumentsParser*> 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<iter_t> 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<PeerErrors> my_guard;
-
-        /**
-         * set by locatepeer, read by handle_no_peer
-         */
-        static iterator_difference<iter_t>::type advance_on_error = 0;
-    }
-
-    error_status<> handle_no_peer(scanner_t const& scan, parser_error<PeerErrors, iter_t>&e )
+    error_status<> PeerParser::handle_no_peer(scanner_t const& scan, parser_error<PeerErrors, iter_t>&e )
     {
         //std::cerr<<"Returning accept, advance "<<advance_on_error<<std::endl;
         int length = advance_on_error;
@@ -122,8 +112,8 @@ namespace RTT
 
         }
 
-        PeerParser::PeerParser(TaskContext* c, bool fullpath)
-            : mcurobject(c), mlastobject("this"), context(c), _peer(context), mfullpath(fullpath)
+        PeerParser::PeerParser(TaskContext* c, CommonParser& cp, bool fullpath)
+            : commonparser(cp), mcurobject(c), mlastobject("this"), context(c), _peer(context), mfullpath(fullpath)
         {
             BOOST_SPIRIT_DEBUG_RULE( peerpath );
             BOOST_SPIRIT_DEBUG_RULE( peerlocator );
@@ -135,7 +125,7 @@ namespace RTT
             peerlocator =
                 !(my_guard
                   ( +((commonparser.notassertingidentifier >> ".")[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<std::string> 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<PeerErrors> my_guard;
+
+        /**
+         * set by locatepeer, read by handle_no_peer
+         */
+        boost::iterator_difference<iter_t>::type advance_on_error;
+        RTT_HIDE error_status<> handle_no_peer(scanner_t const& scan, parser_error<PeerErrors, iter_t>&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<PropertyErrors> my_guard;
-
-        /**
-         * set by locateproperty, read by handle_no_property
-         */
-        static iterator_difference<iter_t>::type advance_on_error = 0;
-    }
-
-    error_status<> handle_no_property(scanner_t const& scan, parser_error<PropertyErrors, iter_t>&e )
+    error_status<> PropertyParser::handle_no_property(scanner_t const& scan, parser_error<PropertyErrors, iter_t>&e )
     {
         //std::cerr<<"Returning accept"<<std::endl;
         // ok, got as far as possible, _property contains the furthest we got.
         return error_status<>( 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<PropertyErrors> my_guard;
+
+        /**
+         * set by locateproperty, read by handle_no_property
+         */
+	boost::iterator_difference<iter_t>::type advance_on_error;
+
+	error_status<> handle_no_property(scanner_t const& scan, parser_error<PropertyErrors, iter_t>&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 <typename ScannerT>
@@ -140,14 +142,11 @@ namespace RTT
         }
     };
 
-    /**
-     * Use this global parser to skip newlines inside statements.
-     */
-    extern functor_parser<eol_skip_functor> 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>( 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

