Orocos Real-Time Toolkit
2.6.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 "../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 // prepare parser to parse statements right away: 00072 programparser->initBodyParser("script", storage, 0); 00073 //mpositer.get_position().line); 00074 stateparser->storeOffset(); 00075 } 00076 00077 void ScriptParser::seenstatement() 00078 { 00079 ProgramInterfacePtr ret = programparser->bodyParserResult(); 00080 int steps = 0; 00081 // we execute the result directly. 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 //mpositer.get_position().line); 00104 stateparser->storeOffset(); 00105 } 00106 00107 void ScriptParser::seenprogram() 00108 { 00109 // Load the programs in the Scripting Service of this component: 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 //mpositer.get_position().line); 00128 stateparser->storeOffset(); 00129 } 00130 00131 void ScriptParser::seenfunction() 00132 { 00133 programparser->initBodyParser("script", storage, 0); 00134 //mpositer.get_position().line); 00135 stateparser->storeOffset(); 00136 } 00137 00138 void ScriptParser::seenstatemachine() 00139 { 00140 // Load the statemachines in the Scripting Service of this component: 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 ); // throws load_exception 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 //mpositer.get_position().line); 00157 stateparser->storeOffset(); 00158 } 00159 00160 void ScriptParser::parse(iter_t& begin, iter_t end) 00161 { 00162 //skip_parser_t skip_parser = SKIP_PARSER; 00163 //iter_pol_t iter_policy( skip_parser ); 00164 //#define SKIP_PARSER 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 ); // begin is by reference. 00176 00177 stateparser->storeOffset(); 00178 try 00179 { 00180 if (!production.parse(scanner)) 00181 { 00182 // on error, we clear all remaining data, cause we can't 00183 // guarantee consistency... 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 // on error, we clear all remaining data, cause we can't 00194 // guarantee consistency... 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 // on error, we clear all remaining data, cause we can't 00203 // guarantee consistency... 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 }