Orocos Real-Time Toolkit  2.5.0
StatementProcessor.cpp
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