Orocos Real-Time Toolkit  2.5.0
Parser.cpp
00001 /***************************************************************************
00002   tag: Peter Soetens  Mon May 10 19:10:37 CEST 2004  Parser.cxx
00003 
00004                         Parser.cxx -  description
00005                            -------------------
00006     begin                : Mon May 10 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 Lesser General Public            *
00013  *   License as published by the Free Software Foundation; either          *
00014  *   version 2.1 of the License, or (at your option) any later version.    *
00015  *                                                                         *
00016  *   This library is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00019  *   Lesser General Public License for more details.                       *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU Lesser General Public      *
00022  *   License along with this library; if not, write to the Free Software   *
00023  *   Foundation, Inc., 59 Temple Place,                                    *
00024  *   Suite 330, Boston, MA  02111-1307  USA                                *
00025  *                                                                         *
00026  ***************************************************************************/
00027 
00028 #include "parser-debug.hpp"
00029 #include "parser-types.hpp"
00030 #include "parse_exception.hpp"
00031 #include "Parser.hpp"
00032 #include "ProgramGraphParser.hpp"
00033 #include "StateGraphParser.hpp"
00034 #include "ConditionParser.hpp"
00035 #include "ExpressionParser.hpp"
00036 #include "ValueChangeParser.hpp"
00037 #include "ProgramService.hpp"
00038 #include "StateMachineService.hpp"
00039 #include "../internal/DataSourceCommand.hpp"
00040 #include "ConditionInterface.hpp"
00041 #include "CommandComposite.hpp"
00042 #include "../internal/GlobalEngine.hpp"
00043 #include "ScriptParser.hpp"
00044 
00045 #include <iostream>
00046 #include <fstream>
00047 
00048 using namespace boost;
00049 
00050 namespace RTT
00051 {
00052   using namespace detail;
00053 
00054   Parser::Parser(TaskContext* c) : mcaller(c ? c->engine() : 0) {
00055 
00056       if (mcaller == 0) {
00057           //log(Warning) << "Parser does not know which TaskContext is executing (calling) the parsed code. Using Global Engine." <<endlog();
00058           mcaller = GlobalEngine::Instance();
00059       } else {
00060           //log(Debug) << "Parsing code as if " << mcaller->getName() << " is executing it."<<endl;
00061       }
00062 
00063   }
00064 
00065   void Parser::runScript(std::string const& code, TaskContext* mowner, ScriptingService* service, std::string const& filename ) {
00066       our_buffer_t script(code + "\n"); // work around mandatory trailing newline/eos for statements.
00067       our_pos_iter_t parsebegin( script.begin(), script.end(), filename );
00068       our_pos_iter_t parseend( script.end(), script.end(), filename );
00069 
00070       // will store all in mowner, functions are loaded in service, caller is the one calling us.
00071       ScriptParser gram( parsebegin, mowner, mcaller );
00072 
00073       try {
00074           gram.parse( parsebegin, parseend );
00075       }
00076       catch( const parse_exception& exc )
00077       {
00078         throw file_parse_exception(
00079           exc.copy(), parsebegin.get_position().file,
00080           parsebegin.get_position().line, parsebegin.get_position().column );
00081       }
00082   }
00083 
00084   Parser::ParsedFunctions Parser::parseFunction( const std::string& text, TaskContext* c, const std::string& filename)
00085   {
00086     our_buffer_t function(text);
00087     our_pos_iter_t parsebegin( function.begin(), function.end(), filename );
00088     our_pos_iter_t parseend( function.end(), function.end(), filename );
00089     // The internal parser.
00090     CommonParser cp;
00091     ProgramGraphParser gram( parsebegin, c, c->engine(), cp );
00092     ParsedFunctions ret = gram.parseFunction( parsebegin, parseend );
00093     return ret;
00094   }
00095 
00096   Parser::ParsedPrograms Parser::parseProgram( const std::string& text, TaskContext* c, const std::string& filename)
00097   {
00098     our_buffer_t program(text);
00099     our_pos_iter_t parsebegin( program.begin(), program.end(), filename );
00100     our_pos_iter_t parseend( program.end(),program.end(),filename );
00101 
00102     // The internal parser.
00103     CommonParser cp;
00104     ProgramGraphParser gram( parsebegin, c, c->engine(), cp );
00105     ParsedPrograms ret = gram.parse( parsebegin, parseend );
00106 
00107     return ret;
00108   }
00109 
00110   Parser::ParsedStateMachines Parser::parseStateMachine( const std::string& text, TaskContext* c, const std::string& filename)
00111   {
00112       // This code is copied from parseProgram()
00113 
00114     our_buffer_t program(text);
00115     our_pos_iter_t parsebegin( program.begin(), program.end(), filename );
00116     our_pos_iter_t parseend( program.end(),program.end(),filename );
00117 
00118     // The internal parser.
00119     CommonParser cp;
00120     StateGraphParser gram( parsebegin, c, c->engine(), &cp );
00121     Parser::ParsedStateMachines ret;
00122     try {
00123       ret = gram.parse( parsebegin, parseend );
00124     }
00125     catch( const parse_exception& exc )
00126     {
00127       throw file_parse_exception(
00128         exc.copy(), parsebegin.get_position().file,
00129         parsebegin.get_position().line, parsebegin.get_position().column );
00130     }
00131     return ret;
00132   }
00133 
00134   ConditionInterface* Parser::parseCondition( const std::string& s,
00135                                               TaskContext* tc )
00136   {
00137     our_buffer_t scopy(s);
00138     our_pos_iter_t parsebegin( scopy.begin(), scopy.end(), "teststring" );
00139     our_pos_iter_t parseend( scopy.end(), scopy.end(), "teststring" );
00140 
00141         CommonParser cp;
00142     ConditionParser parser( tc, mcaller ? mcaller : tc->engine(), cp );
00143     bool skipref=true;
00144     try
00145     {
00146       parse( parsebegin, parseend, parser.parser(), SKIP_PARSER );
00147     }
00148     catch( const parse_exception& )
00149     {
00150       throw;
00151     }
00152     catch( const parser_error<std::string, iter_t>& e )
00153         {
00154             throw parse_exception_syntactic_error( e.descriptor );
00155         }
00156     ConditionInterface* ret = parser.getParseResult();
00157     parser.reset();
00158     if ( ret == 0 )
00159         throw parse_exception_parser_fail("Parser did not find a condition in text.");
00160     return ret;
00161   }
00162 
00163   DataSourceBase::shared_ptr Parser::parseExpression( const std::string& _s,
00164                                            TaskContext* tc )
00165   {
00166     std::string s( _s );
00167 
00168     our_pos_iter_t parsebegin( s.begin(), s.end(), "teststring" );
00169     our_pos_iter_t parseend( s.end(), s.end(), "teststring" );
00170 
00171     CommonParser cp;
00172     ExpressionParser parser( tc, mcaller, cp );
00173     bool skipref=true;
00174     try
00175     {
00176         parse( parsebegin, parseend, parser.parser(), SKIP_PARSER );
00177     }
00178     catch( const parse_exception& )
00179     {
00180         throw;
00181     }
00182     catch( const parser_error<std::string, iter_t>& e )
00183         {
00184             throw parse_exception_syntactic_error( e.descriptor );
00185         }
00186     if ( parser.hasResult() ) {
00187         DataSourceBase::shared_ptr ret = parser.getResult();
00188         parser.dropResult();
00189         return ret;
00190     }
00191     throw parse_exception_parser_fail("Parser did not find a valid expression in text.");
00192   }
00193 
00194   DataSourceBase::shared_ptr Parser::parseValueChange( const std::string& _s,
00195                                                        TaskContext* tc )
00196   {
00197       return parseExpression( _s, tc );
00198   }
00199 
00200   DataSourceBase::shared_ptr Parser::parseValueStatement( const std::string& _s,
00201                                                        TaskContext* tc )
00202   {
00203     std::string s( _s );
00204 
00205     our_pos_iter_t parsebegin( s.begin(), s.end(), "teststring" );
00206     our_pos_iter_t parseend( s.end(), s.end(), "teststring" );
00207 
00208     CommonParser cp;
00209     ValueChangeParser parser( tc, cp, tc->provides(), mcaller ? mcaller : tc->engine() );
00210     bool skipref=true;
00211     try
00212     {
00213         parse( parsebegin, parseend, parser.parser(), SKIP_PARSER );
00214     }
00215     catch( const parse_exception& )
00216     {
00217         throw;
00218     }
00219     catch( const parser_error<std::string, iter_t>& e )
00220         {
00221             // this only happens if input is really wrong.
00222             throw parse_exception_syntactic_error( e.descriptor );
00223         }
00224 
00225     ActionInterface* ac = 0;
00226     std::vector<ActionInterface*> acv = parser.assignCommands();
00227     // and not forget to reset()..
00228     if ( acv.empty() && parser.lastDefinedValue() ) {
00229         return parser.lastDefinedValue()->getDataSource();
00230     }
00231     if ( acv.size() == 1 ) {
00232         if (acv.front() ) { // front will be null if its an alias.
00233             ac = acv.front();
00234             ac->readArguments();
00235             ac->execute();
00236             delete ac;
00237         }
00238         return parser.lastDefinedValue()->getDataSource();
00239     }
00240     else if (acv.size() > 1) {
00241         ac = new CommandComposite(acv);
00242     }
00243 
00244     if ( ac ) {
00245         DataSourceBase::shared_ptr ret = new DataSourceCommand( ac );
00246         //parser.reset(); don't do this, we want to keep it.
00247         return ret;
00248     }
00249     return DataSourceBase::shared_ptr();
00250   }
00251 }