fix(group): named parsers are tried in unnamed parsing

This commit is contained in:
TopchetoEU 2022-10-28 10:07:52 +03:00
parent 1f05551be1
commit e510584b98
2 changed files with 22 additions and 13 deletions

View File

@ -3,6 +3,7 @@
#include <string> #include <string>
#include <set> #include <set>
#include <map> #include <map>
#include <unordered_set>
#include <unordered_map> #include <unordered_map>
#include <memory> #include <memory>
#include "compiler/treeifier/tokenizer.hh" #include "compiler/treeifier/tokenizer.hh"
@ -22,6 +23,7 @@ namespace ppc::comp::tree::ast {
class group_t { class group_t {
private: private:
std::map<lang::namespace_name_t, std::string> named_parsers; std::map<lang::namespace_name_t, std::string> named_parsers;
std::set<std::string> unnamed_parsers;
std::map<std::string, parser_t> parsers; std::map<std::string, parser_t> parsers;
public: public:
group_t &insert(const std::string &name, parser_t parser, const std::string &relative_to, bool after); group_t &insert(const std::string &name, parser_t parser, const std::string &relative_to, bool after);
@ -74,6 +76,7 @@ namespace ppc::comp::tree::ast {
loc_namespace_name_t map_to_nmsp(const data::map_t &map); loc_namespace_name_t map_to_nmsp(const data::map_t &map);
} }
parser_func_t parse_glob, parse_nmsp, parse_identifier, parse_type, parse_func, parse_field, parse_exp, parse_stat_exp; parser_func_t parse_glob, parse_nmsp, parse_identifier, parse_type, parse_exp, parse_stat_exp;
parser_func_t parse_func, parse_field, parse_export;
parser_func_t parse_exp_var, parse_exp_str_lit, parse_exp_int_lit, parse_exp_float_lit; parser_func_t parse_exp_var, parse_exp_str_lit, parse_exp_int_lit, parse_exp_float_lit;
} }

View File

@ -4,6 +4,7 @@
#include <algorithm> #include <algorithm>
#include <unordered_map> #include <unordered_map>
#include <sstream> #include <sstream>
#include <string>
using namespace ppc::comp::tree; using namespace ppc::comp::tree;
using namespace ppc::comp::tree::ast; using namespace ppc::comp::tree::ast;
@ -15,7 +16,7 @@ static bool read_nmsp(ast_ctx_t &ctx, size_t &i, lang::loc_namespace_name_t &nam
map_t res; map_t res;
if (!h.parse(parse_nmsp, res)) return false; if (!h.parse(parse_nmsp, res)) return false;
name = conv::map_to_nmsp(res); name = conv::map_to_nmsp(res);
return true; return h.submit(false);
} }
template <class T> template <class T>
static bool resolve_nmsp(ast_ctx_t &ctx, const lang::namespace_name_t &name, T begin, T end, lang::namespace_name_t &actual_name) { static bool resolve_nmsp(ast_ctx_t &ctx, const lang::namespace_name_t &name, T begin, T end, lang::namespace_name_t &actual_name) {
@ -45,14 +46,14 @@ group_t &group_t::insert(const std::string &name, parser_t parser, const std::st
throw "The parser '" + name + "' is already in the group."; throw "The parser '" + name + "' is already in the group.";
} }
auto it = parsers.find(relative_to); auto it = unnamed_parsers.find(relative_to);
if (it == parsers.end()) { if (it == unnamed_parsers.end()) {
throw "The parser '" + relative_to + "' isn't in the group."; throw "The parser '" + relative_to + "' isn't in the group or isn't unnamed.";
} }
if (after) it++; if (after) it++;
parsers.insert(it, { name, parser }); unnamed_parsers.insert(it, name);
return *this; return *this;
} }
@ -73,11 +74,18 @@ group_t &group_t::add_last(const std::string &name, parser_t parser) {
} }
parsers.emplace(name, parser); parsers.emplace(name, parser);
unnamed_parsers.emplace(name);
return *this; return *this;
} }
group_t &group_t::add_named(const std::string &name, parser_t parser, const lang::namespace_name_t &identifier) { group_t &group_t::add_named(const std::string &name, parser_t parser, const lang::namespace_name_t &identifier) {
add_last(name, parser); if (parsers.find(name) != parsers.end()) {
throw "The parser '" + name + "' is already in the group.";
}
parsers.emplace(name, parser);
named_parsers.emplace(identifier, name);
return *this; return *this;
} }
@ -92,16 +100,14 @@ bool group_t::operator()(ast_ctx_t &ctx, size_t &i, data::map_t &out) const {
if (resolve_nmsp(ctx, name.strip_location(), named_parsers.begin(), named_parsers.end(), actual)) { if (resolve_nmsp(ctx, name.strip_location(), named_parsers.begin(), named_parsers.end(), actual)) {
auto parser = parsers.find(this->named_parsers.find(actual)->second); auto parser = parsers.find(this->named_parsers.find(actual)->second);
out["$_name"] = parser->first; out["$_name"] = parser->first;
if (parser->second(ctx, i, out)) return true; if (h.parse(parser->second, out)) return h.submit(false);
else throw message_t::error("Unexpected construct specifier.", h.res_loc()); else throw message_t::error("Unexpected construct specifier.", h.res_loc());
} }
} }
unordered_map<string, message_t> errors; for (auto name : unnamed_parsers) {
out["$_name"] = name;
for (auto parser : parsers) { if (parsers.at(name)(ctx, i, out)) return true;
out["$_name"] = parser.first;
if ((*parser.second)(ctx, i, out)) return true;
} }
stringstream m; stringstream m;