Improve type-safety of ItemSet transitions methods

This commit is contained in:
Max Brunsfeld 2013-12-22 00:19:55 -08:00
parent 9667b3fd6c
commit 323184f981
8 changed files with 42 additions and 46 deletions

View file

@ -33,7 +33,7 @@ Describe(item_sets) {
AssertThat(
set.sym_transitions(grammar),
Equals(transition_map<rules::Rule, ItemSet>({
Equals(transition_map<rules::Symbol, 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) },
@ -46,7 +46,7 @@ Describe(item_sets) {
AssertThat(
set.char_transitions(grammar),
Equals(transition_map<rules::Rule, ItemSet>({
Equals(transition_map<rules::Character, ItemSet>({
{ character(CharClassWord), item_set({ Item("variable", choice({ repeat(character(CharClassWord)), blank() }), 1) }) },
{ character(CharClassDigit), item_set({ Item("number", choice({ repeat(character(CharClassDigit)), blank() }), 1) }) },
{ character('('), item_set({ Item("left_paren", blank(), 1) }) }

View file

@ -1,8 +1,10 @@
#include "item_set.h"
#include <iostream>
using namespace std;
using std::vector;
using std::initializer_list;
using std::dynamic_pointer_cast;
using std::ostream;
using std::string;
namespace tree_sitter {
namespace lr {
@ -31,38 +33,27 @@ namespace tree_sitter {
ItemSet::ItemSet(const Item &item, const Grammar &grammar) : contents(closure_in_grammar(item, grammar)) {}
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([&](rules::rule_ptr on_rule) -> bool {
return typeid(*on_rule) != typeid(rules::Symbol);
})
.map<ItemSet>([&](const item_ptr &item) -> item_set_ptr {
return std::make_shared<ItemSet>(*item, grammar);
});
result.merge(new_set, [&](const item_set_ptr left, const item_set_ptr right) -> item_set_ptr {
return left;
});
template<typename RuleClass>
static transition_map<RuleClass, ItemSet> transitions(const ItemSet &item_set, const Grammar &grammar) {
transition_map<RuleClass, ItemSet> result;
for (auto item : item_set) {
auto item_transitions = item.transitions();
for (auto pair : item_transitions) {
std::shared_ptr<const RuleClass> rule = dynamic_pointer_cast<const RuleClass>(pair.first);
Item item = *pair.second;
if (rule.get() != nullptr)
result.add(rule, std::make_shared<ItemSet>(item, grammar));
}
}
return result;
}
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([&](rules::rule_ptr on_rule) -> bool {
return typeid(*on_rule) == typeid(rules::Symbol);
})
.map<ItemSet>([&](const item_ptr &item) -> item_set_ptr {
return std::make_shared<ItemSet>(*item, grammar);
});
result.merge(new_set, [&](const item_set_ptr left, const item_set_ptr right) -> item_set_ptr {
return left;
});
}
return result;
transition_map<rules::Character, ItemSet> ItemSet::char_transitions(const Grammar &grammar) const {
return transitions<rules::Character>(*this, grammar);
}
transition_map<rules::Symbol, ItemSet> ItemSet::sym_transitions(const Grammar &grammar) const {
return transitions<rules::Symbol>(*this, grammar);
}
bool ItemSet::operator==(const tree_sitter::lr::ItemSet &other) const {

View file

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

View file

@ -23,9 +23,10 @@ namespace tree_sitter {
void add_shift_actions(const ItemSet &item_set, size_t state_index) {
for (auto transition : item_set.sym_transitions(grammar)) {
auto symbol = static_pointer_cast<const rules::Symbol>(transition.first);
size_t new_state_index = add_item_set(*transition.second);
table.add_action(state_index, symbol->name, ParseAction::Shift(new_state_index));
rules::Symbol symbol = *transition.first;
ItemSet item_set = *transition.second;
size_t new_state_index = add_item_set(item_set);
table.add_action(state_index, symbol.name, ParseAction::Shift(new_state_index));
}
}

View file

@ -17,6 +17,8 @@ namespace tree_sitter {
const CharMatch value;
};
typedef std::shared_ptr<const Character> char_ptr;
}
}

View file

@ -10,11 +10,11 @@ namespace tree_sitter {
return make_shared<Blank>();
}
rule_ptr character(char value) {
char_ptr character(char value) {
return make_shared<Character>(value);
}
rule_ptr character(CharClass value) {
char_ptr character(CharClass value) {
return make_shared<Character>(value);
}
@ -46,7 +46,7 @@ namespace tree_sitter {
return make_shared<String>(value);
}
rule_ptr sym(const string &name) {
sym_ptr sym(const string &name) {
return make_shared<Symbol>(name);
}
}

View file

@ -15,15 +15,15 @@
namespace tree_sitter {
namespace rules {
rule_ptr blank();
rule_ptr character(char value);
rule_ptr character(char min, char max);
rule_ptr character(CharClass value);
char_ptr character(char value);
char_ptr character(char min, char max);
char_ptr character(CharClass value);
rule_ptr choice(const std::initializer_list<rule_ptr> &rules);
rule_ptr pattern(const std::string &value);
rule_ptr repeat(const rule_ptr content);
rule_ptr seq(const std::initializer_list<rule_ptr> &rules);
rule_ptr str(const std::string &value);
rule_ptr sym(const std::string &name);
sym_ptr sym(const std::string &name);
}
}

View file

@ -13,7 +13,9 @@ namespace tree_sitter {
void accept(Visitor &visitor) const;
const std::string name;
};
};
typedef std::shared_ptr<const Symbol> sym_ptr;
}
}