Represent rule metadata as a struct, not a map

This commit is contained in:
Max Brunsfeld 2016-11-19 13:53:16 -08:00
parent cac4f5d5bc
commit 6cf4ccb840
17 changed files with 158 additions and 108 deletions

View file

@ -1,6 +1,7 @@
#include "compiler/rules/metadata.h"
#include <string>
#include <map>
#include <climits>
#include "compiler/rules/visitor.h"
#include "compiler/rules/blank.h"
#include "compiler/util/hash_combine.h"
@ -13,47 +14,80 @@ using std::map;
using std::pair;
using util::hash_combine;
Metadata::Metadata(rule_ptr rule, map<MetadataKey, int> values)
: rule(rule), value(values) {}
MetadataParams::MetadataParams() :
precedence{0},
associativity{AssociativityNone},
has_precedence{false},
has_associativity{false},
is_token{false},
is_string{false},
is_active{false},
is_main_token{false} {}
rule_ptr Metadata::build(rule_ptr rule, map<MetadataKey, int> values) {
return std::make_shared<Metadata>(rule, values);
bool MetadataParams::operator==(const MetadataParams &other) const {
return
precedence == other.precedence &&
associativity == other.associativity &&
has_precedence == other.has_precedence &&
has_associativity == other.has_associativity &&
is_token == other.is_token &&
is_string == other.is_string &&
is_active == other.is_active &&
is_main_token == other.is_main_token;
}
Metadata::Metadata(rule_ptr rule, MetadataParams params)
: rule(rule), params(params) {}
rule_ptr Metadata::build(rule_ptr rule, MetadataParams params) {
return std::make_shared<Metadata>(rule, params);
}
rule_ptr Metadata::main_token(rule_ptr rule) {
MetadataParams params;
params.has_precedence = true;
params.precedence = 0;
params.is_main_token = true;
return Metadata::build(rule, params);
}
rule_ptr Metadata::separator(rule_ptr rule) {
MetadataParams params;
params.has_precedence = true;
params.precedence = INT_MIN;
params.is_active = true;
return Metadata::build(rule, params);
}
bool Metadata::operator==(const Rule &rule) const {
auto other = rule.as<Metadata>();
return other && other->value == value && other->rule->operator==(*this->rule);
return other && other->params == params && other->rule->operator==(*this->rule);
}
size_t Metadata::hash_code() const {
size_t result = 0;
hash_combine(&result, value.size());
for (auto &pair : value) {
hash_combine<int>(&result, pair.first);
hash_combine(&result, pair.second);
}
hash_combine(&result, params.precedence);
hash_combine<int>(&result, params.associativity);
hash_combine(&result, params.has_precedence);
hash_combine(&result, params.has_associativity);
hash_combine(&result, params.is_token);
hash_combine(&result, params.is_string);
hash_combine(&result, params.is_active);
hash_combine(&result, params.is_main_token);
return result;
}
rule_ptr Metadata::copy() const {
return make_shared<Metadata>(rule->copy(), value);
}
pair<int, bool> Metadata::value_for(MetadataKey key) const {
auto entry = value.find(key);
if (entry == value.end())
return { 0, false };
else
return { entry->second, true };
return make_shared<Metadata>(rule->copy(), params);
}
std::string Metadata::to_string() const {
auto precedence = value_for(rules::PRECEDENCE);
if (precedence.second && value_for(rules::IS_ACTIVE).second)
return "(metadata prec:" + std::to_string(precedence.first) + " " +
if (params.has_precedence) {
return "(metadata prec:" + std::to_string(params.precedence) + " " +
rule->to_string() + ")";
else
} else {
return "(metadata " + rule->to_string() + ")";
}
}
void Metadata::accept(Visitor *visitor) const {

View file

@ -14,29 +14,35 @@ enum Associativity {
AssociativityRight,
};
enum MetadataKey {
MAIN_TOKEN,
PRECEDENCE,
ASSOCIATIVITY,
IS_TOKEN,
IS_STRING,
IS_ACTIVE,
struct MetadataParams {
int precedence;
Associativity associativity;
bool has_precedence;
bool has_associativity;
bool is_token;
bool is_string;
bool is_active;
bool is_main_token;
MetadataParams();
bool operator==(const MetadataParams &) const;
};
class Metadata : public Rule {
public:
Metadata(rule_ptr rule, std::map<MetadataKey, int> value);
static rule_ptr build(rule_ptr rule, std::map<MetadataKey, int> value);
Metadata(rule_ptr rule, MetadataParams);
static rule_ptr build(rule_ptr rule, MetadataParams);
static rule_ptr main_token(rule_ptr rule);
static rule_ptr separator(rule_ptr rule);
bool operator==(const Rule &other) const;
size_t hash_code() const;
rule_ptr copy() const;
std::string to_string() const;
void accept(Visitor *visitor) const;
std::pair<int, bool> value_for(MetadataKey key) const;
const rule_ptr rule;
const std::map<MetadataKey, int> value;
MetadataParams params;
};
} // namespace rules

View file

@ -22,9 +22,10 @@ using std::string;
using std::set;
using std::vector;
using std::map;
using rules::MetadataParams;
static rule_ptr metadata(rule_ptr rule, map<rules::MetadataKey, int> values) {
return std::make_shared<rules::Metadata>(rule, values);
static rule_ptr metadata(rule_ptr rule, MetadataParams params) {
return std::make_shared<rules::Metadata>(rule, params);
}
rule_ptr blank() {
@ -60,29 +61,48 @@ rule_ptr str(const string &value) {
}
rule_ptr prec_left(const rule_ptr &rule) {
return metadata(rule, { { rules::ASSOCIATIVITY, rules::AssociativityLeft } });
MetadataParams params;
params.has_associativity = true;
params.associativity = rules::AssociativityLeft;
return metadata(rule, params);
}
rule_ptr prec_left(int precedence, const rule_ptr &rule) {
return metadata(rule, { { rules::PRECEDENCE, precedence },
{ rules::ASSOCIATIVITY, rules::AssociativityLeft } });
MetadataParams params;
params.has_associativity = true;
params.associativity = rules::AssociativityLeft;
params.has_precedence = true;
params.precedence = precedence;
return metadata(rule, params);
}
rule_ptr prec_right(const rule_ptr &rule) {
return metadata(rule, { { rules::ASSOCIATIVITY, rules::AssociativityRight } });
MetadataParams params;
params.has_associativity = true;
params.associativity = rules::AssociativityRight;
return metadata(rule, params);
}
rule_ptr prec_right(int precedence, const rule_ptr &rule) {
return metadata(rule, { { rules::PRECEDENCE, precedence },
{ rules::ASSOCIATIVITY, rules::AssociativityRight } });
MetadataParams params;
params.has_associativity = true;
params.associativity = rules::AssociativityRight;
params.has_precedence = true;
params.precedence = precedence;
return metadata(rule, params);
}
rule_ptr prec(int precedence, const rule_ptr &rule) {
return metadata(rule, { { rules::PRECEDENCE, precedence } });
MetadataParams params;
params.has_precedence = true;
params.precedence = precedence;
return metadata(rule, params);
}
rule_ptr token(const rule_ptr &rule) {
return metadata(rule, { { rules::IS_TOKEN, 1 } });
MetadataParams params;
params.is_token = true;
return metadata(rule, params);
}
} // namespace tree_sitter

View file

@ -37,7 +37,7 @@ rule_ptr IdentityRuleFn::apply_to(const Repeat *rule) {
}
rule_ptr IdentityRuleFn::apply_to(const Metadata *rule) {
return std::make_shared<Metadata>(apply(rule->rule), rule->value);
return Metadata::build(apply(rule->rule), rule->params);
}
} // namespace rules