#include "rule_transitions.h" #include "rule_can_be_blank.h" #include "merge_transitions.h" #include "rules/blank.h" #include "rules/choice.h" #include "rules/seq.h" #include "rules/string.h" #include "rules/repeat.h" #include "rules/pattern.h" #include "rules/visitor.h" #include "rules/character_set.h" namespace tree_sitter { using std::map; using std::set; using std::make_shared; using namespace rules; namespace build_tables { bool is_blank(const rule_ptr &rule) { return typeid(*rule) == typeid(Blank); } template map merge_transitions(const map &left, const map &right); template<> map merge_transitions(const map &left, const map &right) { auto transitions = merge_char_transitions(left, right, [](rule_ptr left, rule_ptr right) -> rule_ptr { return make_shared(left, right); }); return *static_cast *>(&transitions); } template<> map merge_transitions(const map &left, const map &right) { auto transitions = merge_sym_transitions(left, right, [](rule_ptr left, rule_ptr right) -> rule_ptr { return make_shared(left, right); }); return *static_cast *>(&transitions); } template map map_transitions(const map &initial, std::function map_fn) { map result; for (auto &pair : initial) result.insert({ pair.first, map_fn(pair.second) }); return result; } template class TransitionsVisitor : public rules::Visitor { public: map value; static map transitions(const rule_ptr rule) { TransitionsVisitor visitor; rule->accept(visitor); return visitor.value; } void visit_atom(const Rule *rule) { auto atom = dynamic_cast(rule); if (atom) { value = map(); value.insert({ *atom, make_shared() }); } } void visit(const CharacterSet *rule) { visit_atom(rule); } void visit(const Symbol *rule) { visit_atom(rule); } void visit(const Choice *rule) { value = transitions(rule->left); value = merge_transitions(transitions(rule->left), transitions(rule->right)); } void visit(const Seq *rule) { value = map_transitions(transitions(rule->left), [&](const rule_ptr left_rule) { return Seq::Build({ left_rule, rule->right }); }); if (rule_can_be_blank(rule->left)) { value = merge_transitions(value, transitions(rule->right)); } } void visit(const Repeat *rule) { value = map_transitions(transitions(rule->content), [&](const rule_ptr &value) { return Seq::Build({ value, make_shared(rule->copy(), make_shared()) }); }); } void visit(const String *rule) { rule_ptr result = make_shared(); for (char val : rule->value) result = Seq::Build({ result, make_shared(set({ val })) }); value = transitions(result); } void visit(const Pattern *rule) { value = transitions(rule->to_rule_tree()); } }; map char_transitions(const rule_ptr &rule) { return TransitionsVisitor::transitions(rule); } map sym_transitions(const rule_ptr &rule) { return TransitionsVisitor::transitions(rule); } } }