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
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
00052 stateparser(new StateGraphParser(mpositer, context, context->engine(), commonparser)),
00053 programparser(new ProgramGraphParser(mpositer, context, context->engine(), *commonparser)),
00054
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
00079 programparser->initBodyParser("script", storage, 0);
00080 statementparser->initBodyParser("script", storage, 0);
00081
00082 stateparser->storeOffset();
00083 }
00084
00085 void ScriptParser::seenstatement()
00086 {
00087 ProgramInterfacePtr ret = statementparser->bodyParserResult();
00088 int steps = 0;
00089
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
00112 stateparser->storeOffset();
00113 }
00114
00115 void ScriptParser::seenprogram()
00116 {
00117
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
00136 stateparser->storeOffset();
00137 }
00138
00139 void ScriptParser::seenfunction()
00140 {
00141 programparser->initBodyParser("script", storage, 0);
00142
00143 stateparser->storeOffset();
00144 }
00145
00146 void ScriptParser::seenstatemachine()
00147 {
00148
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 );
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
00165 stateparser->storeOffset();
00166 }
00167
00168 void ScriptParser::parse(iter_t& begin, iter_t end)
00169 {
00170
00171
00172
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 );
00184
00185 stateparser->storeOffset();
00186 try
00187 {
00188 if (!production.parse(scanner))
00189 {
00190
00191
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
00202
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
00211
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 }