Remove rule-specific logic from transition map

This commit is contained in:
Max Brunsfeld 2013-12-20 21:59:31 -08:00
parent c10bcf4fab
commit b3b5b8a05a
13 changed files with 86 additions and 97 deletions

View file

@ -15,7 +15,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "12E71793181D02A80051A649"
BuildableName = "specs"
BuildableName = "compiler_specs"
BlueprintName = "compiler_specs"
ReferencedContainer = "container:TreeSitter.xcodeproj">
</BuildableReference>
@ -33,7 +33,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "12E71793181D02A80051A649"
BuildableName = "specs"
BuildableName = "compiler_specs"
BlueprintName = "compiler_specs"
ReferencedContainer = "container:TreeSitter.xcodeproj">
</BuildableReference>
@ -52,7 +52,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "12E71793181D02A80051A649"
BuildableName = "specs"
BuildableName = "compiler_specs"
BlueprintName = "compiler_specs"
ReferencedContainer = "container:TreeSitter.xcodeproj">
</BuildableReference>
@ -77,7 +77,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "12E71793181D02A80051A649"
BuildableName = "specs"
BuildableName = "compiler_specs"
BlueprintName = "compiler_specs"
ReferencedContainer = "container:TreeSitter.xcodeproj">
</BuildableReference>

View file

@ -15,7 +15,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "12FD40B1185EEB5E0041A84E"
BuildableName = "specs copy"
BuildableName = "runtime_specs"
BlueprintName = "runtime_specs"
ReferencedContainer = "container:TreeSitter.xcodeproj">
</BuildableReference>
@ -33,7 +33,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "12FD40B1185EEB5E0041A84E"
BuildableName = "specs copy"
BuildableName = "runtime_specs"
BlueprintName = "runtime_specs"
ReferencedContainer = "container:TreeSitter.xcodeproj">
</BuildableReference>
@ -52,7 +52,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "12FD40B1185EEB5E0041A84E"
BuildableName = "specs copy"
BuildableName = "runtime_specs"
BlueprintName = "runtime_specs"
ReferencedContainer = "container:TreeSitter.xcodeproj">
</BuildableReference>
@ -70,7 +70,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "12FD40B1185EEB5E0041A84E"
BuildableName = "specs copy"
BuildableName = "runtime_specs"
BlueprintName = "runtime_specs"
ReferencedContainer = "container:TreeSitter.xcodeproj">
</BuildableReference>

View file

