Orocos Real-Time Toolkit  2.5.0
ValueParser.cpp
00001 /***************************************************************************
00002   tag: Peter Soetens  Mon May 10 19:10:37 CEST 2004  ValueParser.cxx
00003 
00004                         ValueParser.cxx -  description
00005                            -------------------
00006     begin                : Mon May 10 2004
00007     copyright            : (C) 2004 Peter Soetens
00008     email                : peter.soetens@mech.kuleuven.ac.be
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU Lesser General Public            *
00013  *   License as published by the Free Software Foundation; either          *
00014  *   version 2.1 of the License, or (at your option) any later version.    *
00015  *                                                                         *
00016  *   This library is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00019  *   Lesser General Public License for more details.                       *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU Lesser General Public      *
00022  *   License along with this library; if not, write to the Free Software   *
00023  *   Foundation, Inc., 59 Temple Place,                                    *
00024  *   Suite 330, Boston, MA  02111-1307  USA                                *
00025  *                                                                         *
00026  ***************************************************************************/
00027 
00028 #include "parser-debug.hpp"
00029 #include "parse_exception.hpp"
00030 #include "ValueParser.hpp"
00031 #include "../Attribute.hpp"
00032 
00033 #include "../TaskContext.hpp"
00034 #include "../Service.hpp"
00035 #include "../types/GlobalsRepository.hpp"
00036 
00037 #include <boost/bind.hpp>
00038 #include <boost/lexical_cast.hpp>
00039 
00040 #include <iostream>
00041 using namespace std;
00042 
00043 namespace RTT
00044 {
00045     using boost::bind;
00046     using namespace detail;
00047 
00048     ValueParser::ValueParser( TaskContext* tc, CommonParser& cp)
00049         : commonparser(cp), peerparser(tc,cp), propparser(cp), context(tc)
00050   {
00051     BOOST_SPIRIT_DEBUG_RULE( constant );
00052     BOOST_SPIRIT_DEBUG_RULE( const_float );
00053     BOOST_SPIRIT_DEBUG_RULE( const_double );
00054     BOOST_SPIRIT_DEBUG_RULE( const_int );
00055     BOOST_SPIRIT_DEBUG_RULE( const_hex );
00056     BOOST_SPIRIT_DEBUG_RULE( const_uint );
00057     BOOST_SPIRIT_DEBUG_RULE( const_char );
00058     BOOST_SPIRIT_DEBUG_RULE( const_bool );
00059     BOOST_SPIRIT_DEBUG_RULE( const_string );
00060     BOOST_SPIRIT_DEBUG_RULE( named_constant );
00061 
00062     // note the order is important: commonparser.identifier throws a
00063     // useful "cannot use x as identifier" error if it fails, so we
00064     // must first show all non-identifier rules.
00065     constant =
00066         const_float
00067       | const_double
00068       | const_hex
00069       | const_int
00070       | const_uint
00071       | const_bool
00072       | const_char
00073       | const_string
00074       | named_constant;
00075 
00076     const_float =
00077       strict_real_p [
00078         boost::bind( &ValueParser::seenfloatconstant, this, _1 ) ] >> ch_p('f');
00079 
00080     const_double =
00081       strict_real_p [
00082         boost::bind( &ValueParser::seendoubleconstant, this, _1 ) ];
00083 
00084     const_hex = (str_p("0x") | str_p("0X")) >>
00085       hex_p [
00086         boost::bind( &ValueParser::seenhexconstant, this, _1 ) ];
00087 
00088     const_int =
00089       int_p [
00090         boost::bind( &ValueParser::seenintconstant, this, _1 ) ];
00091 
00092     const_uint =
00093       uint_p [
00094         boost::bind( &ValueParser::seenuintconstant, this, _1 ) ] >> ch_p('u');
00095 
00096     const_bool =
00097       ( keyword_p( "true" ) | keyword_p("false") )[
00098         boost::bind( &ValueParser::seenboolconstant, this, _1, _2 ) ];
00099 
00100     const_char = (ch_p('\'') >> ch_p('\\') >> ch_p('0') >> ch_p('\''))[boost::bind( &ValueParser::seennull,this)] |
00101         confix_p( "'", (c_escape_ch_p[ boost::bind( &ValueParser::seencharconstant, this, _1 ) ]) , "'" );
00102 
00103     const_string = lexeme_d[confix_p(
00104       ch_p( '"' ), *c_escape_ch_p[ boost::bind( &ValueParser::push_str_char, this, _1 ) ], '"' )[ boost::bind( &ValueParser::seenstring, this ) ]];
00105 
00106     named_constant =
00107         ( keyword_p("done")[boost::bind( &ValueParser::seennamedconstant, this, _1, _2 ) ]
00108           |
00109           ( peerparser.locator()[boost::bind( &ValueParser::seenpeer, this) ]
00110             >> propparser.locator()
00111             >> commonparser.identifier[boost::bind( &ValueParser::seennamedconstant, this, _1, _2 ) ]) )
00112         ;
00113   }
00114 
00115     void ValueParser::seenpeer() {
00116         // inform propparser of new peer :
00117         //std::cerr << "ValueParser: seenpeer : "<< peerparser.taskObject()->getName()
00118         //          <<" has props :" << (peerparser.taskObject()->properties() != 0) << std::endl;
00119         propparser.setPropertyBag( peerparser.taskObject()->properties() );
00120     }
00121 
00122   void ValueParser::seenboolconstant( iter_t begin, iter_t end )
00123   {
00124     std::string value( begin, end );
00125     assert( value == "true" || value == "false" );
00126     if ( value == "true" )
00127       ret =
00128         new ConstantDataSource<bool>( true );
00129     else
00130       ret =
00131         new ConstantDataSource<bool>( false );
00132   }
00133 
00134   void ValueParser::seennamedconstant( iter_t begin, iter_t end )
00135   {
00136     std::string name( begin, end );
00137     Service::shared_ptr task = peerparser.taskObject();
00138     peerparser.reset();
00139     //std::cerr << "ValueParser: seenvar : "<< name
00140     //          <<" is bag : " << (propparser.bag() != 0) << " is prop: "<< (propparser.property() != 0) << std::endl;
00141     // in case our task is a taskcontext:
00142     if ( task && propparser.bag() && propparser.property() ) {
00143         // nested property case :
00144         if ( ! propparser.bag()->find( name ) ) {
00145             //std::cerr << "In "<<peer->getName() <<" : " << name << " not present"<<std::endl;
00146             throw parse_exception_semantic_error("Property " + name + " not present in PropertyBag "+propparser.property()->getName()+" in "+ task->getName()+".");
00147         }
00148         ret = propparser.bag()->find( name )->getDataSource();
00149         propparser.reset();
00150         return;
00151     }
00152 
00153     // non-nested property or attribute case :
00154     if ( task && task->hasAttribute( name ) ) {
00155       ret = task->getValue(name)->getDataSource();
00156       return;
00157     }
00158     if ( task && task->hasProperty( name ) ) {
00159         ret = task->properties()->find(name)->getDataSource();
00160         return;
00161     }
00162 
00163     // Global variable case:
00164     if ( GlobalsRepository::Instance()->hasAttribute( name ) ) {
00165         ret = GlobalsRepository::Instance()->getValue(name)->getDataSource();
00166         return;
00167     }
00168 
00169     throw_(begin, "Value " + name + " not defined in "+ task->getName()+".");
00170   }
00171 
00172     void ValueParser::seennull()
00173     {
00174         ret = new ConstantDataSource<char>( '\0' );
00175     }
00176 
00177     void ValueParser::seencharconstant( iter_t c )
00178     {
00179         ret = new ConstantDataSource<char>( *c );
00180     }
00181 
00182     void ValueParser::seenhexconstant( unsigned int i )
00183     {
00184       ret = new ConstantDataSource<unsigned int>( i );
00185     }
00186 
00187   void ValueParser::seenintconstant( int i )
00188   {
00189     ret = new ConstantDataSource<int>( i );
00190   }
00191 
00192   void ValueParser::seenuintconstant( unsigned int i ) // RobWork uint -> unsigned int
00193   {
00194     ret = new ConstantDataSource<unsigned int>( i ); // RobWork uint -> unsigned int
00195   }
00196 
00197   void ValueParser::seenfloatconstant( double i )
00198   {
00199     ret = new ConstantDataSource<float>( float(i) );
00200   }
00201 
00202   void ValueParser::seendoubleconstant( double i )
00203   {
00204     ret = new ConstantDataSource<double>( i );
00205   }
00206 
00207   ValueParser::~ValueParser()
00208   {
00209     clear();
00210   }
00211 
00212   void ValueParser::clear()
00213   {
00214       propparser.reset();
00215   }
00216 
00217   rule_t& ValueParser::parser()
00218   {
00219     return constant;
00220   }
00221 
00222   void ValueParser::push_str_char( char c )
00223   {
00224     mcurstring += c;
00225   }
00226 
00227   void ValueParser::seenstring()
00228   {
00229     // due to our config parse rule, the '"' terminating a
00230     // string will be in mcurstring, and we don't want it, so we
00231     // remove it..
00232     mcurstring.erase( mcurstring.end() - 1 );
00233     ret = new ConstantDataSource<std::string>( mcurstring );
00234     //deleter.reset( ret );
00235     mcurstring.clear();
00236   }
00237 }