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
00072 programparser->initBodyParser("script", storage, 0);
00073
00074 stateparser->storeOffset();
00075 }
00076
00077 void ScriptParser::seenstatement()
00078 {
00079 ProgramInterfacePtr ret = programparser->bodyParserResult();
00080 int steps = 0;
00081
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
00104 stateparser->storeOffset();
00105 }
00106
00107 void ScriptParser::seenprogram()
00108 {
00109
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
00128 stateparser->storeOffset();
00129 }
00130
00131 void ScriptParser::seenfunction()
00132 {
00133 programparser->initBodyParser("script", storage, 0);
00134
00135 stateparser->storeOffset();
00136 }
00137
00138 void ScriptParser::seenstatemachine()
00139 {
00140
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 );
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
00157 stateparser->storeOffset();
00158 }
00159
00160 void ScriptParser::parse(iter_t& begin, iter_t end)
00161 {
00162
00163
00164
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 );
00176
00177 stateparser->storeOffset();
00178 try
00179 {
00180 if (!production.parse(scanner))
00181 {
00182
00183
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
00194
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
00203
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 }