Orocos Real-Time Toolkit
2.5.0
|
00001 /*************************************************************************** 00002 tag: Peter Soetens Tue Dec 21 22:43:07 CET 2004 PeerParser.cxx 00003 00004 PeerParser.cxx - description 00005 ------------------- 00006 begin : Tue December 21 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 General Public * 00013 * License as published by the Free Software Foundation; * 00014 * version 2 of the License. * 00015 * * 00016 * As a special exception, you may use this file as part of a free * 00017 * software library without restriction. Specifically, if other files * 00018 * instantiate templates or use macros or inline functions from this * 00019 * file, or you compile this file and link it with other files to * 00020 * produce an executable, this file does not by itself cause the * 00021 * resulting executable to be covered by the GNU General Public * 00022 * License. This exception does not however invalidate any other * 00023 * reasons why the executable file might be covered by the GNU General * 00024 * Public License. * 00025 * * 00026 * This library is distributed in the hope that it will be useful, * 00027 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00028 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00029 * Lesser General Public License for more details. * 00030 * * 00031 * You should have received a copy of the GNU General Public * 00032 * License along with this library; if not, write to the Free Software * 00033 * Foundation, Inc., 59 Temple Place, * 00034 * Suite 330, Boston, MA 02111-1307 USA * 00035 * * 00036 ***************************************************************************/ 00037 00038 00039 00040 #include "PeerParser.hpp" 00041 #include "parser-debug.hpp" 00042 #include "parse_exception.hpp" 00043 #include "../TaskContext.hpp" 00044 #include "parser-types.hpp" 00045 #include "../internal/GlobalService.hpp" 00046 00047 #include <boost/bind.hpp> 00048 #include <boost/iterator/iterator_traits.hpp> 00049 00050 namespace RTT 00051 { 00052 using boost::bind; 00053 using namespace detail; 00054 using namespace std; 00055 using namespace boost; 00056 00057 error_status<> PeerParser::handle_no_peer(scanner_t const& scan, parser_error<PeerErrors, iter_t>&e ) 00058 { 00059 int length = advance_on_error; 00060 // before, this was not necessary ! 00061 while (advance_on_error != 0) { 00062 ++scan; 00063 --advance_on_error; 00064 } 00065 // ok, got as far as possible, _peer contains the furthest we got. 00066 //std::cerr<<"Returning accept, advance "<< length <<std::endl; 00067 return error_status<>( error_status<>::accept, length ); 00068 } 00069 00070 void PeerParser::done() 00071 { 00072 //std::cerr<<"Peerparser operating in "<< context->getName()<<std::endl; 00073 mlastobject = "this"; 00074 00075 // if size() > 1, it must be a peer or service 00076 // first browse the peers 00077 while ( callqueue.size() > 0 && _peer->hasPeer( callqueue.front() ) ) { 00078 //std::cerr<< _peer->getName() <<" has peer " << callqueue.front()<<std::endl; 00079 _peer = _peer->getPeer( callqueue.front() ); 00080 00081 if ( _peer->ready() == false ) { 00082 throw parse_exception_semantic_error 00083 ("Attempt to use TaskContext "+ callqueue.front() +" which is not ready to use." ); 00084 } 00085 00086 callqueue.pop(); 00087 } 00088 00089 // BC: user uses 'states.' or 'programs'. 00090 if ( !callqueue.empty() ) { 00091 std::string name = callqueue.front(); 00092 if ( (name == "states" || name == "programs") && _peer->provides()->hasService(name) == 0) { 00093 log(Warning) << "'"<<name<<"' peer not found. The use of '"<<name<<"' has been deprecated."<<endlog(); 00094 log(Warning) << "Modify your script to use the program's or state machine's name directly."<<endlog(); 00095 callqueue.pop(); 00096 } 00097 } 00098 00099 mcurobject = _peer->provides(); 00100 00101 // all peers done, now traverse services: 00102 while ( callqueue.size() > 0 && mcurobject->hasService( callqueue.front() ) ) { 00103 //std::cerr<< mcurobject->getName() <<" has object " << callqueue.front()<<std::endl; 00104 mcurobject = mcurobject->provides( callqueue.front() ); 00105 mlastobject = callqueue.front(); 00106 callqueue.pop(); 00107 } 00108 00109 // last resort: browse the global service if not a single match and items in queue 00110 if (mcurobject == context->provides() && callqueue.size() != 0 ) { 00111 mcurobject = GlobalService::Instance(); 00112 while ( callqueue.size() && mcurobject->hasService( callqueue.front() ) ) { 00113 mcurobject = mcurobject->provides( callqueue.front() ); 00114 mlastobject = callqueue.front(); 00115 callqueue.pop(); 00116 } 00117 } 00118 00119 // Something went wrong, a peer or object was not found: 00120 if ( mfullpath && callqueue.size() != 0 ) { 00121 // print to user the mismatch : 00122 string object = callqueue.front(); 00123 while ( !callqueue.empty() ) 00124 callqueue.pop(); 00125 iter_t begin; 00126 if ( _peer->provides() == mcurobject ) 00127 throw_(begin, "From TaskContext '"+context->getName()+"': Task '"+ _peer->getName()+"' has no child Service '"+object+"'." ); 00128 else 00129 throw_(begin, "From TaskContext '"+context->getName()+"': Service '"+ mcurobject->getName()+"' has no child Service '"+object+"'." ); 00130 } 00131 00132 } 00133 00134 PeerParser::PeerParser(TaskContext* c, CommonParser& cp, bool fullpath) 00135 : commonparser(cp), mcurobject(c->provides()), mlastobject("this"), context(c), _peer(context), mfullpath(fullpath), advance_on_error(0) 00136 { 00137 BOOST_SPIRIT_DEBUG_RULE( my_guard ); 00138 BOOST_SPIRIT_DEBUG_RULE( peerpath ); 00139 BOOST_SPIRIT_DEBUG_RULE( peerlocator ); 00140 peerpath = 00141 ( +(commonparser.notassertingidentifier >> ".")[boost::bind( &PeerParser::seenobjectname, this, _1, _2 ) ] )[boost::bind(&PeerParser::done, this)]; 00142 00143 // find as far as possible a peer without throwing an exception 00144 // outside our interface 00145 peerlocator = 00146 my_guard( *((commonparser.notassertingidentifier >> ".")[boost::bind( &PeerParser::locatepeer, this, _1, _2 ) ])) 00147 [ boost::bind(&PeerParser::handle_no_peer, this, _1, _2) ] 00148 ; 00149 } 00150 00151 void PeerParser::reset() 00152 { 00153 _peer = context; 00154 mcurobject = context->provides(); 00155 mlastobject = "this"; 00156 advance_on_error = 0; 00157 while( !callqueue.empty() ) 00158 callqueue.pop(); 00159 } 00160 00161 void PeerParser::seenobjectname( iter_t begin, iter_t end ) 00162 { 00163 std::string name( begin, end ); 00164 name.erase( name.length() -1 ); // compensate for extra "." 00165 callqueue.push( name ); 00166 // std::cerr << "seen " << name <<std::endl; 00167 } 00168 00169 void PeerParser::locatepeer( iter_t begin, iter_t end ) 00170 { 00171 std::string name( begin, end ); 00172 name.erase( name.length() -1 ); // compensate for extra "." 00173 00174 if ( mcurobject == _peer->provides() && _peer->hasPeer( name ) ) { 00175 _peer = _peer->getPeer( name ); 00176 if ( _peer->ready() == false ) { 00177 throw parse_exception_semantic_error 00178 ("Attempt to use TaskContext "+name+" which is not ready to use." ); 00179 } 00180 mcurobject = _peer->provides(); 00181 advance_on_error += end.base() - begin.base(); 00182 00183 // cout << "PP located "<<name <<endl; 00184 } 00185 else if ( mcurobject->hasService(name) ) { 00186 mcurobject = mcurobject->provides(name); 00187 advance_on_error += end.base() - begin.base(); 00188 } 00189 // check global service if we're still on the top-level: 00190 else if (mcurobject == _peer->provides() && GlobalService::Instance()->hasService(name) ) { 00191 mcurobject = GlobalService::Instance()->provides(name); 00192 advance_on_error += end.base() - begin.base(); 00193 } else { 00194 if ( name == "states" || name == "programs") { 00195 log(Warning) << "'"<<name<<"' peer not found. The use of '"<<name<<"' has been deprecated."<<endlog(); 00196 log(Warning) << "Modify your script to use the program's or state machine's name directly."<<endlog(); 00197 advance_on_error += end.base() - begin.base(); 00198 return; 00199 } 00200 // cout << "PP failed "<<name <<endl; 00201 // store object name for higher level access. 00202 // do not consume it though. 00203 // cout << std::string(begin, end)<<endl; 00204 mlastobject = name; 00205 if (mfullpath) 00206 mcurobject.reset(); //when partial paths are OK, leave curobject pointing to last valid object. 00207 throw_(begin, peer_not_found ); 00208 } 00209 } 00210 00211 rule_t& PeerParser::parser() 00212 { 00213 return peerpath; 00214 } 00215 00216 rule_t& PeerParser::locator() 00217 { 00218 return peerlocator; 00219 } 00220 00221 TaskContext* PeerParser::peer() 00222 { 00223 return _peer; 00224 } 00225 00226 Service::shared_ptr PeerParser::taskObject() 00227 { 00228 return mcurobject; 00229 } 00230 00231 std::string PeerParser::object() 00232 { 00233 return mlastobject; 00234 } 00235 00236 } 00237