Lex.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include "../Instancing/ClientMarker.hpp"
4 #include "../Basics/LogTrace.hpp"
5 
6 #include <iostream>
7 #include <vector>
8 #include <string>
9 #include <unordered_set>
10 
11 namespace iv
12 {
13 
14 class Instance;
15 
19 class Lex
20 {
21 public:
23 
24  Lex( Instance * inst );
25  Instance * instance() const;
26 
27  //----------------- configuration --------------------------
28  void DefineKeyword( const char * keyword );
29  void DefineOperator( const char * op );
30 
34  void numbers_enabled( bool enabled );
35 
36  //----------------- tokens ---------------------------------
40  enum Token
41  {
42  Keyword, // keyword must have whitespace characters on both sides to be considered keyword ; can not begin with a number ; can not contain whitespaces and operators
43  Operator, // operator that does not have to be separated with whitespace characters from variables ; can not begin with a number ; can not contain whitespaces ; all prefixes of specified operators are also operators
44  Newline, // newline is skipped if not explicitly requested
45  Eof, // end of input
46 
47  String, // anything that has quotes or apostrophes on both sides; quoted strings support escaping with backslash: \" -> ", \n -> newline, \r -> cr, \t -> tab, \\ -> backslash; Other escaped characters yield error
48  Name, // anything not containing whitespace characters that is not anything else ; can not begin with a number ; can not contain whitespaces and operators
49  Integer, // sequence of numbers (0-9); Whenever Double is requested in Lex's interface, Integer can substitute for it. Negative values work under the same conditions as for Double numbers.
50  Double // Examples: 1.3, 1e3, 1e-3, 1.e-5, 5.5e-5, if operator '-' is defined, then this can only be positive (and it is up on user code to parse the minus and negate the number).
51  };
52 
53  //----------------- parsing --------------------------------
61  void Init( std::istream & in, bool single_line = false );
62  void Close();
63 
70  void EnableNewlineSkipping();
71 
76  bool IsNext( Token token );
77  bool IsNextKeyword( const char * keyword );
78  bool IsNextOperator( const char * op );
79 
86  std::string GetNextTokenValue();
87 
92  void Accept( Token token );
93  void AcceptKeyword( const char * keyword );
94  void AcceptOperator( const char * op );
95  void AcceptFail();
96 
97  std::string AcceptString();
98  std::string AcceptName();
99  int AcceptInteger();
100  double AcceptDouble();
101 
109  void Recover( Token token );
110  void RecoverKeyword( const char * keyword );
111  void RecoverOperator( const char * op );
112 
116  int GetLine() const;
117  int GetColumn() const;
118 
122  void LogicFail( const char * message );
123 
126  void ParserFail( const char * prefix = nullptr);
127 
131  bool Failed();
132 
133 private:
134  void NextChar();
135  void NextToken();
136  void NextTokenImpl();
137  void Error( const char * msg );
138  void ReadNumber( bool negative );
139  void ReadIdentifier();
140  void PrecomputeOperators();
141  std::string TokenToStr( Token token, const char * associated_token_str );
142  bool isspace( char c );
143 
144 private:
145  Instance * inst;
146  bool _single_line;
147 
148  std::unordered_set< std::string > keywords;
149  std::unordered_set< std::string > operators;
150  bool _numbers_enabled;
151 
152  std::istream * in;
153  int line;
154  int column;
155  int prev_line;
156  int prev_column;
157 
158  bool failed;
159 
160  // current token
161  int newlines;
162  bool newline_skipping;
163  Token token;
164  std::string token_str;
165 
166  // current char
167  int c;
168 
169  // tested tokens
170  std::vector< Token > tested_tokens;
171  std::vector< std::string > tested_keywords;
172  std::vector< std::string > tested_operators;
173 
174  // precomputed operators
175  std::unordered_set< char > operators_begins;
176  std::unordered_set< std::string > operators_prefixes;
177 };
178 
179 class Lex_LogTrace : public LogTrace
180 {
181 public:
182  Lex_LogTrace( Lex const & lex ) :
183  lex( lex )
184  {
185  }
186 
187 protected:
188  virtual void PrintTraceLine( std::ostream & out ) override
189  {
190  out << "Line "<< ( lex.GetLine()+1 ) << ":" << ( lex.GetColumn()+1 ) << ":" << std::endl;
191  }
192 
193 private:
194  Lex const & lex;
195 };
196 
197 }