ValueChangeParser.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Mon May 10 19:10:37 CEST 2004 ValueChangeParser.cxx
3 
4  ValueChangeParser.cxx - description
5  -------------------
6  begin : Mon May 10 2004
7  copyright : (C) 2004 Peter Soetens
8  email : peter.soetens@mech.kuleuven.ac.be
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 #include "parser-debug.hpp"
39 #include "parse_exception.hpp"
40 #include "ValueChangeParser.hpp"
41 
42 #include "../Service.hpp"
43 #include "../types/Types.hpp"
44 #include "../Attribute.hpp"
45 #include "../TaskContext.hpp"
46 #include "../types/GlobalsRepository.hpp"
47 //#include "DumpObject.hpp"
48 
49 #include <boost/bind.hpp>
50 #include <boost/lambda/bind.hpp>
51 #include <boost/lambda/construct.hpp>
52 
53 #include <Logger.hpp>
54 
55 #include <sstream>
56 #include <iostream>
57 
58 namespace RTT
59 {
60  using namespace detail;
61 
62  using namespace std;
63 
64  using namespace boost;
65 
66  namespace {
67  boost::spirit::classic::assertion<std::string> expect_open("Open brace expected.");
68  boost::spirit::classic::assertion<std::string> expect_close("Closing brace expected (or could not find out what this line means).");
69  boost::spirit::classic::assertion<std::string> expect_type("Unknown type. Please specify a type.");
70  boost::spirit::classic::assertion<std::string> expect_def("Expected a type definition. Please specify a type.");
71  boost::spirit::classic::assertion<std::string> expect_expr("Expected a valid expression.");
72  boost::spirit::classic::assertion<std::string> expect_ident("Expected a valid identifier.");
73  boost::spirit::classic::assertion<std::string> expect_init("Expected an initialisation value of the variable.");
74  boost::spirit::classic::assertion<std::string> expect_cis("Expected a initialisation ('=') of const.");
75  boost::spirit::classic::assertion<std::string> expect_ais("Expected a initialisation ('=') of alias.");
76  boost::spirit::classic::assertion<std::string> expect_index("Expected an index: [index].");
77  boost::spirit::classic::assertion<std::string> expect_integer("Expected a positive integer expression.");
78  boost::spirit::classic::assertion<std::string> expect_change("Expected a variable assignment after 'set'.");
79  boost::spirit::classic::assertion<std::string> expect_decl("Expected a declaration list.");
80  }
81 
82 
84  : type( 0 ), context( pc ), mstore( storage ? storage : pc->provides() ),
85  expressionparser( pc, caller, cp ), commonparser(cp), sizehint(-1),
86  typerepos( TypeInfoRepository::Instance() )
87  {
88  BOOST_SPIRIT_DEBUG_RULE( constantdefinition );
89  BOOST_SPIRIT_DEBUG_RULE( aliasdefinition );
90  BOOST_SPIRIT_DEBUG_RULE( variabledefinition );
91  BOOST_SPIRIT_DEBUG_RULE( paramdefinition );
92  BOOST_SPIRIT_DEBUG_RULE( baredefinition );
93  BOOST_SPIRIT_DEBUG_RULE( constdecl );
94  BOOST_SPIRIT_DEBUG_RULE( vardecl );
95  BOOST_SPIRIT_DEBUG_RULE( baredecl );
96 
97  // a macro using GCC's C++ extension typeof that is used to not have
98  // to specify impossibly long type names.. See the Boost.Spirit
99  // documentation for more details, as that's where I got it from..
100  // we use __typeof__ instead of typeof because it is not disabled by
101  // using gcc -ansi
102 
103  //TODO: this typeof replaced by boost header might not work.
104 # define RULE( name, def ) \
105  boost_spirit::contiguous<boost_spirit::positive<boost_spirit::chset<char> > > name = (def)
106  //BOOST_TYPE_OF(( (def) ) name = (def)
107  // typeof is not a native c/c++ construct and is gcc specific
108  //__typeof__( (def) ) name = (def)
109 
110  // we can't use commonparser.identifier to parse a type name,
111  // because that one is meant to be used for identifier used by the
112  // user, and excludes keywords such as "int", "string" etc.
113  chset<> identchar( "a-zA-Z-_0-9/<>." );
114  RULE( type_name, lexeme_d[ +identchar ] );
115 
118  | aliasdefinition;
119 
121  keyword_p("const")
122  // the type
123  >> expect_type( type_name[boost::bind( &ValueChangeParser::seentype, this, _1, _2 ) ])
124  >> constdecl[boost::bind( &ValueChangeParser::seenconstantdefinition, this )]
125  >> *(ch_p(',') >> constdecl[boost::bind( &ValueChangeParser::seenconstantdefinition, this )] );
126 
127 
129  keyword_p("alias")
130  // the type
131  >> expect_type(type_name [ boost::bind( &ValueChangeParser::seentype, this, _1, _2 ) ])
132  // next the name for the alias
133  >> expect_ident( commonparser.identifier[ boost::bind( &ValueChangeParser::storedefinitionname, this, _1, _2 ) ])
134  >> expect_ais( ch_p('=') )
135  // and a value to assign to it
136  >> expect_init( expressionparser.parser() )[ boost::bind( &ValueChangeParser::seenaliasdefinition, this ) ];
137 
139  keyword_p("var")
140  >> expect_type( type_name[boost::bind( &ValueChangeParser::seentype, this, _1, _2 ) ])
141  >> vardecl[boost::bind( &ValueChangeParser::seenvariabledefinition, this ) ]
142  >> *(ch_p(',') >> vardecl[boost::bind( &ValueChangeParser::seenvariabledefinition, this ) ] );
143 
145  keyword_p("param")
146  >> expect_type( type_name[boost::bind( &ValueChangeParser::seentype, this, _1, _2 ) ])
147  >> baredecl[boost::bind( &ValueChangeParser::seenbaredefinition, this ) ]
148  >> *(ch_p(',') >> baredecl[boost::bind( &ValueChangeParser::seenbaredefinition, this ) ] );
149 
151  type_name[ boost::bind( &ValueChangeParser::seentype, this, _1, _2 )]
152  >> baredecl[boost::bind( &ValueChangeParser::seenbaredefinition, this )];
153 
154  baredecl =
155  expect_ident( commonparser.identifier[ boost::bind( &ValueChangeParser::storedefinitionname, this, _1, _2 )] )
156  >> !( ch_p('(') >> expect_integer( expressionparser.parser()[boost::bind( &ValueChangeParser::seensizehint, this)]) >> expect_close( ch_p(')')) ) ;
157 
158  vardecl =
159  baredecl >> !( ch_p('=') >> expect_init( expressionparser.parser() ) );
160 
161  constdecl =
162  baredecl >> expect_cis( ch_p('=') ) >> expect_init( expressionparser.parser() );
163 
164  }
165 
167  {
170  assert( expr.get() );
171  //assert( !expressionparser.hasResult() );
172  DataSource<int>::shared_ptr i = dynamic_cast<DataSource<int>* >( expr.get() );
173  std::string typen = type->getTypeName();
174  if ( i.get() == 0 ) {
175  this->cleanup();
177  ("Attempt to initialize "+typen+" "+valuename+" with a "+expr->getTypeName()+", expected an integer expression. Use ' = "+expr->getTypeName()+"( arg )' instead to use the constructor." );
178  }
179  if ( i->get() < 0 ) {
180  std::stringstream value;
181  value << i->get();
182  this->cleanup();
184  ("Attempt to initialize "+typen+" "+valuename+" with an expression leading to a negative number "+value.str()
185  +". Initialization expressions are evaluated once at parse time !" );
186  }
187  if ( i->get() == 0 ) {
189  "Attempt to initialize "<<typen<<" "<<valuename<<" with an expression leading to zero (0)"
190  <<". Initialization expressions are evaluated once at parse time !" << Logger::endl;
191  }
192  sizehint = i->get();
193  }
194 
196  {
199  //assert( !expressionparser.hasResult() );
200  AttributeBase* var;
201  if (sizehint == -1 )
202  var = type->buildConstant(valuename, expr);
203  else {
204  var = type->buildConstant(valuename, expr, sizehint);
205  }
206  if ( var == 0 ) // bad assignment.
207  {
208  Logger::log() << " failed !"<<Logger::endl;
209  this->cleanup();
211  ("Attempt to initialize a const "+type->getTypeName()+" with a "+expr->getTypeName()+"." );
212  }
213 
214  mstore->setValue( var );
215  definedvalues.push_back( var );
216  definednames.push_back( valuename );
217  alldefinednames.push_back( valuename );
218  }
219 
221  {
222  std::string name( begin, end );
223  if ( mstore->getValue( name ) ) {
224  this->cleanup();
225  throw parse_exception_semantic_error( "Identifier \"" + name +
226  "\" is already defined in " + mstore->getName() );
227  }
228 
229  valuename = name;
230  }
231 
233  {
234  std::string name( begin, end );
235  type = typerepos->type( name );
236  if ( type == 0 )
237  throw parse_exception_semantic_error( "\"" + name + "\" is an unknown type..." );
238  }
239 
241  {
244  //assert( !expressionparser.hasResult() );
245  AttributeBase* alias;
246  alias = type->buildAlias( valuename, expr.get() );
247  if ( ! alias ) {
248  this->cleanup();
250  "Attempt to define an alias of type "+type->getTypeName()+" to an expression of type "+expr->getTypeName()+"." );
251  }
252  mstore->setValue( alias );
253  definedvalues.push_back( alias );
254  definednames.push_back( valuename );
255  alldefinednames.push_back( valuename );
256  ActionInterface* nc(0);
257  assigncommands.push_back( nc );
258  }
259 
261  {
262  // type has been stored by calling 'seentype'
263  // valuename has been stored by calling 'storename'
264  AttributeBase* var;
265  if (sizehint == -1 )
266  var = type->buildVariable(valuename);
267  else {
269  }
270  sizehint = -1;
271  mstore->setValue( var );
272  definedvalues.push_back( var );
273  definednames.push_back( valuename );
274  alldefinednames.push_back( valuename );
275  }
276 
278  {
279  // build type.
280  AttributeBase* var;
281  if (sizehint == -1 )
282  var = type->buildVariable(valuename);
283  else {
285  }
286  sizehint = -1;
287  mstore->setValue( var );
288  definedvalues.push_back( var );
289  definednames.push_back( valuename );
290  alldefinednames.push_back( valuename );
291 
292  if ( expressionparser.hasResult() ) {
296  //assert( !expressionparser.hasResult() );
297  try {
298  ActionInterface* ac = var->getDataSource()->updateAction( expr.get() );
299  assert(ac);
300  assigncommands.push_back( ac );
301  if (cond)
302  conditions.push_back(cond);
303  }
304  catch( const bad_assignment& ) {
305  this->cleanup();
307  ( "Attempt to initialize a var "+var->getDataSource()->getTypeName()+" with a "+ expr->getTypeName() + "." );
308  }
309  }
310  }
311 
313  {
314  if (!o)
315  return;
316  for(std::vector<std::string>::iterator it = alldefinednames.begin();
317  it != alldefinednames.end(); ++it) {
318  // only add new values (which didn't come from 'load')
319  if ( o->getValue( *it ) == 0 ) {
320  o->setValue( mstore->getValue(*it)->clone() );
321  //cout << "Storing var "+*it+" from " << mstore->getName() << " into " << o->getName() <<endl;
322  }
323  }
324  }
325 
327  {
328  if (!s)
329  return;
330  vector<string> predefinednames = s->getAttributeNames();
331  for(std::vector<std::string>::iterator it = predefinednames.begin();
332  it != predefinednames.end(); ++it) {
333  if (mstore->getValue(*it) == 0) {
334  //cout << "Loading new var "+*it+" from " << s->getName() << " into " << mstore->getName() <<endl;
335  mstore->setValue( s->getValue(*it)->clone() );
336  alldefinednames.push_back( *it ); // such that it is also again removed from mstore !
337  }
338  }
339  }
340 
342  {
343  for_each(assigncommands.begin(), assigncommands.end(), boost::lambda::bind(boost::lambda::delete_ptr(), boost::lambda::_1));
344  }
345 
347  {
348  assigncommands.clear();
349  conditions.clear();
350 
351  definedvalues.clear();
352 
353  definednames.clear();
354  }
355 
357  {
358  // erase/delete added values from the context:
359  for(std::vector<std::string>::iterator it = alldefinednames.begin();
360  it != alldefinednames.end(); ++it) {
361  mstore->removeValue( *it );
362  }
363  alldefinednames.clear();
364  this->cleanup();
365  this->clear();
366  valuename = "";
367  type = 0;
368  sizehint = -1;
369  }
370 
372  {
373  return valuechange_parsers;
374  }
375 
377  {
378  return constantdefinition;
379  }
380 
382  {
383  return aliasdefinition;
384  }
385 
387  {
388  return variabledefinition;
389  }
390 
392  {
393  return paramdefinition;
394  }
395 
397  {
398  return baredefinition;
399  }
400 }
#define keyword_p(word)
boost::shared_ptr< types::TypeInfoRepository > typerepos
void storedefinitionname(iter_t begin, iter_t end)
void load(Service::shared_ptr source)
const std::string & getTypeName() const
Definition: TypeInfo.hpp:83
#define RULE(name, def)
This interface represents the concept of a condition which can be evaluated and return true or false...
Definition: mystd.hpp:163
virtual DataSourceBase::shared_ptr getDataSource() const =0
ConditionInterface * getCmdResult()
std::vector< scripting::ConditionInterface * > conditions
This class contains some very common parser definitions.
boost::shared_ptr< Service > shared_ptr
Definition: Service.hpp:101
void store(Service::shared_ptr other)
std::vector< base::AttributeBase * > definedvalues
base::AttributeBase * buildConstant(std::string name, base::DataSourceBase::shared_ptr source, int sizehint) const
Definition: TypeInfo.hpp:173
std::vector< base::ActionInterface * > assigncommands
static std::ostream & endl(std::ostream &__os)
Definition: Logger.cpp:383
Based on the software pattern &#39;command&#39;, this interface allows execution of action objects...
base::DataSourceBase::shared_ptr getResult()
rule< scanner_t > rule_t
base::AttributeBase * buildAlias(std::string name, base::DataSourceBase::shared_ptr b) const
Definition: TypeInfo.hpp:206
std::vector< std::string > definednames
base::AttributeBase * buildVariable(std::string name, int sizehint) const
Definition: TypeInfo.cpp:82
std::vector< std::string > alldefinednames
static Logger & log()
Definition: Logger.cpp:117
boost::intrusive_ptr< DataSourceBase > shared_ptr
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:53
our_pos_iter_t iter_t
ValueChangeParser(TaskContext *tc, CommonParser &cp, Service::shared_ptr storage, ExecutionEngine *caller)
void seentype(iter_t begin, iter_t end)


rtt
Author(s): RTT Developers
autogenerated on Tue Jun 25 2019 19:33:38