diff --git a/include/compiler/treeifier/ast.hh b/include/compiler/treeifier/ast.hh index e1ecd3d..6842d6d 100644 --- a/include/compiler/treeifier/ast.hh +++ b/include/compiler/treeifier/ast.hh @@ -2,6 +2,7 @@ #include #include +#include #include #include #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, 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_parser(parser_adder_t factory) { factory(*this); } @@ -107,7 +109,7 @@ namespace ppc::comp::tree::ast { class group_parser_t : public parser_t { private: - std::vector> named_parsers; + std::map named_parsers; std::vector parsers; public: group_parser_t &add(const parser_t &parser); diff --git a/include/lang/common.hh b/include/lang/common.hh index b846bf8..6d193c8 100644 --- a/include/lang/common.hh +++ b/include/lang/common.hh @@ -32,8 +32,14 @@ namespace ppc::lang { struct namespace_name_t : public std::vector { using base = std::vector; - bool operator ==(const namespace_name_t &other) const; - bool operator !=(const namespace_name_t &other) const; + int compare(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(); } std::string to_string() const; @@ -45,10 +51,16 @@ namespace ppc::lang { struct loc_namespace_name_t : public std::vector> { using base = std::vector>; - bool operator ==(const loc_namespace_name_t &other) const; - bool operator !=(const loc_namespace_name_t &other) const; + int compare(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(); } std::string to_string() const; diff --git a/src/compiler/treeifier/ast.cc b/src/compiler/treeifier/ast.cc index aca1368..e0e66b8 100644 --- a/src/compiler/treeifier/ast.cc +++ b/src/compiler/treeifier/ast.cc @@ -28,6 +28,10 @@ namespace ppc::comp::tree::ast { add_parser(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) { auto parser = new group_parser_t(name); if (parsers.find(parser->name()) != parsers.end()) throw "The parser '" + parser->name() + "' already exists."; diff --git a/src/compiler/treeifier/ast/parsers/group.cc b/src/compiler/treeifier/ast/parsers/group.cc index 7e19636..c52d103 100644 --- a/src/compiler/treeifier/ast/parsers/group.cc +++ b/src/compiler/treeifier/ast/parsers/group.cc @@ -10,26 +10,34 @@ using namespace ppc::comp::tree::ast; using namespace std::string_literals; 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); - - size_t equal_i = 0; - - while (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++; + map_t res; + if (!h.parse("$_nmsp", res)) return false; + name = conv::map_to_nmsp(res); + return true; +} +template +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; } - else break; } - - 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,11 +46,14 @@ bool group_parser_t::parse(ast_ctx_t &ctx, size_t &i, data::map_t &out) const { if (h.ended()) return false; - for (auto &pair : named_parsers) { - if (!read_nmsp(ctx, i, pair.first)) continue; - auto &parser = *pair.second; - if (parser(ctx, i, out)) return true; - else throw message_t::error("Unexpected construct specifier.", h.res_loc()); + loc_namespace_name_t name; + if (read_nmsp(ctx, h.i, name)) { + 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; + else throw message_t::error("Unexpected construct specifier.", h.res_loc()); + } } unordered_map 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."; } - named_parsers.push_back({ name, &parser }); + named_parsers[name] = &parser; return *this; } diff --git a/src/lang/common.cc b/src/lang/common.cc index 36f1e8a..bf4bd70 100644 --- a/src/lang/common.cc +++ b/src/lang/common.cc @@ -23,46 +23,31 @@ namespace ppc::lang { return res.str(); } - - bool loc_namespace_name_t::operator==(const loc_namespace_name_t &other) const { - if (other.size() != size()) return false; - for (size_t i = 0; i < size(); i++) { - if (other[i] != (*this)[i]) return false; + int namespace_name_t::compare(const namespace_name_t &b) const { + const auto &a = *this; + for (size_t i = 0; i < a.size() && i < b.size(); i++) { + auto cmp = a[i].compare(b[i]); + 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 { - if (other.size() != size()) return true; - - for (size_t i = 0; i < size(); i++) { - if (other[i] == (*this)[i]) return false; + int loc_namespace_name_t::compare(const loc_namespace_name_t &b) const { + const auto &a = *this; + for (size_t i = 0; i < a.size() && i < b.size(); i++) { + auto cmp = a[i].compare(b[i]); + 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 { - 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 loc_namespace_name_t::strip_location() const { namespace_name_t res; for (const auto &el : *this) { @@ -71,6 +56,5 @@ namespace ppc::lang { return res; } - }