Compute transitions correctly for long sequences

This commit is contained in:
Max Brunsfeld 2013-11-06 13:37:01 -08:00
parent 95d955e779
commit 061d8a8efc
4 changed files with 36 additions and 13 deletions

View file

@ -12,6 +12,7 @@ Describe(Rules) {
Symbol symbol1 = Symbol(1);
Symbol symbol2 = Symbol(2);
Symbol symbol3 = Symbol(3);
Symbol symbol4 = Symbol(3);
It(handles_symbols) {
AssertThat(
@ -40,6 +41,15 @@ Describe(Rules) {
), TransitionMap<Rule>::elements_equal));
}
It(handles_long_sequences) {
AssertThat(
Seq(Seq(symbol1, symbol2), Seq(symbol3, symbol4)).transitions(),
EqualsContainer(TransitionMap<Rule>(
{ symbol1.copy() },
{ new Seq(symbol2, Seq(symbol3, symbol4)) }
), TransitionMap<Rule>::elements_equal));
}
It(handles_choices_with_common_starting_symbols) {
AssertThat(
Choice(

View file

@ -6,7 +6,6 @@ using namespace std;
namespace tree_sitter {
namespace rules {
// Constructors
Blank::Blank() {}
Symbol::Symbol(int id) : id(id) {};
@ -28,14 +27,20 @@ namespace tree_sitter {
TransitionMap<Rule> Choice::transitions() const {
auto result = left->transitions();
result.merge(right->transitions(), [&](const Rule &left, const Rule &right) {
return new Choice(left, right);
result.merge(right->transitions(), [&](rule_ptr left, rule_ptr right) -> rule_ptr {
return rule_ptr(new Choice(left, right));
});
return result;
}
TransitionMap<Rule> Seq::transitions() const {
return TransitionMap<Rule>({ left->copy() }, { right->copy() });
return left->transitions().map([&](rule_ptr left_rule) -> rule_ptr {
if (typeid(*left_rule) == typeid(Blank)) {
return right;
} else {
return rule_ptr(new Seq(left_rule, right));
}
});
}
// Equality

View file

@ -15,6 +15,8 @@ namespace tree_sitter {
virtual std::string to_string() const = 0;
};
typedef std::shared_ptr<const Rule> rule_ptr;
class Blank : public Rule {
public:
Blank();
@ -45,8 +47,8 @@ namespace tree_sitter {
bool operator==(const Rule& other) const;
std::string to_string() const;
private:
std::shared_ptr<const Rule> left;
std::shared_ptr<const Rule> right;
rule_ptr left;
rule_ptr right;
};
class Seq : public Rule {
@ -59,8 +61,8 @@ namespace tree_sitter {
bool operator==(const Rule& other) const;
std::string to_string() const;
private:
std::shared_ptr<const Rule> left;
std::shared_ptr<const Rule> right;
rule_ptr left;
rule_ptr right;
};
}
}

View file

@ -66,16 +66,22 @@ namespace tree_sitter {
return contents[i].second;
}
void merge(const TransitionMap<MappedType> &other, std::function<const MappedType *(const MappedType &, const MappedType &)> merge_fn) {
void merge(const TransitionMap<MappedType> &other, std::function<mapped_ptr(mapped_ptr, mapped_ptr)> merge_fn) {
for (pair_type other_pair : other) {
pair_type *current_pair = pair_for_key(*other_pair.first);
if (current_pair)
current_pair->second = mapped_ptr(merge_fn(*current_pair->second, *other_pair.second));
if (pair_type *current_pair = pair_for_key(*other_pair.first))
current_pair->second = merge_fn(current_pair->second, other_pair.second);
else
add(other_pair.first, other_pair.second);
}
}
TransitionMap<MappedType> map(std::function<mapped_ptr(mapped_ptr)> map_fn) {
TransitionMap<MappedType> result;
for (pair_type pair : *this)
result.add(pair.first, map_fn(pair.second));
return result;
}
private:
pair_type * pair_for_key(rules::Rule const &key) {
for (int i = 0; i < contents.size(); i++) {