@ -33,11 +33,11 @@ Describe(item_sets) {
AssertThat(
set.sym_transitions(grammar),
EqualsContainer(TransitionMap<ItemSet>({
Equals(transition_map<rules::Rule, ItemSet>({
{ sym("variable"), item_set({ Item("factor", blank(), 1) }) },
{ sym("number"), item_set({ Item("factor", blank(), 1) }) },
{ sym("left_paren"), std::make_shared<ItemSet>(Item("factor", seq({ sym("expression"), sym("right_paren") }), 1), grammar) },
}), TransitionMap<ItemSet>::elements_equal));
})));
}
It(computes_character_transitions) {
@ -46,11 +46,11 @@ Describe(item_sets) {
AssertThat(
set.char_transitions(grammar),
EqualsContainer(TransitionMap<ItemSet>({
Equals(transition_map<rules::Rule, ItemSet>({
{ char_class(CharClassTypeWord), item_set({ Item("variable", choice({ repeat(char_class(CharClassTypeWord)), blank() }), 1) }) },
{ char_class(CharClassTypeDigit), item_set({ Item("number", choice({ repeat(char_class(CharClassTypeDigit)), blank() }), 1) }) },
{ character('('), item_set({ Item("left_paren", blank(), 1) }) }
}), TransitionMap<ItemSet>::elements_equal));
})));
}
It(can_be_hashed) {

View file

@ -30,7 +30,7 @@ Describe(Rules) {
It(handles_symbols) {
AssertThat(
rules::transitions(symbol1),
EqualsTransitionMap(TransitionMap<rules::Rule>({
Equals(transition_map<rules::Rule, rules::Rule>({
{ symbol1, rules::blank() }
})));
}
@ -38,7 +38,7 @@ Describe(Rules) {
It(handles_characters) {
AssertThat(
rules::transitions(char1),
EqualsTransitionMap(TransitionMap<rules::Rule>({
Equals(transition_map<rules::Rule, rules::Rule>({
{ char1, rules::blank() }
})));
}
@ -47,7 +47,7 @@ Describe(Rules) {
auto rule = rules::char_class(rules::CharClassTypeDigit);
AssertThat(
rules::transitions(rule),
EqualsTransitionMap(TransitionMap<rules::Rule>({
Equals(transition_map<rules::Rule, rules::Rule>({
{ rule, rules::blank() }
})));
}
@ -55,7 +55,7 @@ Describe(Rules) {
It(handles_choices) {
AssertThat(
rules::transitions(rules::choice({ symbol1, symbol2 })),
EqualsTransitionMap(TransitionMap<rules::Rule>({
Equals(transition_map<rules::Rule, rules::Rule>({
{ symbol1, rules::blank() },
{ symbol2, rules::blank() }
})));
@ -64,7 +64,7 @@ Describe(Rules) {
It(handles_sequences) {
AssertThat(
rules::transitions(rules::seq({ symbol1, symbol2 })),
EqualsTransitionMap(TransitionMap<rules::Rule>({
Equals(transition_map<rules::Rule, rules::Rule>({
{ symbol1, symbol2 }
})));
}
@ -77,7 +77,7 @@ Describe(Rules) {
symbol3,
symbol4
})),
EqualsTransitionMap(TransitionMap<rules::Rule>({
Equals(transition_map<rules::Rule, rules::Rule>({
{ symbol1, rules::seq({ symbol2, symbol3, symbol4 }) }
})));
}
@ -88,7 +88,7 @@ Describe(Rules) {
rules::choice({
rules::seq({ symbol1, symbol2 }),
rules::seq({ symbol1, symbol3 }) })),
EqualsTransitionMap(TransitionMap<rules::Rule>({
Equals(transition_map<rules::Rule, rules::Rule>({
{ symbol1, rules::choice({ symbol2, symbol3 }) }
})));
}
@ -96,7 +96,7 @@ Describe(Rules) {
It(handles_strings) {
AssertThat(
rules::transitions(rules::str("bad")),
EqualsTransitionMap(TransitionMap<rules::Rule>({
Equals(transition_map<rules::Rule, rules::Rule>({
{
rules::character('b'),
rules::seq({ rules::character('a'), rules::character('d') })
@ -107,7 +107,7 @@ Describe(Rules) {
It(handles_patterns) {
AssertThat(
rules::transitions(rules::pattern("a|b")),
EqualsTransitionMap(TransitionMap<rules::Rule>({
Equals(transition_map<rules::Rule, rules::Rule>({
{ rules::character('a'), rules::blank() },
{ rules::character('b'), rules::blank() }
})));
@ -117,7 +117,7 @@ Describe(Rules) {
rules::rule_ptr repeat = rules::repeat(rules::str("ab"));
AssertThat(
rules::transitions(repeat),
EqualsTransitionMap(TransitionMap<rules::Rule>({
Equals(transition_map<rules::Rule, rules::Rule>({
{
rules::character('a'),
rules::seq({
@ -132,7 +132,7 @@ Describe(Rules) {
repeat = rules::repeat(rules::str("a"));
AssertThat(
rules::transitions(repeat),
EqualsTransitionMap(TransitionMap<rules::Rule>({
Equals(transition_map<rules::Rule, rules::Rule>({
{
rules::character('a'),
rules::choice({

View file

@ -1,10 +1,6 @@
#include "spec_helper.h"
EqualsContainerConstraint<TransitionMap<rules::Rule>, rule_tmap_comparator> EqualsTransitionMap(const TransitionMap<rules::Rule> &expected) {
return EqualsContainer(expected, TransitionMap<rules::Rule>::elements_equal);
}
namespace tree_sitter {
namespace lr {
std::ostream& operator<<(std::ostream &stream, const unordered_map<string, unordered_set<ParseAction>> &map) {

View file

@ -18,10 +18,6 @@ using namespace tree_sitter;
using namespace std;
using namespace igloo;
// Assertion helpers for transition maps
typedef bool (* rule_tmap_comparator)(const std::pair<rules::rule_ptr, rules::rule_ptr> &, const std::pair<rules::rule_ptr, rules::rule_ptr> &);
EqualsContainerConstraint<TransitionMap<rules::Rule>, rule_tmap_comparator> EqualsTransitionMap(const TransitionMap<rules::Rule> &expected);
namespace tree_sitter {
namespace lr {
std::ostream& operator<<(std::ostream &stream, const unordered_map<string, unordered_set<ParseAction>> &map);

View file

@ -17,8 +17,8 @@ namespace tree_sitter {
return Item(rule_name, grammar.rule(rule_name), 0);
}
TransitionMap<Item> Item::transitions() const {
return rules::transitions(rule).map<Item>([&](rules::rule_ptr to_rule) {
transition_map<rules::Rule, Item> Item::transitions() const {
return rules::transitions(rule).map<Item>([&](rules::rule_ptr to_rule) -> item_ptr {
return std::make_shared<Item>(rule_name, to_rule, consumed_sym_count + 1);
});
};

View file

@ -10,12 +10,15 @@ namespace tree_sitter {
class Grammar;
namespace lr {
class Item;
typedef std::shared_ptr<const Item> item_ptr;
class Item {
public:
Item(const std::string &rule_name, const rules::rule_ptr rule, int consumed_sym_count);
static Item at_beginning_of_rule(const std::string &rule_name, const Grammar &grammar);
TransitionMap<Item> transitions() const;
transition_map<rules::Rule, Item> transitions() const;
std::vector<rules::Symbol> next_symbols() const;
bool operator==(const Item &other) const;
bool is_done() const;
@ -25,7 +28,7 @@ namespace tree_sitter {
const int consumed_sym_count;
};
typedef std::shared_ptr<const Item> item_ptr;
// typedef std::shared_ptr<const Item> item_ptr;
std::ostream& operator<<(std::ostream &stream, const Item &item);
}

View file

@ -31,11 +31,11 @@ namespace tree_sitter {
ItemSet::ItemSet(const Item &item, const Grammar &grammar) : contents(closure_in_grammar(item, grammar)) {}
TransitionMap<ItemSet> ItemSet::char_transitions(const Grammar &grammar) const {
auto result = TransitionMap<ItemSet>();
transition_map<rules::Rule, ItemSet> ItemSet::char_transitions(const Grammar &grammar) const {
transition_map<rules::Rule, ItemSet> result;
for (auto item : *this) {
auto new_set = item.transitions()
.where([&](const rules::rule_ptr &on_rule) -> bool {
.where([&](rules::rule_ptr on_rule) -> bool {
return typeid(*on_rule) != typeid(rules::Symbol);
})
.map<ItemSet>([&](const item_ptr &item) -> item_set_ptr {
@ -48,11 +48,11 @@ namespace tree_sitter {
return result;
}
TransitionMap<ItemSet> ItemSet::sym_transitions(const Grammar &grammar) const {
auto result = TransitionMap<ItemSet>();
transition_map<rules::Rule, ItemSet> ItemSet::sym_transitions(const Grammar &grammar) const {
transition_map<rules::Rule, ItemSet> result;
for (auto item : *this) {
auto new_set = item.transitions()
.where([&](const rules::rule_ptr &on_rule) -> bool {
.where([&](rules::rule_ptr on_rule) -> bool {
return typeid(*on_rule) == typeid(rules::Symbol);
})
.map<ItemSet>([&](const item_ptr &item) -> item_set_ptr {

View file

@ -22,8 +22,8 @@ namespace tree_sitter {
const_iterator end() const;
size_t size() const;
TransitionMap<ItemSet> sym_transitions(const Grammar &grammar) const;
TransitionMap<ItemSet> char_transitions(const Grammar &grammar) const;
transition_map<rules::Rule, ItemSet> char_transitions(const Grammar &grammar) const;
transition_map<rules::Rule, ItemSet> sym_transitions(const Grammar &grammar) const;
bool operator==(const ItemSet &other) const;
};

View file

@ -5,22 +5,22 @@ namespace tree_sitter {
namespace rules {
class TransitionsVisitor : public Visitor {
public:
TransitionMap<Rule> value;
transition_map<Rule, Rule> value;
void visit(const Blank *rule) {
value = TransitionMap<Rule>();
value = transition_map<Rule, Rule>();
}
void visit(const CharClass *rule) {
value = TransitionMap<Rule>({{ char_class(rule->value), blank() }});
value = transition_map<Rule, Rule>({{ char_class(rule->value), blank() }});
}
void visit(const Char *rule) {
value = TransitionMap<Rule>({{ character(rule->value), blank() }});
value = transition_map<Rule, Rule>({{ character(rule->value), blank() }});
}
void visit(const Symbol *rule) {
value = TransitionMap<Rule>({{ sym(rule->name), blank() }});
value = transition_map<Rule, Rule>({{ sym(rule->name), blank() }});
}
void visit(const Choice *rule) {
@ -31,7 +31,7 @@ namespace tree_sitter {
}
void visit(const Seq *rule) {
value = transitions(rule->left).map<Rule>([&](rule_ptr left_rule) -> rule_ptr {
value = transitions(rule->left).map<Rule>([&](const rule_ptr left_rule) -> rule_ptr {
if (typeid(*left_rule) == typeid(Blank))
return rule->right;
else
@ -57,7 +57,7 @@ namespace tree_sitter {
}
};
TransitionMap<Rule> transitions(const rule_ptr &rule) {
transition_map<Rule, Rule> transitions(const rule_ptr &rule) {
TransitionsVisitor visitor;
rule->accept(visitor);
return visitor.value;

View file

@ -6,7 +6,7 @@
namespace tree_sitter {
namespace rules {
TransitionMap<Rule> transitions(const rule_ptr &rule);
transition_map<Rule, Rule> transitions(const rule_ptr &rule);
}
}

View file

@ -7,50 +7,34 @@
#include "rule.h"
namespace tree_sitter {
template<typename MappedType>
class TransitionMap {
typedef std::shared_ptr<const rules::Rule> rule_ptr;
typedef std::shared_ptr<const MappedType> mapped_ptr;
typedef std::pair<rule_ptr, mapped_ptr> pair_type;
template<typename TKey, typename TValue>
class transition_map {
typedef std::shared_ptr<const TKey> TKeyPtr;
typedef std::shared_ptr<const TValue> TValuePtr;
typedef std::pair<const TKeyPtr, TValuePtr> pair_type;
typedef std::vector<pair_type> contents_type;
public:
static bool elements_equal(const pair_type &left, const pair_type &right) {
return (*left.first == *right.first) && (*left.second == *right.second);
transition_map() : contents(contents_type()) {};
transition_map(std::initializer_list<pair_type> pairs) : contents(pairs) {};
bool operator==(const transition_map<TKey, TValue> &other) const {
if (size() != other.size()) return false;
for (int i = 0; i < size(); i++) {
auto left = contents[i];
auto right = other.contents[i];
if (!(*left.first == *right.first) ||
!(*left.second == *right.second)) return false;
}
return true;
}
TransitionMap() : contents(contents_type()) {};
TransitionMap(std::initializer_list<std::pair<rule_ptr, mapped_ptr>> pairs) : contents(pairs) {};
typedef typename contents_type::const_iterator const_iterator;
typedef typename contents_type::iterator iterator;
iterator begin() { return contents.begin(); }
iterator end() { return contents.end(); }
const_iterator begin() const { return contents.begin(); }
const_iterator end() const { return contents.end(); }
void add(const rule_ptr on_rule, const mapped_ptr to_value) {
contents.push_back(pair_type(on_rule, to_value));
void add(TKeyPtr key, TValuePtr value) {
contents.push_back(pair_type(key, value));
}
size_t size() const {
return contents.size();
}
mapped_ptr operator[](rules::Rule const &on_rule) const {
pair_type *pair = pair_for_key(on_rule);
if (pair)
return pair->second;
else
return NULL;
}
mapped_ptr operator[](int i) const {
return contents[i].second;
}
void merge(const TransitionMap<MappedType> &other, std::function<mapped_ptr(mapped_ptr, mapped_ptr)> merge_fn) {
void merge(const transition_map<TKey, TValue> &other, std::function<TValuePtr(TValuePtr, TValuePtr)> merge_fn) {
for (pair_type other_pair : other) {
if (pair_type *current_pair = pair_for_key(*other_pair.first))
current_pair->second = merge_fn(current_pair->second, other_pair.second);
@ -59,18 +43,17 @@ namespace tree_sitter {
}
}
TransitionMap<MappedType> where(std::function<bool(rule_ptr)> filter_fn) {
TransitionMap<MappedType> result;
transition_map<TKey, TValue> where(std::function<bool(TKeyPtr)> filter_fn) {
transition_map<TKey, TValue> result;
for (pair_type pair : *this)
if (filter_fn(pair.first))
result.add(pair.first, pair.second);
return result;
}
template<typename NewMappedType>
TransitionMap<NewMappedType> map(std::function<std::shared_ptr<const NewMappedType>(mapped_ptr)> map_fn) {
TransitionMap<NewMappedType> result;
template<typename NewV>
transition_map<TKey, NewV> map(std::function<const std::shared_ptr<const NewV>(TValuePtr)> map_fn) {
transition_map<TKey, NewV> result;
for (pair_type pair : *this) {
auto new_value = map_fn(pair.second);
result.add(pair.first, new_value);
@ -78,8 +61,19 @@ namespace tree_sitter {
return result;
}
#pragma mark - Container
typedef typename contents_type::const_iterator const_iterator;
typedef typename contents_type::iterator iterator;
iterator begin() { return contents.begin(); }
iterator end() { return contents.end(); }
const_iterator begin() const { return contents.begin(); }
const_iterator end() const { return contents.end(); }
size_t size() const { return contents.size(); }
private:
pair_type * pair_for_key(rules::Rule const &key) {
pair_type * pair_for_key(const TKey &key) {
for (int i = 0; i < contents.size(); i++) {
pair_type *pair = &contents[i];
if (*pair->first == key) return pair;
@ -90,8 +84,8 @@ namespace tree_sitter {
contents_type contents;
};
template<typename MappedType>
std::ostream& operator<<(std::ostream &stream, const TransitionMap<MappedType> &map) {
template<typename K, typename V>
std::ostream& operator<<(std::ostream &stream, const transition_map<K, V> &map) {
stream << std::string("[");
bool started = false;
for (auto pair : map) {