diff --git a/src/compiler/build_tables/first_set.cpp b/src/compiler/build_tables/first_set.cpp index 57a65067..bf06134e 100644 --- a/src/compiler/build_tables/first_set.cpp +++ b/src/compiler/build_tables/first_set.cpp @@ -11,11 +11,10 @@ namespace tree_sitter { using namespace rules; namespace build_tables { - class FirstSetVisitor : Visitor { - set value; + class FirstSet : public RuleFn> { const PreparedGrammar grammar; - - FirstSetVisitor(const PreparedGrammar &grammar) : grammar(grammar) {} + public: + FirstSet(const PreparedGrammar &grammar) : grammar(grammar) {} set set_union(const set &left, const set &right) { set result = left; @@ -25,33 +24,27 @@ namespace tree_sitter { void visit(const Symbol *rule) { if (grammar.has_definition(*rule)) { - value = apply(grammar.rule(*rule), grammar); + value = apply(grammar.rule(*rule)); } else { value = set({ *rule }); } } void visit(const Choice *rule) { - value = set_union(apply(rule->left, grammar), apply(rule->right, grammar)); + value = set_union(apply(rule->left), apply(rule->right)); } void visit(const Seq *rule) { - value = apply(rule->left, grammar); + auto result = apply(rule->left); if (rule_can_be_blank(rule->left, grammar)) { - value = set_union(value, apply(rule->right, grammar)); + result = set_union(result, apply(rule->right)); } - } - - public: - static set apply(const rule_ptr rule, const PreparedGrammar &grammar) { - FirstSetVisitor visitor(grammar); - rule->accept(visitor); - return visitor.value; + value = result; } }; set first_set(const rule_ptr &rule, const PreparedGrammar &grammar) { - return FirstSetVisitor::apply(rule, grammar); + return FirstSet(grammar).apply(rule); } } } \ No newline at end of file diff --git a/src/compiler/build_tables/rule_can_be_blank.cpp b/src/compiler/build_tables/rule_can_be_blank.cpp index 80dfdb14..343651f5 100644 --- a/src/compiler/build_tables/rule_can_be_blank.cpp +++ b/src/compiler/build_tables/rule_can_be_blank.cpp @@ -11,41 +11,47 @@ namespace tree_sitter { using namespace rules; namespace build_tables { - class EpsilonVisitor : public rules::Visitor { - public: - bool value; - + class CanBeBlank : public RuleFn { + protected: void default_visit(const Rule *) { value = false; } - void visit(const Blank *) { + virtual void visit(const Blank *) { value = true; } - void visit(const Choice *rule) { - value = rule_can_be_blank(rule->left) || rule_can_be_blank(rule->right); - } - - void visit(const Seq *rule) { - value = rule_can_be_blank(rule->left) && rule_can_be_blank(rule->right); - } - - void visit(const Repeat *rule) { + virtual void visit(const Repeat *rule) { value = true; } + + virtual void visit(const Choice *rule) { + value = apply(rule->left) || apply(rule->right); + } + + virtual void visit(const Seq *rule) { + value = apply(rule->left) && apply(rule->right); + } + }; + + class CanBeBlankRecursive : public CanBeBlank { + const PreparedGrammar grammar; + using CanBeBlank::visit; + + public: + CanBeBlankRecursive(const PreparedGrammar &grammar) : grammar(grammar) {} + + void visit(const Symbol *rule) { + value = grammar.has_definition(*rule) && apply(grammar.rule(*rule)); + } }; bool rule_can_be_blank(const rule_ptr &rule) { - EpsilonVisitor visitor; - rule->accept(visitor); - return visitor.value; + return CanBeBlank().apply(rule); } bool rule_can_be_blank(const rule_ptr &rule, const PreparedGrammar &grammar) { - if (rule_can_be_blank(rule)) return true; - auto symbol = std::dynamic_pointer_cast(rule); - return (symbol.get() && grammar.has_definition(*symbol) && rule_can_be_blank(grammar.rule(*symbol), grammar)); + return CanBeBlankRecursive(grammar).apply(rule); } } } diff --git a/src/compiler/build_tables/rule_transitions.cpp b/src/compiler/build_tables/rule_transitions.cpp index 56b88423..b1db4612 100644 --- a/src/compiler/build_tables/rule_transitions.cpp +++ b/src/compiler/build_tables/rule_transitions.cpp @@ -7,8 +7,8 @@ #include "rules/string.h" #include "rules/repeat.h" #include "rules/pattern.h" -#include "rules/visitor.h" #include "rules/character_set.h" +#include "rules/visitor.h" namespace tree_sitter { using std::map; @@ -17,16 +17,12 @@ namespace tree_sitter { 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 { + auto transitions = merge_char_transitions(left, right, [](rule_ptr left, rule_ptr right) { return make_shared(left, right); }); return *static_cast *>(&transitions); @@ -34,7 +30,7 @@ namespace tree_sitter { 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 { + auto transitions = merge_sym_transitions(left, right, [](rule_ptr left, rule_ptr right) { return make_shared(left, right); }); return *static_cast *>(&transitions); @@ -49,22 +45,11 @@ namespace tree_sitter { } template - class TransitionsVisitor : public rules::Visitor { - public: - map value; - - static map transitions(const rule_ptr rule) { - TransitionsVisitor visitor; - rule->accept(visitor); - return visitor.value; - } - + class RuleTransitions : public RuleFn> { void visit_atom(const Rule *rule) { auto atom = dynamic_cast(rule); - if (atom) { - value = map(); - value.insert({ *atom, make_shared() }); - } + if (atom) + this->value = map({{ *atom, make_shared() }}); } void visit(const CharacterSet *rule) { @@ -76,24 +61,22 @@ namespace tree_sitter { } void visit(const Choice *rule) { - value = transitions(rule->left); - value = merge_transitions(transitions(rule->left), transitions(rule->right)); + this->value = merge_transitions(this->apply(rule->left), + this->apply(rule->right)); } void visit(const Seq *rule) { - value = map_transitions(transitions(rule->left), [&](const rule_ptr left_rule) { + auto result = map_transitions(this->apply(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)); - } + if (rule_can_be_blank(rule->left)) + result = merge_transitions(result, this->apply(rule->right)); + this->value = result; } 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()) }); + this->value = map_transitions(this->apply(rule->content), [&](const rule_ptr &value) { + return Seq::Build({ value, make_shared(rule->copy(), make_shared()) }); }); } @@ -101,20 +84,20 @@ namespace tree_sitter { rule_ptr result = make_shared(); for (char val : rule->value) result = Seq::Build({ result, make_shared(set({ val })) }); - value = transitions(result); + this->value = this->apply(result); } void visit(const Pattern *rule) { - value = transitions(rule->to_rule_tree()); + this->value = this->apply(rule->to_rule_tree()); } }; map char_transitions(const rule_ptr &rule) { - return TransitionsVisitor::transitions(rule); + return RuleTransitions().apply(rule); } map sym_transitions(const rule_ptr &rule) { - return TransitionsVisitor::transitions(rule); + return RuleTransitions().apply(rule); } } } diff --git a/src/compiler/prepare_grammar/expand_repeats.cpp b/src/compiler/prepare_grammar/expand_repeats.cpp index 92cb7b2e..421859b0 100644 --- a/src/compiler/prepare_grammar/expand_repeats.cpp +++ b/src/compiler/prepare_grammar/expand_repeats.cpp @@ -16,16 +16,7 @@ namespace tree_sitter { using namespace rules; namespace prepare_grammar { - class RepeatExpander : rules::Visitor { - public: - rule_ptr value; - map aux_rules; - - rule_ptr apply(const rule_ptr &rule) { - rule->accept(*this); - return value; - } - + class ExpandRepeats : public RuleFn { rule_ptr make_repeat_helper(string name, const rule_ptr &rule) { return Choice::Build({ Seq::Build({ rule, make_shared(name, SymbolTypeAuxiliary) }), @@ -50,17 +41,19 @@ namespace tree_sitter { void default_visit(const Rule *rule) { value = rule->copy(); } + + public: + map aux_rules; }; PreparedGrammar expand_repeats(const PreparedGrammar &grammar) { - map rules; - map aux_rules(grammar.aux_rules); - RepeatExpander visitor; + map rules, aux_rules(grammar.aux_rules); + ExpandRepeats expander; - for (auto pair : grammar.rules) - rules.insert({ pair.first, visitor.apply(pair.second) }); + for (auto &pair : grammar.rules) + rules.insert({ pair.first, expander.apply(pair.second) }); - aux_rules.insert(visitor.aux_rules.begin(), visitor.aux_rules.end()); + aux_rules.insert(expander.aux_rules.begin(), expander.aux_rules.end()); return PreparedGrammar(grammar.start_rule_name, rules, aux_rules); } diff --git a/src/compiler/prepare_grammar/extract_tokens.cpp b/src/compiler/prepare_grammar/extract_tokens.cpp index bc78f9b3..1461f817 100644 --- a/src/compiler/prepare_grammar/extract_tokens.cpp +++ b/src/compiler/prepare_grammar/extract_tokens.cpp @@ -7,6 +7,8 @@ #include "rules/repeat.h" #include "rules/blank.h" #include "rules/symbol.h" +#include "rules/string.h" +#include "rules/pattern.h" #include namespace tree_sitter { @@ -18,10 +20,7 @@ namespace tree_sitter { using namespace rules; namespace prepare_grammar { - class TokenChecker : public Visitor { - public: - bool value; - + class IsToken : public RuleFn { void default_visit(const Rule *rule) { value = false; } @@ -34,36 +33,8 @@ namespace tree_sitter { value = true; } }; - - bool is_token(const rule_ptr &rule) { - TokenChecker checker; - rule->accept(checker); - return checker.value; - } - - class TokenExtractor : Visitor { - public: - rule_ptr value; - map tokens; - - rule_ptr initial_apply(const rule_ptr rule) { - if (is_token(rule)) { - return rule_ptr(); - } else { - return apply(rule); - } - } - - rule_ptr apply(const rule_ptr rule) { - if (!is_token(rule) || rule->operator==(Blank())) { - rule->accept(*this); - return value; - } else { - string token_name = add_token(rule); - return make_shared(token_name, SymbolTypeAuxiliary); - } - } - + + class TokenExtractor : public RuleFn { string add_token(const rule_ptr &rule) { for (auto pair : tokens) if (*pair.second == *rule) @@ -72,9 +43,14 @@ namespace tree_sitter { tokens.insert({ name, rule }); return name; } - + void default_visit(const Rule *rule) { - value = rule->copy(); + auto result = rule->copy(); + if (IsToken().apply(result)) { + value = make_shared(add_token(result), SymbolTypeAuxiliary); + } else { + value = result; + } } void visit(const Choice *rule) { @@ -88,33 +64,31 @@ namespace tree_sitter { void visit(const Repeat *rule) { value = make_shared(apply(rule->content)); } + + public: + map tokens; }; pair extract_tokens(const PreparedGrammar &input_grammar) { + map rules, tokens, aux_rules, aux_tokens; TokenExtractor extractor; - map rules; - map tokens; - map aux_rules; - map aux_tokens; - for (auto pair : input_grammar.rules) { + for (auto &pair : input_grammar.rules) { string name = pair.first; rule_ptr rule = pair.second; - rule_ptr new_rule = extractor.initial_apply(rule); - if (new_rule.get()) - rules.insert({ name, new_rule }); - else + if (IsToken().apply(rule)) tokens.insert({ name, rule }); + else + rules.insert({ name, extractor.apply(rule) }); } - for (auto pair : input_grammar.aux_rules) { + for (auto &pair : input_grammar.aux_rules) { string name = pair.first; rule_ptr rule = pair.second; - rule_ptr new_rule = extractor.initial_apply(rule); - if (new_rule.get()) - aux_rules.insert({ name, new_rule }); - else + if (IsToken().apply(rule)) aux_tokens.insert({ name, rule }); + else + aux_rules.insert({ name, extractor.apply(rule) }); } aux_tokens.insert(extractor.tokens.begin(), extractor.tokens.end()); diff --git a/src/compiler/rules/visitor.h b/src/compiler/rules/visitor.h index b5aa5e21..e48a207c 100644 --- a/src/compiler/rules/visitor.h +++ b/src/compiler/rules/visitor.h @@ -1,9 +1,10 @@ #ifndef __tree_sitter__rule_visitor__ #define __tree_sitter__rule_visitor__ +#include "./rule.h" + namespace tree_sitter { namespace rules { - class Rule; class Blank; class Symbol; class CharacterSet; @@ -25,6 +26,18 @@ namespace tree_sitter { virtual void visit(const String *rule); virtual void visit(const Pattern *rule); }; + + template + class RuleFn : public Visitor { + protected: + T value; + public: + T apply(const rule_ptr &rule) { + value = T(); + rule->accept(*this); + return value; + } + }; } }