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 <set>
#include <map>
#include <unordered_map>
#include <memory>
#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<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;
public:
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> {
using base = std::vector<std::string>;
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<located_t<std::string>> {
using base = std::vector<located_t<std::string>>;
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;

View File

@ -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.";

View File

@ -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 <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;
}
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,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;
for (auto &pair : named_parsers) {
if (!read_nmsp(ctx, i, pair.first)) continue;
auto &parser = *pair.second;
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<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.";
}
named_parsers.push_back({ name, &parser });
named_parsers[name] = &parser;
return *this;
}

View File

@ -24,45 +24,30 @@ 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;
}
}