Circus 0.0.1-alpha
C++ Serialization Framework
Loading...
Searching...
No Matches
parser.hpp
1#pragma once
2#include <any>
3#include <iostream>
4#include <unordered_map>
5#include <vector>
6
7#include "circus_error.hpp"
8#include "circus_traits.hpp"
9#include "token.hpp"
10
11namespace circus {
12
20 typedef std::variant<
21 char,
22 std::string,
23 int,
24 float,
25 double,
26 std::vector<circ_variable>,
27 std::unordered_map<std::string, circ_variable>>
29
31 std::string key;
32
35
44 circ_variable& operator[](const std::string& key) {
45 auto& m = std::get<std::unordered_map<std::string, circ_variable>>(value);
46 return m[key];
47 };
48};
49
57class parser__ {
58 using TK = tokens__::TYPE;
59 using error_type = error::parser_error::enum_type;
60
62 std::vector<tokens__> _in;
63
65 std::size_t _curs;
66
69
75 [[nodiscard]] tokens__ f_peek_at(const std::size_t off) const noexcept {
76 return _in[_curs + off];
77 };
78
83 [[nodiscard]] tokens__ f_previous() const noexcept {
84 return _in[_curs - 1];
85 };
86
91 [[nodiscard]] tokens__ f_peek_next() const noexcept {
92 return _in[_curs + 1];
93 };
94
99 [[nodiscard]] tokens__ f_peek() const noexcept {
100 return _in[_curs];
101 };
102
107 tokens__ f_advance() noexcept {
108 if (!f_eof())
109 _curs++;
110 return f_previous();
111 };
112
117 bool f_eof() const {
118 return traits::any_of(f_peek()._token_type, tokens__::TYPE::TK_EOF);
119 };
120
126 bool check(tokens__::TYPE t) {
127 if (f_eof())
128 return false;
129 return f_peek()._token_type == t;
130 }
131
139 template <typename... Args>
140 requires(std::is_same_v<Args, tokens__::TYPE> && ...)
141 bool f_match(Args&&... args) {
142 if ((check(args) || ...)) {
143 f_advance();
144 return true;
145 }
146 return false;
147 }
148
156 template <typename... Args>
157 [[nodiscard]] decltype(auto) to_value(std::variant<Args...> var) const noexcept {
158 return std::visit([](const auto& val) -> circ_variable::circ_type_var_t { return std::forward<decltype(val)>(val); }, var);
159 }
160
166 circ_variable::circ_type_var_t f_parse_primary() {
167 if (f_match(TK::TK_CURL_L)) {
168 std::unordered_map<std::string, circ_variable> obj = f_parse();
169 if (f_match(TK::TK_CURL_R)) {
170 return obj;
171 }
172 throw circus::error::parser_error(error_type::SYNTAX, "Missing Closing Curl '}' ");
173 }
174
175 if (f_match(TK::TK_BRACE_L)) {
176 std::vector<circ_variable> arr = f_parse_array();
177 if (!f_match(TK::TK_BRACE_R)) {
178 throw circus::error::parser_error(error_type::SYNTAX, "Missing Closing Bracket ']' ");
179 }
180 return arr;
181 }
182
183 return to_value(f_advance().literal);
184 }
185
191 std::vector<circ_variable> f_parse_array() {
192 std::vector<circ_variable> ret{};
193 std::size_t index = 0;
194 while (!f_eof() && !check(TK::TK_BRACE_R)) {
196 var.value = f_parse_primary();
197 var.key = std::to_string(index++);
198 if (!check(TK::TK_BRACE_R)) {
199 if (!f_match(TK::TK_COMMA)) {
200 throw circus::error::parser_error(error_type::SYNTAX, "Missing Comma Separator ");
201 }
202 }
203 ret.push_back(var);
204 }
205 if (check(TK::TK_BRACE_R) && f_previous()._token_type == TK::TK_COMMA) {
206 throw circus::error::parser_error(error_type::SYNTAX, "Trailing Comma Separator ");
207 }
208 return ret;
209 }
210
216 circ_variable f_parse_value() {
218 var.key = f_previous().embedded;
219 if (f_match(TK::TK_COLON)) {
220 var.value = f_parse_primary();
221 if (!f_eof() && !check(TK::TK_CURL_R)) {
222 if (!f_match(TK::TK_COMMA)) {
223 throw circus::error::parser_error(error_type::SYNTAX, "Missing Comma Separator ");
224 }
225 }
226 return var;
227 }
228 throw circus::error::parser_error(error_type::SYNTAX, "Missing Colon Operator ");
229 };
230
236 circ_variable f_parse_identifier() {
237 if (f_match(TK::TK_IDENTIFIER)) {
238 return f_parse_value();
239 }
240 throw circus::error::parser_error(error_type::SYNTAX, "Missing Identifier ");
241 };
242
248 circ_variable f_parse_decl() {
249 if (!f_eof() && f_match(TK::TK_DOLLA)) {
250 return f_parse_identifier();
251 };
252 throw circus::error::parser_error(error_type::SYNTAX, "Missing Declaration Specifier '$' ");
253 }
254
258 void f_sync() {
259 if (!f_eof()) f_advance();
260 while (!f_eof()) {
261 if (check(TK::TK_DOLLA)) return;
262 f_advance();
263 }
264 };
265
271 std::unordered_map<std::string, circ_variable> f_parse() {
272 std::unordered_map<std::string, circ_variable> ret{};
273 bool had_error = false;
274 while (!f_eof()) {
275 try {
276 if (check(TK::TK_CURL_R))
277 break;
278 auto v = f_parse_decl();
279 ret.insert(std::make_pair(v.key, v));
280 } catch (circus::error::parser_error& error) {
281 _reporter.report(error.type_of, error.what(), f_previous().location);
282 f_sync();
283 had_error = true;
284 }
285 }
286 _reporter.log_errors();
287 if (had_error) {
288 throw std::runtime_error("halted execution due to parser incomprehension, revise circ source input");
289 }
290 return ret;
291 }
292
293 public:
297 parser__() : _in{}, _curs{0}, _reporter{} {};
298
304 std::unordered_map<std::string, circ_variable> operator()(std::vector<tokens__> toks) {
305 _in = toks;
306 return f_parse();
307 };
308
313};
314
315} // namespace circus
Defines error handling utilities for the Circus parser, including error types, exceptions,...
Provides compile-time traits and C++20 concepts for type introspection used throughout the Circus lib...
Exception class for parser errors, holding an error type flag and a message.
Definition circus_error.hpp:44
Aggregates and manages parser error messages with support for logging and flushing.
Definition circus_error.hpp:61
parser__()
Default constructor.
Definition parser.hpp:297
~parser__()
Destructor.
Definition parser.hpp:312
std::unordered_map< std::string, circ_variable > operator()(std::vector< tokens__ > toks)
Parse tokens into Circus variables.
Definition parser.hpp:304
Represents a variable in Circus serialization.
Definition parser.hpp:18
std::variant< char, std::string, int, float, double, std::vector< circ_variable >, std::unordered_map< std::string, circ_variable > > circ_type_var_t
Variant holding possible Circus variable types.
Definition parser.hpp:28
circ_type_var_t value
The value stored in this variable.
Definition parser.hpp:34
circ_variable & operator[](const std::string &key)
Access nested variables by key, for objects.
Definition parser.hpp:44
std::string key
The key name associated with this variable.
Definition parser.hpp:31
Represents a lexical token with type, literal value, and source location.
Definition token.hpp:17