Refactor avoidance of redundant repeat rules

This commit is contained in:
Max Brunsfeld 2015-01-14 21:09:39 -08:00
parent a0d9da9d5c
commit 160fca6579
7 changed files with 42 additions and 17 deletions

View file

@ -0,0 +1,22 @@
#include "compiler/compiler_spec_helper.h"
#include "compiler/rules/repeat.h"
#include "compiler/rules/symbol.h"
using namespace rules;
START_TEST
describe("Repeat", []() {
describe("constructing repeats", [&]() {
it("doesn't create redundant repeats", [&]() {
auto sym = make_shared<Symbol>(1);
auto repeat = Repeat::build(sym);
auto outer_repeat = Repeat::build(repeat);
AssertThat(repeat, !Equals(sym));
AssertThat(outer_repeat, Equals(repeat));
});
});
});
END_TEST

View file

@ -128,18 +128,9 @@ class LexTableBuilder {
rules::rule_ptr separator_rule() const {
vector<rules::rule_ptr> separators;
for (const auto &rule : lex_grammar.separators) {
// TODO - remove this hack. right now, nested repeats cause
// item sets which are equivalent to appear unequal.
auto repeat = dynamic_pointer_cast<const rules::Repeat>(rule);
if (repeat.get())
separators.push_back(repeat->content);
else
separators.push_back(rule);
}
return rules::repeat(rules::choice(separators));
for (const auto &rule : lex_grammar.separators)
separators.push_back(rules::repeat(rule));
return rules::choice(separators);
}
set<int> precedence_values_for_item_set(const LexItemSet &item_set) const {

View file

@ -78,11 +78,11 @@ class PatternParser {
switch (peek()) {
case '*':
next();
result = make_shared<Repeat>(result);
result = Repeat::build(result);
break;
case '+':
next();
result = make_shared<Seq>(result, make_shared<Repeat>(result));
result = make_shared<Seq>(result, Repeat::build(result));
break;
case '?':
next();

View file

@ -1,14 +1,25 @@
#include "compiler/rules/repeat.h"
#include <memory>
#include <string>
#include "compiler/rules/visitor.h"
namespace tree_sitter {
namespace rules {
using std::dynamic_pointer_cast;
using std::make_shared;
using std::string;
Repeat::Repeat(const rule_ptr content) : content(content) {}
rule_ptr Repeat::build(const rule_ptr &rule) {
auto inner_repeat = dynamic_pointer_cast<Repeat>(rule);
if (inner_repeat.get())
return inner_repeat;
else
return make_shared<Repeat>(rule);
}
bool Repeat::operator==(const Rule &rule) const {
const Repeat *other = dynamic_cast<const Repeat *>(&rule);
return other && (*other->content == *content);
@ -16,7 +27,7 @@ bool Repeat::operator==(const Rule &rule) const {
size_t Repeat::hash_code() const { return content->hash_code(); }
rule_ptr Repeat::copy() const { return std::make_shared<Repeat>(*this); }
rule_ptr Repeat::copy() const { return make_shared<Repeat>(*this); }
string Repeat::to_string() const {
return string("(repeat ") + content->to_string() + ")";

View file

@ -10,6 +10,7 @@ namespace rules {
class Repeat : public Rule {
public:
explicit Repeat(rule_ptr content);
static rule_ptr build(const rule_ptr &rule);
bool operator==(const Rule &other) const;
size_t hash_code() const;

View file

@ -35,7 +35,7 @@ rule_ptr blank() { return make_shared<Blank>(); }
rule_ptr choice(const vector<rule_ptr> &rules) { return Choice::build(rules); }
rule_ptr repeat(const rule_ptr &content) {
return std::make_shared<Repeat>(content);
return Repeat::build(content);
}
rule_ptr seq(const vector<rule_ptr> &rules) { return Seq::build(rules); }

View file

@ -33,7 +33,7 @@ rule_ptr IdentityRuleFn::apply_to(const Seq *rule) {
}
rule_ptr IdentityRuleFn::apply_to(const Repeat *rule) {
return std::make_shared<Repeat>(apply(rule->content));
return Repeat::build(apply(rule->content));
}
rule_ptr IdentityRuleFn::apply_to(const Metadata *rule) {