HAL
token_stream.h
Go to the documentation of this file.
1 // MIT License
2 //
3 // Copyright (c) 2019 Ruhr University Bochum, Chair for Embedded Security. All Rights reserved.
4 // Copyright (c) 2019 Marc Fyrbiak, Sebastian Wallat, Max Hoffmann ("ORIGINAL AUTHORS"). All rights reserved.
5 // Copyright (c) 2021 Max Planck Institute for Security and Privacy. All Rights reserved.
6 // Copyright (c) 2021 Jörn Langheinrich, Julian Speith, Nils Albartus, René Walendy, Simon Klix ("ORIGINAL AUTHORS"). All Rights reserved.
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 // SOFTWARE.
25 
26 #pragma once
27 
28 #include "hal_core/defines.h"
29 
30 #include <algorithm>
31 #include <map>
32 #include <vector>
33 
34 namespace hal
35 {
41  template<typename T>
42  struct CORE_API Token
43  {
50  Token(u32 n, const T s) : number(n), string(s)
51  {
52  }
53 
58 
63 
67  operator T() const
68  {
69  return string;
70  }
71 
78  Token<T>& operator=(const T& s)
79  {
80  this->string = s;
81  return *this;
82  }
83 
90  Token<T>& operator+=(const T& s)
91  {
92  this->string += s;
93  return *this;
94  }
95 
102  bool operator==(const T& s) const
103  {
104  return string == s;
105  }
106 
113  bool operator!=(const T& s) const
114  {
115  return !(*this == s);
116  }
117  };
118 
124  template<typename T>
126  {
127  public:
132  {
137 
142  };
143 
147  static const u32 END_OF_STREAM = 0xFFFFFFFF;
148 
157  TokenStream(const std::vector<T>& increase_level_tokens = {"("}, const std::vector<T>& decrease_level_tokens = {")"})
158  {
159  m_pos = 0;
160  m_increase_level_tokens = increase_level_tokens;
161  m_decrease_level_tokens = decrease_level_tokens;
162  }
163 
173  TokenStream(const std::vector<Token<T>>& init, const std::vector<T>& increase_level_tokens = {"("}, const std::vector<T>& decrease_level_tokens = {")"})
174  : TokenStream(increase_level_tokens, decrease_level_tokens)
175  {
176  m_data = init;
177  }
178 
185  {
186  m_pos = other.m_pos;
187  m_data = other.m_data;
188  m_increase_level_tokens = other.m_increase_level_tokens;
189  m_decrease_level_tokens = other.m_decrease_level_tokens;
190  }
191 
199  {
200  m_pos = other.m_pos;
201  m_data = other.m_data;
202  m_increase_level_tokens = other.m_increase_level_tokens;
203  m_decrease_level_tokens = other.m_decrease_level_tokens;
204  return *this;
205  }
206 
217  {
218  m_pos += num;
219  return at(m_pos - 1);
220  }
221 
230  bool consume(const T& expected, bool throw_on_error = false)
231  {
232  if (m_pos >= size())
233  {
234  if (throw_on_error)
235  {
236  throw TokenStreamException({"expected Token '" + expected + "' but reached the end of the stream", get_current_line_number()});
237  }
238  return false;
239  }
240 
241  if (at(m_pos) != expected)
242  {
243  if (throw_on_error)
244  {
245  throw TokenStreamException({"expected Token '" + expected + "' but got '" + at(m_pos).string + "'", get_current_line_number()});
246  }
247  return false;
248  }
249 
250  m_pos++;
251  return true;
252  }
253 
266  Token<T> consume_until(const T& expected, u32 end = END_OF_STREAM, bool level_aware = true, bool throw_on_error = false)
267  {
268  auto found = find_next(expected, end, level_aware);
269  if (found > size() && throw_on_error)
270  {
271  throw TokenStreamException({"expected Token '" + expected + "' not found", get_current_line_number()});
272  }
273  m_pos = std::min(size(), found);
274  return at(m_pos - 1);
275  }
276 
283  {
284  u32 line = at(m_pos).number;
285 
286  u32 i = m_pos;
287  while (++i < size() && at(i).number == line)
288  {
289  }
290  m_pos = i;
291 
292  return at(m_pos - 1);
293  }
294 
308  TokenStream<T> extract_until(const T& expected, u32 end = END_OF_STREAM, bool level_aware = true, bool throw_on_error = false)
309  {
310  auto found = find_next(expected, end, level_aware);
311  if (found > size() && throw_on_error)
312  {
313  throw TokenStreamException({"expected Token '" + expected + "' not found", get_current_line_number()});
314  }
315  auto end_pos = std::min(size(), found);
316  TokenStream res(m_increase_level_tokens, m_decrease_level_tokens);
317  res.m_data.reserve(res.m_data.size() + (end_pos - m_pos));
318  res.m_data.insert(res.m_data.begin(), m_data.begin() + m_pos, m_data.begin() + end_pos);
319  m_pos = end_pos;
320  return res;
321  }
322 
338  Token<T> join_until(const T& match, const T& joiner, u32 end = END_OF_STREAM, bool level_aware = true, bool throw_on_error = false)
339  {
340  u32 start_line = get_current_line_number();
341  auto found = find_next(match, end, level_aware);
342  if (found > size() && throw_on_error)
343  {
344  throw TokenStreamException({"match Token '" + match + "' not found", start_line});
345  }
346  auto end_pos = std::min(size(), found);
347  T result;
348  while (m_pos < end_pos && remaining() > 0)
349  {
350  if (!result.empty())
351  {
352  result += joiner;
353  }
354  result += consume();
355  }
356  return {start_line, result};
357  }
358 
367  Token<T> join(const T& joiner)
368  {
369  u32 start_line = get_current_line_number();
370  T result;
371  while (remaining() > 0)
372  {
373  if (!result.empty())
374  {
375  result += joiner;
376  }
377  result += consume();
378  }
379  return {start_line, result};
380  }
381 
392  Token<T>& peek(i32 offset = 0)
393  {
394  return at(m_pos + offset);
395  }
396 
400  const Token<T>& peek(i32 offset = 0) const
401  {
402  return at(m_pos + offset);
403  }
404 
415  Token<T>& at(u32 position)
416  {
417  if (position >= m_data.size())
418  {
419  throw TokenStreamException({"reached the end of the stream", get_current_line_number()});
420  }
421  return m_data[position];
422  }
423 
427  const Token<T>& at(u32 position) const
428  {
429  if (position >= m_data.size())
430  {
431  throw TokenStreamException({"reached the end of the stream", get_current_line_number()});
432  }
433  return m_data[position];
434  }
435 
446  u32 find_next(const T& match, u32 end = END_OF_STREAM, bool level_aware = true) const
447  {
448  u32 level = 0;
449  for (u32 i = m_pos; i < size() && i < end; ++i)
450  {
451  const auto& Token = at(i);
452  if ((!level_aware || level == 0) && Token == match)
453  {
454  return i;
455  }
456  else if (level_aware && std::find_if(m_increase_level_tokens.begin(), m_increase_level_tokens.end(), [&Token](const auto& x) { return Token == x; }) != m_increase_level_tokens.end())
457  {
458  level++;
459  }
460  else if (level_aware && level > 0
461  && std::find_if(m_decrease_level_tokens.begin(), m_decrease_level_tokens.end(), [&Token](const auto& x) { return Token == x; }) != m_decrease_level_tokens.end())
462  {
463  level--;
464  }
465  }
466  return end;
467  }
468 
474  u32 size() const
475  {
476  return m_data.size();
477  }
478 
484  u32 consumed() const
485  {
486  return m_pos;
487  }
488 
494  u32 remaining() const
495  {
496  return size() - consumed();
497  }
498 
504  u32 position() const
505  {
506  return m_pos;
507  }
508 
515  {
516  m_pos = p;
517  }
518 
519  private:
520  std::vector<T> m_increase_level_tokens;
521  std::vector<T> m_decrease_level_tokens;
522  std::vector<Token<T>> m_data;
523  u32 m_pos;
524 
525  u32 get_current_line_number() const
526  {
527  if (m_pos < m_data.size())
528  {
529  return m_data[m_pos].number;
530  }
531  else if (!m_data.empty())
532  {
533  return m_data.back().number;
534  }
535  return END_OF_STREAM;
536  }
537  };
538 } // namespace hal
#define NETLIST_API
Definition: arch_linux.h:30
#define CORE_API
Definition: arch_linux.h:28
u32 remaining() const
Definition: token_stream.h:494
Token< T > consume_until(const T &expected, u32 end=END_OF_STREAM, bool level_aware=true, bool throw_on_error=false)
Definition: token_stream.h:266
TokenStream(const std::vector< T > &increase_level_tokens={"("}, const std::vector< T > &decrease_level_tokens={")"})
Definition: token_stream.h:157
Token< T > consume_current_line()
Definition: token_stream.h:282
Token< T > & at(u32 position)
Definition: token_stream.h:415
void set_position(u32 p)
Definition: token_stream.h:514
Token< T > & peek(i32 offset=0)
Definition: token_stream.h:392
TokenStream(const TokenStream< T > &other)
Definition: token_stream.h:184
u32 consumed() const
Definition: token_stream.h:484
u32 find_next(const T &match, u32 end=END_OF_STREAM, bool level_aware=true) const
Definition: token_stream.h:446
const Token< T > & peek(i32 offset=0) const
Definition: token_stream.h:400
Token< T > join_until(const T &match, const T &joiner, u32 end=END_OF_STREAM, bool level_aware=true, bool throw_on_error=false)
Definition: token_stream.h:338
bool consume(const T &expected, bool throw_on_error=false)
Definition: token_stream.h:230
TokenStream(const std::vector< Token< T >> &init, const std::vector< T > &increase_level_tokens={"("}, const std::vector< T > &decrease_level_tokens={")"})
Definition: token_stream.h:173
TokenStream< T > & operator=(const TokenStream< T > &other)
Definition: token_stream.h:198
TokenStream< T > extract_until(const T &expected, u32 end=END_OF_STREAM, bool level_aware=true, bool throw_on_error=false)
Definition: token_stream.h:308
u32 position() const
Definition: token_stream.h:504
Token< T > consume(u32 num=1)
Definition: token_stream.h:216
const Token< T > & at(u32 position) const
Definition: token_stream.h:427
Token< T > join(const T &joiner)
Definition: token_stream.h:367
u32 size() const
Definition: token_stream.h:474
int32_t i32
Definition: defines.h:36
n
Definition: test.py:6
quint32 u32
bool operator!=(const T &s) const
Definition: token_stream.h:113
Token< T > & operator=(const T &s)
Definition: token_stream.h:78
bool operator==(const T &s) const
Definition: token_stream.h:102
Token(u32 n, const T s)
Definition: token_stream.h:50
Token< T > & operator+=(const T &s)
Definition: token_stream.h:90