Orocos Real-Time Toolkit  2.9.0
Parser.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Mon May 10 19:10:37 CEST 2004 Parser.cxx
3 
4  Parser.cxx - description
5  -------------------
6  begin : Mon May 10 2004
7  copyright : (C) 2004 Peter Soetens
8  email : peter.soetens@mech.kuleuven.ac.be
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU Lesser General Public *
13  * License as published by the Free Software Foundation; either *
14  * version 2.1 of the License, or (at your option) any later version. *
15  * *
16  * This library is distributed in the hope that it will be useful, *
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
19  * Lesser General Public License for more details. *
20  * *
21  * You should have received a copy of the GNU Lesser General Public *
22  * License along with this library; if not, write to the Free Software *
23  * Foundation, Inc., 59 Temple Place, *
24  * Suite 330, Boston, MA 02111-1307 USA *
25  * *
26  ***************************************************************************/
27 
28 #include "parser-debug.hpp"
29 #include "parser-types.hpp"
30 #include "parse_exception.hpp"
31 #include "Parser.hpp"
32 #include "ProgramGraphParser.hpp"
33 #include "StateGraphParser.hpp"
34 #include "ConditionParser.hpp"
35 #include "ExpressionParser.hpp"
36 #include "ValueChangeParser.hpp"
37 #include "ProgramService.hpp"
38 #include "StateMachineService.hpp"
39 #include "../internal/DataSourceCommand.hpp"
40 #include "ConditionInterface.hpp"
41 #include "CommandComposite.hpp"
42 #include "../internal/GlobalEngine.hpp"
43 #include "ScriptParser.hpp"
44 
45 #include <iostream>
46 #include <fstream>
47 
48 using namespace boost;
49 
50 namespace RTT
51 {
52  using namespace detail;
53 
54  Parser::Parser(ExecutionEngine* caller) : mcaller(caller) {
55 
56  if (mcaller == 0) {
57  log(Debug) << "WARNING: Parser does not know which TaskContext is executing (calling) the parsed code. Using Global Engine. Please specify the caller explicitly in order to avoid any asynchronous operation problems." <<endlog();
58  mcaller = GlobalEngine::Instance();
59  }
60  }
61 
62  void Parser::runScript(std::string const& code, TaskContext* mowner, ScriptingService* service, std::string const& filename ) {
63  our_buffer_t script(code + "\n"); // work around mandatory trailing newline/eos for statements.
64  our_pos_iter_t parsebegin( script.begin(), script.end(), filename );
65  our_pos_iter_t parseend( script.end(), script.end(), filename );
66 
67  // will store all in mowner, functions are loaded in service, caller is the one calling us.
68  ScriptParser gram( parsebegin, mowner, mcaller );
69 
70  try {
71  gram.parse( parsebegin, parseend );
72  }
73  catch( const parse_exception& exc )
74  {
76  exc.copy(), parsebegin.get_position().file,
77  parsebegin.get_position().line, parsebegin.get_position().column );
78  }
79  }
80 
81  Parser::ParsedFunctions Parser::parseFunction( const std::string& text, TaskContext* c, const std::string& filename)
82  {
83  our_buffer_t function(text);
84  our_pos_iter_t parsebegin( function.begin(), function.end(), filename );
85  our_pos_iter_t parseend( function.end(), function.end(), filename );
86  // The internal parser.
87  CommonParser cp;
88  ProgramGraphParser gram( parsebegin, c, c->engine(), cp );
89  ParsedFunctions ret = gram.parseFunction( parsebegin, parseend );
90  return ret;
91  }
92 
93  Parser::ParsedPrograms Parser::parseProgram( const std::string& text, TaskContext* c, const std::string& filename)
94  {
95  our_buffer_t program(text);
96  our_pos_iter_t parsebegin( program.begin(), program.end(), filename );
97  our_pos_iter_t parseend( program.end(),program.end(),filename );
98 
99  // The internal parser.
100  CommonParser cp;
101  ProgramGraphParser gram( parsebegin, c, c->engine(), cp );
102  ParsedPrograms ret = gram.parse( parsebegin, parseend );
103 
104  return ret;
105  }
106 
107  Parser::ParsedStateMachines Parser::parseStateMachine( const std::string& text, TaskContext* c, const std::string& filename)
108  {
109  // This code is copied from parseProgram()
110 
111  our_buffer_t program(text);
112  our_pos_iter_t parsebegin( program.begin(), program.end(), filename );
113  our_pos_iter_t parseend( program.end(),program.end(),filename );
114 
115  // The internal parser.
116  CommonParser cp;
117  StateGraphParser gram( parsebegin, c, c->engine(), &cp );
119  try {
120  ret = gram.parse( parsebegin, parseend );
121  }
122  catch( const parse_exception& exc )
123  {
124  throw file_parse_exception(
125  exc.copy(), parsebegin.get_position().file,
126  parsebegin.get_position().line, parsebegin.get_position().column );
127  }
128  return ret;
129  }
130 
132  TaskContext* tc )
133  {
134  our_buffer_t scopy(s);
135  our_pos_iter_t parsebegin( scopy.begin(), scopy.end(), "teststring" );
136  our_pos_iter_t parseend( scopy.end(), scopy.end(), "teststring" );
137 
138  CommonParser cp;
139  ConditionParser parser( tc, mcaller ? mcaller : tc->engine(), cp );
140  bool skipref=true;
141  try
142  {
143  parse( parsebegin, parseend, parser.parser(), SKIP_PARSER );
144  }
145  catch( const parse_exception& )
146  {
147  throw;
148  }
149  catch( const parser_error<std::string, iter_t>& e )
150  {
151  throw parse_exception_syntactic_error( e.descriptor );
152  }
153  ConditionInterface* ret = parser.getParseResult();
154  parser.reset();
155  if ( ret == 0 )
156  throw parse_exception_parser_fail("Parser did not find a condition in text.");
157  return ret;
158  }
159 
161  TaskContext* tc )
162  {
163  std::string s( _s );
164 
165  our_pos_iter_t parsebegin( s.begin(), s.end(), "teststring" );
166  our_pos_iter_t parseend( s.end(), s.end(), "teststring" );
167 
168  CommonParser cp;
169  ExpressionParser parser( tc, mcaller, cp );
170  bool skipref=true;
171  try
172  {
173  parse( parsebegin, parseend, parser.parser(), SKIP_PARSER );
174  }
175  catch( const parse_exception& )
176  {
177  throw;
178  }
179  catch( const parser_error<std::string, iter_t>& e )
180  {
181  throw parse_exception_syntactic_error( e.descriptor );
182  }
183  if ( parser.hasResult() ) {
184  DataSourceBase::shared_ptr ret = parser.getResult();
185  parser.dropResult();
186  return ret;
187  }
188  throw parse_exception_parser_fail("Parser did not find a valid expression in text.");
189  }
190 
192  TaskContext* tc )
193  {
194  return parseExpression( _s, tc );
195  }
196 
198  TaskContext* tc )
199  {
200  std::string s( _s );
201 
202  our_pos_iter_t parsebegin( s.begin(), s.end(), "teststring" );
203  our_pos_iter_t parseend( s.end(), s.end(), "teststring" );
204 
205  CommonParser cp;
206  ValueChangeParser parser( tc, cp, tc->provides(), mcaller ? mcaller : tc->engine() );
207  bool skipref=true;
208  try
209  {
210  parse( parsebegin, parseend, parser.parser(), SKIP_PARSER );
211  }
212  catch( const parse_exception& )
213  {
214  throw;
215  }
216  catch( const parser_error<std::string, iter_t>& e )
217  {
218  // this only happens if input is really wrong.
219  throw parse_exception_syntactic_error( e.descriptor );
220  }
221 
222  ActionInterface* ac = 0;
223  std::vector<ActionInterface*> acv = parser.assignCommands();
224  // and not forget to reset()..
225  if ( acv.empty() && parser.lastDefinedValue() ) {
226  return parser.lastDefinedValue()->getDataSource();
227  }
228  if ( acv.size() == 1 ) {
229  if (acv.front() ) { // front will be null if its an alias.
230  ac = acv.front();
231  ac->readArguments();
232  ac->execute();
233  delete ac;
234  }
235  return parser.lastDefinedValue()->getDataSource();
236  }
237  else if (acv.size() > 1) {
238  ac = new CommandComposite(acv);
239  }
240 
241  if ( ac ) {
243  //parser.reset(); don't do this, we want to keep it.
244  return ret;
245  }
247  }
248 }
ParsedFunctions parseFunction(const std::string &s, TaskContext *, const std::string &filename="stream")
Reads out the string, parses it, and returns a new FunctionGraph.
Definition: Parser.cpp:81
Service::shared_ptr provides()
Returns this Service.
This is not a parser in the Boost.spirit sense of the word, it&#39;s just a class used to hold the parser...
#define SKIP_PARSER
When using this macro, you must have a boolean variable skipref defined.
This interface represents the concept of a condition which can be evaluated and return true or false...
virtual void readArguments()=0
This is invoked some time before execute() at a time when the action may read its function arguments...
base::DataSourceBase::shared_ptr parseValueStatement(const std::string &s, TaskContext *)
Parses a whole value manipulation/creation statement.
Definition: Parser.cpp:197
A Parser for Orocos Program Scripts.
virtual parse_exception * copy() const =0
This is an exception class that keeps a parse_exception pointer along with the location in the file a...
void runScript(std::string const &code, TaskContext *mowner, ScriptingService *service, std::string const &filename)
Runs all statements in code.
Definition: Parser.cpp:62
This class contains some very common parser definitions.
parse_exception class that is used for various syntactic errors for which it was not worth defining a...
An execution engine serialises (executes one after the other) the execution of all commands...
How we parse: this parser works like a stack-based RPN calculator.
ConditionInterface * parseCondition(const std::string &s, TaskContext *)
Parses the string as a condition, and returns a new ConditionInterface.
Definition: Parser.cpp:131
position_iterator< our_iterator_t > our_pos_iter_t
ParsedStateMachines parseStateMachine(const std::string &s, TaskContext *, const std::string &filename="stream")
Reads out the string, parses it, and returns a new ParsedStateMachine.
Definition: Parser.cpp:107
static RTT_API ExecutionEngine * Instance()
This is an overloaded member function, provided for convenience. It differs from the above function o...
virtual bool execute()=0
Execute the functionality of this action.
std::vector< ProgramInterfacePtr > ParsedPrograms
List of parsed programs.
Definition: Parser.hpp:101
virtual void reset()
Some conditions need to be reset at some points.
Based on the software pattern &#39;command&#39;, this interface allows execution of action objects...
base::DataSourceBase::shared_ptr getResult()
This is the uppermost exception class in the parser system.
std::vector< ProgramInterfacePtr > ParsedFunctions
List of parsed functions.
Definition: Parser.hpp:89
This class is responsible for parsing constant definitions, variable definitions, variable change ins...
base::DataSourceBase::shared_ptr parseExpression(const std::string &s, TaskContext *)
Parses the expression in s.
Definition: Parser.cpp:160
std::vector< ProgramInterfacePtr > parse(iter_t &begin, iter_t end)
Tries to parse programs, returns the generated programs on success.
std::vector< ProgramInterfacePtr > parseFunction(iter_t &begin, iter_t end)
A class that wraps a Command in a internal::DataSource<bool> interface.
An exception which a parser may throw to indicate that it failed to understand the input...
ParsedPrograms parseProgram(const std::string &s, TaskContext *, const std::string &filename="stream")
Reads out the string, parses it, and returns a new ProgramGraph.
Definition: Parser.cpp:93
The TaskContext is the C++ representation of an Orocos component.
Definition: TaskContext.hpp:93
std::vector< ParsedStateMachinePtr > ParsedStateMachines
List of parsed State Machines.
Definition: Parser.hpp:113
Parsers and executes any RTT script you throw at it.
boost::intrusive_ptr< DataSourceBase > shared_ptr
Use this type to store a pointer to a DataSourceBase.
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:52
This interface allows to load program scripts and state machines and allows execution of code...
This is a class containing a parse function for conditions.
Based on the software pattern &#39;composite&#39;, this class RTT_SCRIPTING_API allows composing command obje...
const ExecutionEngine * engine() const
Get a const pointer to the ExecutionEngine of this Task.
Definition: TaskCore.hpp:306
std::string our_buffer_t
std::vector< ParsedStateMachinePtr > parse(iter_t &begin, iter_t end)
base::DataSourceBase::shared_ptr parseValueChange(const std::string &s, TaskContext *)
Parses a change of a value in s.
Definition: Parser.cpp:191