Orocos Real-Time Toolkit
2.5.0
|
00001 /*************************************************************************** 00002 tag: Peter Soetens Mon May 10 19:10:37 CEST 2004 Parser.cxx 00003 00004 Parser.cxx - description 00005 ------------------- 00006 begin : Mon May 10 2004 00007 copyright : (C) 2004 Peter Soetens 00008 email : peter.soetens@mech.kuleuven.ac.be 00009 00010 *************************************************************************** 00011 * This library is free software; you can redistribute it and/or * 00012 * modify it under the terms of the GNU Lesser General Public * 00013 * License as published by the Free Software Foundation; either * 00014 * version 2.1 of the License, or (at your option) any later version. * 00015 * * 00016 * This library is distributed in the hope that it will be useful, * 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00019 * Lesser General Public License for more details. * 00020 * * 00021 * You should have received a copy of the GNU Lesser General Public * 00022 * License along with this library; if not, write to the Free Software * 00023 * Foundation, Inc., 59 Temple Place, * 00024 * Suite 330, Boston, MA 02111-1307 USA * 00025 * * 00026 ***************************************************************************/ 00027 00028 #include "parser-debug.hpp" 00029 #include "parser-types.hpp" 00030 #include "parse_exception.hpp" 00031 #include "Parser.hpp" 00032 #include "ProgramGraphParser.hpp" 00033 #include "StateGraphParser.hpp" 00034 #include "ConditionParser.hpp" 00035 #include "ExpressionParser.hpp" 00036 #include "ValueChangeParser.hpp" 00037 #include "ProgramService.hpp" 00038 #include "StateMachineService.hpp" 00039 #include "../internal/DataSourceCommand.hpp" 00040 #include "ConditionInterface.hpp" 00041 #include "CommandComposite.hpp" 00042 #include "../internal/GlobalEngine.hpp" 00043 #include "ScriptParser.hpp" 00044 00045 #include <iostream> 00046 #include <fstream> 00047 00048 using namespace boost; 00049 00050 namespace RTT 00051 { 00052 using namespace detail; 00053 00054 Parser::Parser(TaskContext* c) : mcaller(c ? c->engine() : 0) { 00055 00056 if (mcaller == 0) { 00057 //log(Warning) << "Parser does not know which TaskContext is executing (calling) the parsed code. Using Global Engine." <<endlog(); 00058 mcaller = GlobalEngine::Instance(); 00059 } else { 00060 //log(Debug) << "Parsing code as if " << mcaller->getName() << " is executing it."<<endl; 00061 } 00062 00063 } 00064 00065 void Parser::runScript(std::string const& code, TaskContext* mowner, ScriptingService* service, std::string const& filename ) { 00066 our_buffer_t script(code + "\n"); // work around mandatory trailing newline/eos for statements. 00067 our_pos_iter_t parsebegin( script.begin(), script.end(), filename ); 00068 our_pos_iter_t parseend( script.end(), script.end(), filename ); 00069 00070 // will store all in mowner, functions are loaded in service, caller is the one calling us. 00071 ScriptParser gram( parsebegin, mowner, mcaller ); 00072 00073 try { 00074 gram.parse( parsebegin, parseend ); 00075 } 00076 catch( const parse_exception& exc ) 00077 { 00078 throw file_parse_exception( 00079 exc.copy(), parsebegin.get_position().file, 00080 parsebegin.get_position().line, parsebegin.get_position().column ); 00081 } 00082 } 00083 00084 Parser::ParsedFunctions Parser::parseFunction( const std::string& text, TaskContext* c, const std::string& filename) 00085 { 00086 our_buffer_t function(text); 00087 our_pos_iter_t parsebegin( function.begin(), function.end(), filename ); 00088 our_pos_iter_t parseend( function.end(), function.end(), filename ); 00089 // The internal parser. 00090 CommonParser cp; 00091 ProgramGraphParser gram( parsebegin, c, c->engine(), cp ); 00092 ParsedFunctions ret = gram.parseFunction( parsebegin, parseend ); 00093 return ret; 00094 } 00095 00096 Parser::ParsedPrograms Parser::parseProgram( const std::string& text, TaskContext* c, const std::string& filename) 00097 { 00098 our_buffer_t program(text); 00099 our_pos_iter_t parsebegin( program.begin(), program.end(), filename ); 00100 our_pos_iter_t parseend( program.end(),program.end(),filename ); 00101 00102 // The internal parser. 00103 CommonParser cp; 00104 ProgramGraphParser gram( parsebegin, c, c->engine(), cp ); 00105 ParsedPrograms ret = gram.parse( parsebegin, parseend ); 00106 00107 return ret; 00108 } 00109 00110 Parser::ParsedStateMachines Parser::parseStateMachine( const std::string& text, TaskContext* c, const std::string& filename) 00111 { 00112 // This code is copied from parseProgram() 00113 00114 our_buffer_t program(text); 00115 our_pos_iter_t parsebegin( program.begin(), program.end(), filename ); 00116 our_pos_iter_t parseend( program.end(),program.end(),filename ); 00117 00118 // The internal parser. 00119 CommonParser cp; 00120 StateGraphParser gram( parsebegin, c, c->engine(), &cp ); 00121 Parser::ParsedStateMachines ret; 00122 try { 00123 ret = gram.parse( parsebegin, parseend ); 00124 } 00125 catch( const parse_exception& exc ) 00126 { 00127 throw file_parse_exception( 00128 exc.copy(), parsebegin.get_position().file, 00129 parsebegin.get_position().line, parsebegin.get_position().column ); 00130 } 00131 return ret; 00132 } 00133 00134 ConditionInterface* Parser::parseCondition( const std::string& s, 00135 TaskContext* tc ) 00136 { 00137 our_buffer_t scopy(s); 00138 our_pos_iter_t parsebegin( scopy.begin(), scopy.end(), "teststring" ); 00139 our_pos_iter_t parseend( scopy.end(), scopy.end(), "teststring" ); 00140 00141 CommonParser cp; 00142 ConditionParser parser( tc, mcaller ? mcaller : tc->engine(), cp ); 00143 bool skipref=true; 00144 try 00145 { 00146 parse( parsebegin, parseend, parser.parser(), SKIP_PARSER ); 00147 } 00148 catch( const parse_exception& ) 00149 { 00150 throw; 00151 } 00152 catch( const parser_error<std::string, iter_t>& e ) 00153 { 00154 throw parse_exception_syntactic_error( e.descriptor ); 00155 } 00156 ConditionInterface* ret = parser.getParseResult(); 00157 parser.reset(); 00158 if ( ret == 0 ) 00159 throw parse_exception_parser_fail("Parser did not find a condition in text."); 00160 return ret; 00161 } 00162 00163 DataSourceBase::shared_ptr Parser::parseExpression( const std::string& _s, 00164 TaskContext* tc ) 00165 { 00166 std::string s( _s ); 00167 00168 our_pos_iter_t parsebegin( s.begin(), s.end(), "teststring" ); 00169 our_pos_iter_t parseend( s.end(), s.end(), "teststring" ); 00170 00171 CommonParser cp; 00172 ExpressionParser parser( tc, mcaller, cp ); 00173 bool skipref=true; 00174 try 00175 { 00176 parse( parsebegin, parseend, parser.parser(), SKIP_PARSER ); 00177 } 00178 catch( const parse_exception& ) 00179 { 00180 throw; 00181 } 00182 catch( const parser_error<std::string, iter_t>& e ) 00183 { 00184 throw parse_exception_syntactic_error( e.descriptor ); 00185 } 00186 if ( parser.hasResult() ) { 00187 DataSourceBase::shared_ptr ret = parser.getResult(); 00188 parser.dropResult(); 00189 return ret; 00190 } 00191 throw parse_exception_parser_fail("Parser did not find a valid expression in text."); 00192 } 00193 00194 DataSourceBase::shared_ptr Parser::parseValueChange( const std::string& _s, 00195 TaskContext* tc ) 00196 { 00197 return parseExpression( _s, tc ); 00198 } 00199 00200 DataSourceBase::shared_ptr Parser::parseValueStatement( const std::string& _s, 00201 TaskContext* tc ) 00202 { 00203 std::string s( _s ); 00204 00205 our_pos_iter_t parsebegin( s.begin(), s.end(), "teststring" ); 00206 our_pos_iter_t parseend( s.end(), s.end(), "teststring" ); 00207 00208 CommonParser cp; 00209 ValueChangeParser parser( tc, cp, tc->provides(), mcaller ? mcaller : tc->engine() ); 00210 bool skipref=true; 00211 try 00212 { 00213 parse( parsebegin, parseend, parser.parser(), SKIP_PARSER ); 00214 } 00215 catch( const parse_exception& ) 00216 { 00217 throw; 00218 } 00219 catch( const parser_error<std::string, iter_t>& e ) 00220 { 00221 // this only happens if input is really wrong. 00222 throw parse_exception_syntactic_error( e.descriptor ); 00223 } 00224 00225 ActionInterface* ac = 0; 00226 std::vector<ActionInterface*> acv = parser.assignCommands(); 00227 // and not forget to reset().. 00228 if ( acv.empty() && parser.lastDefinedValue() ) { 00229 return parser.lastDefinedValue()->getDataSource(); 00230 } 00231 if ( acv.size() == 1 ) { 00232 if (acv.front() ) { // front will be null if its an alias. 00233 ac = acv.front(); 00234 ac->readArguments(); 00235 ac->execute(); 00236 delete ac; 00237 } 00238 return parser.lastDefinedValue()->getDataSource(); 00239 } 00240 else if (acv.size() > 1) { 00241 ac = new CommandComposite(acv); 00242 } 00243 00244 if ( ac ) { 00245 DataSourceBase::shared_ptr ret = new DataSourceCommand( ac ); 00246 //parser.reset(); don't do this, we want to keep it. 00247 return ret; 00248 } 00249 return DataSourceBase::shared_ptr(); 00250 } 00251 }