File: parser_state.hpp

package info (click to toggle)
actor-framework 0.18.7-1~exp1
  • links: PTS
  • area: main
  • in suites: experimental
  • size: 8,740 kB
  • sloc: cpp: 85,162; sh: 491; python: 187; makefile: 11
file content (142 lines) | stat: -rw-r--r-- 3,524 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.

#pragma once

#include <cctype>
#include <cstdint>

#include "caf/fwd.hpp"
#include "caf/pec.hpp"
#include "caf/string_view.hpp"

namespace caf {

/// Stores all information necessary for implementing an FSM-based parser.
template <class Iterator, class Sentinel>
struct parser_state {
  /// Current position of the parser.
  Iterator i;

  /// End-of-input marker.
  Sentinel e;

  /// Current state of the parser.
  pec code;

  /// Current line in the input.
  int32_t line;

  /// Position in the current line.
  int32_t column;

  parser_state() noexcept : i(), e(), code(pec::success), line(1), column(1) {
    // nop
  }

  explicit parser_state(Iterator first) noexcept : parser_state() {
    i = first;
  }

  parser_state(Iterator first, Sentinel last) noexcept : parser_state() {
    i = first;
    e = last;
  }

  parser_state(const parser_state&) noexcept = default;

  parser_state& operator=(const parser_state&) noexcept = default;

  /// Returns the null terminator when reaching the end of the string,
  /// otherwise the next character.
  char next() noexcept {
    ++i;
    ++column;
    if (i != e) {
      auto c = *i;
      if (c == '\n') {
        ++line;
        column = 1;
      }
      return c;
    }
    return '\0';
  }

  /// Returns the null terminator if `i == e`, otherwise the current character.
  char current() const noexcept {
    return i != e ? *i : '\0';
  }

  /// Checks whether `i == e`.
  bool at_end() const noexcept {
    return i == e;
  }

  /// Skips any whitespaces characters in the input.
  void skip_whitespaces() noexcept {
    auto c = current();
    while (isspace(c))
      c = next();
  }

  /// Tries to read `x` as the next character, automatically skipping leading
  /// whitespaces.
  bool consume(char x) noexcept {
    skip_whitespaces();
    if (current() == x) {
      next();
      return true;
    }
    return false;
  }

  /// Consumes the next character if it satisfies given predicate, automatically
  /// skipping leading whitespaces.
  template <class Predicate>
  bool consume_if(Predicate predicate) noexcept {
    skip_whitespaces();
    if (predicate(current())) {
      next();
      return true;
    }
    return false;
  }

  /// Tries to read `x` as the next character without automatically skipping
  /// leading whitespaces.
  bool consume_strict(char x) noexcept {
    if (current() == x) {
      next();
      return true;
    }
    return false;
  }

  /// Consumes the next character if it satisfies given predicate without
  /// automatically skipping leading whitespaces.
  template <class Predicate>
  bool consume_strict_if(Predicate predicate) noexcept {
    if (predicate(current())) {
      next();
      return true;
    }
    return false;
  }
};

/// Returns an error object from the current code in `ps` as well as its
/// current position.
template <class Iterator, class Sentinel, class... Ts>
auto make_error(const parser_state<Iterator, Sentinel>& ps, Ts&&... xs)
  -> decltype(make_error(ps.code, ps.line, ps.column)) {
  if (ps.code == pec::success)
    return {};
  return make_error(ps.code, ps.line, ps.column, std::forward<Ts>(xs)...);
}

/// Specialization for parsers operating on string views.
using string_parser_state = parser_state<string_view::iterator>;

} // namespace caf