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 #include "ValueChangeParser.hpp"
00031
00032 #include "../Service.hpp"
00033 #include "../types/Types.hpp"
00034 #include "../Attribute.hpp"
00035 #include "../TaskContext.hpp"
00036 #include "../types/GlobalsRepository.hpp"
00037
00038
00039 #include <boost/bind.hpp>
00040 #include <boost/lambda/bind.hpp>
00041 #include <boost/lambda/construct.hpp>
00042
00043 #include <Logger.hpp>
00044
00045 #include <sstream>
00046 #include <iostream>
00047
00048 namespace RTT
00049 {
00050 using namespace detail;
00051
00052 using namespace std;
00053
00054 using namespace boost;;
00055
00056 namespace {
00057 boost::spirit::classic::assertion<std::string> expect_open("Open brace expected.");
00058 boost::spirit::classic::assertion<std::string> expect_close("Closing brace expected (or could not find out what this line means).");
00059 boost::spirit::classic::assertion<std::string> expect_type("Unknown type. Please specify a type.");
00060 boost::spirit::classic::assertion<std::string> expect_def("Expected a type definition. Please specify a type.");
00061 boost::spirit::classic::assertion<std::string> expect_expr("Expected a valid expression.");
00062 boost::spirit::classic::assertion<std::string> expect_ident("Expected a valid identifier.");
00063 boost::spirit::classic::assertion<std::string> expect_init("Expected an initialisation value of the variable.");
00064 boost::spirit::classic::assertion<std::string> expect_cis("Expected a initialisation ('=') of const.");
00065 boost::spirit::classic::assertion<std::string> expect_ais("Expected a initialisation ('=') of alias.");
00066 boost::spirit::classic::assertion<std::string> expect_index("Expected an index: [index].");
00067 boost::spirit::classic::assertion<std::string> expect_integer("Expected a positive integer expression.");
00068 boost::spirit::classic::assertion<std::string> expect_change("Expected a variable assignment after 'set'.");
00069 boost::spirit::classic::assertion<std::string> expect_decl("Expected a declaration list.");
00070 }
00071
00072
00073 ValueChangeParser::ValueChangeParser( TaskContext* pc, CommonParser& cp, Service::shared_ptr storage, ExecutionEngine* caller )
00074 : type( 0 ), context( pc ), mstore( storage ? storage : pc->provides() ),
00075 expressionparser( pc, caller, cp ), commonparser(cp), sizehint(-1),
00076 typerepos( TypeInfoRepository::Instance() )
00077 {
00078 BOOST_SPIRIT_DEBUG_RULE( constantdefinition );
00079 BOOST_SPIRIT_DEBUG_RULE( aliasdefinition );
00080 BOOST_SPIRIT_DEBUG_RULE( variabledefinition );
00081 BOOST_SPIRIT_DEBUG_RULE( paramdefinition );
00082 BOOST_SPIRIT_DEBUG_RULE( baredefinition );
00083 BOOST_SPIRIT_DEBUG_RULE( constdecl );
00084 BOOST_SPIRIT_DEBUG_RULE( vardecl );
00085 BOOST_SPIRIT_DEBUG_RULE( baredecl );
00086
00087
00088
00089
00090
00091
00092
00093
00094 # define RULE( name, def ) \
00095 boost_spirit::contiguous<boost_spirit::positive<boost_spirit::chset<char> > > name = (def)
00096
00097
00098
00099
00100
00101
00102
00103 chset<> identchar( "a-zA-Z-_0-9/<>." );
00104 RULE( type_name, lexeme_d[ +identchar ] );
00105
00106 valuechange_parsers = constantdefinition
00107 | variabledefinition
00108 | aliasdefinition;
00109
00110 constantdefinition =
00111 keyword_p("const")
00112
00113 >> expect_type( type_name[boost::bind( &ValueChangeParser::seentype, this, _1, _2 ) ])
00114 >> constdecl[boost::bind( &ValueChangeParser::seenconstantdefinition, this )]
00115 >> *(ch_p(',') >> constdecl[boost::bind( &ValueChangeParser::seenconstantdefinition, this )] );
00116
00117
00118 aliasdefinition =
00119 keyword_p("alias")
00120
00121 >> expect_type(type_name [ boost::bind( &ValueChangeParser::seentype, this, _1, _2 ) ])
00122
00123 >> expect_ident( commonparser.identifier[ boost::bind( &ValueChangeParser::storedefinitionname, this, _1, _2 ) ])
00124 >> expect_ais( ch_p('=') )
00125
00126 >> expect_init( expressionparser.parser() )[ boost::bind( &ValueChangeParser::seenaliasdefinition, this ) ];
00127
00128 variabledefinition =
00129 keyword_p("var")
00130 >> expect_type( type_name[boost::bind( &ValueChangeParser::seentype, this, _1, _2 ) ])
00131 >> vardecl[boost::bind( &ValueChangeParser::seenvariabledefinition, this ) ]
00132 >> *(ch_p(',') >> vardecl[boost::bind( &ValueChangeParser::seenvariabledefinition, this ) ] );
00133
00134 paramdefinition =
00135 keyword_p("param")
00136 >> expect_type( type_name[boost::bind( &ValueChangeParser::seentype, this, _1, _2 ) ])
00137 >> baredecl[boost::bind( &ValueChangeParser::seenbaredefinition, this ) ]
00138 >> *(ch_p(',') >> baredecl[boost::bind( &ValueChangeParser::seenbaredefinition, this ) ] );
00139
00140 baredefinition =
00141 type_name[ boost::bind( &ValueChangeParser::seentype, this, _1, _2 )]
00142 >> baredecl[boost::bind( &ValueChangeParser::seenbaredefinition, this )];
00143
00144 baredecl =
00145 expect_ident( commonparser.identifier[ boost::bind( &ValueChangeParser::storedefinitionname, this, _1, _2 )] )
00146 >> !( ch_p('(') >> expect_integer( expressionparser.parser()[boost::bind( &ValueChangeParser::seensizehint, this)]) >> expect_close( ch_p(')')) ) ;
00147
00148 vardecl =
00149 baredecl >> !( ch_p('=') >> expect_init( expressionparser.parser() ) );
00150
00151 constdecl =
00152 baredecl >> expect_cis( ch_p('=') ) >> expect_init( expressionparser.parser() );
00153
00154 }
00155
00156 void ValueChangeParser::seensizehint()
00157 {
00158 DataSourceBase::shared_ptr expr = expressionparser.getResult();
00159 expressionparser.dropResult();
00160 assert( expr.get() );
00161
00162 DataSource<int>::shared_ptr i = dynamic_cast<DataSource<int>* >( expr.get() );
00163 std::string typen = type->getTypeName();
00164 if ( i.get() == 0 ) {
00165 this->cleanup();
00166 throw parse_exception_semantic_error
00167 ("Attempt to initialize "+typen+" "+valuename+" with a "+expr->getTypeName()+", expected an integer expression. Use ' = "+expr->getTypeName()+"( arg )' instead to use the constructor." );
00168 }
00169 if ( i->get() < 0 ) {
00170 std::stringstream value;
00171 value << i->get();
00172 this->cleanup();
00173 throw parse_exception_semantic_error
00174 ("Attempt to initialize "+typen+" "+valuename+" with an expression leading to a negative number "+value.str()
00175 +". Initialization expressions are evaluated once at parse time !" );
00176 }
00177 if ( i->get() == 0 ) {
00178 Logger::log() << Logger::Warning <<
00179 "Attempt to initialize "<<typen<<" "<<valuename<<" with an expression leading to zero (0)"
00180 <<". Initialization expressions are evaluated once at parse time !" << Logger::endl;
00181 }
00182 sizehint = i->get();
00183 }
00184
00185 void ValueChangeParser::seenconstantdefinition()
00186 {
00187 DataSourceBase::shared_ptr expr = expressionparser.getResult();
00188 expressionparser.dropResult();
00189
00190 AttributeBase* var;
00191 if (sizehint == -1 )
00192 var = type->buildConstant(valuename, expr);
00193 else {
00194 var = type->buildConstant(valuename, expr, sizehint);
00195 }
00196 if ( var == 0 )
00197 {
00198 Logger::log() << " failed !"<<Logger::endl;
00199 this->cleanup();
00200 throw parse_exception_semantic_error
00201 ("Attempt to initialize a const "+type->getTypeName()+" with a "+expr->getTypeName()+"." );
00202 }
00203
00204 mstore->setValue( var );
00205 definedvalues.push_back( var );
00206 definednames.push_back( valuename );
00207 alldefinednames.push_back( valuename );
00208 }
00209
00210 void ValueChangeParser::storedefinitionname( iter_t begin, iter_t end )
00211 {
00212 std::string name( begin, end );
00213 if ( mstore->getValue( name ) ) {
00214 this->cleanup();
00215 throw parse_exception_semantic_error( "Identifier \"" + name +
00216 "\" is already defined in " + mstore->getName() );
00217 }
00218
00219 valuename = name;
00220 }
00221
00222 void ValueChangeParser::seentype( iter_t begin, iter_t end )
00223 {
00224 std::string name( begin, end );
00225 type = typerepos->type( name );
00226 if ( type == 0 )
00227 throw parse_exception_semantic_error( "\"" + name + "\" is an unknown type..." );
00228 }
00229
00230 void ValueChangeParser::seenaliasdefinition()
00231 {
00232 DataSourceBase::shared_ptr expr = expressionparser.getResult();
00233 expressionparser.dropResult();
00234
00235 AttributeBase* alias;
00236 alias = type->buildAlias( valuename, expr.get() );
00237 if ( ! alias ) {
00238 this->cleanup();
00239 throw parse_exception_semantic_error(
00240 "Attempt to define an alias of type "+type->getTypeName()+" to an expression of type "+expr->getTypeName()+"." );
00241 }
00242 mstore->setValue( alias );
00243 definedvalues.push_back( alias );
00244 definednames.push_back( valuename );
00245 alldefinednames.push_back( valuename );
00246 ActionInterface* nc(0);
00247 assigncommands.push_back( nc );
00248 }
00249
00250 void ValueChangeParser::seenbaredefinition()
00251 {
00252
00253
00254 AttributeBase* var;
00255 if (sizehint == -1 )
00256 var = type->buildVariable(valuename);
00257 else {
00258 var = type->buildVariable(valuename,sizehint);
00259 }
00260 sizehint = -1;
00261 mstore->setValue( var );
00262 definedvalues.push_back( var );
00263 definednames.push_back( valuename );
00264 alldefinednames.push_back( valuename );
00265 }
00266
00267 void ValueChangeParser::seenvariabledefinition()
00268 {
00269
00270 AttributeBase* var;
00271 if (sizehint == -1 )
00272 var = type->buildVariable(valuename);
00273 else {
00274 var = type->buildVariable(valuename,sizehint);
00275 }
00276 sizehint = -1;
00277 mstore->setValue( var );
00278 definedvalues.push_back( var );
00279 definednames.push_back( valuename );
00280 alldefinednames.push_back( valuename );
00281
00282 if ( expressionparser.hasResult() ) {
00283 DataSourceBase::shared_ptr expr = expressionparser.getResult();
00284 expressionparser.dropResult();
00285
00286 try {
00287 ActionInterface* ac = var->getDataSource()->updateAction( expr.get() );
00288 assert(ac);
00289 assigncommands.push_back( ac );
00290 }
00291 catch( const bad_assignment& ) {
00292 this->cleanup();
00293 throw parse_exception_semantic_error
00294 ( "Attempt to initialize a var "+var->getDataSource()->getTypeName()+" with a "+ expr->getTypeName() + "." );
00295 }
00296 }
00297 }
00298
00299 void ValueChangeParser::store(Service::shared_ptr o)
00300 {
00301 if (!o)
00302 return;
00303 for(std::vector<std::string>::iterator it = alldefinednames.begin();
00304 it != alldefinednames.end(); ++it) {
00305
00306 if ( o->getValue( *it ) == 0 ) {
00307 o->setValue( mstore->getValue(*it)->clone() );
00308
00309 }
00310 }
00311 }
00312
00313 void ValueChangeParser::load(Service::shared_ptr s)
00314 {
00315 if (!s)
00316 return;
00317 vector<string> predefinednames = s->getAttributeNames();
00318 for(std::vector<std::string>::iterator it = predefinednames.begin();
00319 it != predefinednames.end(); ++it) {
00320 if (mstore->getValue(*it) == 0) {
00321
00322 mstore->setValue( s->getValue(*it)->clone() );
00323 alldefinednames.push_back( *it );
00324 }
00325 }
00326 }
00327
00328 void ValueChangeParser::cleanup()
00329 {
00330 for_each(assigncommands.begin(), assigncommands.end(), boost::lambda::bind(boost::lambda::delete_ptr(), boost::lambda::_1));
00331 }
00332
00333 void ValueChangeParser::clear()
00334 {
00335 assigncommands.clear();
00336
00337 definedvalues.clear();
00338
00339 definednames.clear();
00340 }
00341
00342 void ValueChangeParser::reset()
00343 {
00344
00345 for(std::vector<std::string>::iterator it = alldefinednames.begin();
00346 it != alldefinednames.end(); ++it) {
00347 mstore->removeValue( *it );
00348 }
00349 alldefinednames.clear();
00350 this->cleanup();
00351 this->clear();
00352 valuename = "";
00353 type = 0;
00354 sizehint = -1;
00355 }
00356
00357 rule_t& ValueChangeParser::parser()
00358 {
00359 return valuechange_parsers;
00360 }
00361
00362 rule_t& ValueChangeParser::constantDefinitionParser()
00363 {
00364 return constantdefinition;
00365 }
00366
00367 rule_t& ValueChangeParser::aliasDefinitionParser()
00368 {
00369 return aliasdefinition;
00370 }
00371
00372 rule_t& ValueChangeParser::variableDefinitionParser()
00373 {
00374 return variabledefinition;
00375 }
00376
00377 rule_t& ValueChangeParser::paramDefinitionParser()
00378 {
00379 return paramdefinition;
00380 }
00381
00382 rule_t& ValueChangeParser::bareDefinitionParser()
00383 {
00384 return baredefinition;
00385 }
00386 }