ScriptParser.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Fri Oct 22 20:28:53 2010 +0200 ScriptParser.cpp
3 
4  ScriptParser.cpp - description
5  -------------------
6  begin : Fri Oct 22 2010
7  copyright : (C) 2010 Peter Soetens
8  email : peter@thesourceworks.com
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 
39 #include "parser-debug.hpp"
40 #include "parse_exception.hpp"
41 #include "ScriptParser.hpp"
42 #include "CommonParser.hpp"
43 #include "StateGraphParser.hpp"
44 #include "ProgramGraphParser.hpp"
45 #include "../TaskContext.hpp"
46 #include "../internal/Exceptions.hpp"
47 #include "ScriptingService.hpp"
48 
49 #include <iostream>
50 #include <functional>
51 #include <algorithm>
52 #include <boost/bind.hpp>
53 #include <boost/lambda/lambda.hpp>
54 #include <boost/call_traits.hpp>
55 #include <iostream>
56 #include <memory>
57 #include "../internal/mystd.hpp"
58 #include "../internal/GlobalEngine.hpp"
59 #include "ParsedStateMachine.hpp"
60 
61 namespace RTT
62 {
63  using namespace boost;
64  using namespace detail;
65  using boost::bind;
66 
67  using namespace std;
68 
69  namespace {
70  boost::spirit::classic::assertion<std::string> expect_eof("Invalid input in file.");
71  guard<std::string> no_function_guard;
72 
73  }
74 
75  error_status<> ScriptParser::handle_no_function(scanner_t const& scan, parser_error<std::string, iter_t>&e )
76  {
77  // only fail if the parser could not make sense of it, otherwise, rethrow:
78  if ( programparser->parserUsed() == false )
79  return error_status<>( error_status<>::fail );
80  else
81  return error_status<>( error_status<>::rethrow );
82  }
83 
85  ExecutionEngine* tcaller) :
86  context(tc), caller(tcaller), storage( Service::Create("stack") ),
87  mpositer(positer), ln_offset(0),
88  commonparser(new CommonParser),
89  // Both state and programs are executed (called) in the target context (see seenprogram, seenstatemachine):
90  stateparser(new StateGraphParser(mpositer, context, context->engine(), commonparser)),
91  programparser(new ProgramGraphParser(mpositer, context, context->engine(), *commonparser)),
92  // statements are directly executed:
93  statementparser(new ProgramGraphParser(mpositer, context, caller, *commonparser))
94  {
95  BOOST_SPIRIT_DEBUG_RULE( production );
96  BOOST_SPIRIT_DEBUG_RULE( statemachine );
97  BOOST_SPIRIT_DEBUG_RULE( program );
98  BOOST_SPIRIT_DEBUG_RULE( function );
99  BOOST_SPIRIT_DEBUG_RULE( statement );
100 
101  production
102  = *(
104  | program[bind(&ScriptParser::seenprogram, this)]
105  | no_function_guard(function[bind(&ScriptParser::seenfunction, this)])[boost::bind(&ScriptParser::handle_no_function,this,_1,_2)]
106  | statement[bind(&ScriptParser::seenstatement, this)]
108  )
109  >> expect_eof(end_p);
110 
113  function = programparser->functionParser();
115 
116  // prepare parser to parse statements right away:
117  programparser->initBodyParser("script", storage, 0);
118  statementparser->initBodyParser("script", storage, 0);
119  //mpositer.get_position().line);
121  }
122 
124  {
126  int steps = 0;
127  // we execute the result directly.
128  ret->loaded( GlobalEngine::Instance() );
129  ret->start();
130  while (ret->execute() && ret->isRunning())
131  {
132  if (ret->inError())
133  {
134  log(Error)
135  << "Script encountered an error during execution of line "
136  << ret->getLineNumber() << endlog();
137  }
138  ++steps;
139  if (steps > 10000)
140  {
141  log(Error)
142  << "Parser refuses to execute more than 10000 yield statements. Fix your program."
143  << endlog();
144  break;
145  }
146  }
147  ret->unloaded();
148  statementparser->initBodyParser("script", storage, 0);
149  //mpositer.get_position().line);
151  }
152 
154  {
155  // Load the programs in the Scripting Service of this component:
156  assert( context->provides()->hasService("scripting"));
157  ScriptingService::shared_ptr ss = dynamic_pointer_cast<ScriptingService>( context->provides("scripting") );
158  assert(ss);
160  try {
161  FunctionGraphPtr func = dynamic_pointer_cast<FunctionGraph>(ret);
162  if (func)
163  func->setText(program_text);
164  log(Info) << "Loading Program '"<< ret->getName() <<"'" <<endlog();
165  if ( ss->loadProgram( ret ) == false)
166  throw program_load_exception( "Could not load Program '"+ ret->getName() +"' :\n failed to load in ScriptingService.\n");
167  } catch (program_load_exception& e ) {
168  log(Error) << "Could not load Program '"<< ret->getName() <<"' :" << endlog();
169  log(Error) << e.what() << endlog();
170  throw;
171  }
172  programparser->initBodyParser("script", storage, 0);
173  //mpositer.get_position().line);
175  }
176 
178  {
179  programparser->initBodyParser("script", storage, 0);
180  //mpositer.get_position().line);
182  }
183 
185  {
186  // Load the statemachines in the Scripting Service of this component:
187  assert( context->provides()->hasService("scripting"));
188  ScriptingService::shared_ptr ss = dynamic_pointer_cast<ScriptingService>( context->provides("scripting") );
189  assert(ss);
191  if (ret) {
192  try {
193  log(Info) << "Loading StateMachine '"<< ret->getName() <<"'" <<endlog();
194  ss->loadStateMachine( ret ); // throws load_exception
195  } catch (program_load_exception& e ) {
196  log(Error) << "Could not load StateMachine'"<< ret->getName() <<"' :" << endlog();
197  log(Error) << e.what() << endlog();
198  throw;
199  }
200  }
201  programparser->initBodyParser("script", storage, 0);
202  //mpositer.get_position().line);
204  }
205 
207  {
208  //skip_parser_t skip_parser = SKIP_PARSER;
209  //iter_pol_t iter_policy( skip_parser );
210  //#define SKIP_PARSER
211  skip_parser_t skippers = (comment_p("#") | comment_p("//")
212  | comment_p("/*", "*/")
213  | (space_p - eol_p)
214  | (commonparser->skipper));
215 
216  iter_pol_t iter_policy(skippers);
217  scanner_pol_t policies(iter_policy);
218  scanner_t scanner(begin, end, policies);
219 
220  ln_offset = mpositer.get_position().line - 1;
221  program_text = std::string( begin, end ); // begin is by reference.
222 
224  try
225  {
226  if (!production.parse(scanner))
227  {
228  // on error, we clear all remaining data, cause we can't
229  // guarantee consistency...
230  clear();
232  "Syntax error"), mpositer.get_position().file,
233  mpositer.get_position().line,
234  mpositer.get_position().column);
235  }
236  return;
237  } catch (const parser_error<std::string, iter_t>& e)
238  {
239  // on error, we clear all remaining data, cause we can't
240  // guarantee consistency...
241  clear();
243  e.descriptor), mpositer.get_position().file,
244  mpositer.get_position().line,
245  mpositer.get_position().column);
246  } catch (const parse_exception& e)
247  {
248  // on error, we clear all remaining data, cause we can't
249  // guarantee consistency...
250  clear();
251  throw file_parse_exception(e.copy(), mpositer.get_position().file,
252  mpositer.get_position().line,
253  mpositer.get_position().column);
254  } catch (...)
255  {
256  assert( false );
257  }
258  }
259 
261  {
262  clear();
263  delete statementparser;
264  delete programparser;
265  delete stateparser;
266  delete commonparser;
267  }
268 
270  {
271 
272  }
273 
274 }
boost::shared_ptr< ScriptingService > shared_ptr
boost::shared_ptr< ParsedStateMachine > ParsedStateMachinePtr
boost::shared_ptr< FunctionGraph > FunctionGraphPtr
Service::shared_ptr provides()
void parse(iter_t &begin, iter_t end)
Definition: mystd.hpp:163
Service::shared_ptr storage
A Parser for Orocos Program Scripts.
boost::shared_ptr< ProgramInterface > ProgramInterfacePtr
virtual parse_exception * copy() const =0
void initBodyParser(const std::string &name, Service::shared_ptr stck, int offset)
This class contains some very common parser definitions.
ScriptParser(iter_t &positer, TaskContext *tc, ExecutionEngine *caller)
scanner< iter_t, scanner_pol_t > scanner_t
StateGraphParser * stateparser
ParsedStateMachinePtr getParserResult()
skip_parser_iteration_policy< skip_parser_t > iter_pol_t
static RTT_API ExecutionEngine * Instance()
functor_parser< eol_skip_functor > skipper
ProgramGraphParser * programparser
boost_spirit::alternative< boost_spirit::alternative< boost_spirit::alternative< boost_spirit::alternative< boost_spirit::confix_parser< boost_spirit::impl::string_as_parser::type, boost_spirit::kleene_star< boost_spirit::anychar_parser >, boost_spirit::alternative< boost_spirit::eol_parser, boost_spirit::end_parser >, boost_spirit::unary_parser_category, boost_spirit::non_nested, boost_spirit::is_lexeme >, boost_spirit::confix_parser< boost_spirit::impl::string_as_parser::type, boost_spirit::kleene_star< boost_spirit::anychar_parser >, boost_spirit::alternative< boost_spirit::eol_parser, boost_spirit::end_parser >, boost_spirit::unary_parser_category, boost_spirit::non_nested, boost_spirit::is_lexeme > >, boost_spirit::confix_parser< boost_spirit::impl::string_as_parser::type, boost_spirit::kleene_star< boost_spirit::anychar_parser >, boost_spirit::impl::string_as_parser::type, boost_spirit::unary_parser_category, boost_spirit::non_nested, boost_spirit::is_lexeme > >, boost_spirit::difference< boost_spirit::space_parser, boost_spirit::eol_parser > >, boost_spirit::functor_parser< eol_skip_functor > > skip_parser_t
error_status handle_no_function(scanner_t const &scan, parser_error< std::string, iter_t > &e)
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:53
our_pos_iter_t iter_t
ProgramGraphParser * statementparser
static Logger & log()
Definition: Logger.hpp:350
scanner_policies< iter_pol_t > scanner_pol_t
static Logger::LogFunction endlog()
Definition: Logger.hpp:362
void setText(const std::string &t)


rtt
Author(s): RTT Developers
autogenerated on Fri Oct 25 2019 03:59:35