Move rule transitions to visitor class

This commit is contained in:
Max Brunsfeld 2013-12-18 20:58:05 -08:00
parent 84a7afbca5
commit b1bbeae2a1
29 changed files with 205 additions and 125 deletions

View file

@ -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 = "<group>"; };
12FD40DC185FF12C0041A84E /* parser.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = parser.c; sourceTree = "<group>"; };
12FD40DE1860064C0041A84E /* tree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tree.c; sourceTree = "<group>"; };
12FD40E0186245FE0041A84E /* transitions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = transitions.cpp; sourceTree = "<group>"; };
12FD40E1186245FE0041A84E /* transitions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = transitions.h; sourceTree = "<group>"; };
12FD40E41862B3530041A84E /* rule_visitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rule_visitor.h; sourceTree = "<group>"; };
27A340F3EEB184C040521323 /* pattern.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pattern.cpp; sourceTree = "<group>"; };
27A3438C4FA59A3882E8493B /* pattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pattern.h; sourceTree = "<group>"; };
/* 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 = "<group>";
@ -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 */,

View file

@ -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<rules::Rule>({
{ symbol1, rules::blank() }
})));
@ -36,7 +37,7 @@ Describe(Rules) {
It(handles_characters) {
AssertThat(
char1->transitions(),
rules::transitions(char1),
EqualsTransitionMap(TransitionMap<rules::Rule>({
{ 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<rules::Rule>({
{ 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<rules::Rule>({
{ 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<rules::Rule>({
{ 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<rules::Rule>({
{ 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<rules::Rule>({
{ 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::Rule>({
{
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::Rule>({
{ 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::Rule>({
{
rules::character('a'),
@ -129,7 +131,7 @@ Describe(Rules) {
repeat = rules::repeat(rules::str("a"));
AssertThat(
repeat->transitions(),
rules::transitions(repeat),
EqualsTransitionMap(TransitionMap<rules::Rule>({
{
rules::character('a'),

View file

@ -1,5 +1,6 @@
#include "item.h"
#include "grammar.h"
#include "transitions.h"
#include <iostream>
@ -17,14 +18,14 @@ namespace tree_sitter {
}
TransitionMap<Item> Item::transitions() const {
return rule->transitions().map<Item>([&](rules::rule_ptr to_rule) {
return rules::transitions(rule).map<Item>([&](rules::rule_ptr to_rule) {
return std::make_shared<Item>(rule_name, to_rule, consumed_sym_count + 1);
});
};
vector<rules::sym_ptr> Item::next_symbols() const {
vector<rules::sym_ptr> result;
for (auto pair : rule->transitions()) {
for (auto pair : rules::transitions(rule)) {
shared_ptr<const rules::Symbol> sym = dynamic_pointer_cast<const rules::Symbol>(pair.first);
if (sym) result.push_back(sym);
}

View file

@ -3,6 +3,7 @@
#include <string>
#include "rule.h"
#include "symbol.h"
#include "transition_map.h"
namespace tree_sitter {

View file

@ -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<Blank>();
}
TransitionMap<Rule> Blank::transitions() const {
return TransitionMap<Rule>();
}
bool Blank::operator==(const Rule &rule) const {
return dynamic_cast<const Blank *>(&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);
}
}
}

View file

@ -8,13 +8,12 @@ namespace tree_sitter {
class Blank : public Rule {
public:
Blank();
TransitionMap<Rule> transitions() const;
bool operator==(const Rule& other) const;
std::string to_string() const;
void accept(RuleVisitor &visitor) const;
};
typedef std::shared_ptr<const Blank> blank_ptr;
blank_ptr blank();
rule_ptr blank();
}
}

View file

@ -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<Char>(value);
}
TransitionMap<Rule> Char::transitions() const {
return TransitionMap<Rule>({{ character(value), blank() }});
}
bool Char::operator==(const Rule &rule) const {
const Char *other = dynamic_cast<const Char *>(&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);
}
}
}

View file

@ -8,10 +8,10 @@ namespace tree_sitter {
class Char : public Rule {
public:
Char(char value);
TransitionMap<Rule> transitions() const;
bool operator==(const Rule& other) const;
std::string to_string() const;
private:
void accept(RuleVisitor &visitor) const;
const char value;
};

View file

@ -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<CharClass>(type);
}
TransitionMap<Rule> CharClass::transitions() const {
return TransitionMap<Rule>({{ char_class(value), blank() }});
}
bool CharClass::operator==(const Rule &rule) const {
const CharClass *other = dynamic_cast<const CharClass *>(&rule);
return other && (other->value == value);
@ -29,5 +24,9 @@ namespace tree_sitter {
return "<word>";
}
}
void CharClass::accept(RuleVisitor &visitor) const {
visitor.visit(this);
}
}
}

View file

@ -13,10 +13,10 @@ namespace tree_sitter {
class CharClass : public Rule {
public:
CharClass(CharClassType type);
TransitionMap<Rule> transitions() const;
bool operator==(const Rule& other) const;
std::string to_string() const;
private:
void accept(RuleVisitor &visitor) const;
const CharClassType value;
};

View file

@ -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<Rule> 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<const Choice *>(&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);
}
}
}

View file

@ -8,10 +8,10 @@ namespace tree_sitter {
class Choice : public Rule {
public:
Choice(rule_ptr left, rule_ptr right);
TransitionMap<Rule> 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;
};

View file

@ -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<Pattern>(value);
}
TransitionMap<Rule> 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<const Pattern *>(&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();
}
}
}

View file

@ -6,14 +6,13 @@
namespace tree_sitter {
namespace rules {
class Pattern : public Rule {
const std::string value;
public:
Pattern(const std::string &string);
TransitionMap<Rule> 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<const Pattern> pattern_ptr;

View file

@ -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<Repeat>(content);
}
TransitionMap<Rule> Repeat::transitions() const {
return content->transitions().map<Rule>([&](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<const Repeat *>(&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);
}
}
}

View file

@ -8,10 +8,10 @@ namespace tree_sitter {
class Repeat : public Rule {
public:
Repeat(rule_ptr content);
TransitionMap<Rule> transitions() const;
bool operator==(const Rule& other) const;
std::string to_string() const;
private:
void accept(RuleVisitor &visitor) const;
const rule_ptr content;
};

View file

@ -3,10 +3,6 @@
namespace tree_sitter {
namespace rules {
size_t Rule::hash_code() const {
return std::hash<std::string>()(to_string());
}
std::ostream& operator<<(std::ostream& stream, const Rule &rule)
{
stream << rule.to_string();

View file

@ -4,21 +4,17 @@
#include <string>
namespace tree_sitter {
template<class value> class TransitionMap;
namespace rules {
class Rule;
typedef std::shared_ptr<const Rule> rule_ptr;
class RuleVisitor;
class Rule {
public:
virtual TransitionMap<Rule> 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<const Rule> 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<tree_sitter::rules::Rule> {
size_t operator()(const tree_sitter::rules::Rule &rule) {
return rule.hash_code();
return std::hash<std::string>()(rule.to_string());
}
};
}

View file

@ -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

View file

@ -11,5 +11,6 @@
#include "char.h"
#include "char_class.h"
#include "repeat.h"
#include "rule_visitor.h"
#endif

View file

@ -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<Rule> Seq::transitions() const {
return left->transitions().map<Rule>([&](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<const Seq *>(&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);
}
}
}

View file

@ -8,10 +8,10 @@ namespace tree_sitter {
class Seq : public Rule {
public:
Seq(rule_ptr left, rule_ptr right);
TransitionMap<Rule> 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;
};

View file

@ -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<String>(value);
}
TransitionMap<Rule> 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<const String *>(&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);
}
}
}

View file

@ -8,10 +8,10 @@ namespace tree_sitter {
class String : public Rule {
public:
String(std::string value);
TransitionMap<Rule> transitions() const;
bool operator==(const Rule& other) const;
std::string to_string() const;
private:
void accept(RuleVisitor &visitor) const;
const std::string value;
};

View file

@ -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<Symbol>(name);
}
TransitionMap<Rule> Symbol::transitions() const {
return TransitionMap<Rule>({{ sym(name) , blank() }});
}
bool Symbol::operator==(const Rule &rule) const {
const Symbol *other = dynamic_cast<const Symbol *>(&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);
}
}
}

View file

@ -8,9 +8,10 @@ namespace tree_sitter {
class Symbol : public Rule {
public:
Symbol(const std::string &name);
TransitionMap<Rule> transitions() const;
bool operator==(const Rule& other) const;
std::string to_string() const;
void accept(RuleVisitor &visitor) const;
const std::string name;
};

View file

@ -0,0 +1,66 @@
#include "transitions.h"
#include "rules.h"
namespace tree_sitter {
namespace rules {
class TransitionsVisitor : public RuleVisitor {
public:
TransitionMap<Rule> value;
void visit(const Blank *rule) {
value = TransitionMap<Rule>();
}
void visit(const CharClass *rule) {
value = TransitionMap<Rule>({{ char_class(rule->value), blank() }});
}
void visit(const Char *rule) {
value = TransitionMap<Rule>({{ character(rule->value), blank() }});
}
void visit(const Symbol *rule) {
value = TransitionMap<Rule>({{ 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>([&](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<Rule>([&](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<Rule> transitions(const rule_ptr &rule) {
TransitionsVisitor visitor;
rule->accept(visitor);
return visitor.value;
}
}
}

View file

@ -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<Rule> transitions(const rule_ptr &rule);
}
}
#endif

View file

@ -4,7 +4,7 @@
#include <vector>
#include <functional>
#include <initializer_list>
#include "rules.h"
#include "rule.h"
namespace tree_sitter {
template<typename MappedType>