chore: improve named constructs in groups
This commit is contained in:
parent
0cb7e25097
commit
eb167d0a50
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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.";
|
||||||
|
@ -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;
|
template <class T>
|
||||||
auto &curr = h.curr();
|
static bool resolve_nmsp(ast_ctx_t &ctx, const lang::namespace_name_t &name, T begin, T end, lang::namespace_name_t &actual_name) {
|
||||||
if (!curr.is_identifier()) return false;
|
for (auto it = begin; it != end; it++) {
|
||||||
|
const namespace_name_t &curr = it->first;
|
||||||
if (name[equal_i] != curr.identifier()) return false;
|
if (curr == name) {
|
||||||
|
actual_name = name;
|
||||||
if (h.try_advance() && h.curr().is_operator(operator_t::DOUBLE_COLON)) {
|
return true;
|
||||||
equal_i++;
|
|
||||||
}
|
}
|
||||||
else break;
|
|
||||||
}
|
}
|
||||||
|
for (const auto &import : ctx.imports) {
|
||||||
return equal_i != name.size();
|
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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user