00001 /*************************************************************************** 00002 tag: Peter Soetens Mon Jun 26 13:25:57 CEST 2006 StatementProcessor.cxx 00003 00004 StatementProcessor.cxx - description 00005 ------------------- 00006 begin : Mon June 26 2006 00007 copyright : (C) 2006 Peter Soetens 00008 email : peter.soetens@fmtc.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 "StatementProcessor.hpp" 00041 #include "Parser.hpp" 00042 #include "parse_exception.hpp" 00043 00044 #include "../TaskContext.hpp" 00045 #include "../types/TypeStream.hpp" 00046 #include "../Logger.hpp" 00047 00048 #include <vector> 00049 #include <boost/tuple/tuple.hpp> 00050 #include <iostream> 00051 00052 00053 using namespace boost; 00054 00055 namespace RTT 00056 { 00057 using namespace detail; 00058 struct StatementProcessor::D 00059 { 00060 public: 00061 TaskContext* tc; 00062 D() {} 00063 00064 void printResult( DataSourceBase* ds, bool recurse) { 00065 std::string prompt(" = "); 00066 // setup prompt : 00067 Logger::log() << Logger::Info <<prompt; 00068 doPrint( ds, recurse ); 00069 Logger::log() << Logger::endl; 00070 } 00071 00072 void doPrint( DataSourceBase* ds, bool recurse) { 00073 // this is needed for ds's that rely on initialision. 00074 // e.g. eval true once or time measurements. 00075 // becomes only really handy for 'watches' (todo). 00076 ds->reset(); 00081 // this method can print some primitive DataSource<>'s. 00082 DataSource<bool>* dsb = DataSource<bool>::narrow(ds); 00083 if (dsb) { 00084 Logger::log() << dsb->get(); 00085 return; 00086 } 00087 DataSource<int>* dsi = DataSource<int>::narrow(ds); 00088 if (dsi) { 00089 Logger::log() << dsi->get() ; 00090 return; 00091 } 00092 #if 0 00093 // does not work yet with CORBA layer. 00094 DataSource<long>* dsl = DataSource<long>::narrow(ds); 00095 if (dsl) { 00096 Logger::log() << dsl->get() ; 00097 return; 00098 } 00099 #endif 00100 DataSource<unsigned int>* dsui = DataSource<unsigned int>::narrow(ds); 00101 if (dsui) { 00102 Logger::log() << dsui->get() ; 00103 return; 00104 } 00105 DataSource<std::string>* dss = DataSource<std::string>::narrow(ds); 00106 if (dss) { 00107 Logger::log() <<'"'<< dss->get() << '"' ; 00108 return; 00109 } 00110 #if 0 00111 DataSource<std::vector<double> >* dsvval = DataSource< std::vector<double> >::narrow(ds); 00112 if (dsvval) { 00113 Logger::log() << dsvval->get() ; 00114 return; 00115 } 00116 DataSource< Double6D >* ds6d = DataSource<Double6D>::narrow(ds); 00117 if (ds6d) { 00118 Logger::log() << ds6d->get() ; 00119 return; 00120 } 00121 #endif 00122 DataSource<double>* dsd = DataSource<double>::narrow(ds); 00123 if (dsd) { 00124 Logger::log() << dsd->get() ; 00125 return; 00126 } 00127 DataSource<char>* dsc = DataSource<char>::narrow(ds); 00128 if (dsc) { 00129 Logger::log() <<'\''<< dsc->get()<<'\'' ; 00130 return; 00131 } 00132 00133 DataSource<PropertyBag>* dspbag = DataSource<PropertyBag>::narrow(ds); 00134 if (dspbag) { 00135 PropertyBag bag( dspbag->get() ); 00136 if (!recurse) { 00137 int siz = bag.getProperties().size(); 00138 Logger::log() << siz <<" Properties"; 00139 } else { 00140 if ( ! bag.empty() ) { 00141 Logger::log() <<Logger::nl; 00142 for( PropertyBag::iterator it= bag.getProperties().begin(); it!=bag.getProperties().end(); ++it) { 00143 Logger::log() <<(*it)->getType()<<" "<< (*it)->getName(); 00144 DataSourceBase::shared_ptr propds = (*it)->getDataSource(); 00145 this->printResult( propds.get(), false ); 00146 Logger::log() <<" ("<<(*it)->getDescription()<<')' << Logger::nl; 00147 } 00148 } else { 00149 Logger::log() <<"(empty PropertyBag)"; 00150 } 00151 } 00152 return; 00153 } 00154 00155 // Leave void as last since any DS is convertible to void ! 00156 DataSource<void>* dsvd = DataSource<void>::narrow(ds); 00157 if (dsvd) { 00158 dsvd->get(); 00159 Logger::log() << "(void)" ; 00160 return; 00161 } 00162 00163 if (ds) { 00164 ds->evaluate(); 00165 Logger::log() << "( result type '"+ds->getType()+"' not known to TaskBrowser )" ; 00166 } 00167 00168 } 00169 00170 }; 00171 00172 00173 StatementProcessor::StatementProcessor(TaskContext* tc) 00174 : d ( new D() ) 00175 { 00176 d->tc = tc; 00177 } 00178 00179 StatementProcessor::~StatementProcessor() { 00180 delete d; 00181 } 00182 00183 int StatementProcessor::execute(const std::string& comm) 00184 { 00185 Logger::In in("StatementProcessor"); 00186 TaskContext* taskcontext = d->tc; 00187 00188 // Minor hack : also check if it was an attribute of current TC, for example, 00189 // if both the object and attribute with that name exist. the if 00190 // statement after this one would return and not give the expr parser 00191 // time to evaluate 'comm'. 00192 if ( taskcontext->provides()->getValue( comm ) ) { 00193 d->printResult( taskcontext->provides()->getValue( comm )->getDataSource().get(), true ); 00194 return 0; 00195 } 00196 00197 Parser _parser; 00198 00199 Logger::log() <<Logger::Debug << "Trying ValueChange..."; 00200 try { 00201 // Check if it was a method or datasource : 00202 DataSourceBase::shared_ptr ds = _parser.parseValueChange( comm, taskcontext ); 00203 // methods and DS'es are processed immediately. 00204 if ( ds.get() != 0 ) { 00205 Logger::log() << "ok" << Logger::endl; 00206 d->printResult( ds.get(), false ); 00207 return 0; // done here 00208 } else 00209 Logger::log() <<Logger::Debug << "no"<<Logger::endl; 00210 } catch ( fatal_semantic_parse_exception& pe ) { // incorr args, ... 00211 // way to fatal, must be reported immediately 00212 Logger::log() << Logger::Debug << "fatal_semantic_parse_exception: "; 00213 Logger::log() << Logger::Error << pe.what() <<Logger::nl; 00214 return -1; 00215 } catch ( syntactic_parse_exception& pe ) { // wrong content after = sign etc.. 00216 // syntactic errors must be reported immediately 00217 Logger::log() << Logger::Error << "syntactic_parse_exception: "; 00218 Logger::log() << Logger::Error << pe.what() <<Logger::nl; 00219 return -1; 00220 } catch ( parse_exception_parser_fail &pe ) 00221 { 00222 // ignore, try next parser 00223 Logger::log() << Logger::Debug << "Ignoring ValueChange exception :"<<Logger::nl; 00224 Logger::log() << Logger::Debug << pe.what() <<Logger::nl; 00225 } catch ( parse_exception& pe ) { 00226 // syntactic errors must be reported immediately 00227 Logger::log() << Logger::Error << "parse_exception :"; 00228 Logger::log() << Logger::Error << pe.what() <<Logger::nl; 00229 return -1; 00230 } 00231 Logger::log() << Logger::Debug << "Trying Expression..."<<Logger::nl; 00232 try { 00233 // Check if it was a method or datasource : 00234 DataSourceBase::shared_ptr ds = _parser.parseExpression( comm, taskcontext ); 00235 // methods and DS'es are processed immediately. 00236 if ( ds.get() != 0 ) { 00237 d->printResult( ds.get(), true ); 00238 return 0; // done here 00239 } else 00240 Logger::log() << Logger::Error << "returned zero !"<<Logger::nl; 00241 } catch ( syntactic_parse_exception& pe ) { // missing brace etc 00242 // syntactic errors must be reported immediately 00243 Logger::log() << Logger::Error << "syntactic_parse_exception :"; 00244 Logger::log() << Logger::Error << pe.what() <<Logger::nl; 00245 return -1; 00246 } catch ( fatal_semantic_parse_exception& pe ) { // incorr args, ... 00247 // way to fatal, must be reported immediately 00248 Logger::log() << Logger::Error << "fatal_semantic_parse_exception :"; 00249 Logger::log() << Logger::Error << pe.what() <<Logger::nl; 00250 return -1; 00251 } catch ( parse_exception_parser_fail &pe ) { 00252 // ignore, try next parser 00253 Logger::log() << Logger::Debug << "Ignoring Expression exception :"<<Logger::nl; 00254 Logger::log() << Logger::Debug << pe.what() <<Logger::nl; 00255 } catch ( parse_exception& pe ) { 00256 // ignore, try next parser 00257 Logger::log() << Logger::Debug << "Ignoring Expression parse_exception :"<<Logger::nl; 00258 Logger::log() << Logger::Debug << pe.what() <<Logger::nl; 00259 } 00260 return -1; 00261 } 00262 00263 } 00264