Orocos Real-Time Toolkit  2.8.3
StateGraphParser.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Mon May 10 19:10:37 CEST 2004 StateGraphParser.cxx
3 
4  StateGraphParser.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 Lesser General Public *
13  * License as published by the Free Software Foundation; either *
14  * version 2.1 of the License, or (at your option) any later version. *
15  * *
16  * This library is distributed in the hope that it will be useful, *
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
19  * Lesser General Public License for more details. *
20  * *
21  * You should have received a copy of the GNU Lesser General Public *
22  * License along with this library; if not, write to the Free Software *
23  * Foundation, Inc., 59 Temple Place, *
24  * Suite 330, Boston, MA 02111-1307 USA *
25  * *
26  ***************************************************************************/
27 
28 #include "parser-debug.hpp"
29 #include "parse_exception.hpp"
30 #include "StateGraphParser.hpp"
31 #include "CommonParser.hpp"
32 #include "ConditionParser.hpp"
33 #include "ConditionCompare.hpp"
34 #include "ConditionComposite.hpp"
35 #include "ConditionCache.hpp"
37 #include "ValueChangeParser.hpp"
38 #include "ProgramGraphParser.hpp"
39 #include "PeerParser.hpp"
40 #include "ArgumentsParser.hpp"
41 #include "StateMachineBuilder.hpp"
42 #include "../TaskContext.hpp"
43 #include "StateMachineService.hpp"
44 
45 #include "CommandComposite.hpp"
46 #include "../internal/Exceptions.hpp"
47 #include "../base/AttributeBase.hpp"
48 #include "ConditionTrue.hpp"
49 #include "ConditionInvert.hpp"
50 #include "StateDescription.hpp"
51 #include "ParsedStateMachine.hpp"
52 
53 #include <iostream>
54 #include <functional>
55 #include <algorithm>
56 #include <boost/bind.hpp>
57 #include <boost/lambda/lambda.hpp>
58 #include <boost/call_traits.hpp>
59 #include <iostream>
60 #include <memory>
61 #include "../internal/mystd.hpp"
62 
63 namespace RTT
64 {
65  using namespace boost;
66  using namespace detail;
67  using boost::bind;
68 
69  using namespace std;
70 
71  namespace {
73  {
74  state_expected,
75  handle_expected,
76  transition_expected,
77  };
78 
79  boost::spirit::classic::assertion<GraphSyntaxErrors> expect_state(state_expected);
80  boost::spirit::classic::assertion<GraphSyntaxErrors> expect_handle(handle_expected);
81  boost::spirit::classic::assertion<GraphSyntaxErrors> expect_transition(transition_expected);
82  boost::spirit::classic::assertion<std::string> expect_end("Ending '}' expected ( or could not find out what this line means ).");
83  boost::spirit::classic::assertion<std::string> expect_end_of_state("Exptected ending '}' at end of state ( or could not find out what this line means ).");
84  boost::spirit::classic::assertion<std::string> expect_if("Wrongly formatted \"if ... then select\" clause.");
85  boost::spirit::classic::assertion<std::string> expect_select("'select' statement required after emty transition program.");
86  boost::spirit::classic::assertion<std::string> expect_select_ident("'select' requires a valid state name.");
87  boost::spirit::classic::assertion<std::string> expect_comma("Expected a comma separator.");
88  boost::spirit::classic::assertion<std::string> expect_ident("Expected a valid identifier.");
89  boost::spirit::classic::assertion<std::string> expect_event_or_if("Expected an event name or an if clause in transition statement.");
90  boost::spirit::classic::assertion<std::string> expect_open("Open brace expected.");
91  boost::spirit::classic::assertion<std::string> expect_eof("Invalid input in file.");
92  boost::spirit::classic::assertion<std::string> expect_eol("Newline expected at end of statement.");
93  boost::spirit::classic::assertion<std::string> expect_semicolon("Semi colon expected after statement.");
94  boost::spirit::classic::assertion<std::string> expect_open_parenth( "Open parenthesis expected." );
95  boost::spirit::classic::assertion<std::string> expect_close_parenth( "Open parenthesis expected." );
96  boost::spirit::classic::assertion<std::string> expect_eventselect("'select' statement required after event or transition program.");
97  boost::spirit::classic::assertion<std::string> expect_eventargs("Could not parse arguments after event.");
98  }
99 
100 
102  TaskContext* tc, ExecutionEngine* tcaller, CommonParser* cp )
103  : context( tc ),
104  caller( tcaller ),
105  mpositer( positer ),
106  ln_offset(0),
107  curtemplate(),
108  curinstantiatedmachine(),
109  curmachinebuilder( 0 ),
110  curinitialstateflag( false ),
111  curfinalstateflag( false ),
112  curstate( 0 ),
113  curnonprecstate( 0 ),
114  progParser( 0 ),
115  elsestate(0),
116  curcondition( 0 ),
117  isroot(false),
118  selectln(0),
119  evname(""),
120  commonparser( cp ),
121  conditionparser( new ConditionParser( context, caller, *commonparser ) ),
122  valuechangeparser( new ValueChangeParser(context, *commonparser, context->provides(), caller) ),
123  expressionparser( new ExpressionParser(context, caller, *commonparser) ),
124  argsparser(0),
125  peerparser( new PeerParser(context, *commonparser, true) ) // full-path peer parser for events.
126  {
127  BOOST_SPIRIT_DEBUG_RULE( production );
128  BOOST_SPIRIT_DEBUG_RULE( body );
129  BOOST_SPIRIT_DEBUG_RULE( rootmachineinstantiation );
130  BOOST_SPIRIT_DEBUG_RULE( statemachine );
131  BOOST_SPIRIT_DEBUG_RULE( machineinstantiation );
132  BOOST_SPIRIT_DEBUG_RULE( statemachinecontent );
133  BOOST_SPIRIT_DEBUG_RULE( varline );
134  BOOST_SPIRIT_DEBUG_RULE( state );
135  BOOST_SPIRIT_DEBUG_RULE( vardec );
136  BOOST_SPIRIT_DEBUG_RULE( subMachinedecl );
137  BOOST_SPIRIT_DEBUG_RULE( statecontent );
138  BOOST_SPIRIT_DEBUG_RULE( statecontentline );
139  BOOST_SPIRIT_DEBUG_RULE( entry );
140  BOOST_SPIRIT_DEBUG_RULE( preconditions );
141  BOOST_SPIRIT_DEBUG_RULE( precondition );
142  BOOST_SPIRIT_DEBUG_RULE( handle );
143  BOOST_SPIRIT_DEBUG_RULE( transitions );
144  BOOST_SPIRIT_DEBUG_RULE( transition );
145  BOOST_SPIRIT_DEBUG_RULE( exit );
146  BOOST_SPIRIT_DEBUG_RULE( transline );
147  BOOST_SPIRIT_DEBUG_RULE( eventline );
148  BOOST_SPIRIT_DEBUG_RULE( ifbranch );
149  BOOST_SPIRIT_DEBUG_RULE( elsebranch );
150  BOOST_SPIRIT_DEBUG_RULE( progselect );
151  BOOST_SPIRIT_DEBUG_RULE( program );
152  BOOST_SPIRIT_DEBUG_RULE( selector );
153  BOOST_SPIRIT_DEBUG_RULE( machineinstarguments );
154  BOOST_SPIRIT_DEBUG_RULE( machineinstargument );
155  BOOST_SPIRIT_DEBUG_RULE( machinememvar );
156  BOOST_SPIRIT_DEBUG_RULE( machinevariable );
157  BOOST_SPIRIT_DEBUG_RULE( machineparam );
158  BOOST_SPIRIT_DEBUG_RULE( machineconstant );
159  BOOST_SPIRIT_DEBUG_RULE( machinealias );
160  BOOST_SPIRIT_DEBUG_RULE( subMachinevarchange );
161 
162  storeOffset();
163 
164  production = *body >> expect_eof(end_p);
165 
166  body = statemachine[ boost::bind( &StateGraphParser::seenstatemachineend, this ) ][boost::bind( &StateGraphParser::saveText, this, _1, _2)]
167  | rootmachineinstantiation;
168 
169 
170  rootmachineinstantiation =
171  keyword_p("RootMachine")[boost::bind (&StateGraphParser::startrootmachineinstantiation, this) ]
172  >> machineinstantiation[ boost::bind( &StateGraphParser::seenrootmachineinstantiation, this ) ];
173 
174  statemachine =
175  keyword_p("StateMachine") //[boost::bind( &StateGraphParser::storeOffset, this)]
176  >> expect_ident( commonparser->identifier[ boost::bind( &StateGraphParser::seenstatemachinename, this, _1, _2 )] )
177  >> expect_open( ch_p( '{' ) )
178  >> statemachinecontent
179  >> expect_end( ch_p( '}' ) );
180 
181  // Zero or more declarations and Zero or more states. Once a state is encountered, no more global transitions may be defined.
182  statemachinecontent = *( varline | transitions | transition) >> *( varline | state);
183 
184  varline = vardec[lambda::var(commonparser->skipeol) = false] >> commonparser->eos[lambda::var(commonparser->skipeol) = true];
185 
186  vardec = subMachinedecl | machinememvar | machineparam;
187 
188  machinememvar = ( machineconstant | machinevariable | machinealias )[boost::bind( &StateGraphParser::seenmachinevariable, this )];
189  machineconstant = valuechangeparser->constantDefinitionParser();
190  machinevariable = valuechangeparser->variableDefinitionParser();
191  machinealias = valuechangeparser->aliasDefinitionParser();
192 
193  machineparam = valuechangeparser->paramDefinitionParser()[boost::bind( &StateGraphParser::seenmachineparam, this )];
194 
195  subMachinedecl = keyword_p("SubMachine")
196  >> machineinstantiation[boost::bind( &StateGraphParser::seensubMachineinstantiation, this )];
197 
198  machineinstantiation =
199  expect_ident( commonparser->identifier[ boost::bind( &StateGraphParser::seenmachinetypename, this, _1, _2 )] )
200  >> expect_ident( commonparser->identifier[ boost::bind( &StateGraphParser::seeninstmachinename, this, _1, _2 )] )
201  >> ( ! ( ch_p( '(' )
202  >> !machineinstarguments
203  >> expect_close_parenth( ch_p( ')' ) ) ) )[ boost::bind( &StateGraphParser::seenmachineinstantiation, this )];
204 
205  machineinstarguments =
206  machineinstargument >> *( ',' >> machineinstargument );
207 
208  machineinstargument =
209  commonparser->identifier[ boost::bind( &StateGraphParser::seenmachineinstargumentname, this, _1, _2 )]
210  >> '='
211  >> expressionparser->parser()[ boost::bind( &StateGraphParser::seenmachineinstargumentvalue, this )];
212 
213  state =
214  !( keyword_p( "initial" )[boost::bind( &StateGraphParser::seeninitialstate,this )]
215  | keyword_p( "final" )[boost::bind( &StateGraphParser::seenfinalstate,this )] )
216  >> keyword_p( "state" )
217  >> expect_ident(commonparser->identifier[ boost::bind( &StateGraphParser::statedef, this, _1, _2 ) ])
218  >> expect_open(ch_p( '{' ))
219  >> statecontent
220  >> expect_end_of_state(ch_p( '}' ))[ boost::bind( &StateGraphParser::seenstateend, this ) ];
221 
222  // the content of a program can be any number of lines
223  // a line is not strictly defined in the sense of text-line.
224  statecontent = *statecontentline;
225 
226  // a state can contain various programs and variable definitions
227  statecontentline =
228  entry
229  | preconditions
230  | run
231  | handle
232  | transitions
233  | transition
234  | exit
235  | (machinememvar[lambda::var(commonparser->skipeol) = false] >> commonparser->eos[lambda::var(commonparser->skipeol) = true]);
236 
237  precondition = keyword_p( "precondition")
238  >> conditionparser->parser()[ boost::bind( &StateGraphParser::seenprecondition, this)] ;
239 
240  preconditions = (keyword_p( "preconditions" )[ boost::bind( &StateGraphParser::inpreconditions, this )]
241  >> expect_open( ch_p( '{' ))
242  >> *transline[boost::bind(&StateGraphParser::seenendcondition,this)]
243  >> expect_end( ch_p( '}' ) )[
244  boost::bind( &StateGraphParser::seenpreconditions, this )]) | precondition;
245 
246  entry = keyword_p( "entry" )[ boost::bind( &StateGraphParser::inprogram, this, "entry" )]
247  >> expect_open(ch_p('{'))>> programBody >> expect_end(ch_p('}'))[
248  boost::bind( &StateGraphParser::seenentry, this )];
249 
250  run = keyword_p( "run" )[ boost::bind( &StateGraphParser::inprogram, this, "run" )]
251  >> expect_open(ch_p('{'))>> programBody >> expect_end(ch_p('}'))[
252  boost::bind( &StateGraphParser::seenrun, this )];
253 
254  exit = keyword_p( "exit" )[ boost::bind( &StateGraphParser::inprogram, this, "exit" )]
255  >> expect_open(ch_p('{')) >> programBody >> expect_end(ch_p('}'))[
256  boost::bind( &StateGraphParser::seenexit, this )];
257 
258  handle = keyword_p( "handle" )[ boost::bind( &StateGraphParser::inprogram, this, "handle" )]
259  >> expect_open(ch_p('{'))>> programBody >> expect_end(ch_p('}'))[
260  boost::bind( &StateGraphParser::seenhandle, this )];
261 
262  // formal:
263  // transition [event] [[ {program} ][ select s]] | [ if c then ][ {program} ][select s][ else [ {program} ][select s]]
264  // parsed:
265  // transition [ [if c then ][ {program} ][select s][ else [ {program} ][select s]]]
266  // | [ event [[ {program} ][ select s]] | [ if c then ][ {program} ][select s][ else [ {program} ][select s]] ]
267  // rules:
268  // transition = "transition" >> (transline | eventline)
269  // transline = progselect
270  // | (ifbranch >> !elsebranch)
271  // eventline = eventname >> transline
272  // progselect = (selector | (program >> !selector))
273  // ifbranch = "if" >> c >> "then" >> progselect
274  // elsebranch = "else" >> progselect
275  // selector = "select" >> ...
276  // program = "{" >> ...
277  //
278 
279  // old transition statements
280  // the order of rule "transition" vs "transitions" is important
281  transitions = ( keyword_p( "transitions" )
282  >> expect_open(ch_p('{'))
283  >> *((transline|eventline)[boost::bind(&StateGraphParser::seenendcondition,this)])
284  >> expect_end(ch_p('}')) );
285 
286  // new transition statements
287  transition = keyword_p("transition") >> expect_event_or_if( transline | eventline )[boost::bind(&StateGraphParser::seenendcondition,this)];
288  transline = progselect | (ifbranch >> !elsebranch);
289 
290  // @todo: capturing events are only on local ports ?!.
291  eventline =
292  !peerparser->parser() >> commonparser->identifier[ boost::bind( &StateGraphParser::seeneventname, this,_1,_2)]
293  >> expect_eventargs(argslist[ boost::bind( &StateGraphParser::seeneventargs, this)])
294  >> expect_eventselect(transline[ boost::bind( &StateGraphParser::seeneventtrans, this)]);
295 
296  progselect = selector | (program >> (selector | eps_p[boost::bind( &StateGraphParser::noselect, this )] ));
297  // | eps_p[boost::bind( &StateGraphParser::noselect, this )] ); // if eos fails skipeol stays false !, see clear() !
298 
299  ifbranch = keyword_p( "if") >> conditionparser->parser()[ boost::bind( &StateGraphParser::seencondition, this)]
300  >> !keyword_p( "then" )
301  >> progselect;
302  elsebranch = keyword_p("else")[boost::bind( &StateGraphParser::seenelse, this )]
303  >> progselect;
304 
305  program =
306  ch_p('{')[ boost::bind( &StateGraphParser::inprogram, this, "transition" )]
307  >> programBody
308  >> expect_end(ch_p('}'))[boost::bind( &StateGraphParser::seentransprog, this )];
309 
310  selector = keyword_p( "select" ) >> expect_select_ident(( commonparser->identifier[ boost::bind( &StateGraphParser::seenselect, this, _1, _2) ]
311  >> *(keyword_p("or") >> commonparser->identifier[ boost::bind( &StateGraphParser::seenselect, this, _1, _2) ])
312  )[lambda::var(commonparser->skipeol) = false]
313  >> commonparser->eos[lambda::var(commonparser->skipeol) = true]);
314 
315  }
316 
318  return body;
319  }
320 
321  ParsedStateMachinePtr StateGraphParser::getParserResult() {
322  ParsedStateMachinePtr ret;
323  if ( rootmachines.empty() )
324  return ret;
325  std::vector<ParsedStateMachinePtr> vret = values( rootmachines );
326  rootmachines.clear();
327  return vret.front();
328  }
329 
330 
331  void StateGraphParser::seeninitialstate()
332  {
333  curinitialstateflag = true;
334  }
335 
336  void StateGraphParser::seenfinalstate()
337  {
338  curfinalstateflag = true;
339  }
340 
341  void StateGraphParser::statedef( iter_t s, iter_t f)
342  {
343  assert( !curstate );
344 
345  std::string def(s, f);
346  if ( curtemplate->getState( def ) != 0 )
347  {
348  assert( dynamic_cast<StateDescription*>( curtemplate->getState( def ) ) );
349  StateDescription* existingstate = static_cast<StateDescription*>( curtemplate->getState( def ) );
350  if ( existingstate->isDefined() )
351  ORO_THROW(parse_exception_semantic_error("state " + def + " redefined.") );
352  else
353  curstate = existingstate;
354  curstate->setEntryPoint( mpositer.get_position().line - ln_offset );
355  }
356  else
357  {
358  curstate = new StateDescription(def, mpositer.get_position().line - ln_offset ); // create an empty state
359  curtemplate->addState( curstate );
360  }
361 
362  }
363 
364  void StateGraphParser::seenstateend()
365  {
366  if ( curinitialstateflag )
367  {
368  if ( curtemplate->getInitialState() )
369  ORO_THROW(parse_exception_semantic_error( "Attempt to define more than one initial state." ));
370  else curtemplate->setInitialState( curstate );
371  }
372  if ( curfinalstateflag )
373  {
374  if ( curtemplate->getFinalState() )
375  ORO_THROW(parse_exception_semantic_error( "Attempt to define more than one final state." ));
376  else curtemplate->setFinalState( curstate );
377  }
378 
379  assert( curstate );
380  curstate->setDefined( true );
381  curstate = 0;
382  curinitialstateflag = false;
383  curfinalstateflag = false;
384  // clear all port-triggered transitions for this state.
385  cur_port_events.clear();
386  }
387 
388  void StateGraphParser::inprogram(const std::string& name)
389  {
390  // setup the progParser to parse the program body,
391  // dynamically assign this parser to body.
392  assert( progParser != 0 );
393  // program name, stack, line offset.
394  //cerr << "SGP : Stack is " << curobject->getName() <<endl;
395  progParser->initBodyParser( name, curobject, ln_offset );
396 
397  programBody = progParser->bodyParser();
398  }
399 
400  ProgramInterfacePtr StateGraphParser::finishProgram()
401  {
402  return progParser->bodyParserResult();
403  }
404 
405  void StateGraphParser::seenentry()
406  {
407  if ( curstate->getEntryProgram() )
408  ORO_THROW( parse_exception_semantic_error( "Attempt to define entry twice in state "+ curstate->getName() ));
409  curstate->setEntryProgram( finishProgram() );
410  }
411 
412  void StateGraphParser::seenexit()
413  {
414  if ( curstate->getExitProgram() )
415  ORO_THROW( parse_exception_semantic_error( "Attempt to define exit twice in state "+ curstate->getName() ));
416  curstate->setExitProgram( finishProgram() );
417  }
418 
419  void StateGraphParser::seenhandle()
420  {
421  if ( curstate->getHandleProgram() )
422  ORO_THROW( parse_exception_semantic_error( "Attempt to define handle twice in state "+ curstate->getName() ));
423  curstate->setHandleProgram( finishProgram() );
424  }
425 
426  void StateGraphParser::seenrun()
427  {
428  if ( curstate->getRunProgram() )
429  ORO_THROW( parse_exception_semantic_error( "Attempt to define run twice in state "+ curstate->getName() ));
430  curstate->setRunProgram( finishProgram() );
431  }
432 
433  void StateGraphParser::seentransprog()
434  {
435  transProgram = finishProgram();
436  }
437 
438  void StateGraphParser::seenelseprog()
439  {
440  // reuse transProgram to store else progr. See seenselect().
441  //transProgram = finishProgram();
442  //transProgram->setProgramProcessor(curtemplate->getService()->engine()->programs());
443  }
444 
445  void StateGraphParser::seenelse()
446  {
447  assert( curcondition);
448  curcondition = new ConditionInvert( curcondition );
449  }
450 
451  void StateGraphParser::seencondition()
452  {
453  assert( !curcondition );
454  curcondition = conditionparser->getParseResult();
455  assert( curcondition );
456  conditionparser->reset();
457  selectln = mpositer.get_position().line - ln_offset;
458  }
459 
460  void StateGraphParser::seeneventname(iter_t s, iter_t f)
461  {
462  evname = string(s,f);
463 
464  // seenselect() will use evname to see if event is causing transition
465  assert(evname.length());
466  peer = peerparser->taskObject();
467  peerparser->reset();
468 
469  // check if it's an operation:
470  if (peer->hasOperation(evname) ) {
471  argsparser =
472  new ArgumentsParser( *expressionparser, context, peer->provides(),
473  evname, "callback" );
474  } else {
475  // check if it's a port.
476  if ( peer->hasService(evname) == false || peer->getService(evname)->hasOperation("read") == false) {
477  if (curstate)
478  ORO_THROW( parse_exception_fatal_semantic_error("In state "+curstate->getName()+": InputPort or Operation "+evname+" not found in Task "+peer->getName() ));
479  else
480  ORO_THROW( parse_exception_fatal_semantic_error("In statemachine: InputPort or Operation "+evname+" not found in Task "+peer->getName() ));
481  }
482  argsparser =
483  new ArgumentsParser( *expressionparser, context, peer->getService(evname),
484  evname, "read" );
485  }
486 
487  argslist = argsparser->parser();
488  }
489 
490  void StateGraphParser::seeneventargs()
491  {
492  evargs = argsparser->result();
493  delete argsparser;
494  argsparser = 0;
495  }
496 
497  void StateGraphParser::noselect()
498  {
499  // if omitted, implicitly re-enter current state.
500  if (curstate)
501  doselect( curstate->getName() );
502  else
503  doselect(""); // global events/transitions
504  }
505 
506  void StateGraphParser::seenselect( iter_t s, iter_t f)
507  {
508  std::string state_id(s,f);
509  doselect(state_id);
510  }
511 
512  void StateGraphParser::doselect( const std::string& state_id )
513  {
514  StateInterface* next_state = 0;
515  if ( !state_id.empty() ) {
516  if ( curtemplate->getState( state_id ) != 0 )
517  {
518  next_state = curtemplate->getState( state_id );
519  }
520  else
521  {
522  next_state = new StateDescription(state_id, 1); // create an empty state
523  curtemplate->addState( next_state );
524  }
525  assert( next_state );
526  }
527 
528  // this transition has a lower priority than the previous one
529  if ( selectln == 0)
530  selectln = mpositer.get_position().line - ln_offset;
531 
532  if (evname.empty()) {
533  if (curcondition == 0)
534  curcondition = new ConditionTrue;
535  } else if ( peer->hasService(evname) && peer->getService(evname)->hasOperation("read") ) { // is a port
536  try {
537  assert(peer->hasService(evname)); // checked in seeneventname()
538  ConditionInterface* evcondition = 0;
539  if ( global_port_events.count(evname) ){
540  // clone the cached condition in order to avoid a second read on the port.
541  evcondition = new ConditionBoolDataSource( global_port_events[evname]->getResult().get() );
542  } else
543  if ( cur_port_events.count(evname) ){
544  // clone the cached condition in order to avoid a second read on the port.
545  evcondition = new ConditionBoolDataSource( cur_port_events[evname]->getResult().get() );
546  } else {
547  // combine the implicit 'read(arg) == NewData' with the guard, if any.
548  DataSourceBase::shared_ptr read_dsb = peer->getService(evname)->produce("read", evargs, context->engine() );
549  DataSource<FlowStatus>* read_ds = dynamic_cast<DataSource<FlowStatus>*>(read_dsb.get());
550  assert(read_ds);
552  if (curstate) {
553  cur_port_events[evname] = new ConditionCache( evcondition ); // caches result until reset().
554  evcondition = cur_port_events[evname]->clone();
555  } else {
556  //global event:
557  global_port_events[evname] = new ConditionCache( evcondition ); // caches result until reset().
558  evcondition = global_port_events[evname]->clone();
559  }
560  }
561  if (curcondition == 0) {
562  curcondition = evcondition;
563  } else {
564  curcondition = new ConditionBinaryCompositeAND( evcondition, curcondition );
565  }
566  }
567  catch( const wrong_number_of_args_exception& e )
568  {
570  ( peer->getName(), evname + ".read", e.wanted, e.received );
571  }
572  catch( const wrong_types_of_args_exception& e )
573  {
575  ( peer->getName(), evname + ".read", e.whicharg, e.expected_, e.received_ );
576  }
577  elsestate = 0;
578  elseProgram.reset();
579  } else { // is an operation
580  assert( peer->provides()->hasMember(evname) );
581  bool res;
582  if (curcondition == 0)
583  curcondition = new ConditionTrue;
584 
585  // if ( elsestate != 0)
586  // res = curtemplate->createEventTransition( &(peer->eventService), evname, evargs, curstate, next_state, curcondition->clone()
587  // else
588  //cerr << "Registering "<<evname<<" handler for SM."<<endl;
589  try {
590  res = curtemplate->createEventTransition( peer->provides(), caller, evname, evargs, curstate, next_state, curcondition->clone(), transProgram );
591  if (!res)
592  throw parse_exception_fatal_semantic_error("StateMachine could not install a Signal Handler for Operation "+evname);
593  }
594  catch( const wrong_number_of_args_exception& e )
595  {
597  ( peer->getName(), evname, e.wanted, e.received );
598  }
599  catch( const wrong_types_of_args_exception& e )
600  {
602  ( peer->getName(), evname, e.whicharg, e.expected_, e.received_ );
603  }
604  catch( const no_asynchronous_operation_exception& e )
605  {
606  throw parse_exception_fatal_semantic_error("StateMachine can't create EventTransition on Operation '" + evname + "' since it was not added with addEventOperation()." );
607  }
608  catch( ... )
609  {
610  assert( false );
611  }
612 
613  assert( res ); // checked in seeneventname()
614  elsestate = 0;
615  elseProgram.reset();
616  return; // we installed the Signal Handler !
617  }
618  // finally, install the handler:
619  curtemplate->transitionSet( curstate, next_state, curcondition->clone(), transProgram, rank--, selectln );
620  }
621 
622  void StateGraphParser::seenendcondition() {
623  delete curcondition;
624  curcondition = 0;
625  selectln = 0;
626  transProgram.reset();
627  }
628 
629  void StateGraphParser::seeneventtrans() {
630  // cleanup all event related state.
631  evname.clear();
632  evargs.clear();
633  }
634 
635  void StateGraphParser::seenprecondition()
636  {
637  assert( !curcondition );
638  curcondition = conditionparser->getParseResult();
639  assert( curcondition );
640  conditionparser->reset();
641  selectln = mpositer.get_position().line - ln_offset;
642 
643  curtemplate->preconditionSet(curstate, curcondition, selectln );
644  selectln = 0;
645  curcondition = 0;
646  }
647 
648 
649  void StateGraphParser::seenstatemachineend()
650  {
651  assert( curtemplate );
652  assert( ! curstate );
653 
654  // reclaim the defined variables:
655 
656 
657  // Check if the Initial and Final States are ok.
658  if ( curtemplate->getInitialState() == 0 )
659  ORO_THROW( parse_exception_semantic_error("No initial state defined."));
660  if ( curtemplate->getFinalState() == 0 )
661  ORO_THROW( parse_exception_semantic_error("No final state defined."));
662 
663  if ( curtemplate->getStateList().empty() )
664  ORO_THROW( parse_exception_semantic_error("No states defined in this state machine !"));
665 
666  // Check if all States are defined.
667  vector<string> states = curtemplate->getStateList();
668  for( vector<string>::const_iterator it = states.begin(); it != states.end(); ++it)
669  {
670  assert( dynamic_cast<StateDescription*>( curtemplate->getState( *it ) ) );
671  StateDescription* sd = static_cast<StateDescription*>( curtemplate->getState( *it ) );
672  if ( !sd->isDefined() )
673  ORO_THROW( parse_exception_semantic_error("State " + *it + " not defined, but referenced to."));
674  }
675 
676  // retrieve _all_ defined variables and parameters, store them and cleanup the
677  // valuechangeparser.
678  valuechangeparser->store( curtemplate->getService() );
679  valuechangeparser->reset();
680 
681  // prepend the commands for initialising the subMachine
682  // variables..
683  assert( curtemplate->getInitCommand() == 0);
684  if ( varinitcommands.size() > 1 )
685  {
686  CommandComposite* comcom = new CommandComposite;
687  for ( std::vector<ActionInterface*>::iterator i = varinitcommands.begin();
688  i != varinitcommands.end(); ++i )
689  comcom->add( *i );
690  curtemplate->setInitCommand( comcom );
691  }
692  else if (varinitcommands.size() == 1 )
693  curtemplate->setInitCommand( *varinitcommands.begin() );
694 
695  varinitcommands.clear();
696 
697  // remove temporary subMachine peers from current task.
698  for( StateMachine::ChildList::const_iterator it= curtemplate->getChildren().begin();
699  it != curtemplate->getChildren().end(); ++it ) {
700  ParsedStateMachine* psc = dynamic_cast<ParsedStateMachine*>( it->get() );
701  if (psc) {
702  // remove from parent
703  context->provides()->removeService( psc->getService()->getName() );
704  }
705 
706  }
707 
708  // finally :
709  curtemplate->finish();
710 
711  delete progParser;
712  progParser = 0;
713 
714  StateMachineBuilder* scb = new StateMachineBuilder( curtemplate );
715  machinebuilders[curmachinename] = scb;
716 
717  // save curmachinename for saveText.
718  curobject.reset();
719  curtemplate.reset();
720  }
721 
722  std::vector<ParsedStateMachinePtr> StateGraphParser::parse( iter_t& begin, iter_t end )
723  {
724  //skip_parser_t skip_parser = SKIP_PARSER;
725  //iter_pol_t iter_policy( skip_parser );
726  //#define SKIP_PARSER
727  skip_parser_t skip_parser = comment_p( "#" ) | comment_p( "//" ) | comment_p( "/*", "*/" ) | (space_p - eol_p) | commonparser->skipper;
728  iter_pol_t iter_policy( skip_parser );
729  scanner_pol_t policies( iter_policy );
730  scanner_t scanner( begin, end, policies );
731 
732  // reset the condition-transition priority.
733  rank = 0;
734 
735  this->storeOffset();
736 
737  try {
738  if ( ! production.parse( scanner ) )
739  {
740  // on error, we clear all remaining data, cause we can't
741  // guarantee consistency...
742  clear();
743  throw file_parse_exception(
744  new parse_exception_syntactic_error( "Syntax error" ),
745  mpositer.get_position().file, mpositer.get_position().line,
746  mpositer.get_position().column );
747  }
748  std::vector<ParsedStateMachinePtr> ret = values( rootmachines );
749  rootmachines.clear();
750  return ret;
751  }
752  catch( const parser_error<std::string, iter_t>& e )
753  {
754  // on error, we clear all remaining data, cause we can't
755  // guarantee consistency...
756  clear();
757  throw file_parse_exception(
758  new parse_exception_syntactic_error( e.descriptor ),
759  mpositer.get_position().file, mpositer.get_position().line,
760  mpositer.get_position().column );
761  }
762  catch( const parser_error<GraphSyntaxErrors, iter_t>& )
763  {
764  // on error, we clear all remaining data, cause we can't
765  // guarantee consistency...
766  clear();
767  throw file_parse_exception(
768  new parse_exception_syntactic_error( "Expected one of: entry, handle, exit, transitions" ),
769  mpositer.get_position().file, mpositer.get_position().line,
770  mpositer.get_position().column );
771  }
772  catch( const parse_exception& e )
773  {
774  // on error, we clear all remaining data, cause we can't
775  // guarantee consistency...
776  clear();
777  throw file_parse_exception(
778  e.copy(), mpositer.get_position().file,
779  mpositer.get_position().line, mpositer.get_position().column );
780  }
781 // catch( ... ) {
782 // assert( false );
783 // }
784  }
785 
787  clear();
788  delete valuechangeparser;
789  delete expressionparser;
790  delete conditionparser;
791  delete peerparser;
792  }
793 
794  void StateGraphParser::clear() {
795 
796  // remove tmp vars from TaskContext
797  valuechangeparser->reset();
798 
799  // in case of corrupt file, skipeol could have remained on false,
800  // so make sure it is set correctly again
801  commonparser->skipeol = true;
802  selectln = 0;
803  transProgram.reset();
804  elseProgram.reset();
805  delete argsparser;
806  argsparser = 0;
807  delete curcondition;
808  curcondition = 0;
809  // we own curstate, but not through this pointer...
810  curstate = 0;
811  delete curnonprecstate;
812  curnonprecstate = 0;
813  // we own curmachinebuilder, but not through this pointer...
814  curmachinebuilder = 0;
815  curinstantiatedmachine.reset();
816  // If non null, there was a parse-error, undo all :
817  if ( curtemplate )
818  {
819 
820  // remove temporary subMachine peers from current task.
821  for( StateMachine::ChildList::const_iterator it= curtemplate->getChildren().begin();
822  it != curtemplate->getChildren().end(); ++it ) {
823  ParsedStateMachine* psc = dynamic_cast<ParsedStateMachine*>( it->get() );
824  if (psc && psc->getService() ) {
825  context->provides()->removeService( psc->getService()->getName() );
826  }
827  }
828  // remove all 'this' data factories
829  curtemplate->getService()->clear();
830 
831  // will also delete all children :
832  curtemplate.reset();
833  }
834  // should be empty in most cases :
835  for ( std::vector<ActionInterface*>::iterator i = varinitcommands.begin();
836  i != varinitcommands.end(); ++ i )
837  delete *i;
838  varinitcommands.clear();
839  for ( std::vector<ActionInterface*>::iterator i = paraminitcommands.begin();
840  i != paraminitcommands.end(); ++ i )
841  delete *i;
842  paraminitcommands.clear();
843  for ( machinebuilders_t::iterator i = machinebuilders.begin();
844  i != machinebuilders.end(); ++i )
845  delete i->second;
846  machinebuilders.clear();
847 
848  }
849 
850  void StateGraphParser::seenstatemachinename( iter_t begin, iter_t end ) {
851  // the 'type' of the SC :
852  curmachinename = std::string ( begin, end );
853 
854  // check if the type exists already :
855  if ( machinebuilders.count( curmachinename ) != 0 )
856  ORO_THROW( parse_exception_semantic_error("StateMachine type " + curmachinename + " redefined."));
857 
858  curtemplate.reset(new ParsedStateMachine());
859  // Connect the new SC to the relevant machines.
860  // 'sc' acts as a stack for storing variables.
861  curobject.reset( new StateMachineService(curtemplate, context ) );
862  curobject->setName( curmachinename );
863  curtemplate->setService( curobject ); // store.
864 
865  // we pass the plain file positer such that parse errors are
866  // refering to correct file line numbers.
867  progParser = new ProgramGraphParser(mpositer, context, caller, *commonparser);
868 
869  // set the 'type' name :
870  curtemplate->setName( curmachinename, false );
871  }
872 
874  // stores the begining of a (possible) new statemachine definition.
875  // start line number :
876  ln_offset = mpositer.get_position().line - 1;
877  // start of text :
878  saveStartPos = mpositer;
879  }
880 
881  void StateGraphParser::saveText( iter_t begin, iter_t end ) {
882  assert( curmachinename.length() != 0 );
883  //cerr << std::string(begin, end)<<endl;
884  if ( machinebuilders.count( curmachinename ) == 0 )
885  return; // yes this might be possible
886  // due to the shared-text implementation, we can set the text afterwards.
887  machinebuilders[curmachinename]->item()->setText( std::string( saveStartPos, end) );
888  this->storeOffset();
889  }
890 
891  void StateGraphParser::inpreconditions() {
892  // we postpone the current state
893  assert( curnonprecstate == 0 );
894  curnonprecstate = curstate->postponeState();
895  // add the postponed state in PSM :
896  curtemplate->addState( curnonprecstate );
897  }
898 
899  void StateGraphParser::seenpreconditions() {
900  curtemplate->transitionSet( curstate, curnonprecstate, new ConditionTrue, rank--, mpositer.get_position().line - ln_offset );
901  curstate->setDefined( true );
902  curstate = curnonprecstate;
903  curnonprecstate = 0;
904  }
905 
906  void StateGraphParser::startrootmachineinstantiation() {
907  isroot = true;
908  }
909 
910  void StateGraphParser::seenrootmachineinstantiation() {
911  // first reset the flag.
912  isroot = false;
913  if( rootmachines.find( curinstmachinename ) != rootmachines.end() )
914  ORO_THROW( parse_exception_semantic_error( "Root machine \"" + curinstmachinename + "\" already defined." ));
915  rootmachines[curinstmachinename] = curinstantiatedmachine;
916 
917  // recursively set the name of this SC and all subs :
918  // furthermore, it adds the TC of each child as peer TC to the parent.
919  curinstantiatedmachine->setName( curinstmachinename, true );
920 
921  // check if the type exists already :
922  if ( context->provides()->hasService( curinstmachinename ) )
923  ORO_THROW( parse_exception_semantic_error("TaskContext '"+context->getName()+"' has already a Service named '" + curinstmachinename + "' ."));
924 
925  // Transfer ownership to the owning task.
926  context->provides()->addService( curinstantiatedmachine->getService() );
927 
928  curinstantiatedmachine.reset();
929  curinstmachinename.clear();
930  }
931 
932  void StateGraphParser::seensubMachineinstantiation() {
933  if ( find_if( curtemplate->getChildren().begin(),
934  curtemplate->getChildren().end(),
935  boost::bind( equal_to<string>(), boost::bind(&StateMachine::getName,_1), curinstmachinename )) != curtemplate->getChildren().end() )
936  ORO_THROW( parse_exception_semantic_error( "SubMachine \"" + curinstmachinename + "\" already defined." ));
937 
938  // Since we parse in the task context, we must _temporarily_
939  // make each subMachine a peer of the task so that we can access
940  // its methods.
941 
942  // Warning: use context->unmountService() since curinstantiatedmachine must owns it.
943  if ( !context->provides()->addService( curinstantiatedmachine->getService() ) )
945  "Name clash: name of instantiated machine \"" + curinstmachinename +
946  "\" already used as object name in task '"+context->getName()+"'." ));
947 
948  // SM child relation
949  curtemplate->addChild( curinstantiatedmachine );
950  // sub-Service relation.
951  curtemplate->getService()->addService( curinstantiatedmachine->getService() );
952 
953  curinstantiatedmachine->setName(curinstmachinename, false ); // not recursive !
954 
955  curinstantiatedmachine.reset();
956  curinstmachinename.clear();
957  }
958 
959  void StateGraphParser::seenmachinetypename( iter_t begin, iter_t end ) {
960  assert( curmachinebuilder == 0 );
961  std::string name( begin, end );
962  machinebuilders_t::iterator i = machinebuilders.find( name );
963  if ( i == machinebuilders.end() )
964  ORO_THROW( parse_exception_semantic_error( "StateMachine \"" + name + "\" not defined." ));
965  curmachinebuilder = i->second;
966  }
967 
968  void StateGraphParser::seeninstmachinename( iter_t begin, iter_t end ) {
969  assert( curmachinebuilder != 0 );
970  assert( curinstmachinename.empty() );
971  curinstmachinename = std::string( begin, end );
972  }
973 
974  void StateGraphParser::seenmachineinstargumentname( iter_t begin, iter_t end ) {
975  assert( curmachineinstargumentname.empty() );
976  std::string name( begin, end );
977  curmachineinstargumentname = name;
978  }
979 
980  void StateGraphParser::seenmachineinstargumentvalue() {
981  DataSourceBase::shared_ptr value = expressionparser->getResult();
982  // let's not forget this...
983  expressionparser->dropResult();
984  if ( curinstmachineparams.find( curmachineinstargumentname ) != curinstmachineparams.end() )
986  "In initialisation of StateMachine \"" + curinstmachinename +
987  "\": Parameter \"" + curmachineinstargumentname +"\" initialised twice..." ));
988  curinstmachineparams[curmachineinstargumentname] = value;
989  curmachineinstargumentname.clear();
990  }
991 
992  void StateGraphParser::seenmachineinstantiation()
993  {
994  // TODO : move this code to the ParsedStateMachine builder.
995 
996  // Create a full depth copy (including subMachines)
997  // if RootMachine, make special copy which fixes attributes such
998  // that on subsequent copy() they keep pointing to same var.
999  // use shared_ptr to release on throw's below.
1000  ParsedStateMachinePtr nsc( curmachinebuilder->build( isroot ) );
1001 
1002  // we stored the attributes which are params of nsc
1003  // in the build operation :
1004  machineparams_t params = nsc->getParameters();
1005 
1006  // first run over the given parameters to see if they all exist in
1007  // the context we're instantiating...
1008  for ( machineparamvalues_t::iterator i = curinstmachineparams.begin(); i != curinstmachineparams.end(); ++i )
1009  {
1010  machineparams_t::iterator j = params.find( i->first );
1011  if ( j == params.end() )
1012  ORO_THROW( parse_exception_semantic_error( "No parameter \"" + i->first + "\" in this StateMachine." ) );
1013  }
1014 
1015  for ( machineparams_t::iterator i = params.begin(); i != params.end(); ++i )
1016  {
1017  machineparamvalues_t::iterator j = curinstmachineparams.find( i->first );
1018  if ( j == curinstmachineparams.end() )
1020  "No value given for argument \"" + i->first + "\" in instantiation of this StateMachine." ));
1021 #ifndef ORO_EMBEDDED
1022  try {
1023  paraminitcommands.push_back( i->second->getDataSource()->updateAction( j->second.get() ) );
1024  }
1025  catch( const bad_assignment& )
1026  {
1027  throw parse_exception_semantic_error("Attempt to initialize parameter '"+i->first+"' with a value which is of a different type." );
1028  }
1029 #else
1030  ActionInterface* ret = i->second->getDataSource()->updateAction( j->second.get());
1031  if (ret)
1032  paraminitcommands.push_back( ret );
1033  else
1034  return;
1035 #endif
1036  }
1037 
1038  curinstantiatedmachine = nsc;
1039 
1040  // prepend the commands for initialising the subMachine
1041  // parameters
1042  if ( paraminitcommands.size() > 0 )
1043  {
1044  CommandComposite* comcom = new CommandComposite;
1045  for ( std::vector<ActionInterface*>::iterator i = paraminitcommands.begin();
1046  i != paraminitcommands.end(); ++i )
1047  comcom->add( *i );
1048  // init the vars as last (if any), so that they can be inited by an expression containing the params :
1049  if ( curinstantiatedmachine->getInitCommand() )
1050  comcom->add( curinstantiatedmachine->getInitCommand() );
1051  curinstantiatedmachine->setInitCommand( comcom );
1052  }
1053  paraminitcommands.clear();
1054 
1055  curmachinebuilder = 0;
1056  curinstmachineparams.clear();
1057 
1058  // set the TaskContext name to the instance name :
1059  curinstantiatedmachine->getService()->setName(curinstmachinename );
1060  }
1061 
1062  void StateGraphParser::seenmachinevariable() {
1063  std::vector<ActionInterface*> acv = valuechangeparser->assignCommands();
1064  for(std::vector<ActionInterface*>::iterator it = acv.begin(); it!=acv.end(); ++it)
1065  varinitcommands.push_back( *it );
1066  // this only clears the last parsed variables, not the 'store' (see reset())
1067  valuechangeparser->clear();
1068  }
1069 
1070  void StateGraphParser::seenmachineparam() {
1071  std::vector<std::string> pnames = valuechangeparser->definedNames();
1072  std::vector<AttributeBase*> tbases = valuechangeparser->definedValues();
1073  assert( pnames.size() == tbases.size() );
1074  for (unsigned int i = 0; i < pnames.size(); ++i)
1075  curtemplate->addParameter( pnames[i] , tbases[i] );
1076  // this only clears the last parsed variables, not the 'store' (see reset())
1077  valuechangeparser->clear();
1078  }
1079 
1080 
1081 }
ProgramInterface * getHandleProgram() const
Get the handle program of this State.
#define keyword_p(word)
Returns a rule which parses a keyword followed by a non-identifier character, newline or semicolon...
std::vector< base::DataSourceBase::shared_ptr > result()
Get the parsed internal::DataSource&#39;s.
DataSource is a base class representing a generic way to read data of type T.
Definition: DataSource.hpp:94
void setEntryProgram(ProgramInterfacePtr entry)
std::vector< base::AttributeBase * > definedValues()
rule_t eos
End Of Statement Parser.
ConditionInterface * getParseResult()
Call this to get the parsed condition.
Service::shared_ptr provides()
Returns this Service.
#define ORO_THROW(x)
Definition: Exceptions.hpp:52
rule_t & aliasDefinitionParser()
The parser that parses alias definitions.
A conditional that evaluates and caches another Condition.
void setHandleProgram(ProgramInterfacePtr handle)
void reset()
After reset, peer() == current context and object() == "this".
Definition: PeerParser.cpp:151
void setRunProgram(ProgramInterfacePtr run)
This interface represents the concept of a condition which can be evaluated and return true or false...
const std::string & getName() const
This method must be overloaded to get a useful hierarchy.
const std::string & getName() const
Get the name of this state.
STL namespace.
bool skipeol
Saves eol skipping state.
A conditional that evaluates true.
This class represents a state with all actions stored in an external program.
StateDescription * postponeState()
This function returns a new state that contains all the data of this state ( its handle, entry, exit programs, and its name and inited state ), while this state&#39;s data is reset ( i.e.
StateGraphParser(iter_t &positer, TaskContext *tc, ExecutionEngine *caller, CommonParser *cp)
void reset()
Completely clear all data and erase all parsed definitions from the taskcontext given in the construc...
virtual ConditionInterface * clone() const =0
The Clone Software Pattern.
Compose an &#39;AND&#39; function of two Conditions.
parse_exception class that is used for various semantic errors for which it was not worth defining a ...
A Parser for Orocos Program Scripts.
boost::shared_ptr< ProgramInterface > ProgramInterfacePtr
A general compare condition.
virtual parse_exception * copy() const =0
void initBodyParser(const std::string &name, Service::shared_ptr stck, int offset)
Initialize the bodyParser to parse and store each statement it sees.
This is a parser that you construct to parse a set of arguments.
This is an exception class that keeps a parse_exception pointer along with the location in the file a...
This class contains some very common parser definitions.
void storeOffset()
Stores the current position in the input stream (iterator received from the constructor) in order to ...
This exception is thrown if the target and source type of an assignment of a DataSource with a base::...
Definition: DataSource.hpp:62
parse_exception class that is used for various syntactic errors for which it was not worth defining a...
An execution engine serialises (executes one after the other) the execution of all commands...
A conditional that evaluates to the inverse of another Condition.
void store(Service::shared_ptr other)
Store allDefinedNames() in a service.
scanner< iter_t, scanner_pol_t > scanner_t
How we parse: this parser works like a stack-based RPN calculator.
ProgramInterface * getEntryProgram() const
Get the entry program of this State.
ParsedStateMachinePtr getParserResult()
Returns the last state machine instantiation of parser() or null if no instantiations were seen...
void setExitProgram(ProgramInterfacePtr exit)
skip_parser_iteration_policy< skip_parser_t > iter_pol_t
boost::shared_ptr< StateMachineService > getService() const
Get the peer and object from an invocation path like a.b.c.d() .
Definition: PeerParser.hpp:58
ServicePtr taskObject()
Returns the last matching Service or zero if not found.
Definition: PeerParser.cpp:230
functor_parser< eol_skip_functor > skipper
End Of Statement Parser.
Based on the software pattern &#39;command&#39;, this interface allows execution of action objects...
std::vector< std::string > definedNames()
base::DataSourceBase::shared_ptr getResult()
This is the uppermost exception class in the parser system.
rule< scanner_t > rule_t
This class is responsible for parsing constant definitions, variable definitions, variable change ins...
rule_t & bodyParser()
Parses a multi-line program, which you can retrieve with bodyParserResult().
A Condition which holds a boolean DataSource.
ProgramInterface * getRunProgram() const
Get the run program of this State.
boost_spirit::alternative< boost_spirit::alternative< boost_spirit::alternative< boost_spirit::alternative< boost_spirit::confix_parser< boost_spirit::impl::string_as_parser::type, boost_spirit::kleene_star< boost_spirit::anychar_parser >, boost_spirit::alternative< boost_spirit::eol_parser, boost_spirit::end_parser >, boost_spirit::unary_parser_category, boost_spirit::non_nested, boost_spirit::is_lexeme >, boost_spirit::confix_parser< boost_spirit::impl::string_as_parser::type, boost_spirit::kleene_star< boost_spirit::anychar_parser >, boost_spirit::alternative< boost_spirit::eol_parser, boost_spirit::end_parser >, boost_spirit::unary_parser_category, boost_spirit::non_nested, boost_spirit::is_lexeme > >, boost_spirit::confix_parser< boost_spirit::impl::string_as_parser::type, boost_spirit::kleene_star< boost_spirit::anychar_parser >, boost_spirit::impl::string_as_parser::type, boost_spirit::unary_parser_category, boost_spirit::non_nested, boost_spirit::is_lexeme > >, boost_spirit::difference< boost_spirit::space_parser, boost_spirit::eol_parser > >, boost_spirit::functor_parser< eol_skip_functor > > skip_parser_t
parse_exception class that is used for fatal semantic errors for which it was not worth defining a pr...
A DataSource which holds a constant value and returns it in its get() method.
void clear()
Clear assignCommands(), definedValues() and definedNames().
rule_t & paramDefinitionParser()
The parser that parses state context parameter definitions.
rule_t & constantDefinitionParser()
the parser that parses definitions of constants.
rule_t & variableDefinitionParser()
the parser that parses variable definitions, don&#39;t forget to check assignCommand after a variable def...
virtual void add(base::ActionInterface *com)
add a command to the vect
The TaskContext is the C++ representation of an Orocos component.
Definition: TaskContext.hpp:93
Exception thrown when a factory is requested to create an object, but a wrong argument type was given...
std::vector< base::ActionInterface * > assignCommands()
ParsedStateMachinePtr build(bool instantiate)
Throws wrong_context_params_exception if params is wrong...
std::vector< typename MapT::mapped_type > values(const MapT &map)
Definition: mystd.hpp:140
rule_t & parser()
The parser tries to traverse a full peer-to-object path and throws if it got stuck in the middle...
Definition: PeerParser.cpp:215
Exception thrown when a factory is requested to create an object but the wrong number of arguments wa...
boost::intrusive_ptr< DataSourceBase > shared_ptr
Use this type to store a pointer to a DataSourceBase.
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:51
State machine created by the scripting engine which represents a parsed state machine.
rule_t & parser()
Returns the top-level parser for state machines.
our_pos_iter_t iter_t
A State contains an entry, run, handle and exit program.
This is a class containing a parse function for conditions.
scanner_policies< iter_pol_t > scanner_pol_t
Based on the software pattern &#39;composite&#39;, this class RTT_SCRIPTING_API allows composing command obje...
const ExecutionEngine * engine() const
Get a const pointer to the ExecutionEngine of this Task.
Definition: TaskCore.hpp:327
ProgramInterface * getExitProgram() const
Get the exit program of this State.
This class represents a stateMachine as a Service in the Orocos TaskContext system.
std::vector< ParsedStateMachinePtr > parse(iter_t &begin, iter_t end)
Exception thrown when a factory is requested to produce an asynchronous object while it is not availa...
virtual const std::string & getName() const
Returns the name of this TaskContext.