Remove now-unused symbol rule-transition functions

This commit is contained in:
Max Brunsfeld 2015-10-04 22:20:34 -07:00
parent c4ef228397
commit 39a0934088
6 changed files with 72 additions and 164 deletions

View file

@ -6,11 +6,11 @@ using namespace build_tables;
START_TEST
describe("merge_char_transitions", []() {
describe("merge_transition", []() {
typedef map<CharacterSet, int> int_map;
auto do_merge = [&](int_map *left, const pair<CharacterSet, int> &new_pair) {
merge_char_transition<int>(left, new_pair, [](int *l, const int *r) {
merge_transition<int>(left, new_pair, [](int *l, const int *r) {
*l = *l | *r;
});
};

View file

@ -5,10 +5,9 @@
using namespace rules;
using namespace build_tables;
template<typename K>
class rule_map : public std::map<K, rule_ptr> {
class transition_map : public std::map<CharacterSet, rule_ptr> {
public:
bool operator==(const std::map<K, rule_ptr> &other) const {
bool operator==(const std::map<CharacterSet, rule_ptr> &other) const {
if (this->size() != other.size()) return false;
for (const auto &pair : *this) {
auto other_pair = other.find(pair.first);
@ -18,108 +17,72 @@ class rule_map : public std::map<K, rule_ptr> {
return true;
}
rule_map(const std::initializer_list<std::pair<const K, rule_ptr>> &list) : std::map<K, rule_ptr>(list) {}
transition_map(const std::initializer_list<std::pair<const CharacterSet, rule_ptr>> &list) :
std::map<CharacterSet, rule_ptr>(list) {}
};
START_TEST
describe("sym_transitions", []() {
it("handles symbols", [&]() {
describe("rule_transitions", []() {
it("handles single characters", [&]() {
AssertThat(
sym_transitions(i_sym(1)),
Equals(rule_map<Symbol>({
{ Symbol(1), blank() }
})));
});
it("handles choices", [&]() {
AssertThat(
sym_transitions(choice({ i_sym(1), i_sym(2) })),
Equals(rule_map<Symbol>({
{ Symbol(1), blank() },
{ Symbol(2), blank() }
rule_transitions(character({ '1' })),
Equals(transition_map({
{ CharacterSet().include('1'), blank() }
})));
});
it("handles sequences", [&]() {
AssertThat(
sym_transitions(seq({ i_sym(1), i_sym(2) })),
Equals(rule_map<Symbol>({
{ Symbol(1), i_sym(2) }
rule_transitions(seq({ character({ '1' }), character({ '2' }) })),
Equals(transition_map({
{ CharacterSet().include('1'), character({ '2' }) }
})));
});
it("handles long sequences", [&]() {
AssertThat(
sym_transitions(seq({
i_sym(1),
i_sym(2),
i_sym(3),
i_sym(4)
rule_transitions(seq({
character({ '1' }),
character({ '2' }),
character({ '3' }),
character({ '4' })
})),
Equals(rule_map<Symbol>({
{ Symbol(1), seq({ i_sym(2), i_sym(3), i_sym(4) }) }
Equals(transition_map({
{
CharacterSet().include('1'),
seq({ character({ '2' }), character({ '3' }), character({ '4' }) }),
}
})));
});
it("handles sequences whose left sides can be blank", [&]() {
AssertThat(
sym_transitions(seq({
rule_transitions(seq({
choice({
i_sym(1),
character({ '1' }),
blank() }),
seq({
i_sym(1),
i_sym(2) })
})), Equals(rule_map<Symbol>({
{ Symbol(1), choice({ seq({ i_sym(1), i_sym(2) }), i_sym(2), }) }
})));
});
it("handles choices with common starting symbols", [&]() {
AssertThat(
sym_transitions(
choice({
seq({ i_sym(1), i_sym(2) }),
seq({ i_sym(1), i_sym(3) }) })),
Equals(rule_map<Symbol>({
{ Symbol(1), choice({ i_sym(2), i_sym(3) }) }
})));
});
it("preserves metadata", [&]() {
map<MetadataKey, int> metadata_value({
{ PRECEDENCE, 5 }
});
rule_ptr rule = make_shared<Metadata>(seq({ i_sym(1), i_sym(2) }), metadata_value);
AssertThat(
sym_transitions(rule),
Equals(rule_map<Symbol>({
{ Symbol(1), make_shared<Metadata>(i_sym(2), metadata_value)},
})));
});
});
describe("char_transitions", []() {
it("handles characters", [&]() {
AssertThat(
char_transitions(character({ '1' })),
Equals(rule_map<CharacterSet>({
{ CharacterSet().include('1'), blank() }
character({ '1' }),
character({ '2' }) })
})), Equals(transition_map({
{
CharacterSet().include('1'),
choice({ seq({ character({ '1' }), character({ '2' }) }), character({ '2' }), }),
}
})));
});
it("handles choices between overlapping character sets", [&]() {
AssertThat(
char_transitions(choice({
rule_transitions(choice({
seq({
character({ 'a', 'b', 'c', 'd' }),
sym("x") }),
seq({
character({ 'c', 'd', 'e', 'f' }),
sym("y") }) })),
Equals(rule_map<CharacterSet>({
Equals(transition_map({
{ CharacterSet().include('a', 'b'), sym("x") },
{ CharacterSet().include('c', 'd'), choice({ sym("x"), sym("y") }) },
{ CharacterSet().include('e', 'f'), sym("y") },
@ -128,7 +91,7 @@ describe("char_transitions", []() {
it("handles choices between whitelisted and blacklisted character sets", [&]() {
AssertThat(
char_transitions(seq({
rule_transitions(seq({
choice({
character({ '/' }, false),
seq({
@ -136,7 +99,7 @@ describe("char_transitions", []() {
character({ '/' }) }) }),
character({ '/' }) })),
Equals(rule_map<CharacterSet>({
Equals(transition_map({
{ CharacterSet()
.include_all()
.exclude('/')
@ -154,42 +117,42 @@ describe("char_transitions", []() {
it("handles choices between a subset and a superset of characters", [&]() {
AssertThat(
char_transitions(choice({
rule_transitions(choice({
seq({
character({ 'b', 'c', 'd' }),
sym("x") }),
seq({
character({ 'a', 'b', 'c', 'd', 'e', 'f' }),
sym("y") }) })),
Equals(rule_map<CharacterSet>({
Equals(transition_map({
{ CharacterSet().include('b', 'd'), choice({ sym("x"), sym("y") }) },
{ CharacterSet().include('a').include('e', 'f'), sym("y") },
})));
AssertThat(
char_transitions(choice({
rule_transitions(choice({
seq({
character({ 'a', 'b', 'c', 'd', 'e', 'f' }),
sym("x") }),
seq({
character({ 'b', 'c', 'd' }),
sym("y") }) })),
Equals(rule_map<CharacterSet>({
Equals(transition_map({
{ CharacterSet().include('b', 'd'), choice({ sym("x"), sym("y") }) },
{ CharacterSet().include('a').include('e', 'f'), sym("x") },
})));
});
it("handles blanks", [&]() {
AssertThat(char_transitions(blank()), Equals(rule_map<CharacterSet>({})));
AssertThat(rule_transitions(blank()), Equals(transition_map({})));
});
it("handles repeats", [&]() {
rule_ptr rule = repeat(seq({ character({ 'a' }), character({ 'b' }) }));
AssertThat(
char_transitions(rule),
Equals(rule_map<CharacterSet>({
rule_transitions(rule),
Equals(transition_map({
{
CharacterSet().include('a'),
seq({
@ -200,8 +163,8 @@ describe("char_transitions", []() {
rule = repeat(character({ 'a' }));
AssertThat(
char_transitions(rule),
Equals(rule_map<CharacterSet>({
rule_transitions(rule),
Equals(transition_map({
{ CharacterSet().include('a'), rule }
})));
});

View file

@ -40,9 +40,9 @@ map<Symbol, ParseItemSet> sym_transitions(const ParseItemSet &input_item_set,
map<CharacterSet, LexItemSet> char_transitions(const LexItemSet &item_set) {
map<CharacterSet, LexItemSet> result;
for (const LexItem &item : item_set) {
for (auto &transition : char_transitions(item.rule)) {
for (auto &transition : rule_transitions(item.rule)) {
LexItem next_item(item.lhs, transition.second);
merge_char_transition<LexItemSet>(
merge_transition<LexItemSet>(
&result, { transition.first, LexItemSet({ next_item }) },
[](LexItemSet *left, const LexItemSet *right) {
left->insert(right->begin(), right->end());

View file

@ -9,29 +9,6 @@
namespace tree_sitter {
namespace build_tables {
/*
* Merges a new transition into a map with symbol keys.
* If the symbol already exists in the map, the new value for that
* symbol will be computed by merging the old and new values
* using the given function.
*/
template <typename T>
void merge_sym_transition(std::map<rules::Symbol, T> *left,
const std::pair<rules::Symbol, T> &new_pair,
std::function<void(T *, const T *)> merge_fn) {
auto new_symbol = new_pair.first;
for (auto &existing_pair : *left) {
auto existing_symbol = existing_pair.first;
if (new_symbol < existing_symbol)
break;
if (existing_symbol == new_symbol) {
merge_fn(&existing_pair.second, &new_pair.second);
return;
}
}
left->insert(new_pair);
}
/*
* Merges two transition maps with character set keys. If the
* two maps contain values for overlapping character sets, the
@ -39,9 +16,9 @@ void merge_sym_transition(std::map<rules::Symbol, T> *left,
* merging the old and new values using the given function.
*/
template <typename T>
void merge_char_transition(std::map<rules::CharacterSet, T> *left,
const std::pair<rules::CharacterSet, T> &new_pair,
std::function<void(T *, const T *)> merge_fn) {
void merge_transition(std::map<rules::CharacterSet, T> *left,
const std::pair<rules::CharacterSet, T> &new_pair,
std::function<void(T *, const T *)> merge_fn) {
rules::CharacterSet new_char_set = new_pair.first;
T new_value = new_pair.second;

View file

@ -19,72 +19,46 @@ using rules::CharacterSet;
using rules::Choice;
using rules::Symbol;
template <typename T>
void merge_transitions(map<T, rule_ptr> *, const map<T, rule_ptr> &);
struct MergeAsChoice {
void operator()(rule_ptr *left, const rule_ptr *right) {
*left = Choice::build({ *left, *right });
}
};
template <>
void merge_transitions(map<CharacterSet, rule_ptr> *left,
const map<CharacterSet, rule_ptr> &right) {
for (auto &pair : right)
merge_char_transition<rule_ptr>(left, pair, MergeAsChoice());
}
template <>
void merge_transitions(map<Symbol, rule_ptr> *left,
const map<Symbol, rule_ptr> &right) {
for (auto &pair : right)
merge_sym_transition<rule_ptr>(left, pair, MergeAsChoice());
}
template <typename T>
class RuleTransitions : public rules::RuleFn<map<T, rule_ptr>> {
class RuleTransitions : public rules::RuleFn<map<CharacterSet, rule_ptr>> {
private:
map<T, rule_ptr> apply_to_primitive(const Rule *rule) {
auto primitive = dynamic_cast<const T *>(rule);
if (primitive)
return map<T, rule_ptr>({ { *primitive, make_shared<rules::Blank>() } });
else
return map<T, rule_ptr>();
void merge_transitions(map<CharacterSet, rule_ptr> *left,
const map<CharacterSet, rule_ptr> &right) {
for (auto &pair : right)
merge_transition<rule_ptr>(
left, pair, [](rule_ptr *left, const rule_ptr *right) {
*left = Choice::build({ *left, *right });
});
}
map<T, rule_ptr> apply_to(const CharacterSet *rule) {
return apply_to_primitive(rule);
map<CharacterSet, rule_ptr> apply_to(const CharacterSet *rule) {
return map<CharacterSet, rule_ptr>(
{ { *rule, make_shared<rules::Blank>() } });
}
map<T, rule_ptr> apply_to(const Symbol *rule) {
return apply_to_primitive(rule);
}
map<T, rule_ptr> apply_to(const rules::Choice *rule) {
map<T, rule_ptr> result;
map<CharacterSet, rule_ptr> apply_to(const rules::Choice *rule) {
map<CharacterSet, rule_ptr> result;
for (const auto &el : rule->elements)
merge_transitions<T>(&result, this->apply(el));
merge_transitions(&result, this->apply(el));
return result;
}
map<T, rule_ptr> apply_to(const rules::Seq *rule) {
map<CharacterSet, rule_ptr> apply_to(const rules::Seq *rule) {
auto result = this->apply(rule->left);
for (auto &pair : result)
pair.second = rules::Seq::build({ pair.second, rule->right });
if (rule_can_be_blank(rule->left))
merge_transitions<T>(&result, this->apply(rule->right));
merge_transitions(&result, this->apply(rule->right));
return result;
}
map<T, rule_ptr> apply_to(const rules::Repeat *rule) {
map<CharacterSet, rule_ptr> apply_to(const rules::Repeat *rule) {
auto result = this->apply(rule->content);
for (auto &pair : result)
pair.second = rules::Seq::build({ pair.second, rule->copy() });
return result;
}
map<T, rule_ptr> apply_to(const rules::Metadata *rule) {
map<CharacterSet, rule_ptr> apply_to(const rules::Metadata *rule) {
auto result = this->apply(rule->rule);
for (auto &pair : result)
pair.second = make_shared<rules::Metadata>(pair.second, rule->value);
@ -92,12 +66,8 @@ class RuleTransitions : public rules::RuleFn<map<T, rule_ptr>> {
}
};
map<CharacterSet, rule_ptr> char_transitions(const rule_ptr &rule) {
return RuleTransitions<CharacterSet>().apply(rule);
}
map<Symbol, rule_ptr> sym_transitions(const rule_ptr &rule) {
return RuleTransitions<Symbol>().apply(rule);
map<CharacterSet, rule_ptr> rule_transitions(const rule_ptr &rule) {
return RuleTransitions().apply(rule);
}
} // namespace build_tables

View file

@ -8,9 +8,7 @@
namespace tree_sitter {
namespace build_tables {
std::map<rules::CharacterSet, rule_ptr> char_transitions(const rule_ptr &rule);
std::map<rules::Symbol, rule_ptr> sym_transitions(const rule_ptr &rule);
std::map<rules::CharacterSet, rule_ptr> rule_transitions(const rule_ptr &);
} // namespace build_tables
} // namespace tree_sitter