41 std::vector<group_association>
groups;
42 std::vector<value_association>
values;
72 case token_type::none:
return "none";
73 case token_type::group_ident:
return "group_ident";
74 case token_type::group_item_ident:
return "group_item_ident";
75 case token_type::ident:
return "ident";
76 case token_type::lparen:
return "(";
77 case token_type::rparen:
return ")";
78 case token_type::newline:
return "newline";
97 char_facet = &std::use_facet<std::ctype<char>>(std::locale(
"C"));
102 if(local_loc_info.
row > 0) {
103 if(local_loc_info.
column > 0)
104 console_stream <<
"(" << std::to_string(local_loc_info.
row) <<
"," << std::to_string(local_loc_info.
column) <<
")";
108 console_stream <<
": " << severity <<
" " << std::to_string(code) <<
": " << fmt.data() <<
"\n";
112 report_any(
"error", code, local_loc_info, fmt);
116size_t get_column(std::string_view
const s, std::string_view::iterator
const it) {
117 return size_t(std::distance(s.begin(), it));
121 return std::isalnum(c) || c ==
'#' || c ==
'@' || c ==
'_';
128 auto it = line.begin();
130 while(it != line.cend()) {
133 if(it == line.begin() && (std::isspace(*it) || *it ==
',')) {
134 tok.
type = token_type::group_item_ident;
136 }
else if(it == line.begin()) {
137 tok.type = token_type::group_ident;
141 if(std::isspace(*it) || *it ==
',')
143 if(it == line.cend())
147 while(std::isspace(*it) || *it ==
',')
149 if(it == line.cend()) {
155 tok.type = token_type::lparen;
157 }
else if(*it ==
')') {
158 tok.type = token_type::rparen;
161 if(tok.type != token_type::group_ident && tok.type != token_type::group_item_ident)
162 tok.type = token_type::ident;
163 auto start_ident = it;
164 while(it != line.cend() &&
is_ident(*it))
166 auto start_idx = std::distance(line.begin(), start_ident);
167 auto end_idx = std::distance(line.begin(), it);
168 tok.data = line.substr(start_idx, end_idx - start_idx);
171 bool violated_casing =
false;
172 for(
auto const c : tok.data)
173 if(std::isalpha(c) && !std::islower(c)) {
174 violated_casing =
true;
190 for(std::string line; std::getline(stream, line); ) {
195 tok.type = token_type::newline;
203 return std::optional(*it++);
214 token tok{o.value()};
215 if(tok.type != type) {
225 while(it !=
tokens.end()) {
227 if(key.type == token_type::group_ident) {
228 if(key.data[0] ==
'#') {
229 groups.back().group_context_type = key.data.substr(1);
232 groups.back().group_object_type = key.data;
234 }
else if(key.type == token_type::group_item_ident) {
236 report_error(120, key.loc_info,
"Item '" + key.data +
"' defined before first group\n");
240 if(key.data ==
"#free") {
241 auto err_cond =
false;
247 auto const handler_opt = tmp.type == token_type::lparen
250 if(tmp.type == token_type::lparen)
256 if(type.data ==
"parser" || type.data ==
"group") {
258 }
else if(type.data ==
"extern") {
260 }
else if(type.data ==
"value") {
261 groups.back().single_value_handler_type = opt.data;
264 report_error(102, type.loc_info,
"Invalid #free type '" + type.data +
"'\n");
266 }
else if(key.data ==
"#base") {
267 auto err_cond =
false;
273 if(g.group_object_type == base_class_name.data) {
274 for(
auto& v : g.groups)
275 groups.back().groups.push_back(v);
276 for(
auto& v : g.values)
277 groups.back().values.push_back(v);
278 groups.back().any_group_handler = g.any_group_handler;
279 groups.back().any_value_handler = g.any_value_handler;
280 groups.back().single_value_handler_result = g.single_value_handler_result;
281 groups.back().single_value_handler_type = g.single_value_handler_type;
282 groups.back().any_value_handler = g.any_value_handler;
283 groups.back().set_handler = g.set_handler;
286 }
else if(key.data ==
"#any") {
288 auto err_cond =
false;
294 auto const handler_opt = tmp.type == token_type::lparen
297 if(tmp.type == token_type::lparen)
303 static std::vector<std::string_view>
const valid_group_handler_values = {
304 "discard",
"member",
"member_fn",
"function"
307 if(type.data ==
"parser" || type.data ==
"group") {
309 }
else if(type.data ==
"value") {
311 }
else if(type.data ==
"extern") {
314 if(std::find(valid_group_handler_values.begin(), valid_group_handler_values.end(),
groups.back().any_group_handler.handler.value) == valid_group_handler_values.end())
315 report_error(104, type.loc_info,
"Unhandled #any group '" + type.data +
"' with invalid handler_type '" + handler_type.data +
"'\n");
317 report_error(103, type.loc_info,
"Invalid #any type '" + type.data +
"'\n");
321 auto err_cond =
false;
327 auto const handler_opt = tmp.type == token_type::lparen
330 if(tmp.type == token_type::lparen)
333 if(std::find_if(
groups.back().groups.begin(),
groups.back().groups.end(), [&](
auto const& g) { return g.key == key.data; }) !=
groups.back().groups.end()) {
334 report_error(116, type.loc_info,
"Duplicate key '" + key.data +
"' in group '" +
groups.back().group_object_type +
"'\n");
341 if(key.data.empty()) {
342 report_error(118, type.loc_info,
"Empty member '" + type.data +
"' in group '" +
groups.back().group_object_type +
"'\n");
345 if(type.data ==
"parser" || type.data ==
"group") {
347 }
else if(type.data ==
"value") {
349 }
else if(type.data ==
"extern") {
352 report_error(104, type.loc_info,
"Invalid #free type '" + type.data +
"'\n");
355 }
else if(key.type == token_type::newline) {
365 static std::string_view hexmap =
"0123456789ABCDEF";
368 temp.push_back(hexmap[(v / 16) % 16]);
369 temp.push_back(hexmap[v % 16]);
373std::string
string_to_hex(std::string_view
const s, int32_t start, int32_t count) {
374 std::string res =
"0x";
375 for(int32_t i = count - 1; i >= 0; --i)
381 if(starting_position >= ending_position)
384 if(ending_position - starting_position >= 8) {
386 " && (*(uint64_t const*)(&cur.content[" + std::to_string(starting_position) +
"]) | uint64_t(0x2020202020202020) ) == uint64_t(" +
string_to_hex(key, starting_position, 8) +
")"
388 }
else if(ending_position - starting_position >= 4) {
390 " && (*(uint32_t const*)(&cur.content[" + std::to_string(starting_position) +
"]) | uint32_t(0x20202020) ) == uint32_t(" +
string_to_hex(key, starting_position, 4) +
")"
392 }
else if(ending_position - starting_position >= 2) {
394 " && (*(uint16_t const*)(&cur.content[" + std::to_string(starting_position) +
"]) | 0x2020 ) == " +
string_to_hex(key, starting_position, 2)
397 return " && (cur.content[" + std::to_string(starting_position) +
"] | 0x20 ) == " +
string_to_hex(key, starting_position, 1);
403 ending_position = key.length();
404 assert(ending_position <= key.length());
405 assert(starting_position <= ending_position);
409template<
typename V,
typename F>
410void enum_with_prefix(V
const& vector, std::string_view
const prefix, int32_t length, F
const& fn) {
411 for(int32_t i = 0; i < int32_t(vector.size()); ++i) {
414 if(int32_t(vector[i].key.length()) == length) {
416 for(int32_t j = 0; j < int32_t(prefix.length()); ++j) {
417 if((vector[i].key[j] | 0x20) != (prefix[j] | 0x20)) {
441 for(
auto const& e : vector)
442 mx = mx > int32_t(e.key.length()) ? mx : int32_t(e.key.length());
450 tabs.push_back(
'\t');
457std::string
tabulate(std::string_view
const s)
const {
458 return tabs + s.data();
464 for(int32_t c = 32; c <= 95; ++c) {
466 if(top_count == count) {
474template<
typename V,
typename F>
475std::string
construct_match_tree_internal(V
const& vector, F
const& generator_match, std::string_view
const no_match, std::string_view
const prefix, int32_t length) {
478 bool has_switch =
false;
479 for(int32_t c = 32; c <= 95; ++c) {
480 int32_t count =
count_with_prefix(vector, std::string(prefix) +
char(c), length);
483 }
else if(top_count == count) {
491 assert(!running_prefix.empty());
492 output +=
tabulate(
"// " + running_prefix +
"\n");
493 assert(running_prefix.length() > prefix.length() && running_prefix != prefix);
495 output +=
tabulate(
"// running - " + running_prefix.substr(prefix.length()) +
"\n");
503 output +=
tabulate(std::string(no_match) +
"\n");
506 }
else if(count == 1) {
508 output +=
tabulate(
"switch(0x20 | int32_t(cur.content[" + std::to_string(prefix.length()) +
"])) {\n");
514 enum_with_prefix(vector, std::string(prefix) +
char(c), length, [&](
auto& v) {
515 output +=
tabulate(
"// " + v.key +
"\n");
518 output +=
tabulate(generator_match(v) +
"\n");
522 output +=
tabulate(std::string(no_match) +
"\n");
530 output +=
tabulate(
"switch(0x20 | int32_t(cur.content[" + std::to_string(prefix.length()) +
"])) {\n");
545 output +=
tabulate(std::string(no_match) +
"\n");
555 std::string output =
tabulate(
"switch(int32_t(cur.content.length())) {\n");
556 for(int32_t l = 1; l <= maxlen; ++l) {
560 }
else if(count == 1) {
561 output +=
tabulate(
"case " + std::to_string(l) +
":\n");
564 output +=
tabulate(
"// " + v.key +
"\n");
567 output +=
tabulate(generator_match(v) +
"\n");
571 output +=
tabulate(std::string(no_match) +
"\n");
578 output +=
tabulate(
"case " + std::to_string(l) +
":\n");
587 output +=
tabulate(std::string(no_match) +
"\n");
597 output +=
"#include \"parsers.hpp\"\n";
602 output +=
"namespace parsers {\n";
604 std::vector<bool> declared_groups(groups.size(),
false);
605 for(
size_t i = 0; i < groups.size(); i++) {
606 auto const& g = groups[i];
608 for(
size_t j = 0; j < groups.size(); j++)
609 if(!declared_groups[j]) {
610 bool fwd_decl =
false;
611 auto const& f = groups[j];
612 fwd_decl = f.group_object_type == g.any_group_handler.handler.opt
613 || f.group_object_type == g.set_handler.handler.opt
614 || f.group_object_type == g.any_value_handler.handler.opt;
615 for(
const auto& e : g.groups)
616 fwd_decl = fwd_decl || f.group_object_type == e.handler.opt;
617 for(
const auto& e : g.values)
618 fwd_decl = fwd_decl || f.group_object_type == e.handler.opt;
620 declared_groups[j] = fwd_decl;
621 if(g.group_context_type.empty()) {
622 output +=
"template<typename C>\n";
623 output += g.group_object_type +
" parse_" + g.group_object_type +
"(token_generator& gen, error_handler& err, C&& context);\n";
625 output += g.group_object_type +
" parse_" + g.group_object_type +
"(token_generator& gen, error_handler& err, " + g.group_context_type +
"&& context);\n";
629 declared_groups[i] =
true;
631 if(g.group_context_type.empty()) {
632 output +=
"template<typename C>\n";
633 output += g.group_object_type +
" parse_" + g.group_object_type +
"(token_generator& gen, error_handler& err, C&& context) {\n";
635 output += g.group_object_type +
" parse_" + g.group_object_type +
"(token_generator& gen, error_handler& err, " + g.group_context_type +
"&& context) {\n";
638 output +=
"\t" + g.group_object_type +
" cobj;\n";
639 output +=
"\tfor(token_and_type cur = gen.get(); cur.type != token_type::unknown && cur.type != token_type::close_brace; cur = gen.get()) {\n";
641 output +=
"\t\tif(cur.type == token_type::open_brace) { \n";
646 std::string set_effect;
647 if(g.set_handler.is_extern ==
false) {
648 if(g.set_handler.handler.value ==
"discard") {
649 set_effect =
"gen.discard_group();";
650 }
else if(g.set_handler.handler.value ==
"member") {
651 set_effect =
"cobj." +
652 (g.set_handler.handler.opt.length() > 0 ? g.set_handler.handler.opt : std::string(
"free_group")) +
653 " = parse_" + g.set_handler.type_or_function +
"(gen, err, context);";
654 }
else if(g.set_handler.handler.value ==
"member_fn") {
655 set_effect =
"cobj." +
656 (g.set_handler.handler.opt.length() > 0 ? g.set_handler.handler.opt : std::string(
"free_group")) +
657 "(parse_" + g.set_handler.type_or_function +
"(gen, err, context), err, cur.line, context);";
658 }
else if(g.set_handler.handler.value ==
"function") {
660 (g.set_handler.handler.opt.length() > 0 ? g.set_handler.handler.opt : std::string(
"free_group")) +
661 "(cobj, parse_" + g.set_handler.type_or_function +
"(gen, err, context), err, cur.line, context);";
663 set_effect =
"err.unhandled_free_group(cur); gen.discard_group();";
666 if(g.set_handler.handler.value ==
"discard") {
667 set_effect =
"gen.discard_group();";
668 }
else if(g.set_handler.handler.value ==
"member") {
669 set_effect =
"cobj." +
670 (g.set_handler.handler.opt.length() > 0 ? g.set_handler.handler.opt : std::string(
"free_group")) +
671 " = " + g.set_handler.type_or_function +
"(gen, err, context);";
672 }
else if(g.set_handler.handler.value ==
"member_fn") {
673 set_effect =
"cobj." +
674 (g.set_handler.handler.opt.length() > 0 ? g.set_handler.handler.opt : std::string(
"free_group")) +
675 "(" + g.set_handler.type_or_function +
"(gen, err, context), err, cur.line, context);";
676 }
else if(g.set_handler.handler.value ==
"function") {
678 (g.set_handler.handler.opt.length() > 0 ? g.set_handler.handler.opt : std::string(
"free_group")) +
679 "(cobj, " + g.set_handler.type_or_function +
"(gen, err, context), err, cur.line, context);";
681 set_effect =
"err.unhandled_free_group(cur); gen.discard_group();";
684 output +=
"\t\t\t" + set_effect +
"\n";
685 output +=
"\t\t\tcontinue;\n";
688 output +=
"\t\tauto peek_result = gen.next();\n";
689 output +=
"\t\tif(peek_result.type == token_type::special_identifier) {\n";
690 output +=
"\t\t\tauto peek2_result = gen.next_next();\n";
691 output +=
"\t\t\tif(peek2_result.type == token_type::open_brace) {\n";
693 output +=
"\t\t\t\tgen.get(); gen.get();\n";
705 std::string no_match_effect;
706 if(g.any_group_handler.is_extern ==
false) {
707 if(g.any_group_handler.handler.value ==
"discard") {
708 no_match_effect =
"gen.discard_group();";
709 }
else if(g.any_group_handler.handler.value ==
"member") {
710 no_match_effect =
"cobj." +
711 (g.any_group_handler.handler.opt.length() > 0 ? g.any_group_handler.handler.opt : std::string(
"any_group")) +
712 " = parse_" + g.any_group_handler.type_or_function +
"(gen, err, context);";
713 }
else if(g.any_group_handler.handler.value ==
"member_fn") {
714 no_match_effect =
"cobj." +
715 (g.any_group_handler.handler.opt.length() > 0 ? g.any_group_handler.handler.opt : std::string(
"any_group")) +
716 "(cur.content, parse_" + g.any_group_handler.type_or_function +
"(gen, err, context), err, cur.line, context);";
717 }
else if(g.any_group_handler.handler.value ==
"function") {
719 (g.any_group_handler.handler.opt.length() > 0 ? g.any_group_handler.handler.opt : std::string(
"any_group")) +
720 "(cobj, cur.content, parse_" + g.any_group_handler.type_or_function +
"(gen, err, context), err, cur.line, context);";
722 no_match_effect =
"err.unhandled_group_key(cur); gen.discard_group();";
725 if(g.any_group_handler.handler.value ==
"discard") {
726 no_match_effect = g.any_group_handler.type_or_function +
"(cur.content, gen, err, context);";
727 }
else if(g.any_group_handler.handler.value ==
"member") {
728 no_match_effect =
"cobj." +
729 (g.any_group_handler.handler.opt.length() > 0 ? g.any_group_handler.handler.opt : std::string(
"any_group")) +
730 " = " + g.any_group_handler.type_or_function +
"(cur.content, gen, err, context);";
731 }
else if(g.any_group_handler.handler.value ==
"member_fn") {
732 no_match_effect =
"cobj." +
733 (g.any_group_handler.handler.opt.length() > 0 ? g.any_group_handler.handler.opt : std::string(
"any_group")) +
734 "(cur.content, " + g.any_group_handler.type_or_function +
"(cur.content, gen, err, context), err, cur.line, context);";
735 }
else if(g.any_group_handler.handler.value ==
"function") {
737 (g.any_group_handler.handler.opt.length() > 0 ? g.any_group_handler.handler.opt : std::string(
"any_group")) +
738 "(cobj, cur.content, " + g.any_group_handler.type_or_function +
"(cur.content, gen, err, context), err, cur.line, context);";
740 no_match_effect =
"err.unhandled_group_key(cur); gen.discard_group();";
756 if(v.handler.value ==
"discard") {
757 out = v.type_or_function +
"(gen, err, context);";
758 }
else if(v.handler.value ==
"member") {
759 out =
"cobj." + (v.handler.opt.length() > 0 ? v.handler.opt : v.key) +
760 " = " + v.type_or_function +
"(gen, err, context);";
761 }
else if(v.handler.value ==
"member_fn") {
762 out =
"cobj." + (v.handler.opt.length() > 0 ? v.handler.opt : v.key) +
763 "(" + v.type_or_function +
"(gen, err, context), err, cur.line, context);";
764 }
else if(v.handler.value ==
"function") {
765 out = (v.handler.opt.length() > 0 ? v.handler.opt : v.key) +
766 "(cobj, " + v.type_or_function +
"(gen, err, context), err, cur.line, context);";
768 out =
"err.unhandled_group_key(cur);";
771 if(v.handler.value ==
"discard") {
772 out =
"gen.discard_group();";
773 }
else if(v.handler.value ==
"member") {
774 out =
"cobj." + (v.handler.opt.length() > 0 ? v.handler.opt : v.key) +
775 " = parse_" + v.type_or_function +
"(gen, err, context);";
776 }
else if(v.handler.value ==
"member_fn") {
777 out =
"cobj." + (v.handler.opt.length() > 0 ? v.handler.opt : v.key) +
778 "(parse_" + v.type_or_function +
"(gen, err, context), err, cur.line, context);";
779 }
else if(v.handler.value ==
"function") {
780 out = (v.handler.opt.length() > 0 ? v.handler.opt : v.key) +
781 "(cobj, parse_" + v.type_or_function +
"(gen, err, context), err, cur.line, context);";
783 out =
"err.unhandled_group_key(cur);";
798 output +=
"\t\t\t} else {\n";
799 output +=
"\t\t\t\tauto const assoc_token = gen.get();\n";
800 output +=
"\t\t\t\tauto const assoc_type = parse_association_type(assoc_token.content, assoc_token.line, err);\n";
801 output +=
"\t\t\t\tauto const rh_token = gen.get();\n";
804 std::string no_match_effect;
805 if(g.any_value_handler.handler.value ==
"discard") {
806 }
else if(g.any_value_handler.handler.value ==
"member") {
807 no_match_effect =
"cobj." +
808 (g.any_value_handler.handler.opt.length() > 0 ? g.any_value_handler.handler.opt : std::string(
"any_value")) +
809 " = parse_" + g.any_value_handler.type +
"(rh_token.content, rh_token.line, err);";
810 }
else if(g.any_value_handler.handler.value ==
"member_fn") {
811 no_match_effect =
"cobj." +
812 (g.any_value_handler.handler.opt.length() > 0 ? g.any_value_handler.handler.opt : std::string(
"any_value")) +
813 "(cur.content, assoc_type, parse_" + g.any_value_handler.type +
"(rh_token.content, rh_token.line, err), err, cur.line, context);";
814 }
else if(g.any_value_handler.handler.value ==
"function") {
816 (g.any_value_handler.handler.opt.length() > 0 ? g.any_value_handler.handler.opt : std::string(
"any_value")) +
817 "(cobj, cur.content, assoc_type, parse_" + g.any_value_handler.type +
"(rh_token.content, rh_token.line, err), err, cur.line, context);";
819 no_match_effect =
"err.unhandled_association_key(cur);";
833 if(v.handler.value ==
"discard") {
834 }
else if(v.handler.value ==
"member") {
835 out =
"cobj." + (v.handler.opt.length() > 0 ? v.handler.opt : v.key) +
836 " = parse_" + v.type +
"(rh_token.content, rh_token.line, err);";
837 }
else if(v.handler.value ==
"member_fn") {
838 out =
"cobj." + (v.handler.opt.length() > 0 ? v.handler.opt : v.key) +
839 "(assoc_type, parse_" + v.type +
"(rh_token.content, rh_token.line, err), err, cur.line, context);";
840 }
else if(v.handler.value ==
"function") {
841 out = (v.handler.opt.length() > 0 ? v.handler.opt : v.key) +
842 "(cobj, assoc_type, parse_" + v.type +
"(rh_token.content, rh_token.line, err), err, cur.line, context);";
844 out =
"err.unhandled_association_key(cur);";
858 output +=
"\t\t\t}\n";
859 output +=
"\t\t} else {\n";
861 if(g.single_value_handler_result.value.length() > 0) {
862 if(g.single_value_handler_result.value ==
"discard") {
864 }
else if(g.single_value_handler_result.value ==
"member") {
865 output +=
"\t\t\tcobj." +
866 (g.single_value_handler_result.opt.length() > 0 ? g.single_value_handler_result.opt : std::string(
"free_value")) +
867 "= parse_" + g.single_value_handler_type +
"(cur.content, cur.line, err);\n";
868 }
else if(g.single_value_handler_result.value ==
"member_fn") {
869 output +=
"\t\t\tcobj." +
870 (g.single_value_handler_result.opt.length() > 0 ? g.single_value_handler_result.opt : std::string(
"free_value")) +
871 "(parse_" + g.single_value_handler_type +
"(cur.content, cur.line, err), err, cur.line, context);\n";
872 }
else if(g.single_value_handler_result.value ==
"function") {
874 (g.single_value_handler_result.opt.length() > 0 ? g.single_value_handler_result.opt : std::string(
"free_value")) +
875 "(cobj, parse_" + g.single_value_handler_type +
"(cur.content, cur.line, err), err, cur.line, context);\n";
878 output +=
"\t\t\terr.unhandled_free_value(cur);\n";
882 output +=
"\tcobj.finish(context);\n";
883 output +=
"\treturn cobj;\n";
891 stream.write(output.data(), output.size());
895int main(
int argc,
char *argv[]) {
897 auto const input_filename = std::string(argv[1]);
898 std::string output_filename;
900 output_filename = std::string(argv[2]);
902 output_filename = std::string(argv[1]);
903 if(output_filename.length() >= 4 && output_filename[output_filename.length() - 4] ==
'.') {
904 output_filename.pop_back();
905 output_filename.pop_back();
906 output_filename.pop_back();
907 output_filename.pop_back();
909 output_filename +=
"_generated.hpp";
912 std::fstream input_file;
913 input_file.open(input_filename, std::ios::in);
915 std::fstream output_file;
916 output_file.open(output_filename, std::ios::out);
918 std::stringstream file_contents_stream{std::string((std::istreambuf_iterator<char>(input_file)), std::istreambuf_iterator<char>{})};
920 state.tokenize_file(file_contents_stream);
923 std::cout << state.console_stream.str() << std::endl;
924 if(state.error_count > 0)
925 std::exit(EXIT_FAILURE);
930 fprintf(stderr,
"Usage: %s <input> [output]\n", argv[0]);
#define assert(condition)
int main(int argc, char *argv[])
std::string final_match_condition(std::string_view const key, size_t starting_position, size_t ending_position)
std::string final_match_condition_internal(std::string_view const key, int32_t starting_position, int32_t ending_position)
std::string string_to_hex(std::string_view const s, int32_t start, int32_t count)
std::string char_to_hex(char c)
int32_t max_length(V const &vector)
void enum_with_prefix(V const &vector, std::string_view const prefix, int32_t length, F const &fn)
int32_t count_with_prefix(V const &vector, std::string_view const prefix, int32_t length)
std::string construct_match_tree_internal(V const &vector, F const &generator_match, std::string_view const no_match, std::string_view const prefix, int32_t length)
std::string construct_match_tree_outer(auto const &vector, auto const &generator_match, std::string_view const no_match)
void tabulate_decrement()
std::string tabulate(std::string_view const s) const
void tabulate_increment()
std::string get_match_tree_running_prefix(V const &vector, std::string prefix, int32_t length)
void file_write_out(std::fstream &stream, std::vector< group_contents > &groups)
std::string type_or_function
value_and_optional handler
std::string single_value_handler_type
std::string group_context_type
group_association set_handler
std::vector< value_association > values
std::string group_object_type
value_association any_value_handler
value_and_optional single_value_handler_result
std::vector< group_association > groups
group_association any_group_handler
location_info(int _row, int _column)
size_t get_column(std::string_view const s, std::string_view::iterator const it)
void tokenize_file(std::stringstream &stream)
void report_any(std::string_view const severity, int code, location_info local_loc_info, std::string_view const fmt)
void tokenize_line(std::string_view const line)
std::string_view file_name
std::ctype< char > const * char_facet
void report_error(int code, location_info local_loc_info, std::string_view const fmt)
std::vector< group_contents > groups
token get_specific_token(auto &it, bool &err_cond, token_type const &type)
parser_state(std::string_view const _file_name)
std::optional< token > get_token(auto &it)
std::stringstream console_stream
std::vector< token > tokens
static std::string_view get_type_name(token_type const &type)
value_and_optional handler