InFact
Interpreter and factory for easily creating C++ objects at run-time
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
interpreter.h
Go to the documentation of this file.
1 // Copyright 2014, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 // -----------------------------------------------------------------------------
30 //
31 //
36 
37 #ifndef INFACT_INTERPRETER_H_
38 #define INFACT_INTERPRETER_H_
39 
40 #include <iostream>
41 #include <fstream>
42 #include <memory>
43 #include <string>
44 #include <unordered_map>
45 #include <unordered_set>
46 
47 #include "environment-impl.h"
48 
49 namespace infact {
50 
51 using std::ifstream;
52 using std::istream;
53 using std::unique_ptr;
54 
57  public:
58  virtual ~IStreamBuilder() = default;
59 
60  virtual unique_ptr<istream> Build(
61  const string &filename,
62  std::ios_base::openmode mode = std::ios_base::in) const = 0;
63 };
64 
68  public:
69  ~DefaultIStreamBuilder() override = default;
70 
71  unique_ptr<istream> Build(const string &filename,
72  std::ios_base::openmode mode = std::ios_base::in)
73  const override;
74 };
75 
76 class EnvironmentImpl;
77 
212 class Interpreter {
213  public:
217  Interpreter(int debug = 0) :
219  debug) { }
220 
224  Interpreter(unique_ptr<IStreamBuilder> istream_builder, int debug = 0) :
225  env_(new EnvironmentImpl(debug)),
226  istream_builder_(std::move(istream_builder)),
227  debug_(debug) { }
228 
230  virtual ~Interpreter() = default;
231 
233  void SetIStreamBuilder(unique_ptr<IStreamBuilder> istream_builder) {
234  istream_builder_ = std::move(istream_builder);
235  }
236 
238  void Eval(const string &filename);
239 
241  void EvalString(const string& input) {
242  StreamTokenizer st(input);
243  Eval(st);
244  }
245 
247  void Eval(istream &is) {
248  StreamTokenizer st(is);
249  Eval(st);
250  }
251 
252  void PrintEnv(ostream &os) const {
253  env_->Print(os);
254  }
255 
256  void PrintFactories(ostream &os) const {
257  env_->PrintFactories(os);
258  }
259 
261  bool GetMany() { return true; }
262 
293  template<typename T, typename... Args>
294  bool GetMany(const string &varname, T *var,
295  Args &&...rest) {
296  bool success = Get(varname, var);
297  if (!success) {
298  std::ostringstream err_ss;
299  err_ss << "infact::Interpreter: no variable with name '"
300  << varname << "'";
301  Error(err_ss.str());
302  return false;
303  }
304  return GetMany(std::forward<Args>(rest)...); // compile-time recursion ftw
305  }
306 
316  template<typename T>
317  bool Get(const string &varname, T *value) const {
318  return env_->Get(varname, value);
319  }
320 
327  EnvironmentImpl *env() { return env_.get(); }
328 
329  private:
331  bool IsAbsolute(const string &filename) const;
332 
334  bool CanReadFile(const string &filename) const;
335 
347  bool CanReadFile(const string &f1, const string &f2, string *filename) const;
348 
351  bool HasCycle(const string &filename, const vector<string> &filenames) const;
352 
354  void EvalFile(const string &filename);
355 
357  void Eval(StreamTokenizer &st);
358 
360  void Import(StreamTokenizer &st);
361 
364  string curr_filename() const {
365  return filenames_.size() > 0 ? filenames_.back() : "";
366  }
367 
374  string filestack(StreamTokenizer &st, size_t pos) const;
375 
376  void WrongTokenError(StreamTokenizer &st,
377  size_t pos,
378  const string &expected,
379  const string &found,
380  StreamTokenizer::TokenType found_type) const;
381 
382  void WrongTokenTypeError(StreamTokenizer &st,
383  size_t pos,
386  const string &token) const;
387 
388  void WrongTokenTypeError(StreamTokenizer &st,
389  size_t pos,
390  const string &expected_type,
391  const string &found_type,
392  const string &token) const;
393 
395  unique_ptr<EnvironmentImpl> env_;
396 
402  vector<string> filenames_;
403 
404  // The object for building new istream objects from named files.
405  unique_ptr<IStreamBuilder> istream_builder_;
406 
407  // The debug level of this interpreter.
408  int debug_;
409 };
410 
411 } // namespace infact
412 
413 #endif
void PrintFactories(ostream &os) const
Definition: interpreter.h:256
void EvalString(const string &input)
Evaluates the statements in the specified string.
Definition: interpreter.h:241
~DefaultIStreamBuilder() override=default
virtual unique_ptr< istream > Build(const string &filename, std::ios_base::openmode mode=std::ios_base::in) const =0
void Eval(istream &is)
Evaluates the statements in the specified stream.
Definition: interpreter.h:247
bool GetMany()
The base case for the variadic template method GetMany defined below.
Definition: interpreter.h:261
void Eval(const string &filename)
Evaluates the statements in the specified text file.
Definition: interpreter.cc:91
virtual ~Interpreter()=default
Destroys this interpreter.
The default implementation for the IStreamBuilder interface, returning std::ifstream instances...
Definition: interpreter.h:67
EnvironmentImpl * env()
Returns a pointer to the environment of this interpreter.
Definition: interpreter.h:327
Interpreter(int debug=0)
Constructs a new instance with the specified debug level.
Definition: interpreter.h:217
bool Get(const string &varname, T *value) const
Retrieves the value of the specified variable.
Definition: interpreter.h:317
bool GetMany(const string &varname, T *var, Args &&...rest)
Retrieves values for many variables, specified as a sequence of pairs of arguments.
Definition: interpreter.h:294
A simple class for tokenizing a stream of tokens for the formally specified language used to construc...
void SetIStreamBuilder(unique_ptr< IStreamBuilder > istream_builder)
Sets the IStreamBuilder object, to be owned by this object.
Definition: interpreter.h:233
void PrintEnv(ostream &os) const
Definition: interpreter.h:252
void Error(const std::string &message)
Reports an error encountered during parsing and/or construction of an object.
Definition: error.cc:47
Provides an environment for variables and their values, either primitive or Factory-constructible obj...
virtual ~IStreamBuilder()=default
TokenType
The set of types of tokens read by this stream tokenizer.
Provides a set of named variables and their types, as well as the values for those variables...
unique_ptr< istream > Build(const string &filename, std::ios_base::openmode mode=std::ios_base::in) const override
Definition: interpreter.cc:49
An interface for classes that can build istreams for named files.
Definition: interpreter.h:56
Provides an interpreter for assigning primitives and Factory-constructible objects to named variables...
Definition: interpreter.h:212
Interpreter(unique_ptr< IStreamBuilder > istream_builder, int debug=0)
Constructs a new instance with the specified IStreamBuilder and debug level.
Definition: interpreter.h:224