Refactor rule visitors
This commit is contained in:
parent
bd5ec68c96
commit
a5816a9624
9 changed files with 126 additions and 113 deletions
|
|
@ -24,32 +24,35 @@ namespace tree_sitter {
|
|||
public:
|
||||
explicit FirstSet(const PreparedGrammar &grammar) : grammar(grammar) {}
|
||||
|
||||
void visit(const Symbol *rule) {
|
||||
set<Symbol> apply_to(const Symbol *rule) {
|
||||
if (visited_symbols.find(*rule) == visited_symbols.end()) {
|
||||
visited_symbols.insert(*rule);
|
||||
|
||||
if (grammar.has_definition(*rule)) {
|
||||
value = apply(grammar.rule(*rule));
|
||||
return apply(grammar.rule(*rule));
|
||||
} else {
|
||||
value = set<Symbol>({ *rule });
|
||||
return set<Symbol>({ *rule });
|
||||
}
|
||||
} else {
|
||||
return set<Symbol>();
|
||||
}
|
||||
}
|
||||
|
||||
void visit(const rules::Metadata *rule) {
|
||||
value = apply(rule->rule);
|
||||
set<Symbol> apply_to(const rules::Metadata *rule) {
|
||||
return apply(rule->rule);
|
||||
}
|
||||
|
||||
void visit(const rules::Choice *rule) {
|
||||
value = set_union(apply(rule->left), apply(rule->right));
|
||||
set<Symbol> apply_to(const rules::Choice *rule) {
|
||||
return set_union(apply(rule->left), apply(rule->right));
|
||||
}
|
||||
|
||||
void visit(const rules::Seq *rule) {
|
||||
set<Symbol> apply_to(const rules::Seq *rule) {
|
||||
auto result = apply(rule->left);
|
||||
if (rule_can_be_blank(rule->left, grammar)) {
|
||||
result = set_union(result, apply(rule->right));
|
||||
return set_union(result, apply(rule->right));
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
value = result;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -13,25 +13,27 @@ namespace tree_sitter {
|
|||
GetMetadata(rules::MetadataKey key) :
|
||||
metadata_key(key) {}
|
||||
|
||||
void visit(const rules::Choice *rule) {
|
||||
value = apply(rule->left) || apply(rule->right);
|
||||
int apply_to(const rules::Choice *rule) {
|
||||
return apply(rule->left) || apply(rule->right);
|
||||
}
|
||||
|
||||
void visit(const rules::Repeat *rule) {
|
||||
value = apply(rule->content);
|
||||
int apply_to(const rules::Repeat *rule) {
|
||||
return apply(rule->content);
|
||||
}
|
||||
|
||||
void visit(const rules::Seq *rule) {
|
||||
int apply_to(const rules::Seq *rule) {
|
||||
int result = apply(rule->left);
|
||||
if (rule_can_be_blank(rule->left) && result == 0)
|
||||
result = apply(rule->right);
|
||||
value = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
void visit(const rules::Metadata *rule) {
|
||||
int apply_to(const rules::Metadata *rule) {
|
||||
auto pair = rule->value.find(metadata_key);
|
||||
if (pair != rule->value.end())
|
||||
value = pair->second;
|
||||
return pair->second;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -15,28 +15,24 @@ namespace tree_sitter {
|
|||
namespace build_tables {
|
||||
class CanBeBlank : public rules::RuleFn<bool> {
|
||||
protected:
|
||||
void default_visit(const rules::Rule *) {
|
||||
value = false;
|
||||
bool apply_to(const rules::Blank *) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void visit(const rules::Blank *) {
|
||||
value = true;
|
||||
bool apply_to(const rules::Repeat *rule) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void visit(const rules::Repeat *rule) {
|
||||
value = true;
|
||||
bool apply_to(const rules::Choice *rule) {
|
||||
return apply(rule->left) || apply(rule->right);
|
||||
}
|
||||
|
||||
void visit(const rules::Choice *rule) {
|
||||
value = apply(rule->left) || apply(rule->right);
|
||||
bool apply_to(const rules::Seq *rule) {
|
||||
return apply(rule->left) && apply(rule->right);
|
||||
}
|
||||
|
||||
void visit(const rules::Seq *rule) {
|
||||
value = apply(rule->left) && apply(rule->right);
|
||||
}
|
||||
|
||||
void visit(const rules::Metadata *rule) {
|
||||
value = apply(rule->rule);
|
||||
bool apply_to(const rules::Metadata *rule) {
|
||||
return apply(rule->rule);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -46,12 +42,15 @@ namespace tree_sitter {
|
|||
using CanBeBlank::visit;
|
||||
|
||||
public:
|
||||
using CanBeBlank::apply_to;
|
||||
explicit CanBeBlankRecursive(const PreparedGrammar &grammar) : grammar(grammar) {}
|
||||
|
||||
void visit(const rules::Symbol *rule) {
|
||||
bool apply_to(const rules::Symbol *rule) {
|
||||
if (visited_symbols.find(*rule) == visited_symbols.end()) {
|
||||
visited_symbols.insert(*rule);
|
||||
value = grammar.has_definition(*rule) && apply(grammar.rule(*rule));
|
||||
return grammar.has_definition(*rule) && apply(grammar.rule(*rule));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ namespace tree_sitter {
|
|||
|
||||
namespace build_tables {
|
||||
template<typename T>
|
||||
map<T, rule_ptr> merge_transitions(const map<T, rule_ptr> &left, const map<T, rule_ptr> &right);
|
||||
map<T, rule_ptr>
|
||||
merge_transitions(const map<T, rule_ptr> &left, const map<T, rule_ptr> &right);
|
||||
|
||||
template<>
|
||||
map<CharacterSet, rule_ptr>
|
||||
|
|
@ -51,28 +52,29 @@ namespace tree_sitter {
|
|||
|
||||
template<typename T>
|
||||
class RuleTransitions : public rules::RuleFn<map<T, rule_ptr>> {
|
||||
void visit_atom(const rules::Rule *rule) {
|
||||
map<T, rule_ptr> apply_to_atom(const rules::Rule *rule) {
|
||||
auto atom = dynamic_cast<const T *>(rule);
|
||||
if (atom)
|
||||
this->value = map<T, rule_ptr>({{ *atom, make_shared<rules::Blank>() }});
|
||||
return map<T, rule_ptr>({{ *atom, make_shared<rules::Blank>() }});
|
||||
else
|
||||
return map<T, rule_ptr>();
|
||||
}
|
||||
|
||||
void visit(const CharacterSet *rule) {
|
||||
visit_atom(rule);
|
||||
map<T, rule_ptr> apply_to(const CharacterSet *rule) {
|
||||
return apply_to_atom(rule);
|
||||
}
|
||||
|
||||
void visit(const Symbol *rule) {
|
||||
visit_atom(rule);
|
||||
map<T, rule_ptr> apply_to(const Symbol *rule) {
|
||||
return apply_to_atom(rule);
|
||||
}
|
||||
|
||||
void visit(const rules::Choice *rule) {
|
||||
map<T, rule_ptr> apply_to(const rules::Choice *rule) {
|
||||
auto left_transitions = this->apply(rule->left);
|
||||
auto right_transitions = this->apply(rule->right);
|
||||
this->value = merge_transitions<T>(left_transitions,
|
||||
right_transitions);
|
||||
return merge_transitions<T>(left_transitions, right_transitions);
|
||||
}
|
||||
|
||||
void visit(const rules::Seq *rule) {
|
||||
map<T, rule_ptr> apply_to(const rules::Seq *rule) {
|
||||
auto result = map_transitions(this->apply(rule->left), [&](const rule_ptr left_rule) {
|
||||
return rules::Seq::Build({ left_rule, rule->right });
|
||||
});
|
||||
|
|
@ -80,31 +82,31 @@ namespace tree_sitter {
|
|||
auto right_transitions = this->apply(rule->right);
|
||||
result = merge_transitions<T>(result, right_transitions);
|
||||
}
|
||||
this->value = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
void visit(const rules::Repeat *rule) {
|
||||
this->value = map_transitions(this->apply(rule->content), [&](const rule_ptr &value) {
|
||||
map<T, rule_ptr> apply_to(const rules::Repeat *rule) {
|
||||
return map_transitions(this->apply(rule->content), [&](const rule_ptr &value) {
|
||||
return rules::Seq::Build({ value, rule->copy() });
|
||||
});
|
||||
}
|
||||
|
||||
void visit(const rules::Metadata *rule) {
|
||||
this->value = this->apply(rule->rule);
|
||||
map<T, rule_ptr> apply_to(const rules::Metadata *rule) {
|
||||
return this->apply(rule->rule);
|
||||
}
|
||||
|
||||
void visit(const rules::String *rule) {
|
||||
|
||||
map<T, rule_ptr> apply_to(const rules::String *rule) {
|
||||
rule_ptr result = make_shared<rules::Blank>();
|
||||
for (char val : rule->value)
|
||||
result = rules::Seq::Build({
|
||||
result,
|
||||
make_shared<CharacterSet>(set<rules::CharacterRange>({ val }))
|
||||
});
|
||||
this->value = this->apply(result);
|
||||
return this->apply(result);
|
||||
}
|
||||
|
||||
void visit(const rules::Pattern *rule) {
|
||||
this->value = this->apply(rule->to_rule_tree());
|
||||
map<T, rule_ptr> apply_to(const rules::Pattern *rule) {
|
||||
return this->apply(rule->to_rule_tree());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -18,12 +18,12 @@ namespace tree_sitter {
|
|||
|
||||
class TokenName : public rules::RuleFn<string> {
|
||||
protected:
|
||||
virtual void visit(const rules::Pattern *rule) {
|
||||
value = "/" + util::escape_string(rule->value) + "/";
|
||||
string apply_to(const rules::Pattern *rule) {
|
||||
return "/" + util::escape_string(rule->value) + "/";
|
||||
}
|
||||
|
||||
virtual void visit(const rules::String *rule) {
|
||||
value = "'" + util::escape_string(rule->value) + "'";
|
||||
string apply_to(const rules::String *rule) {
|
||||
return "'" + util::escape_string(rule->value) + "'";
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -31,11 +31,11 @@ namespace tree_sitter {
|
|||
make_shared<Blank>() });
|
||||
}
|
||||
|
||||
void visit(const Repeat *rule) {
|
||||
rule_ptr apply_to(const Repeat *rule) {
|
||||
rule_ptr inner_rule = apply(rule->content);
|
||||
string helper_rule_name = string("repeat_helper") + to_string(aux_rules.size() + 1);
|
||||
aux_rules.push_back({ helper_rule_name, make_repeat_helper(helper_rule_name, inner_rule) });
|
||||
value = make_shared<Symbol>(helper_rule_name, rules::SymbolTypeAuxiliary);
|
||||
return make_shared<Symbol>(helper_rule_name, rules::SymbolTypeAuxiliary);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -22,16 +22,12 @@ namespace tree_sitter {
|
|||
|
||||
namespace prepare_grammar {
|
||||
class IsToken : public rules::RuleFn<bool> {
|
||||
void default_visit(const rules::Rule *rule) {
|
||||
value = false;
|
||||
bool apply_to(const rules::String *rule) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void visit(const rules::String *rule) {
|
||||
value = true;
|
||||
}
|
||||
|
||||
void visit(const rules::Pattern *rule) {
|
||||
value = true;
|
||||
bool apply_to(const rules::Pattern *rule) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -45,12 +41,12 @@ namespace tree_sitter {
|
|||
return name;
|
||||
}
|
||||
|
||||
void default_visit(const rules::Rule *rule) {
|
||||
rule_ptr default_apply(const rules::Rule *rule) {
|
||||
auto result = rule->copy();
|
||||
if (IsToken().apply(result)) {
|
||||
value = make_shared<rules::Symbol>(add_token(result), rules::SymbolTypeAuxiliary);
|
||||
return make_shared<rules::Symbol>(add_token(result), rules::SymbolTypeAuxiliary);
|
||||
} else {
|
||||
value = result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,35 +12,24 @@
|
|||
|
||||
namespace tree_sitter {
|
||||
namespace rules {
|
||||
void Visitor::default_visit(const Rule *rule) {}
|
||||
void Visitor::visit(const Blank *rule) { default_visit(rule); }
|
||||
void Visitor::visit(const CharacterSet *rule) { default_visit(rule); }
|
||||
void Visitor::visit(const Choice *rule) { default_visit(rule); }
|
||||
void Visitor::visit(const Metadata *rule) { default_visit(rule); }
|
||||
void Visitor::visit(const Pattern *rule) { default_visit(rule); }
|
||||
void Visitor::visit(const Repeat *rule) { default_visit(rule); }
|
||||
void Visitor::visit(const Seq *rule) { default_visit(rule); }
|
||||
void Visitor::visit(const String *rule) { default_visit(rule); }
|
||||
void Visitor::visit(const Symbol *rule) { default_visit(rule); }
|
||||
|
||||
void IdentityRuleFn::default_visit(const Rule *rule) {
|
||||
value = rule->copy();
|
||||
rule_ptr IdentityRuleFn::default_apply(const Rule *rule) {
|
||||
return rule->copy();
|
||||
}
|
||||
|
||||
void IdentityRuleFn::visit(const Choice *rule) {
|
||||
value = Choice::Build({ apply(rule->left), apply(rule->right) });
|
||||
rule_ptr IdentityRuleFn::apply_to(const Choice *rule) {
|
||||
return Choice::Build({ apply(rule->left), apply(rule->right) });
|
||||
}
|
||||
|
||||
void IdentityRuleFn::visit(const Seq *rule) {
|
||||
value = Seq::Build({ apply(rule->left), apply(rule->right) });
|
||||
rule_ptr IdentityRuleFn::apply_to(const Seq *rule) {
|
||||
return Seq::Build({ apply(rule->left), apply(rule->right) });
|
||||
}
|
||||
|
||||
void IdentityRuleFn::visit(const Repeat *rule) {
|
||||
value = std::make_shared<Repeat>(apply(rule->content));
|
||||
rule_ptr IdentityRuleFn::apply_to(const Repeat *rule) {
|
||||
return std::make_shared<Repeat>(apply(rule->content));
|
||||
}
|
||||
|
||||
void IdentityRuleFn::visit(const Metadata *rule) {
|
||||
value = std::make_shared<Metadata>(apply(rule->rule), rule->value);
|
||||
rule_ptr IdentityRuleFn::apply_to(const Metadata *rule) {
|
||||
return std::make_shared<Metadata>(apply(rule->rule), rule->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,36 +17,58 @@ namespace tree_sitter {
|
|||
|
||||
class Visitor {
|
||||
public:
|
||||
virtual void default_visit(const Rule *rule);
|
||||
virtual void visit(const Blank *rule);
|
||||
virtual void visit(const CharacterSet *rule);
|
||||
virtual void visit(const Choice *rule);
|
||||
virtual void visit(const Metadata *rule);
|
||||
virtual void visit(const Pattern *rule);
|
||||
virtual void visit(const Repeat *rule);
|
||||
virtual void visit(const Seq *rule);
|
||||
virtual void visit(const String *rule);
|
||||
virtual void visit(const Symbol *rule);
|
||||
virtual void visit(const Blank *rule) = 0;
|
||||
virtual void visit(const CharacterSet *rule) = 0;
|
||||
virtual void visit(const Choice *rule) = 0;
|
||||
virtual void visit(const Metadata *rule) = 0;
|
||||
virtual void visit(const Pattern *rule) = 0;
|
||||
virtual void visit(const Repeat *rule) = 0;
|
||||
virtual void visit(const Seq *rule) = 0;
|
||||
virtual void visit(const String *rule) = 0;
|
||||
virtual void visit(const Symbol *rule) = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class RuleFn : public Visitor {
|
||||
protected:
|
||||
T value;
|
||||
class RuleFn : private Visitor {
|
||||
public:
|
||||
T apply(const rule_ptr &rule) {
|
||||
value = T();
|
||||
value_ = T();
|
||||
rule->accept(this);
|
||||
return value;
|
||||
return value_;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual T default_apply(const Rule *rule) { return T(); }
|
||||
virtual T apply_to(const Blank *rule) { return default_apply((const Rule *)rule); }
|
||||
virtual T apply_to(const CharacterSet *rule) { return default_apply((const Rule *)rule); }
|
||||
virtual T apply_to(const Choice *rule) { return default_apply((const Rule *)rule); }
|
||||
virtual T apply_to(const Metadata *rule) { return default_apply((const Rule *)rule); }
|
||||
virtual T apply_to(const Pattern *rule) { return default_apply((const Rule *)rule); }
|
||||
virtual T apply_to(const Repeat *rule) { return default_apply((const Rule *)rule); }
|
||||
virtual T apply_to(const Seq *rule) { return default_apply((const Rule *)rule); }
|
||||
virtual T apply_to(const String *rule) { return default_apply((const Rule *)rule); }
|
||||
virtual T apply_to(const Symbol *rule) { return default_apply((const Rule *)rule); }
|
||||
|
||||
void visit(const Blank *rule) { value_ = apply_to(rule); }
|
||||
void visit(const CharacterSet *rule) { value_ = apply_to(rule); }
|
||||
void visit(const Choice *rule) { value_ = apply_to(rule); }
|
||||
void visit(const Metadata *rule) { value_ = apply_to(rule); }
|
||||
void visit(const Pattern *rule) { value_ = apply_to(rule); }
|
||||
void visit(const Repeat *rule) { value_ = apply_to(rule); }
|
||||
void visit(const Seq *rule) { value_ = apply_to(rule); }
|
||||
void visit(const String *rule) { value_ = apply_to(rule); }
|
||||
void visit(const Symbol *rule) { value_ = apply_to(rule); }
|
||||
|
||||
private:
|
||||
T value_;
|
||||
};
|
||||
|
||||
class IdentityRuleFn : public RuleFn<rule_ptr> {
|
||||
virtual void default_visit(const Rule *rule);
|
||||
virtual void visit(const Choice *rule);
|
||||
virtual void visit(const Metadata *rule);
|
||||
virtual void visit(const Seq *rule);
|
||||
virtual void visit(const Repeat *rule);
|
||||
virtual rule_ptr default_apply(const Rule *rule);
|
||||
virtual rule_ptr apply_to(const Choice *rule);
|
||||
virtual rule_ptr apply_to(const Metadata *rule);
|
||||
virtual rule_ptr apply_to(const Seq *rule);
|
||||
virtual rule_ptr apply_to(const Repeat *rule);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue