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
00071 programparser->initBodyParser("script", storage, 0);
00072
00073 stateparser->storeOffset();
00074 }
00075
00076 void ScriptParser::seenstatement()
00077 {
00078 ProgramInterfacePtr ret = programparser->bodyParserResult();
00079 int steps = 0;
00080
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
00103 stateparser->storeOffset();
00104 }
00105
00106 void ScriptParser::seenprogram()
00107 {
00108
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
00127 stateparser->storeOffset();
00128 }
00129
00130 void ScriptParser::seenfunction()
00131 {
00132 programparser->initBodyParser("script", storage, 0);
00133
00134 stateparser->storeOffset();
00135 }
00136
00137 void ScriptParser::seenstatemachine()
00138 {
00139
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 );
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
00156 stateparser->storeOffset();
00157 }
00158
00159 void ScriptParser::parse(iter_t& begin, iter_t end)
00160 {
00161
00162
00163
00164 iter_pol_t iter_policy((comment_p("#") | comment_p("//") | comment_p(
00165 "/*", "*/") | (space_p - eol_p) | commonparser->skipper));
00166 scanner_pol_t policies(iter_policy);
00167 scanner_t scanner(begin, end, policies);
00168
00169 ln_offset = mpositer.get_position().line - 1;
00170 program_text = std::string( begin, end );
00171
00172 stateparser->storeOffset();
00173 try
00174 {
00175 if (!production.parse(scanner))
00176 {
00177
00178
00179 clear();
00180 throw file_parse_exception(new parse_exception_syntactic_error(
00181 "Syntax error"), mpositer.get_position().file,
00182 mpositer.get_position().line,
00183 mpositer.get_position().column);
00184 }
00185 return;
00186 } catch (const parser_error<std::string, iter_t>& e)
00187 {
00188
00189
00190 clear();
00191 throw file_parse_exception(new parse_exception_syntactic_error(
00192 e.descriptor), mpositer.get_position().file,
00193 mpositer.get_position().line,
00194 mpositer.get_position().column);
00195 } catch (const parse_exception& e)
00196 {
00197
00198
00199 clear();
00200 throw file_parse_exception(e.copy(), mpositer.get_position().file,
00201 mpositer.get_position().line,
00202 mpositer.get_position().column);
00203 } catch (...)
00204 {
00205 assert( false );
00206 }
00207 }
00208
00209 ScriptParser::~ScriptParser()
00210 {
00211 clear();
00212 delete programparser;
00213 delete stateparser;
00214 delete commonparser;
00215 }
00216
00217 void ScriptParser::clear()
00218 {
00219
00220 }
00221
00222 }