fix(group): named parsers are tried in unnamed parsing
This commit is contained in:
parent
1f05551be1
commit
e510584b98
@ -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;
|
||||||
}
|
}
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user