diff --git a/TreeSitter.xcodeproj/xcshareddata/xcschemes/compiler_specs.xcscheme b/TreeSitter.xcodeproj/xcshareddata/xcschemes/compiler_specs.xcscheme index 563d642a..313d8625 100644 --- a/TreeSitter.xcodeproj/xcshareddata/xcschemes/compiler_specs.xcscheme +++ b/TreeSitter.xcodeproj/xcshareddata/xcschemes/compiler_specs.xcscheme @@ -15,7 +15,7 @@ @@ -33,7 +33,7 @@ @@ -52,7 +52,7 @@ @@ -77,7 +77,7 @@ diff --git a/TreeSitter.xcodeproj/xcshareddata/xcschemes/runtime_specs.xcscheme b/TreeSitter.xcodeproj/xcshareddata/xcschemes/runtime_specs.xcscheme index 9787e07f..72f0958d 100644 --- a/TreeSitter.xcodeproj/xcshareddata/xcschemes/runtime_specs.xcscheme +++ b/TreeSitter.xcodeproj/xcshareddata/xcschemes/runtime_specs.xcscheme @@ -15,7 +15,7 @@ @@ -33,7 +33,7 @@ @@ -52,7 +52,7 @@ @@ -70,7 +70,7 @@ diff --git a/spec/compiler/lr/item_set_spec.cpp b/spec/compiler/lr/item_set_spec.cpp index 76696d53..027cd9f5 100644 --- a/spec/compiler/lr/item_set_spec.cpp +++ b/spec/compiler/lr/item_set_spec.cpp @@ -33,11 +33,11 @@ Describe(item_sets) { AssertThat( set.sym_transitions(grammar), - EqualsContainer(TransitionMap({ + Equals(transition_map({ { sym("variable"), item_set({ Item("factor", blank(), 1) }) }, { sym("number"), item_set({ Item("factor", blank(), 1) }) }, { sym("left_paren"), std::make_shared(Item("factor", seq({ sym("expression"), sym("right_paren") }), 1), grammar) }, - }), TransitionMap::elements_equal)); + }))); } It(computes_character_transitions) { @@ -46,11 +46,11 @@ Describe(item_sets) { AssertThat( set.char_transitions(grammar), - EqualsContainer(TransitionMap({ + Equals(transition_map({ { 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::elements_equal)); + }))); } It(can_be_hashed) { diff --git a/spec/compiler/rules/rules_spec.cpp b/spec/compiler/rules/rules_spec.cpp index 1cfd3cde..f9d6607d 100644 --- a/spec/compiler/rules/rules_spec.cpp +++ b/spec/compiler/rules/rules_spec.cpp @@ -30,7 +30,7 @@ Describe(Rules) { It(handles_symbols) { AssertThat( rules::transitions(symbol1), - EqualsTransitionMap(TransitionMap({ + Equals(transition_map({ { symbol1, rules::blank() } }))); } @@ -38,7 +38,7 @@ Describe(Rules) { It(handles_characters) { AssertThat( rules::transitions(char1), - EqualsTransitionMap(TransitionMap({ + Equals(transition_map({ { char1, rules::blank() } }))); } @@ -47,7 +47,7 @@ Describe(Rules) { auto rule = rules::char_class(rules::CharClassTypeDigit); AssertThat( rules::transitions(rule), - EqualsTransitionMap(TransitionMap({ + Equals(transition_map({ { rule, rules::blank() } }))); } @@ -55,7 +55,7 @@ Describe(Rules) { It(handles_choices) { AssertThat( rules::transitions(rules::choice({ symbol1, symbol2 })), - EqualsTransitionMap(TransitionMap({ + Equals(transition_map({ { symbol1, rules::blank() }, { symbol2, rules::blank() } }))); @@ -64,7 +64,7 @@ Describe(Rules) { It(handles_sequences) { AssertThat( rules::transitions(rules::seq({ symbol1, symbol2 })), - EqualsTransitionMap(TransitionMap({ + Equals(transition_map({ { symbol1, symbol2 } }))); } @@ -77,7 +77,7 @@ Describe(Rules) { symbol3, symbol4 })), - EqualsTransitionMap(TransitionMap({ + Equals(transition_map({ { symbol1, rules::seq({ symbol2, symbol3, symbol4 }) } }))); } @@ -88,7 +88,7 @@ Describe(Rules) { rules::choice({ rules::seq({ symbol1, symbol2 }), rules::seq({ symbol1, symbol3 }) })), - EqualsTransitionMap(TransitionMap({ + Equals(transition_map({ { symbol1, rules::choice({ symbol2, symbol3 }) } }))); } @@ -96,7 +96,7 @@ Describe(Rules) { It(handles_strings) { AssertThat( rules::transitions(rules::str("bad")), - EqualsTransitionMap(TransitionMap({ + Equals(transition_map({ { 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({ + Equals(transition_map({ { 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({ + Equals(transition_map({ { rules::character('a'), rules::seq({ @@ -132,7 +132,7 @@ Describe(Rules) { repeat = rules::repeat(rules::str("a")); AssertThat( rules::transitions(repeat), - EqualsTransitionMap(TransitionMap({ + Equals(transition_map({ { rules::character('a'), rules::choice({ diff --git a/spec/compiler/spec_helper.cpp b/spec/compiler/spec_helper.cpp index e2b2dd89..d9d069aa 100644 --- a/spec/compiler/spec_helper.cpp +++ b/spec/compiler/spec_helper.cpp @@ -1,10 +1,6 @@ #include "spec_helper.h" -EqualsContainerConstraint, rule_tmap_comparator> EqualsTransitionMap(const TransitionMap &expected) { - return EqualsContainer(expected, TransitionMap::elements_equal); -} - namespace tree_sitter { namespace lr { std::ostream& operator<<(std::ostream &stream, const unordered_map> &map) { diff --git a/spec/compiler/spec_helper.h b/spec/compiler/spec_helper.h index 57b9d5be..0a054d1b 100644 --- a/spec/compiler/spec_helper.h +++ b/spec/compiler/spec_helper.h @@ -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 &, const std::pair &); -EqualsContainerConstraint, rule_tmap_comparator> EqualsTransitionMap(const TransitionMap &expected); - namespace tree_sitter { namespace lr { std::ostream& operator<<(std::ostream &stream, const unordered_map> &map); diff --git a/src/compiler/lr/item.cpp b/src/compiler/lr/item.cpp index cda1a856..317aed76 100644 --- a/src/compiler/lr/item.cpp +++ b/src/compiler/lr/item.cpp @@ -17,8 +17,8 @@ namespace tree_sitter { return Item(rule_name, grammar.rule(rule_name), 0); } - TransitionMap Item::transitions() const { - return rules::transitions(rule).map([&](rules::rule_ptr to_rule) { + transition_map Item::transitions() const { + return rules::transitions(rule).map([&](rules::rule_ptr to_rule) -> item_ptr { return std::make_shared(rule_name, to_rule, consumed_sym_count + 1); }); }; diff --git a/src/compiler/lr/item.h b/src/compiler/lr/item.h index 4e3498cd..e2e15036 100644 --- a/src/compiler/lr/item.h +++ b/src/compiler/lr/item.h @@ -10,12 +10,15 @@ namespace tree_sitter { class Grammar; namespace lr { + class Item; + typedef std::shared_ptr 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 transitions() const; + transition_map transitions() const; std::vector 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 item_ptr; +// typedef std::shared_ptr item_ptr; std::ostream& operator<<(std::ostream &stream, const Item &item); } diff --git a/src/compiler/lr/item_set.cpp b/src/compiler/lr/item_set.cpp index 53882288..bf320817 100644 --- a/src/compiler/lr/item_set.cpp +++ b/src/compiler/lr/item_set.cpp @@ -31,11 +31,11 @@ namespace tree_sitter { ItemSet::ItemSet(const Item &item, const Grammar &grammar) : contents(closure_in_grammar(item, grammar)) {} - TransitionMap ItemSet::char_transitions(const Grammar &grammar) const { - auto result = TransitionMap(); + transition_map ItemSet::char_transitions(const Grammar &grammar) const { + transition_map 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([&](const item_ptr &item) -> item_set_ptr { @@ -48,11 +48,11 @@ namespace tree_sitter { return result; } - TransitionMap ItemSet::sym_transitions(const Grammar &grammar) const { - auto result = TransitionMap(); + transition_map ItemSet::sym_transitions(const Grammar &grammar) const { + transition_map 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([&](const item_ptr &item) -> item_set_ptr { diff --git a/src/compiler/lr/item_set.h b/src/compiler/lr/item_set.h index 43d580f4..128cad52 100644 --- a/src/compiler/lr/item_set.h +++ b/src/compiler/lr/item_set.h @@ -22,8 +22,8 @@ namespace tree_sitter { const_iterator end() const; size_t size() const; - TransitionMap sym_transitions(const Grammar &grammar) const; - TransitionMap char_transitions(const Grammar &grammar) const; + transition_map char_transitions(const Grammar &grammar) const; + transition_map sym_transitions(const Grammar &grammar) const; bool operator==(const ItemSet &other) const; }; diff --git a/src/compiler/rules/transitions.cpp b/src/compiler/rules/transitions.cpp index 5bbdf410..b779772d 100644 --- a/src/compiler/rules/transitions.cpp +++ b/src/compiler/rules/transitions.cpp @@ -5,22 +5,22 @@ namespace tree_sitter { namespace rules { class TransitionsVisitor : public Visitor { public: - TransitionMap value; + transition_map value; void visit(const Blank *rule) { - value = TransitionMap(); + value = transition_map(); } void visit(const CharClass *rule) { - value = TransitionMap({{ char_class(rule->value), blank() }}); + value = transition_map({{ char_class(rule->value), blank() }}); } void visit(const Char *rule) { - value = TransitionMap({{ character(rule->value), blank() }}); + value = transition_map({{ character(rule->value), blank() }}); } void visit(const Symbol *rule) { - value = TransitionMap({{ sym(rule->name), blank() }}); + value = transition_map({{ 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_ptr left_rule) -> rule_ptr { + value = transitions(rule->left).map([&](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 transitions(const rule_ptr &rule) { + transition_map transitions(const rule_ptr &rule) { TransitionsVisitor visitor; rule->accept(visitor); return visitor.value; diff --git a/src/compiler/rules/transitions.h b/src/compiler/rules/transitions.h index 6f52bf93..153fcc54 100644 --- a/src/compiler/rules/transitions.h +++ b/src/compiler/rules/transitions.h @@ -6,7 +6,7 @@ namespace tree_sitter { namespace rules { - TransitionMap transitions(const rule_ptr &rule); + transition_map transitions(const rule_ptr &rule); } } diff --git a/src/compiler/transition_map.h b/src/compiler/transition_map.h index ef727ccd..ad63844d 100644 --- a/src/compiler/transition_map.h +++ b/src/compiler/transition_map.h @@ -7,50 +7,34 @@ #include "rule.h" namespace tree_sitter { - template - class TransitionMap { - typedef std::shared_ptr rule_ptr; - typedef std::shared_ptr mapped_ptr; - typedef std::pair pair_type; + template + class transition_map { + typedef std::shared_ptr TKeyPtr; + typedef std::shared_ptr TValuePtr; + typedef std::pair pair_type; typedef std::vector 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 pairs) : contents(pairs) {}; + + bool operator==(const transition_map &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> 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 &other, std::function merge_fn) { + void merge(const transition_map &other, std::function 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 where(std::function filter_fn) { - TransitionMap result; + transition_map where(std::function filter_fn) { + transition_map result; for (pair_type pair : *this) if (filter_fn(pair.first)) result.add(pair.first, pair.second); return result; } - template - TransitionMap map(std::function(mapped_ptr)> map_fn) { - TransitionMap result; + template + transition_map map(std::function(TValuePtr)> map_fn) { + transition_map 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 - std::ostream& operator<<(std::ostream &stream, const TransitionMap &map) { + template + std::ostream& operator<<(std::ostream &stream, const transition_map &map) { stream << std::string("["); bool started = false; for (auto pair : map) {