Store choice rules using vectors, not pairs

This commit is contained in:
Max Brunsfeld 2014-04-26 19:09:22 -07:00
parent c9e0d4bdf0
commit 29bbff655c
9 changed files with 9273 additions and 8919 deletions

View file

@ -1,29 +1,37 @@
#include "compiler/rules/choice.h"
#include <string>
#include <set>
#include "compiler/rules/visitor.h"
namespace tree_sitter {
using std::string;
using std::make_shared;
using std::vector;
using std::set;
using std::dynamic_pointer_cast;
namespace rules {
Choice::Choice(rule_ptr left, rule_ptr right) : left(left), right(right) {}
Choice::Choice(const vector<rule_ptr> &elements) : elements(elements) {}
rule_ptr Choice::Build(const vector<rule_ptr> &rules) {
rule_ptr result;
for (auto rule : rules)
result = result.get() ? make_shared<Choice>(result, rule) : rule;
return result;
rule_ptr Choice::Build(const vector<rule_ptr> &elements) {
return make_shared<Choice>(elements);
}
bool Choice::operator==(const Rule &rule) const {
const Choice *other = dynamic_cast<const Choice *>(&rule);
return other && (*other->left == *left) && (*other->right == *right);
if (!other) return false;
size_t size = elements.size();
if (size != other->elements.size()) return false;
for (size_t i = 0; i < size; i++)
if (!elements[i]->operator==(*other->elements[i])) return false;
return true;
}
size_t Choice::hash_code() const {
return left->hash_code() ^ right->hash_code();
size_t result = std::hash<size_t>()(elements.size());
for (const auto &element : elements)
result ^= element->hash_code();
return result;
}
rule_ptr Choice::copy() const {
@ -31,7 +39,10 @@ namespace tree_sitter {
}
string Choice::to_string() const {
return string("#<choice ") + left->to_string() + " " + right->to_string() + ">";
string result = "#<choice";
for (const auto &element : elements)
result += " " + element->to_string();
return result + ">";
}
void Choice::accept(Visitor *visitor) const {

View file

@ -9,7 +9,7 @@ namespace tree_sitter {
namespace rules {
class Choice : public Rule {
public:
Choice(rule_ptr left, rule_ptr right);
Choice(const std::vector<rule_ptr> &elements);
static rule_ptr Build(const std::vector<rule_ptr> &rules);
bool operator==(const Rule& other) const;
@ -18,8 +18,7 @@ namespace tree_sitter {
std::string to_string() const;
void accept(Visitor *visitor) const;
const rule_ptr left;
const rule_ptr right;
const std::vector<rule_ptr> elements;
};
}
}

View file

@ -15,6 +15,7 @@ namespace tree_sitter {
using std::hash;
using std::make_shared;
using std::set;
using std::vector;
class PatternParser {
public:
@ -24,12 +25,12 @@ namespace tree_sitter {
position(0) {}
rule_ptr rule() {
auto result = term();
vector<rule_ptr> choices = { term() };
while (has_more_input() && peek() == '|') {
next();
result = make_shared<Choice>(result, term());
choices.push_back(term());
}
return result;
return (choices.size() > 1) ? Choice::Build(choices) : choices.front();
}
private:
@ -54,7 +55,7 @@ namespace tree_sitter {
break;
case '?':
next();
result = make_shared<Choice>(result, make_shared<Blank>());
result = Choice::Build({ result, make_shared<Blank>() });
break;
}
}

View file

@ -11,13 +11,18 @@
#include "compiler/rules/repeat.h"
namespace tree_sitter {
using std::vector;
namespace rules {
rule_ptr IdentityRuleFn::default_apply(const Rule *rule) {
return rule->copy();
}
rule_ptr IdentityRuleFn::apply_to(const Choice *rule) {
return Choice::Build({ apply(rule->left), apply(rule->right) });
vector<rule_ptr> rules;
for (const auto &el : rule->elements)
rules.push_back(apply(el));
return Choice::Build(rules);
}
rule_ptr IdentityRuleFn::apply_to(const Seq *rule) {