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


rtt
Author(s): RTT Developers
autogenerated on Fri Sep 9 2016 04:01:58