Orocos Real-Time Toolkit  2.6.0
ScriptParser.cpp
00001 #include "parser-debug.hpp"
00002 #include "parse_exception.hpp"
00003 #include "ScriptParser.hpp"
00004 #include "CommonParser.hpp"
00005 #include "StateGraphParser.hpp"
00006 #include "ProgramGraphParser.hpp"
00007 #include "../TaskContext.hpp"
00008 #include "../internal/Exceptions.hpp"
00009 #include "ScriptingService.hpp"
00010 
00011 #include <iostream>
00012 #include <functional>
00013 #include <algorithm>
00014 #include <boost/bind.hpp>
00015 #include <boost/lambda/lambda.hpp>
00016 #include <boost/call_traits.hpp>
00017 #include <iostream>
00018 #include <memory>
00019 #include "../internal/mystd.hpp"
00020 #include "../internal/GlobalEngine.hpp"
00021 #include "ParsedStateMachine.hpp"
00022 
00023 namespace RTT
00024 {
00025     using namespace boost;
00026     using namespace detail;
00027     using boost::bind;
00028 
00029     using namespace std;
00030 
00031     namespace {
00032         boost::spirit::classic::assertion<std::string> expect_eof("Invalid input in file.");
00033         guard<std::string> no_function_guard;
00034 
00035         error_status<> handle_no_function(scanner_t const& scan, parser_error<std::string, iter_t>&e )
00036         {
00037             return error_status<>( error_status<>::fail );
00038         }
00039 
00040     }
00041 
00042     ScriptParser::ScriptParser(iter_t& positer, TaskContext* tc,
00043             ExecutionEngine* tcaller) :
00044             context(tc), caller(tcaller), storage( Service::Create("stack") ),
00045             mpositer(positer), ln_offset(0),
00046             commonparser(new CommonParser),
00047             stateparser(new StateGraphParser(mpositer, context, caller, commonparser)),
00048             programparser(new ProgramGraphParser(mpositer, tc, tcaller, *commonparser))
00049     {
00050         BOOST_SPIRIT_DEBUG_RULE( production );
00051         BOOST_SPIRIT_DEBUG_RULE( statemachine );
00052         BOOST_SPIRIT_DEBUG_RULE( program );
00053         BOOST_SPIRIT_DEBUG_RULE( function );
00054         BOOST_SPIRIT_DEBUG_RULE( statement );
00055 
00056         production
00057                 = *(
00058                         statemachine[bind(&ScriptParser::seenstatemachine, this)]
00059                         | program[bind(&ScriptParser::seenprogram, this)]
00060                         | no_function_guard(function[bind(&ScriptParser::seenfunction, this)])[&handle_no_function]
00061                         | statement[bind(&ScriptParser::seenstatement, this)]
00062                         | commonparser->notassertingeos
00063                         )
00064                         >> expect_eof(end_p);
00065 
00066         statemachine = stateparser->parser();
00067         program = programparser->programParser();
00068         function = programparser->functionParser();
00069         statement = programparser->statementParser();
00070 
00071         // prepare parser to parse statements right away:
00072         programparser->initBodyParser("script", storage, 0);
00073                 //mpositer.get_position().line);
00074         stateparser->storeOffset();
00075     }
00076 
00077     void ScriptParser::seenstatement()
00078     {
00079         ProgramInterfacePtr ret = programparser->bodyParserResult();
00080         int steps = 0;
00081         // we execute the result directly.
00082         ret->loaded( GlobalEngine::Instance() );
00083         ret->start();
00084         while (ret->execute() && ret->isRunning())
00085         {
00086             if (ret->inError())
00087             {
00088                 log(Error)
00089                         << "Script encountered an error during execution of line "
00090                         << ret->getLineNumber() << endlog();
00091             }
00092             ++steps;
00093             if (steps > 10000)
00094             {
00095                 log(Error)
00096                         << "Parser refuses to execute more than 10000 yield statements. Fix your program."
00097                         << endlog();
00098                 break;
00099             }
00100         }
00101         ret->unloaded();
00102         programparser->initBodyParser("script", storage, 0);
00103                 //mpositer.get_position().line);
00104         stateparser->storeOffset();
00105     }
00106 
00107     void ScriptParser::seenprogram()
00108     {
00109         // Load the programs in the Scripting Service of this component:
00110         assert( context->provides()->hasService("scripting"));
00111         ScriptingService::shared_ptr ss = dynamic_pointer_cast<ScriptingService>( context->provides("scripting") );
00112         assert(ss);
00113         ProgramInterfacePtr ret = programparser->programParserResult();
00114         try {
00115             FunctionGraphPtr func = dynamic_pointer_cast<FunctionGraph>(ret);
00116             if (func)
00117                 func->setText(program_text);
00118             log(Info) << "Loading Program '"<< ret->getName() <<"'" <<endlog();
00119             if ( ss->loadProgram( ret ) == false)
00120                 throw program_load_exception( "Could not load Program '"+ ret->getName() +"' :\n failed to load in ScriptingService.\n");
00121         } catch (program_load_exception& e ) {
00122             log(Error) << "Could not load Program '"<< ret->getName() <<"' :" << endlog();
00123             log(Error) << e.what() << endlog();
00124             throw;
00125         }
00126         programparser->initBodyParser("script", storage, 0);
00127                 //mpositer.get_position().line);
00128         stateparser->storeOffset();
00129     }
00130 
00131     void ScriptParser::seenfunction()
00132     {
00133         programparser->initBodyParser("script", storage, 0);
00134                 //mpositer.get_position().line);
00135         stateparser->storeOffset();
00136     }
00137 
00138     void ScriptParser::seenstatemachine()
00139     {
00140         // Load the statemachines in the Scripting Service of this component:
00141         assert( context->provides()->hasService("scripting"));
00142         ScriptingService::shared_ptr ss = dynamic_pointer_cast<ScriptingService>( context->provides("scripting") );
00143         assert(ss);
00144         ParsedStateMachinePtr ret = stateparser->getParserResult();
00145         if (ret) {
00146             try {
00147                 log(Info) << "Loading StateMachine '"<< ret->getName() <<"'" <<endlog();
00148                 ss->loadStateMachine( ret ); // throws load_exception
00149             } catch (program_load_exception& e ) {
00150                 log(Error) << "Could not load StateMachine'"<< ret->getName() <<"' :" << endlog();
00151                 log(Error) << e.what() << endlog();
00152                 throw;
00153             }
00154         }
00155         programparser->initBodyParser("script", storage, 0);
00156                 //mpositer.get_position().line);
00157         stateparser->storeOffset();
00158     }
00159 
00160     void ScriptParser::parse(iter_t& begin, iter_t end)
00161     {
00162         //skip_parser_t skip_parser = SKIP_PARSER;
00163         //iter_pol_t iter_policy( skip_parser );
00164         //#define SKIP_PARSER
00165         skip_parser_t skippers = (comment_p("#") | comment_p("//") 
00166                           | comment_p("/*", "*/") 
00167                           | (space_p - eol_p) 
00168              | (commonparser->skipper));
00169 
00170         iter_pol_t iter_policy(skippers);
00171         scanner_pol_t policies(iter_policy);
00172         scanner_t scanner(begin, end, policies);
00173 
00174         ln_offset = mpositer.get_position().line - 1;
00175         program_text = std::string( begin, end ); // begin is by reference.
00176 
00177         stateparser->storeOffset();
00178         try
00179         {
00180             if (!production.parse(scanner))
00181             {
00182                 // on error, we clear all remaining data, cause we can't
00183                 // guarantee consistency...
00184                 clear();
00185                 throw file_parse_exception(new parse_exception_syntactic_error(
00186                         "Syntax error"), mpositer.get_position().file,
00187                         mpositer.get_position().line,
00188                         mpositer.get_position().column);
00189             }
00190             return;
00191         } catch (const parser_error<std::string, iter_t>& e)
00192         {
00193             // on error, we clear all remaining data, cause we can't
00194             // guarantee consistency...
00195             clear();
00196             throw file_parse_exception(new parse_exception_syntactic_error(
00197                     e.descriptor), mpositer.get_position().file,
00198                     mpositer.get_position().line,
00199                     mpositer.get_position().column);
00200         } catch (const parse_exception& e)
00201         {
00202             // on error, we clear all remaining data, cause we can't
00203             // guarantee consistency...
00204             clear();
00205             throw file_parse_exception(e.copy(), mpositer.get_position().file,
00206                     mpositer.get_position().line,
00207                     mpositer.get_position().column);
00208         } catch (...)
00209         {
00210             assert( false );
00211         }
00212     }
00213 
00214     ScriptParser::~ScriptParser()
00215     {
00216         clear();
00217         delete programparser;
00218         delete stateparser;
00219         delete commonparser;
00220     }
00221 
00222     void ScriptParser::clear()
00223     {
00224 
00225     }
00226 
00227 }