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