Project Alice
Loading...
Searching...
No Matches
parsers.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <string_view>
4#include <stdint.h>
5#include <string>
6#include "date_interface.hpp"
7
8/*
9 * must support
10 * class token_generator
11 * --- member function get() of type token_and_type
12 * * --- member function next() of type token_and_type
13 * * --- member function next_next() of type token_and_type
14 * --- member function discard_group()
15 * struct token_and_type
16 * --- member type of enum class token_type
17 * --- member string_view content
18 * --- member line_number int32_t
19 * class error_handler
20 * --- member function unhandled_free_set(token_and_type)
21 * --- member function unhandled_group_key(token_and_type)
22 * --- member function unhandled_association_key(token_and_type)
23 */
24
25namespace parsers {
27
28enum class association_type : unsigned short { none, eq, lt, le, gt, ge, ne, eq_default, list };
29
31 std::string_view content;
32 int32_t line = 0;
34};
35
37private:
38 char const* position = nullptr;
39 char const* file_end = nullptr;
40 int32_t current_line = 1;
41
42 token_and_type peek_1;
43 token_and_type peek_2;
44
45 token_and_type internal_next();
46
47public:
49 token_generator(char const* file_start, char const* fe) : position(file_start), file_end(fe) { }
50 bool at_end() const {
51 return peek_2.type == token_type::unknown && peek_1.type == token_type::unknown && position >= file_end;
52 }
56 void discard_group();
57};
58
60public:
61 std::string file_name;
62 std::string accumulated_errors;
64 bool fatal = false;
65
66 error_handler(std::string file_name) : file_name(std::move(file_name)) { }
67
69 accumulated_errors += "unexpected group key " + std::string(t.content) + " found on line " + std::to_string(t.line) +
70 " of file " + file_name + "\n";
71 }
73 accumulated_errors += "unexpected value key " + std::string(t.content) + " found on line " + std::to_string(t.line) +
74 " of file " + file_name + "\n";
75 }
77 accumulated_errors += "unexpected free value " + std::string(t.content) + " found on line " + std::to_string(t.line) +
78 " of file " + file_name + "\n";
79 }
81 accumulated_errors += "unhandled free set beginning with " + std::string(t.content) + " found on line " +
82 std::to_string(t.line) + " of file " + file_name + "\n";
83 }
84 void bad_date(std::string_view s, int32_t l) {
86 "tried to parse " + std::string(s) + " as a date on line " + std::to_string(l) + " of file " + file_name + "\n";
87 }
88 void bad_float(std::string_view s, int32_t l) {
90 "tried to parse " + std::string(s) + " as a float on line " + std::to_string(l) + " of file " + file_name + "\n";
91 }
92 void bad_double(std::string_view s, int32_t l) {
94 "tried to parse " + std::string(s) + " as a double on line " + std::to_string(l) + " of file " + file_name + "\n";
95 }
96 void bad_bool(std::string_view s, int32_t l) {
98 "tried to parse " + std::string(s) + " as a boolean on line " + std::to_string(l) + " of file " + file_name + "\n";
99 }
100 void bad_int(std::string_view s, int32_t l) {
102 "tried to parse " + std::string(s) + " as an integer on line " + std::to_string(l) + " of file " + file_name + "\n";
103 }
104 void bad_unsigned_int(std::string_view s, int32_t l) {
105 accumulated_errors += "tried to parse " + std::string(s) + " as an unsigned integer on line " + std::to_string(l) +
106 " of file " + file_name + "\n";
107 }
108 void bad_association_token(std::string_view s, int32_t l) {
109 accumulated_errors += "tried to parse " + std::string(s) + " as equality or comparison on line " + std::to_string(l) +
110 " of file " + file_name + "\n";
111 }
112};
113
114bool float_from_chars(char const* start, char const* end, float& float_out); // returns true on success
115bool double_from_chars(char const* start, char const* end, double& dbl_out); // returns true on success
116
117std::string_view remove_surrounding_whitespace(std::string_view txt);
118
119float parse_float(std::string_view content, int32_t line, error_handler& err);
120double parse_double(std::string_view content, int32_t line, error_handler& err);
121bool parse_bool(std::string_view content, int32_t line, error_handler& err);
122int32_t parse_int(std::string_view content, int32_t line, error_handler& err);
123uint32_t parse_uint(std::string_view content, int32_t line, error_handler& err);
124uint32_t parse_tag(std::string_view content, int32_t line, error_handler& err);
125association_type parse_association_type(std::string_view content, int32_t line, error_handler& err);
126inline std::string_view parse_text(std::string_view content, int32_t line, error_handler& err) {
127 return content;
128}
129sys::year_month_day parse_date(std::string_view content, int32_t line, error_handler& err);
130
131//
132// CSV file parsing
133// Note: this does not parse CSV files according to the standard
134// instead it parses them according to the "paradox standard"
135//
136
138 char const* new_position = nullptr;
139 bool found = false;
140};
141
142char const* csv_advance(char const* start, char const* end, char seperator);
143char const* csv_advance_n(uint32_t n, char const* start, char const* end, char seperator);
144char const* csv_advance_to_next_line(char const* start, char const* end);
145separator_scan_result csv_find_separator_token(char const* start, char const* end, char seperator);
146
147template<size_t count_values, typename T>
148char const* parse_fixed_amount_csv_values(char const* start, char const* end, char separator, T&& function) {
149 std::string_view values[count_values];
150 for(uint32_t i = 0; i < count_values; ++i) {
151 auto r = csv_find_separator_token(start, end, separator);
152 values[i] = std::string_view(start, r.new_position - start);
153 start = r.new_position + int32_t(r.found);
154 }
155 function(values);
156
157 return csv_advance_to_next_line(start, end);
158}
159
160template<typename T>
161char const* parse_first_and_nth_csv_values(uint32_t nth, char const* start, char const* end, char separator, T&& function) {
162 auto first_separator = csv_find_separator_token(start, end, separator);
163
164 std::string_view first_value = std::string_view(start, first_separator.new_position - start);
165
166 start = csv_advance_n(nth - uint32_t(2), first_separator.new_position + int32_t(first_separator.found), end, separator);
167
168 auto second_end = csv_find_separator_token(start, end, separator);
169
170 function(first_value, std::string_view(start, second_end.new_position - start));
171 return csv_advance_to_next_line(second_end.new_position + int32_t(second_end.found), end);
172}
173
174template<size_t count_values, typename T>
175char const* parse_first_and_fixed_amount_csv_values(char const* start, char const* end, char separator, T&& function) {
176 auto first_separator = csv_find_separator_token(start, end, separator);
177 std::string_view first_value = std::string_view(start, first_separator.new_position - start);
178 start = first_separator.new_position + int32_t(first_separator.found);
179 for(uint32_t i = 0; i < count_values; ++i) {
180 auto r = csv_find_separator_token(start, end, separator);
181 function(first_value, std::string_view(start, r.new_position - start), i);
182 start = r.new_position + int32_t(r.found);
183 if(!r.found)
184 break;
185 }
186 return csv_advance_to_next_line(start, end);
187}
188
189//
190// other utility functions
191//
192
193bool is_integer(char const* start, char const* end);
194
195template<size_t N>
196bool has_fixed_prefix(char const* start, char const* end, char const (&t)[N]) {
197 if(end - start < ((std::ptrdiff_t)N - 1))
198 return false;
199 for(unsigned int i = 0; i < N - 1; ++i) {
200 if(start[i] != t[i])
201 return false;
202 }
203 return true;
204}
205
206template<size_t N>
207bool has_fixed_prefix_ci(char const* start, char const* end, char const (&t)[N]) {
208 if(end - start < ((std::ptrdiff_t)N - 1))
209 return false;
210 for(unsigned int i = 0; i < N - 1; ++i) {
211 if(tolower(start[i]) != t[i])
212 return false;
213 }
214 return true;
215}
216
217template<size_t N>
218bool has_fixed_suffix(char const* start, char const* end, char const (&t)[N]) {
219 if(end - start < ((std::ptrdiff_t)N - 1))
220 return false;
221 for(int32_t i = 0; i < int32_t(N) - 1; ++i) {
222 if(end[-1 - i] != t[(N - i) - 2])
223 return false;
224 }
225 return true;
226}
227
228template<size_t N>
229bool has_fixed_suffix_ci(char const* start, char const* end, char const (&t)[N]) {
230 if(end - start < ((std::ptrdiff_t)N - 1))
231 return false;
232 for(int32_t i = 0; i < int32_t(N) - 1; ++i) {
233 if(tolower(end[-1 - i]) != t[(N - i) - 2])
234 return false;
235 }
236 return true;
237}
238
239#ifdef _WIN64
240template<size_t N>
241bool native_has_fixed_suffix_ci(wchar_t const* start, wchar_t const* end, const wchar_t (&t)[N]) {
242 if(end - start < ((std::ptrdiff_t)N - 1))
243 return false;
244 for(int32_t i = 0; i < int32_t(N) - 1; ++i) {
245 if(towlower(end[-1 - i]) != t[(N - i) - 2])
246 return false;
247 }
248 return true;
249}
250#else
251template<size_t N>
252bool native_has_fixed_suffix_ci(char const* start, char const* end, char const (&t)[N]) {
253 if(end - start < ((std::ptrdiff_t)N - 1))
254 return false;
255 for(int32_t i = 0; i < int32_t(N) - 1; ++i) {
256 if(tolower(end[-1 - i]) != t[(N - i) - 2])
257 return false;
258 }
259 return true;
260}
261#endif
262
263template<size_t N>
264bool is_fixed_token(char const* start, char const* end, char const (&t)[N]) {
265 if(end - start != (N - 1))
266 return false;
267 for(unsigned int i = 0; i < N - 1; ++i) {
268 if(start[i] != t[i])
269 return false;
270 }
271 return true;
272}
273
274template<size_t N>
275bool is_fixed_token_ci(char const* start, char const* end, char const (&t)[N]) {
276 if(end - start != (N - 1))
277 return false;
278 for(unsigned int i = 0; i < N - 1; ++i) {
279 if(tolower(start[i]) != t[i])
280 return false;
281 }
282 return true;
283}
284} // namespace parsers
std::string accumulated_errors
Definition: parsers.hpp:62
void unhandled_group_key(token_and_type const &t)
Definition: parsers.hpp:68
std::string accumulated_warnings
Definition: parsers.hpp:63
void unhandled_free_group(token_and_type const &t)
Definition: parsers.hpp:80
void bad_int(std::string_view s, int32_t l)
Definition: parsers.hpp:100
void bad_date(std::string_view s, int32_t l)
Definition: parsers.hpp:84
void bad_double(std::string_view s, int32_t l)
Definition: parsers.hpp:92
void bad_association_token(std::string_view s, int32_t l)
Definition: parsers.hpp:108
std::string file_name
Definition: parsers.hpp:61
void unhandled_association_key(token_and_type const &t)
Definition: parsers.hpp:72
void bad_float(std::string_view s, int32_t l)
Definition: parsers.hpp:88
void bad_bool(std::string_view s, int32_t l)
Definition: parsers.hpp:96
error_handler(std::string file_name)
Definition: parsers.hpp:66
void bad_unsigned_int(std::string_view s, int32_t l)
Definition: parsers.hpp:104
void unhandled_free_value(token_and_type const &t)
Definition: parsers.hpp:76
token_generator(char const *file_start, char const *fe)
Definition: parsers.hpp:49
token_and_type get()
Definition: parsers.cpp:160
bool at_end() const
Definition: parsers.hpp:50
token_and_type next()
Definition: parsers.cpp:171
token_and_type next_next()
Definition: parsers.cpp:178
bool float_from_chars(char const *start, char const *end, float &float_out)
token_type
Definition: parsers.hpp:26
bool is_integer(char const *start, char const *end)
Definition: parsers.cpp:46
bool has_fixed_suffix_ci(char const *start, char const *end, char const (&t)[N])
Definition: parsers.hpp:229
char const * parse_fixed_amount_csv_values(char const *start, char const *end, char separator, T &&function)
Definition: parsers.hpp:148
char const * parse_first_and_nth_csv_values(uint32_t nth, char const *start, char const *end, char separator, T &&function)
Definition: parsers.hpp:161
char const * csv_advance_n(uint32_t n, char const *start, char const *end, char seperator)
Definition: parsers.cpp:348
separator_scan_result csv_find_separator_token(char const *start, char const *end, char seperator)
Definition: parsers.cpp:324
char const * parse_first_and_fixed_amount_csv_values(char const *start, char const *end, char separator, T &&function)
Definition: parsers.hpp:175
association_type
Definition: parsers.hpp:28
std::string_view parse_text(std::string_view content, int32_t line, error_handler &err)
Definition: parsers.hpp:126
char const * csv_advance(char const *start, char const *end, char seperator)
Definition: parsers.cpp:336
bool native_has_fixed_suffix_ci(char const *start, char const *end, char const (&t)[N])
Definition: parsers.hpp:252
bool is_fixed_token(char const *start, char const *end, char const (&t)[N])
Definition: parsers.hpp:264
bool double_from_chars(char const *start, char const *end, double &dbl_out)
bool is_fixed_token_ci(char const *start, char const *end, char const (&t)[N])
Definition: parsers.hpp:275
sys::year_month_day parse_date(std::string_view content, int32_t line, error_handler &err)
Definition: parsers.cpp:253
int32_t parse_int(std::string_view content, int32_t line, error_handler &err)
Definition: parsers.cpp:226
std::string_view remove_surrounding_whitespace(std::string_view txt)
Definition: parsers.cpp:381
bool parse_bool(std::string_view content, int32_t, error_handler &)
Definition: parsers.cpp:201
uint32_t parse_tag(std::string_view tag, int32_t line, error_handler &err)
Definition: parsers.cpp:244
bool has_fixed_suffix(char const *start, char const *end, char const (&t)[N])
Definition: parsers.hpp:218
float parse_float(std::string_view content, int32_t line, error_handler &err)
Definition: parsers.cpp:208
uint32_t parse_uint(std::string_view content, int32_t line, error_handler &err)
Definition: parsers.cpp:235
bool has_fixed_prefix_ci(char const *start, char const *end, char const (&t)[N])
Definition: parsers.hpp:207
association_type parse_association_type(std::string_view content, int32_t line, error_handler &err)
Definition: parsers.cpp:287
double parse_double(std::string_view content, int32_t line, error_handler &err)
Definition: parsers.cpp:218
char const * csv_advance_to_next_line(char const *start, char const *end)
Definition: parsers.cpp:368
bool has_fixed_prefix(char const *start, char const *end, char const (&t)[N])
Definition: parsers.hpp:196
uint uint32_t
std::string_view content
Definition: parsers.hpp:31