Orocos Real-Time Toolkit
2.5.0
|
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 }