chore: improve named constructs in groups

This commit is contained in:
TopchetoEU 2022-10-20 14:30:19 +03:00
parent 0cb7e25097
commit eb167d0a50
5 changed files with 75 additions and 62 deletions

View File

@ -2,6 +2,7 @@
#include <string> #include <string>
#include <set> #include <set>
#include <map>
#include <unordered_map> #include <unordered_map>
#include <memory> #include <memory>
#include "compiler/treeifier/tokenizer.hh" #include "compiler/treeifier/tokenizer.hh"
@ -56,6 +57,7 @@ namespace ppc::comp::tree::ast {
void add_parser(const parser_t *parser); void add_parser(const parser_t *parser);
void add_parser(const parser_t *parser, const std::string &group); void add_parser(const parser_t *parser, const std::string &group);
void add_parser(const parser_t *parser, const std::string &group, const namespace_name_t &name);
void add_group(const std::string &name); void add_group(const std::string &name);
void add_parser(parser_adder_t factory) { factory(*this); } void add_parser(parser_adder_t factory) { factory(*this); }
@ -107,7 +109,7 @@ namespace ppc::comp::tree::ast {
class group_parser_t : public parser_t { class group_parser_t : public parser_t {
private: private:
std::vector<std::pair<lang::namespace_name_t, const parser_t*>> named_parsers; std::map<lang::namespace_name_t, const parser_t*> named_parsers;
std::vector<const parser_t*> parsers; std::vector<const parser_t*> parsers;
public: public:
group_parser_t &add(const parser_t &parser); group_parser_t &add(const parser_t &parser);

View File

@ -32,8 +32,14 @@ namespace ppc::lang {
struct namespace_name_t : public std::vector<std::string> { struct namespace_name_t : public std::vector<std::string> {
using base = std::vector<std::string>; using base = std::vector<std::string>;
bool operator ==(const namespace_name_t &other) const; int compare(const namespace_name_t &other) const;
bool operator !=(const namespace_name_t &other) const;
bool operator==(const namespace_name_t &other) const { return compare(other) == 0; }
bool operator!=(const namespace_name_t &other) const { return compare(other) != 0; }
bool operator<(const namespace_name_t &other) const { return compare(other) < 0; }
bool operator<=(const namespace_name_t &other) const { return compare(other) <= 0; }
bool operator>(const namespace_name_t &other) const { return compare(other) > 0; }
bool operator>=(const namespace_name_t &other) const { return compare(other) >= 0; }
operator std::string() const { return to_string(); } operator std::string() const { return to_string(); }
std::string to_string() const; std::string to_string() const;
@ -45,10 +51,16 @@ namespace ppc::lang {
struct loc_namespace_name_t : public std::vector<located_t<std::string>> { struct loc_namespace_name_t : public std::vector<located_t<std::string>> {
using base = std::vector<located_t<std::string>>; using base = std::vector<located_t<std::string>>;
bool operator ==(const loc_namespace_name_t &other) const; int compare(const loc_namespace_name_t &other) const;
bool operator !=(const loc_namespace_name_t &other) const;
namespace_name_t strip_location(); bool operator==(const loc_namespace_name_t &other) const { return compare(other) == 0; }
bool operator!=(const loc_namespace_name_t &other) const { return compare(other) != 0; }
bool operator<(const loc_namespace_name_t &other) const { return compare(other) < 0; }
bool operator<=(const loc_namespace_name_t &other) const { return compare(other) <= 0; }
bool operator>(const loc_namespace_name_t &other) const { return compare(other) > 0; }
bool operator>=(const loc_namespace_name_t &other) const { return compare(other) >= 0; }
namespace_name_t strip_location() const;
operator std::string() const { return to_string(); } operator std::string() const { return to_string(); }
std::string to_string() const; std::string to_string() const;

View File

@ -28,6 +28,10 @@ namespace ppc::comp::tree::ast {
add_parser(parser); add_parser(parser);
this->group[group].add(*parser); this->group[group].add(*parser);
} }
void ast_ctx_t::add_parser(const parser_t *parser, const std::string &group, const namespace_name_t &name) {
add_parser(parser);
this->group[group].add(*parser, name);
}
void ast_ctx_t::add_group(const std::string &name) { void ast_ctx_t::add_group(const std::string &name) {
auto parser = new group_parser_t(name); auto parser = new group_parser_t(name);
if (parsers.find(parser->name()) != parsers.end()) throw "The parser '" + parser->name() + "' already exists."; if (parsers.find(parser->name()) != parsers.end()) throw "The parser '" + parser->name() + "' already exists.";

View File

@ -10,26 +10,34 @@ using namespace ppc::comp::tree::ast;
using namespace std::string_literals; using namespace std::string_literals;
using namespace std; using namespace std;
static bool read_nmsp(ast_ctx_t &ctx, size_t &i, const lang::namespace_name_t &name) { static bool read_nmsp(ast_ctx_t &ctx, size_t &i, lang::loc_namespace_name_t &name) {
tree_helper_t h(ctx, i); tree_helper_t h(ctx, i);
map_t res;
size_t equal_i = 0; if (!h.parse("$_nmsp", res)) return false;
name = conv::map_to_nmsp(res);
while (true) { return true;
if (h.ended()) break;
if (equal_i >= name.size()) return false;
auto &curr = h.curr();
if (!curr.is_identifier()) return false;
if (name[equal_i] != curr.identifier()) return false;
if (h.try_advance() && h.curr().is_operator(operator_t::DOUBLE_COLON)) {
equal_i++;
} }
else break; 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) {
for (auto it = begin; it != end; it++) {
const namespace_name_t &curr = it->first;
if (curr == name) {
actual_name = name;
return true;
} }
}
return equal_i != name.size(); for (const auto &import : ctx.imports) {
auto new_name = name;
new_name.insert(new_name.begin(), import.begin(), import.end());
for (auto it = begin; it != end; it++) {
const namespace_name_t &curr = it->first;
if (curr == new_name) {
actual_name = name;
return true;
}
}
}
return false;
} }
@ -38,12 +46,15 @@ bool group_parser_t::parse(ast_ctx_t &ctx, size_t &i, data::map_t &out) const {
if (h.ended()) return false; if (h.ended()) return false;
for (auto &pair : named_parsers) { loc_namespace_name_t name;
if (!read_nmsp(ctx, i, pair.first)) continue; if (read_nmsp(ctx, h.i, name)) {
auto &parser = *pair.second; namespace_name_t actual;
if (resolve_nmsp(ctx, name.strip_location(), named_parsers.begin(), named_parsers.end(), actual)) {
auto &parser = *this->named_parsers.find(actual)->second;
if (parser(ctx, i, out)) return true; if (parser(ctx, i, out)) return true;
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; unordered_map<string, message_t> errors;
@ -66,7 +77,7 @@ group_parser_t &group_parser_t::add(const parser_t &parser, const lang::namespac
throw "Parser '" + name.to_string() + "' already in group."; throw "Parser '" + name.to_string() + "' already in group.";
} }
named_parsers.push_back({ name, &parser }); named_parsers[name] = &parser;
return *this; return *this;
} }

View File

@ -24,45 +24,30 @@ namespace ppc::lang {
return res.str(); return res.str();
} }
bool loc_namespace_name_t::operator==(const loc_namespace_name_t &other) const { int namespace_name_t::compare(const namespace_name_t &b) const {
if (other.size() != size()) return false; const auto &a = *this;
for (size_t i = 0; i < a.size() && i < b.size(); i++) {
for (size_t i = 0; i < size(); i++) { auto cmp = a[i].compare(b[i]);
if (other[i] != (*this)[i]) return false; if (cmp != 0) return cmp;
} }
return true; if (a.size() > b.size()) return 1;
else if (a.size() == b.size()) return 0;
else return -1;
} }
bool loc_namespace_name_t::operator!=(const loc_namespace_name_t &other) const { int loc_namespace_name_t::compare(const loc_namespace_name_t &b) const {
if (other.size() != size()) return true; const auto &a = *this;
for (size_t i = 0; i < a.size() && i < b.size(); i++) {
for (size_t i = 0; i < size(); i++) { auto cmp = a[i].compare(b[i]);
if (other[i] == (*this)[i]) return false; if (cmp != 0) return cmp;
} }
return true; if (a.size() > b.size()) return 1;
else if (a.size() == b.size()) return 0;
else return -1;
} }
bool namespace_name_t::operator==(const namespace_name_t &other) const { namespace_name_t loc_namespace_name_t::strip_location() const {
if (other.size() != size()) return false;
for (size_t i = 0; i < size(); i++) {
if (other[i] != (*this)[i]) return false;
}
return true;
}
bool namespace_name_t::operator!=(const namespace_name_t &other) const {
if (other.size() != size()) return true;
for (size_t i = 0; i < size(); i++) {
if (other[i] == (*this)[i]) return false;
}
return true;
}
namespace_name_t loc_namespace_name_t::strip_location() {
namespace_name_t res; namespace_name_t res;
for (const auto &el : *this) { for (const auto &el : *this) {
@ -71,6 +56,5 @@ namespace ppc::lang {
return res; return res;
} }
} }