Orocos Real-Time Toolkit  2.8.3
PeerParser.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Tue Dec 21 22:43:07 CET 2004 PeerParser.cxx
3 
4  PeerParser.cxx - description
5  -------------------
6  begin : Tue December 21 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  * Lesser 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 
39 
40 #include "PeerParser.hpp"
41 #include "parser-debug.hpp"
42 #include "parse_exception.hpp"
43 #include "../TaskContext.hpp"
44 #include "parser-types.hpp"
45 #include "../internal/GlobalService.hpp"
46 
47 #include <boost/bind.hpp>
48 #include <boost/iterator/iterator_traits.hpp>
49 
50 namespace RTT
51 {
52  using boost::bind;
53  using namespace detail;
54  using namespace std;
55  using namespace boost;
56 
57  error_status<> PeerParser::handle_no_peer(scanner_t const& scan, parser_error<PeerErrors, iter_t>&e )
58  {
59  int length = advance_on_error;
60  // before, this was not necessary !
61  while (advance_on_error != 0) {
62  ++scan;
63  --advance_on_error;
64  }
65  // ok, got as far as possible, _peer contains the furthest we got.
66  //std::cerr<<"Returning accept, advance "<< length <<std::endl;
67  return error_status<>( error_status<>::accept, length );
68  }
69 
70  void PeerParser::done()
71  {
72  //std::cerr<<"Peerparser operating in "<< context->getName()<<std::endl;
73  mlastobject = "this";
74 
75  // if size() > 1, it must be a peer or service
76  // first browse the peers
77  while ( callqueue.size() > 0 && _peer->hasPeer( callqueue.front() ) ) {
78  //std::cerr<< _peer->getName() <<" has peer " << callqueue.front()<<std::endl;
79  _peer = _peer->getPeer( callqueue.front() );
80 
81  if ( _peer->ready() == false ) {
82  throw parse_exception_semantic_error
83  ("Attempt to use TaskContext "+ callqueue.front() +" which is not ready to use." );
84  }
85 
86  callqueue.pop();
87  }
88 
89  // BC: user uses 'states.' or 'programs'.
90  if ( !callqueue.empty() ) {
91  std::string name = callqueue.front();
92  if ( (name == "states" || name == "programs") && _peer->provides()->hasService(name) == 0) {
93  log(Warning) << "'"<<name<<"' peer not found. The use of '"<<name<<"' has been deprecated."<<endlog();
94  log(Warning) << "Modify your script to use the program's or state machine's name directly."<<endlog();
95  callqueue.pop();
96  }
97  }
98 
99  mcurobject = _peer->provides();
100 
101  // all peers done, now traverse services:
102  while ( callqueue.size() > 0 && mcurobject->hasService( callqueue.front() ) ) {
103  //std::cerr<< mcurobject->getName() <<" has object " << callqueue.front()<<std::endl;
104  mcurobject = mcurobject->provides( callqueue.front() );
105  mlastobject = callqueue.front();
106  callqueue.pop();
107  }
108 
109  // last resort: browse the global service if not a single match and items in queue
110  if (mcurobject == context->provides() && callqueue.size() != 0 ) {
111  mcurobject = GlobalService::Instance();
112  while ( callqueue.size() && mcurobject->hasService( callqueue.front() ) ) {
113  mcurobject = mcurobject->provides( callqueue.front() );
114  mlastobject = callqueue.front();
115  callqueue.pop();
116  }
117  }
118 
119  // Something went wrong, a peer or object was not found:
120  if ( mfullpath && callqueue.size() != 0 ) {
121  // print to user the mismatch :
122  string object = callqueue.front();
123  while ( !callqueue.empty() )
124  callqueue.pop();
125  iter_t begin;
126  if ( _peer->provides() == mcurobject )
127  throw_(begin, "From TaskContext '"+context->getName()+"': Task '"+ _peer->getName()+"' has no child Service '"+object+"'." );
128  else
129  throw_(begin, "From TaskContext '"+context->getName()+"': Service '"+ mcurobject->getName()+"' has no child Service '"+object+"'." );
130  }
131  mfoundpath = true;
132  }
133 
135  : commonparser(cp), mcurobject(c->provides()), mlastobject("this"), context(c), _peer(context), mfullpath(fullpath), mfoundpath(false), advance_on_error(0)
136  {
137  BOOST_SPIRIT_DEBUG_RULE( my_guard );
138  BOOST_SPIRIT_DEBUG_RULE( peerpath );
139  BOOST_SPIRIT_DEBUG_RULE( peerlocator );
140  peerpath =
141  ( +(commonparser.notassertingidentifier >> ".")[boost::bind( &PeerParser::seenobjectname, this, _1, _2 ) ] )[boost::bind(&PeerParser::done, this)];
142 
143  // find as far as possible a peer without throwing an exception
144  // outside our interface
145  peerlocator =
146  my_guard( *((commonparser.notassertingidentifier >> ".")[boost::bind( &PeerParser::locatepeer, this, _1, _2 ) ]))
147  [ boost::bind(&PeerParser::handle_no_peer, this, _1, _2) ]
148  ;
149  }
150 
152  {
153  _peer = context;
154  mcurobject = context->provides();
155  mlastobject = "this";
156  advance_on_error = 0;
157  mfoundpath = false;
158  while( !callqueue.empty() )
159  callqueue.pop();
160  }
161 
162  void PeerParser::seenobjectname( iter_t begin, iter_t end )
163  {
164  std::string name( begin, end );
165  name.erase( name.length() -1 ); // compensate for extra "."
166  callqueue.push( name );
167 // std::cerr << "seen " << name <<std::endl;
168  }
169 
170  void PeerParser::locatepeer( iter_t begin, iter_t end )
171  {
172  std::string name( begin, end );
173  name.erase( name.length() -1 ); // compensate for extra "."
174 
175  if ( mcurobject == _peer->provides() && _peer->hasPeer( name ) ) {
176  _peer = _peer->getPeer( name );
177  if ( _peer->ready() == false ) {
179  ("Attempt to use TaskContext "+name+" which is not ready to use." );
180  }
181  mcurobject = _peer->provides();
182  advance_on_error += end.base() - begin.base();
183 
184 // cout << "PP located "<<name <<endl;
185  }
186  else if ( mcurobject->hasService(name) ) {
187  mcurobject = mcurobject->provides(name);
188  advance_on_error += end.base() - begin.base();
189  }
190  // check global service if we're still on the top-level:
191  else if (mcurobject == _peer->provides() && GlobalService::Instance()->hasService(name) ) {
192  mcurobject = GlobalService::Instance()->provides(name);
193  advance_on_error += end.base() - begin.base();
194  mfoundpath = true;
195  } else {
196  if ( name == "states" || name == "programs") {
197  log(Warning) << "'"<<name<<"' peer not found. The use of '"<<name<<"' has been deprecated."<<endlog();
198  log(Warning) << "Modify your script to use the program's or state machine's name directly."<<endlog();
199  advance_on_error += end.base() - begin.base();
200  return;
201  }
202 // cout << "PP failed "<<name <<endl;
203  // store object name for higher level access.
204  // do not consume it though.
205 // cout << std::string(begin, end)<<endl;
206  mlastobject = name;
207  if (mfullpath) {
208  mcurobject.reset(); //when partial paths are OK, leave curobject pointing to last valid object.
209  mfoundpath = false;
210  }
211  throw_(begin, peer_not_found );
212  }
213  }
214 
216  {
217  return peerpath;
218  }
219 
221  {
222  return peerlocator;
223  }
224 
226  {
227  return _peer;
228  }
229 
231  {
232  return mcurobject;
233  }
234 
235  std::string PeerParser::object()
236  {
237  return mlastobject;
238  }
239 
241  {
242  return mfoundpath;
243  }
244 }
245 
PeerParser(TaskContext *c, CommonParser &cp, bool fullpath=false)
Create a PeerParser which starts looking for peers from a task.
Definition: PeerParser.cpp:134
std::string object()
Returns the last matching object name.
Definition: PeerParser.cpp:235
Service::shared_ptr provides()
Returns this Service.
void reset()
After reset, peer() == current context and object() == "this".
Definition: PeerParser.cpp:151
STL namespace.
parse_exception class that is used for various semantic errors for which it was not worth defining a ...
This class contains some very common parser definitions.
TaskContext * peer()
Returns the last matching peer.
Definition: PeerParser.cpp:225
virtual TaskContext * getPeer(const std::string &peer_name) const
Get a pointer to a peer of this task.
rule_t & locator()
The locator tries to go as far as possible in the peer-to-object path and will never throw...
Definition: PeerParser.cpp:220
boost::shared_ptr< Service > shared_ptr
Definition: Service.hpp:101
virtual bool hasPeer(const std::string &peer_name) const
Return true if it knows a peer by that name.
scanner< iter_t, scanner_pol_t > scanner_t
ServicePtr taskObject()
Returns the last matching Service or zero if not found.
Definition: PeerParser.cpp:230
rule< scanner_t > rule_t
The TaskContext is the C++ representation of an Orocos component.
Definition: TaskContext.hpp:93
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
bool foundPath()
Returns true if the PeerParser found a valid path.
Definition: PeerParser.cpp:240
rule_t notassertingidentifier
identifier with <template> marks in it
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:51
our_pos_iter_t iter_t
static RTT_API Service::shared_ptr Instance()
virtual bool ready()
Checks the validity of this TaskContext.