Split up item set transition functions

This commit is contained in:
Max Brunsfeld 2014-02-12 22:56:44 -08:00
parent 7490a7ac94
commit a8588cd4d3
7 changed files with 67 additions and 58 deletions

View file

@ -2,10 +2,11 @@
#include "rule_can_be_blank.h"
#include "grammar.h"
using std::set;
using namespace tree_sitter::rules;
namespace tree_sitter {
using std::set;
using namespace rules;
namespace build_tables {
class FirstSetVisitor : Visitor {
set<Symbol> value;

View file

@ -4,24 +4,25 @@
#include "rule_can_be_blank.h"
#include "grammar.h"
using std::map;
using std::set;
using tree_sitter::rules::Symbol;
namespace tree_sitter {
using std::set;
using std::map;
using rules::Symbol;
using rules::rule_ptr;
class Grammar;
namespace build_tables {
map<Symbol, set<Symbol>> follow_sets(const ParseItem &item, const Grammar &grammar) {
map<Symbol, set<Symbol>> result;
for (auto pair : sym_transitions(item.rule)) {
auto symbol = pair.first;
for (auto &pair : sym_transitions(item.rule)) {
Symbol symbol = pair.first;
rule_ptr next_rule = pair.second;
if (grammar.has_definition(symbol)) {
auto following_non_terminals = first_set(pair.second, grammar);
if (rule_can_be_blank(pair.second)) {
set<Symbol> following_non_terminals = first_set(next_rule, grammar);
if (rule_can_be_blank(next_rule))
following_non_terminals.insert(item.lookahead_sym);
}
result.insert({ symbol, following_non_terminals });
}
}

View file

@ -2,13 +2,13 @@
#include "grammar.h"
#include "rule_can_be_blank.h"
using std::string;
using std::to_string;
using std::ostream;
using std::vector;
using tree_sitter::rules::Symbol;
namespace tree_sitter {
using std::string;
using std::to_string;
using std::ostream;
using std::vector;
using rules::Symbol;
namespace build_tables {
Item::Item(const Symbol &lhs, const rules::rule_ptr rule) :
lhs(lhs),

View file

@ -4,6 +4,9 @@
#include "item.h"
namespace tree_sitter {
using std::set;
using rules::Symbol;
namespace build_tables {
static bool contains(ParseItemSet items, ParseItem item) {
return (std::find(items.begin(), items.end(), item) != items.end());
@ -13,10 +16,10 @@ namespace tree_sitter {
if (!contains(item_set, item)) {
item_set.insert(item);
for (auto pair : follow_sets(item, grammar)) {
auto non_terminal = pair.first;
auto terminals = pair.second;
for (rules::Symbol terminal : terminals) {
auto next_item = ParseItem(non_terminal, grammar.rule(non_terminal), {}, terminal);
Symbol non_terminal = pair.first;
set<Symbol> terminals = pair.second;
for (auto &terminal : terminals) {
ParseItem next_item(non_terminal, grammar.rule(non_terminal), {}, terminal);
add_item(item_set, next_item, grammar);
}
}

View file

@ -3,56 +3,60 @@
#include "rule_transitions.h"
#include "merge_transitions.h"
using std::map;
namespace tree_sitter {
using std::map;
using std::set;
using rules::CharacterSet;
using rules::Symbol;
namespace build_tables {
template<typename T>
static std::set<T> merge_sets(const std::set<T> &left, const std::set<T> &right) {
std::set<T> result = left;
result.insert(right.begin(), right.end());
map<CharacterSet, LexItemSet> char_transitions(const LexItem &item) {
map<CharacterSet, LexItemSet> result;
for (auto &transition : char_transitions(item.rule)) {
LexItem next_item(item.lhs, transition.second);
result.insert({ transition.first, LexItemSet({ next_item }) });
}
return result;
}
map<Symbol, ParseItemSet> sym_transitions(const ParseItem &item, const Grammar &grammar) {
map<Symbol, ParseItemSet> result;
for (auto transition : sym_transitions(item.rule)) {
Symbol rule = transition.first;
auto consumed_symbols = item.consumed_symbols;
consumed_symbols.push_back(rule.is_auxiliary);
ParseItem new_item(item.lhs, transition.second, consumed_symbols, item.lookahead_sym);
result.insert({ rule, item_set_closure(ParseItemSet({ new_item }), grammar) });
}
return result;
}
template<typename T>
static set<T> merge_sets(const set<T> &left, const set<T> &right) {
set<T> result = left;
result.insert(right.begin(), right.end());
return result;
}
map<CharacterSet, LexItemSet> char_transitions(const LexItemSet &item_set, const Grammar &grammar) {
map<CharacterSet, LexItemSet> result;
for (const LexItem &item : item_set) {
map<CharacterSet, LexItemSet> item_transitions;
for (auto transition : char_transitions(item.rule)) {
auto rule = transition.first;
auto new_item = LexItem(item.lhs, transition.second);
auto new_item_set = LexItemSet({ new_item });
item_transitions.insert({ rule, LexItemSet(new_item_set) });
}
map<CharacterSet, LexItemSet> item_transitions = char_transitions(item);
result = merge_char_transitions<LexItemSet>(result, item_transitions, [](LexItemSet left, LexItemSet right) {
return merge_sets(left, right);
});
}
return result;
}
map<rules::Symbol, ParseItemSet> sym_transitions(const ParseItemSet &item_set, const Grammar &grammar) {
map<rules::Symbol, ParseItemSet> result;
for (const ParseItem &item : item_set) {
map<rules::Symbol, ParseItemSet> item_transitions;
for (auto transition : sym_transitions(item.rule)) {
auto rule = transition.first;
auto consumed_symbols = item.consumed_symbols;
consumed_symbols.push_back(rule.is_auxiliary);
auto new_item = ParseItem(item.lhs, transition.second, consumed_symbols, item.lookahead_sym);
auto new_item_set = item_set_closure(ParseItemSet({ new_item }), grammar);
item_transitions.insert({ rule, ParseItemSet(new_item_set) });
}
result = merge_sym_transitions<ParseItemSet>(result, item_transitions, [](ParseItemSet left, ParseItemSet right) {
map<Symbol, ParseItemSet> sym_transitions(const ParseItemSet &item_set, const Grammar &grammar) {
map<Symbol, ParseItemSet> result;
for (const ParseItem &item : item_set) {
map<Symbol, ParseItemSet> item_transitions = sym_transitions(item, grammar);
result = merge_sym_transitions<ParseItemSet>(result, item_transitions, [&](ParseItemSet left, ParseItemSet right) {
return merge_sets(left, right);
});
}
return result;
}
}

View file

@ -5,11 +5,11 @@
#include "rules.h"
#include "grammar.h"
using std::pair;
using std::string;
using std::map;
namespace tree_sitter {
using std::pair;
using std::string;
using std::map;
namespace build_tables {
static int NOT_FOUND = -1;
static rules::Symbol START("start", true);

View file

@ -3,10 +3,10 @@
#include "rule_can_be_blank.h"
#include "merge_transitions.h"
using namespace tree_sitter::rules;
using std::map;
namespace tree_sitter {
using std::map;
using namespace rules;
namespace build_tables {
bool is_blank(const rule_ptr &rule) {
return typeid(*rule) == typeid(Blank);