diff --git a/TreeSitter.xcodeproj/project.pbxproj b/TreeSitter.xcodeproj/project.pbxproj index 9280e21b..7661e9b1 100644 --- a/TreeSitter.xcodeproj/project.pbxproj +++ b/TreeSitter.xcodeproj/project.pbxproj @@ -53,6 +53,7 @@ 12FD40DB185FEF0D0041A84E /* arithmetic_spec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 12FD40DA185FEF0D0041A84E /* arithmetic_spec.cpp */; }; 12FD40DD185FF12C0041A84E /* parser.c in Sources */ = {isa = PBXBuildFile; fileRef = 12FD40DC185FF12C0041A84E /* parser.c */; }; 12FD40DF1860064C0041A84E /* tree.c in Sources */ = {isa = PBXBuildFile; fileRef = 12FD40DE1860064C0041A84E /* tree.c */; }; + 12FD40E2186245FE0041A84E /* transitions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 12FD40E0186245FE0041A84E /* transitions.cpp */; }; 27A343CA69E17E0F9EBEDF1C /* pattern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27A340F3EEB184C040521323 /* pattern.cpp */; }; /* End PBXBuildFile section */ @@ -129,6 +130,9 @@ 12FD40DA185FEF0D0041A84E /* arithmetic_spec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = arithmetic_spec.cpp; sourceTree = ""; }; 12FD40DC185FF12C0041A84E /* parser.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = parser.c; sourceTree = ""; }; 12FD40DE1860064C0041A84E /* tree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tree.c; sourceTree = ""; }; + 12FD40E0186245FE0041A84E /* transitions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = transitions.cpp; sourceTree = ""; }; + 12FD40E1186245FE0041A84E /* transitions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = transitions.h; sourceTree = ""; }; + 12FD40E41862B3530041A84E /* rule_visitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rule_visitor.h; sourceTree = ""; }; 27A340F3EEB184C040521323 /* pattern.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pattern.cpp; sourceTree = ""; }; 27A3438C4FA59A3882E8493B /* pattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pattern.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -175,6 +179,9 @@ 1213060A182C389100FCF928 /* symbol.h */, 12F8BE8C183C79B2006CCF99 /* char_class.cpp */, 12F8BE8D183C79B2006CCF99 /* char_class.h */, + 12FD40E0186245FE0041A84E /* transitions.cpp */, + 12FD40E1186245FE0041A84E /* transitions.h */, + 12FD40E41862B3530041A84E /* rule_visitor.h */, ); path = rules; sourceTree = ""; @@ -416,6 +423,7 @@ 1213061B182C84DF00FCF928 /* item.cpp in Sources */, 12FD40D9185FEEDF0041A84E /* pattern_spec.cpp in Sources */, 12130617182C3D2900FCF928 /* string.cpp in Sources */, + 12FD40E2186245FE0041A84E /* transitions.cpp in Sources */, 12F8BE8E183C79B2006CCF99 /* char_class.cpp in Sources */, 12130611182C3A1100FCF928 /* blank.cpp in Sources */, 1213060E182C398300FCF928 /* choice.cpp in Sources */, diff --git a/spec/compiler/rules/rules_spec.cpp b/spec/compiler/rules/rules_spec.cpp index e6147cd8..1cfd3cde 100644 --- a/spec/compiler/rules/rules_spec.cpp +++ b/spec/compiler/rules/rules_spec.cpp @@ -1,5 +1,6 @@ #include "spec_helper.h" #include "rules.h" +#include "transitions.h" #include "transition_map.h" Describe(Rules) { @@ -28,7 +29,7 @@ Describe(Rules) { It(handles_symbols) { AssertThat( - symbol1->transitions(), + rules::transitions(symbol1), EqualsTransitionMap(TransitionMap({ { symbol1, rules::blank() } }))); @@ -36,7 +37,7 @@ Describe(Rules) { It(handles_characters) { AssertThat( - char1->transitions(), + rules::transitions(char1), EqualsTransitionMap(TransitionMap({ { char1, rules::blank() } }))); @@ -45,7 +46,7 @@ Describe(Rules) { It(handles_character_classes) { auto rule = rules::char_class(rules::CharClassTypeDigit); AssertThat( - rule->transitions(), + rules::transitions(rule), EqualsTransitionMap(TransitionMap({ { rule, rules::blank() } }))); @@ -53,7 +54,7 @@ Describe(Rules) { It(handles_choices) { AssertThat( - rules::choice({ symbol1, symbol2 })->transitions(), + rules::transitions(rules::choice({ symbol1, symbol2 })), EqualsTransitionMap(TransitionMap({ { symbol1, rules::blank() }, { symbol2, rules::blank() } @@ -62,7 +63,7 @@ Describe(Rules) { It(handles_sequences) { AssertThat( - rules::seq({ symbol1, symbol2 })->transitions(), + rules::transitions(rules::seq({ symbol1, symbol2 })), EqualsTransitionMap(TransitionMap({ { symbol1, symbol2 } }))); @@ -70,12 +71,12 @@ Describe(Rules) { It(handles_long_sequences) { AssertThat( - rules::seq({ + rules::transitions(rules::seq({ symbol1, symbol2, symbol3, symbol4 - })->transitions(), + })), EqualsTransitionMap(TransitionMap({ { symbol1, rules::seq({ symbol2, symbol3, symbol4 }) } }))); @@ -83,9 +84,10 @@ Describe(Rules) { It(handles_choices_with_common_starting_symbols) { AssertThat( - rules::choice({ - rules::seq({ symbol1, symbol2 }), - rules::seq({ symbol1, symbol3 }) })->transitions(), + rules::transitions( + rules::choice({ + rules::seq({ symbol1, symbol2 }), + rules::seq({ symbol1, symbol3 }) })), EqualsTransitionMap(TransitionMap({ { symbol1, rules::choice({ symbol2, symbol3 }) } }))); @@ -93,7 +95,7 @@ Describe(Rules) { It(handles_strings) { AssertThat( - rules::str("bad")->transitions(), + rules::transitions(rules::str("bad")), EqualsTransitionMap(TransitionMap({ { rules::character('b'), @@ -104,7 +106,7 @@ Describe(Rules) { It(handles_patterns) { AssertThat( - rules::pattern("a|b")->transitions(), + rules::transitions(rules::pattern("a|b")), EqualsTransitionMap(TransitionMap({ { rules::character('a'), rules::blank() }, { rules::character('b'), rules::blank() } @@ -114,7 +116,7 @@ Describe(Rules) { It(handles_repeats) { rules::rule_ptr repeat = rules::repeat(rules::str("ab")); AssertThat( - repeat->transitions(), + rules::transitions(repeat), EqualsTransitionMap(TransitionMap({ { rules::character('a'), @@ -129,7 +131,7 @@ Describe(Rules) { repeat = rules::repeat(rules::str("a")); AssertThat( - repeat->transitions(), + rules::transitions(repeat), EqualsTransitionMap(TransitionMap({ { rules::character('a'), diff --git a/src/compiler/lr/item.cpp b/src/compiler/lr/item.cpp index 75b53618..38ce3cd2 100644 --- a/src/compiler/lr/item.cpp +++ b/src/compiler/lr/item.cpp @@ -1,5 +1,6 @@ #include "item.h" #include "grammar.h" +#include "transitions.h" #include @@ -17,14 +18,14 @@ namespace tree_sitter { } TransitionMap Item::transitions() const { - return rule->transitions().map([&](rules::rule_ptr to_rule) { + return rules::transitions(rule).map([&](rules::rule_ptr to_rule) { return std::make_shared(rule_name, to_rule, consumed_sym_count + 1); }); }; vector Item::next_symbols() const { vector result; - for (auto pair : rule->transitions()) { + for (auto pair : rules::transitions(rule)) { shared_ptr sym = dynamic_pointer_cast(pair.first); if (sym) result.push_back(sym); } diff --git a/src/compiler/lr/item.h b/src/compiler/lr/item.h index fc389357..e779b4d5 100644 --- a/src/compiler/lr/item.h +++ b/src/compiler/lr/item.h @@ -3,6 +3,7 @@ #include #include "rule.h" +#include "symbol.h" #include "transition_map.h" namespace tree_sitter { diff --git a/src/compiler/rules/blank.cpp b/src/compiler/rules/blank.cpp index b306aa21..acf89c58 100644 --- a/src/compiler/rules/blank.cpp +++ b/src/compiler/rules/blank.cpp @@ -1,18 +1,14 @@ -#include "blank.h" +#include "rules.h" #include "transition_map.h" namespace tree_sitter { namespace rules { Blank::Blank() {} - blank_ptr blank() { + rule_ptr blank() { return std::make_shared(); } - TransitionMap Blank::transitions() const { - return TransitionMap(); - } - bool Blank::operator==(const Rule &rule) const { return dynamic_cast(&rule) != nullptr; } @@ -20,5 +16,9 @@ namespace tree_sitter { std::string Blank::to_string() const { return "blank"; } + + void Blank::accept(RuleVisitor &visitor) const { + visitor.visit(this); + } } } \ No newline at end of file diff --git a/src/compiler/rules/blank.h b/src/compiler/rules/blank.h index 99f1a577..2c313674 100644 --- a/src/compiler/rules/blank.h +++ b/src/compiler/rules/blank.h @@ -8,13 +8,12 @@ namespace tree_sitter { class Blank : public Rule { public: Blank(); - TransitionMap transitions() const; bool operator==(const Rule& other) const; std::string to_string() const; + void accept(RuleVisitor &visitor) const; }; - typedef std::shared_ptr blank_ptr; - blank_ptr blank(); + rule_ptr blank(); } } diff --git a/src/compiler/rules/char.cpp b/src/compiler/rules/char.cpp index 6c693c90..73776d95 100644 --- a/src/compiler/rules/char.cpp +++ b/src/compiler/rules/char.cpp @@ -1,5 +1,4 @@ -#include "char.h" -#include "blank.h" +#include "rules.h" #include "transition_map.h" using namespace std; @@ -12,10 +11,6 @@ namespace tree_sitter { return std::make_shared(value); } - TransitionMap Char::transitions() const { - return TransitionMap({{ character(value), blank() }}); - } - bool Char::operator==(const Rule &rule) const { const Char *other = dynamic_cast(&rule); return other && (other->value == value); @@ -24,5 +19,9 @@ namespace tree_sitter { string Char::to_string() const { return std::string("'") + value + "'"; } + + void Char::accept(RuleVisitor &visitor) const { + visitor.visit(this); + } } } diff --git a/src/compiler/rules/char.h b/src/compiler/rules/char.h index 61a2aed9..2d360745 100644 --- a/src/compiler/rules/char.h +++ b/src/compiler/rules/char.h @@ -8,10 +8,10 @@ namespace tree_sitter { class Char : public Rule { public: Char(char value); - TransitionMap transitions() const; bool operator==(const Rule& other) const; std::string to_string() const; - private: + void accept(RuleVisitor &visitor) const; + const char value; }; diff --git a/src/compiler/rules/char_class.cpp b/src/compiler/rules/char_class.cpp index 8b7174ac..2bde4ac8 100644 --- a/src/compiler/rules/char_class.cpp +++ b/src/compiler/rules/char_class.cpp @@ -1,5 +1,4 @@ -#include "char_class.h" -#include "blank.h" +#include "rules.h" #include "transition_map.h" using namespace std; @@ -12,10 +11,6 @@ namespace tree_sitter { return std::make_shared(type); } - TransitionMap CharClass::transitions() const { - return TransitionMap({{ char_class(value), blank() }}); - } - bool CharClass::operator==(const Rule &rule) const { const CharClass *other = dynamic_cast(&rule); return other && (other->value == value); @@ -29,5 +24,9 @@ namespace tree_sitter { return ""; } } + + void CharClass::accept(RuleVisitor &visitor) const { + visitor.visit(this); + } } } diff --git a/src/compiler/rules/char_class.h b/src/compiler/rules/char_class.h index 55200c89..f2a30347 100644 --- a/src/compiler/rules/char_class.h +++ b/src/compiler/rules/char_class.h @@ -13,10 +13,10 @@ namespace tree_sitter { class CharClass : public Rule { public: CharClass(CharClassType type); - TransitionMap transitions() const; bool operator==(const Rule& other) const; std::string to_string() const; - private: + void accept(RuleVisitor &visitor) const; + const CharClassType value; }; diff --git a/src/compiler/rules/choice.cpp b/src/compiler/rules/choice.cpp index ae37e0aa..5dfc6f66 100644 --- a/src/compiler/rules/choice.cpp +++ b/src/compiler/rules/choice.cpp @@ -1,4 +1,4 @@ -#include "choice.h" +#include "rules.h" #include "transition_map.h" namespace tree_sitter { @@ -12,14 +12,6 @@ namespace tree_sitter { return result; } - TransitionMap Choice::transitions() const { - auto result = left->transitions(); - result.merge(right->transitions(), [&](rule_ptr left, rule_ptr right) -> rule_ptr { - return choice({ left, right }); - }); - return result; - } - bool Choice::operator==(const Rule &rule) const { const Choice *other = dynamic_cast(&rule); return other && (*other->left == *left) && (*other->right == *right); @@ -28,5 +20,9 @@ namespace tree_sitter { std::string Choice::to_string() const { return std::string("(choice ") + left->to_string() + " " + right->to_string() + ")"; } + + void Choice::accept(RuleVisitor &visitor) const { + visitor.visit(this); + } } } \ No newline at end of file diff --git a/src/compiler/rules/choice.h b/src/compiler/rules/choice.h index f612cdfc..48b7714f 100644 --- a/src/compiler/rules/choice.h +++ b/src/compiler/rules/choice.h @@ -8,10 +8,10 @@ namespace tree_sitter { class Choice : public Rule { public: Choice(rule_ptr left, rule_ptr right); - TransitionMap transitions() const; bool operator==(const Rule& other) const; std::string to_string() const; - private: + void accept(RuleVisitor &visitor) const; + const rule_ptr left; const rule_ptr right; }; diff --git a/src/compiler/rules/pattern.cpp b/src/compiler/rules/pattern.cpp index 6ecc18ba..7c4f0605 100644 --- a/src/compiler/rules/pattern.cpp +++ b/src/compiler/rules/pattern.cpp @@ -1,6 +1,4 @@ -#include "choice.h" -#include "seq.h" -#include "Pattern.h" +#include "rules.h" #include "transition_map.h" using namespace std; @@ -108,16 +106,8 @@ namespace tree_sitter { pattern_ptr pattern(const std::string &value) { return std::make_shared(value); } - - TransitionMap Pattern::transitions() const { - return to_rule_tree()->transitions(); - } - rule_ptr Pattern::to_rule_tree() const { - return PatternParser(value).rule(); - } - - bool Pattern::operator ==(tree_sitter::rules::Rule const &other) const { + bool Pattern::operator==(tree_sitter::rules::Rule const &other) const { auto pattern = dynamic_cast(&other); return pattern && (pattern->value == value); } @@ -125,5 +115,13 @@ namespace tree_sitter { std::string Pattern::to_string() const { return value; } + + void Pattern::accept(RuleVisitor &visitor) const { + visitor.visit(this); + } + + rule_ptr Pattern::to_rule_tree() const { + return PatternParser(value).rule(); + } } } diff --git a/src/compiler/rules/pattern.h b/src/compiler/rules/pattern.h index 7202d347..b08b8ea1 100644 --- a/src/compiler/rules/pattern.h +++ b/src/compiler/rules/pattern.h @@ -6,14 +6,13 @@ namespace tree_sitter { namespace rules { class Pattern : public Rule { + const std::string value; public: Pattern(const std::string &string); - TransitionMap transitions() const; bool operator==(const Rule& other) const; std::string to_string() const; + void accept(RuleVisitor &visitor) const; rule_ptr to_rule_tree() const; - private: - const std::string value; }; typedef std::shared_ptr pattern_ptr; diff --git a/src/compiler/rules/repeat.cpp b/src/compiler/rules/repeat.cpp index f4e61275..eaae7361 100644 --- a/src/compiler/rules/repeat.cpp +++ b/src/compiler/rules/repeat.cpp @@ -1,7 +1,4 @@ -#include "blank.h" -#include "seq.h" -#include "choice.h" -#include "repeat.h" +#include "rules.h" #include "transition_map.h" namespace tree_sitter { @@ -12,12 +9,6 @@ namespace tree_sitter { return std::make_shared(content); } - TransitionMap Repeat::transitions() const { - return content->transitions().map([&](const rule_ptr &value) -> rule_ptr { - return seq({ value, choice({ repeat(content), blank() }) }); - }); - } - bool Repeat::operator==(const Rule &rule) const { const Repeat *other = dynamic_cast(&rule); return other && (*other->content == *content); @@ -26,5 +17,9 @@ namespace tree_sitter { std::string Repeat::to_string() const { return std::string("(repeat ") + content->to_string() + ")"; } + + void Repeat::accept(RuleVisitor &visitor) const { + visitor.visit(this); + } } } diff --git a/src/compiler/rules/repeat.h b/src/compiler/rules/repeat.h index 9557464e..53aacf48 100644 --- a/src/compiler/rules/repeat.h +++ b/src/compiler/rules/repeat.h @@ -8,10 +8,10 @@ namespace tree_sitter { class Repeat : public Rule { public: Repeat(rule_ptr content); - TransitionMap transitions() const; bool operator==(const Rule& other) const; std::string to_string() const; - private: + void accept(RuleVisitor &visitor) const; + const rule_ptr content; }; diff --git a/src/compiler/rules/rule.cpp b/src/compiler/rules/rule.cpp index 90361113..eebdd36a 100644 --- a/src/compiler/rules/rule.cpp +++ b/src/compiler/rules/rule.cpp @@ -3,10 +3,6 @@ namespace tree_sitter { namespace rules { - size_t Rule::hash_code() const { - return std::hash()(to_string()); - } - std::ostream& operator<<(std::ostream& stream, const Rule &rule) { stream << rule.to_string(); diff --git a/src/compiler/rules/rule.h b/src/compiler/rules/rule.h index cbb386b5..275fc1f4 100644 --- a/src/compiler/rules/rule.h +++ b/src/compiler/rules/rule.h @@ -4,21 +4,17 @@ #include namespace tree_sitter { - template class TransitionMap; - namespace rules { - class Rule; - typedef std::shared_ptr rule_ptr; + class RuleVisitor; class Rule { public: - virtual TransitionMap transitions() const = 0; virtual bool operator==(const Rule& other) const = 0; virtual std::string to_string() const = 0; - virtual size_t hash_code() const; + virtual void accept(RuleVisitor &visitor) const = 0; }; - + typedef std::shared_ptr rule_ptr; std::ostream& operator<<(std::ostream& stream, const Rule &rule); std::ostream& operator<<(std::ostream& stream, const rule_ptr &rule); } @@ -28,7 +24,7 @@ namespace std { template<> struct hash { size_t operator()(const tree_sitter::rules::Rule &rule) { - return rule.hash_code(); + return std::hash()(rule.to_string()); } }; } diff --git a/src/compiler/rules/rule_visitor.h b/src/compiler/rules/rule_visitor.h new file mode 100644 index 00000000..26cf3e48 --- /dev/null +++ b/src/compiler/rules/rule_visitor.h @@ -0,0 +1,23 @@ +#ifndef __tree_sitter__rule_visitor__ +#define __tree_sitter__rule_visitor__ + +#include "rules.h" + +namespace tree_sitter { + namespace rules { + class RuleVisitor { + public: + virtual void visit(const Blank *rule) = 0; + virtual void visit(const Symbol *rule) = 0; + virtual void visit(const Char *rule) = 0; + virtual void visit(const CharClass *rule) = 0; + virtual void visit(const Choice *rule) = 0; + virtual void visit(const Repeat *rule) = 0; + virtual void visit(const Seq *rule) = 0; + virtual void visit(const String *rule) = 0; + virtual void visit(const Pattern *rule) = 0; + }; + } +} + +#endif diff --git a/src/compiler/rules/rules.h b/src/compiler/rules/rules.h index 4f923682..148f8dee 100644 --- a/src/compiler/rules/rules.h +++ b/src/compiler/rules/rules.h @@ -11,5 +11,6 @@ #include "char.h" #include "char_class.h" #include "repeat.h" +#include "rule_visitor.h" #endif diff --git a/src/compiler/rules/seq.cpp b/src/compiler/rules/seq.cpp index 0bfa64af..23fede7a 100644 --- a/src/compiler/rules/seq.cpp +++ b/src/compiler/rules/seq.cpp @@ -1,5 +1,4 @@ -#include "seq.h" -#include "blank.h" +#include "rules.h" #include "transition_map.h" namespace tree_sitter { @@ -15,15 +14,6 @@ namespace tree_sitter { return result; } - TransitionMap Seq::transitions() const { - return left->transitions().map([&](rule_ptr left_rule) -> rule_ptr { - if (typeid(*left_rule) == typeid(Blank)) - return right; - else - return seq({ left_rule, right }); - }); - } - bool Seq::operator==(const Rule &rule) const { const Seq *other = dynamic_cast(&rule); return other && (*other->left == *left) && (*other->right == *right); @@ -32,5 +22,9 @@ namespace tree_sitter { std::string Seq::to_string() const { return std::string("(seq ") + left->to_string() + " " + right->to_string() + ")"; } + + void Seq::accept(RuleVisitor &visitor) const { + visitor.visit(this); + } } } diff --git a/src/compiler/rules/seq.h b/src/compiler/rules/seq.h index bb28eaf9..3babe2fb 100644 --- a/src/compiler/rules/seq.h +++ b/src/compiler/rules/seq.h @@ -8,10 +8,10 @@ namespace tree_sitter { class Seq : public Rule { public: Seq(rule_ptr left, rule_ptr right); - TransitionMap transitions() const; bool operator==(const Rule& other) const; std::string to_string() const; - private: + void accept(RuleVisitor &visitor) const; + const rule_ptr left; const rule_ptr right; }; diff --git a/src/compiler/rules/string.cpp b/src/compiler/rules/string.cpp index aae1f9c9..652d69d2 100644 --- a/src/compiler/rules/string.cpp +++ b/src/compiler/rules/string.cpp @@ -1,7 +1,5 @@ -#include "string.h" +#include "rules.h" #include "transition_map.h" -#include "char.h" -#include "seq.h" namespace tree_sitter { namespace rules { @@ -11,13 +9,6 @@ namespace tree_sitter { return std::make_shared(value); } - TransitionMap String::transitions() const { - rule_ptr result = character(value[0]); - for (int i = 1; i < value.length(); i++) - result = seq({ result, character(value[i]) }); - return result->transitions(); - } - bool String::operator==(const Rule &rule) const { const String *other = dynamic_cast(&rule); return (other != NULL) && (other->value == value); @@ -26,6 +17,9 @@ namespace tree_sitter { std::string String::to_string() const { return std::string("(string '") + value + "')"; } - + + void String::accept(RuleVisitor &visitor) const { + visitor.visit(this); + } } } \ No newline at end of file diff --git a/src/compiler/rules/string.h b/src/compiler/rules/string.h index 0a18fda9..bd99bd5f 100644 --- a/src/compiler/rules/string.h +++ b/src/compiler/rules/string.h @@ -8,10 +8,10 @@ namespace tree_sitter { class String : public Rule { public: String(std::string value); - TransitionMap transitions() const; bool operator==(const Rule& other) const; std::string to_string() const; - private: + void accept(RuleVisitor &visitor) const; + const std::string value; }; diff --git a/src/compiler/rules/symbol.cpp b/src/compiler/rules/symbol.cpp index 7ed19363..b6323b9a 100644 --- a/src/compiler/rules/symbol.cpp +++ b/src/compiler/rules/symbol.cpp @@ -1,5 +1,4 @@ -#include "symbol.h" -#include "blank.h" +#include "rules.h" #include "transition_map.h" namespace tree_sitter { @@ -10,10 +9,6 @@ namespace tree_sitter { return std::make_shared(name); } - TransitionMap Symbol::transitions() const { - return TransitionMap({{ sym(name) , blank() }}); - } - bool Symbol::operator==(const Rule &rule) const { const Symbol *other = dynamic_cast(&rule); return other && (other->name == name); @@ -22,5 +17,9 @@ namespace tree_sitter { std::string Symbol::to_string() const { return std::string("(sym '") + name + "')"; } + + void Symbol::accept(RuleVisitor &visitor) const { + visitor.visit(this); + } } } \ No newline at end of file diff --git a/src/compiler/rules/symbol.h b/src/compiler/rules/symbol.h index bb3b429e..a4b3cbfc 100644 --- a/src/compiler/rules/symbol.h +++ b/src/compiler/rules/symbol.h @@ -8,9 +8,10 @@ namespace tree_sitter { class Symbol : public Rule { public: Symbol(const std::string &name); - TransitionMap transitions() const; bool operator==(const Rule& other) const; std::string to_string() const; + void accept(RuleVisitor &visitor) const; + const std::string name; }; diff --git a/src/compiler/rules/transitions.cpp b/src/compiler/rules/transitions.cpp new file mode 100644 index 00000000..c40da8ab --- /dev/null +++ b/src/compiler/rules/transitions.cpp @@ -0,0 +1,66 @@ +#include "transitions.h" +#include "rules.h" + +namespace tree_sitter { + namespace rules { + class TransitionsVisitor : public RuleVisitor { + public: + TransitionMap value; + + void visit(const Blank *rule) { + value = TransitionMap(); + } + + void visit(const CharClass *rule) { + value = TransitionMap({{ char_class(rule->value), blank() }}); + } + + void visit(const Char *rule) { + value = TransitionMap({{ character(rule->value), blank() }}); + } + + void visit(const Symbol *rule) { + value = TransitionMap({{ sym(rule->name), blank() }}); + } + + void visit(const Choice *rule) { + value = transitions(rule->left); + value.merge(transitions(rule->right), [&](rule_ptr left, rule_ptr right) -> rule_ptr { + return choice({ left, right }); + }); + } + + void visit(const Seq *rule) { + value = transitions(rule->left).map([&](rule_ptr left_rule) -> rule_ptr { + if (typeid(*left_rule) == typeid(Blank)) + return rule->right; + else + return seq({ left_rule, rule->right }); + }); + } + + void visit(const Repeat *rule) { + value = transitions(rule->content).map([&](const rule_ptr &value) -> rule_ptr { + return seq({ value, choice({ repeat(rule->content), blank() }) }); + }); + } + + void visit(const String *rule) { + rule_ptr result = character(rule->value[0]); + for (int i = 1; i < rule->value.length(); i++) + result = seq({ result, character(rule->value[i]) }); + value = transitions(result); + } + + void visit(const Pattern *rule) { + value = transitions(rule->to_rule_tree()); + } + }; + + TransitionMap 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 new file mode 100644 index 00000000..6f52bf93 --- /dev/null +++ b/src/compiler/rules/transitions.h @@ -0,0 +1,13 @@ +#ifndef __tree_sitter__transitions__ +#define __tree_sitter__transitions__ + +#include "rule.h" +#include "transition_map.h" + +namespace tree_sitter { + namespace rules { + TransitionMap transitions(const rule_ptr &rule); + } +} + +#endif \ No newline at end of file diff --git a/src/compiler/transition_map.h b/src/compiler/transition_map.h index 93d94bfa..ef727ccd 100644 --- a/src/compiler/transition_map.h +++ b/src/compiler/transition_map.h @@ -4,7 +4,7 @@ #include #include #include -#include "rules.h" +#include "rule.h" namespace tree_sitter { template