Make Grammar a simple struct
This commit is contained in:
parent
4b04afac5e
commit
36870bfced
16 changed files with 53 additions and 100 deletions
1
externals/json-parser
vendored
Submodule
1
externals/json-parser
vendored
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 70533215eea575e40a0b91a34ae01a779641d73a
|
||||
|
|
@ -27,18 +27,10 @@ rule_ptr prec_right(const rule_ptr &);
|
|||
rule_ptr prec_right(int precedence, const rule_ptr &);
|
||||
rule_ptr token(const rule_ptr &rule);
|
||||
|
||||
class Grammar {
|
||||
const std::vector<std::pair<std::string, rule_ptr>> rules_;
|
||||
std::vector<rule_ptr> extra_tokens_;
|
||||
std::vector<std::vector<std::string>> expected_conflicts_;
|
||||
|
||||
public:
|
||||
explicit Grammar(const std::vector<std::pair<std::string, rule_ptr>> &);
|
||||
Grammar &extra_tokens(const std::vector<rule_ptr> &);
|
||||
Grammar &expected_conflicts(const std::vector<std::vector<std::string>> &);
|
||||
const std::vector<std::pair<std::string, rule_ptr>> &rules() const;
|
||||
const std::vector<rule_ptr> &extra_tokens() const;
|
||||
const std::vector<std::vector<std::string>> &expected_conflicts() const;
|
||||
struct Grammar {
|
||||
std::vector<std::pair<std::string, rule_ptr>> rules;
|
||||
std::vector<rule_ptr> extra_tokens;
|
||||
std::vector<std::vector<std::string>> expected_conflicts;
|
||||
};
|
||||
|
||||
enum GrammarErrorType {
|
||||
|
|
@ -51,8 +43,11 @@ enum GrammarErrorType {
|
|||
|
||||
class GrammarError {
|
||||
public:
|
||||
GrammarError(GrammarErrorType type, std::string message);
|
||||
bool operator==(const GrammarError &other) const;
|
||||
GrammarError(GrammarErrorType type, std::string message) : type(type), message(message) {}
|
||||
bool operator==(const GrammarError &other) const {
|
||||
return type == other.type && message == other.message;
|
||||
}
|
||||
|
||||
GrammarErrorType type;
|
||||
std::string message;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
'src/compiler/build_tables/rule_can_be_blank.cc',
|
||||
'src/compiler/compile.cc',
|
||||
'src/compiler/generate_code/c_code.cc',
|
||||
'src/compiler/grammar.cc',
|
||||
'src/compiler/lex_table.cc',
|
||||
'src/compiler/parse_table.cc',
|
||||
'src/compiler/precedence_range.cc',
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ START_TEST
|
|||
describe("Compile", []() {
|
||||
describe("when the grammar's start symbol is a token", [&]() {
|
||||
it("does not fail", [&]() {
|
||||
Grammar grammar({
|
||||
Grammar grammar{{
|
||||
{ "rule1", str("the-value") }
|
||||
});
|
||||
}, {}, {}};
|
||||
|
||||
auto result = compile(grammar, "test_grammar");
|
||||
const GrammarError *error = result.second;
|
||||
|
|
@ -20,9 +20,9 @@ describe("Compile", []() {
|
|||
|
||||
describe("when the grammar's start symbol is blank", [&]() {
|
||||
it("does not fail", [&]() {
|
||||
Grammar grammar({
|
||||
Grammar grammar{{
|
||||
{ "rule1", blank() }
|
||||
});
|
||||
}, {}, {}};
|
||||
|
||||
auto result = compile(grammar, "test_grammar");
|
||||
const GrammarError *error = result.second;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ ostream &operator<<(ostream &stream, const Grammar &grammar) {
|
|||
stream << string("#<grammar");
|
||||
stream << string(" rules: {");
|
||||
bool started = false;
|
||||
for (auto pair : grammar.rules()) {
|
||||
for (auto pair : grammar.rules) {
|
||||
if (started)
|
||||
stream << string(", ");
|
||||
stream << pair.first;
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ using prepare_grammar::intern_symbols;
|
|||
|
||||
describe("intern_symbols", []() {
|
||||
it("replaces named symbols with numerically-indexed symbols", [&]() {
|
||||
Grammar grammar({
|
||||
Grammar grammar{{
|
||||
{ "x", choice({ sym("y"), sym("_z") }) },
|
||||
{ "y", sym("_z") },
|
||||
{ "_z", str("stuff") }
|
||||
});
|
||||
}, {}, {}};
|
||||
|
||||
auto result = intern_symbols(grammar);
|
||||
|
||||
|
|
@ -28,9 +28,9 @@ describe("intern_symbols", []() {
|
|||
|
||||
describe("when there are symbols that reference undefined rules", [&]() {
|
||||
it("returns an error", []() {
|
||||
Grammar grammar({
|
||||
Grammar grammar{{
|
||||
{ "x", sym("y") },
|
||||
});
|
||||
}, {}, {}};
|
||||
|
||||
auto result = intern_symbols(grammar);
|
||||
|
||||
|
|
@ -39,11 +39,13 @@ describe("intern_symbols", []() {
|
|||
});
|
||||
|
||||
it("translates the grammar's optional 'extra_tokens' to numerical symbols", [&]() {
|
||||
auto grammar = Grammar({
|
||||
Grammar grammar{{
|
||||
{ "x", choice({ sym("y"), sym("z") }) },
|
||||
{ "y", sym("z") },
|
||||
{ "z", str("stuff") }
|
||||
}).extra_tokens({ sym("z") });
|
||||
}, {
|
||||
sym("z")
|
||||
}, {}};
|
||||
|
||||
auto result = intern_symbols(grammar);
|
||||
|
||||
|
|
|
|||
6
spec/fixtures/grammars/anonymous_tokens.cc
vendored
6
spec/fixtures/grammars/anonymous_tokens.cc
vendored
|
|
@ -3,14 +3,14 @@
|
|||
|
||||
namespace tree_sitter_examples {
|
||||
|
||||
extern const Grammar anonymous_tokens = Grammar({
|
||||
extern const Grammar anonymous_tokens{{
|
||||
{ "program", choice({
|
||||
str("\n"),
|
||||
str("\r"),
|
||||
pattern("\\d"),
|
||||
str("\"hello\"") }) },
|
||||
}).extra_tokens({
|
||||
}, {
|
||||
pattern("\\s"),
|
||||
});
|
||||
}, {}};
|
||||
|
||||
} // namespace tree_sitter_examples
|
||||
|
|
|
|||
6
spec/fixtures/grammars/arithmetic.cc
vendored
6
spec/fixtures/grammars/arithmetic.cc
vendored
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
namespace tree_sitter_examples {
|
||||
|
||||
extern const Grammar arithmetic = Grammar({
|
||||
extern const Grammar arithmetic{{
|
||||
{ "program", sym("_expression") },
|
||||
|
||||
{ "_expression", choice({
|
||||
|
|
@ -37,9 +37,9 @@ extern const Grammar arithmetic = Grammar({
|
|||
pattern("[0-9]") })) })) },
|
||||
|
||||
{ "comment", pattern("#.*") },
|
||||
}).extra_tokens({
|
||||
}, {
|
||||
sym("comment"),
|
||||
pattern("\\s"),
|
||||
});
|
||||
}, {}};
|
||||
|
||||
} // namespace tree_sitter_examples
|
||||
|
|
|
|||
8
spec/fixtures/grammars/c.cc
vendored
8
spec/fixtures/grammars/c.cc
vendored
|
|
@ -5,7 +5,7 @@ namespace tree_sitter_examples {
|
|||
|
||||
// http://slps.github.io/zoo/c/iso-9899-tc3.html
|
||||
|
||||
extern const Grammar c = Grammar({
|
||||
extern const Grammar c{{
|
||||
{ "translation_unit", repeat(choice({
|
||||
sym("preproc_define"),
|
||||
sym("function_definition"),
|
||||
|
|
@ -251,13 +251,13 @@ extern const Grammar c = Grammar({
|
|||
pattern("[^\\*]"),
|
||||
pattern("\\*[^/]") })),
|
||||
str("*/") }) })) },
|
||||
}).extra_tokens({
|
||||
}, {
|
||||
sym("comment"),
|
||||
pattern("[ \t\r\n]"),
|
||||
}).expected_conflicts({
|
||||
}, {
|
||||
{ "_type_specifier", "_expression" },
|
||||
{ "_type_specifier", "_expression", "macro_type" },
|
||||
{ "_type_specifier", "macro_type" },
|
||||
});
|
||||
}};
|
||||
|
||||
} // namespace tree_sitter_examples
|
||||
|
|
|
|||
8
spec/fixtures/grammars/cpp.cc
vendored
8
spec/fixtures/grammars/cpp.cc
vendored
|
|
@ -5,7 +5,7 @@ namespace tree_sitter_examples {
|
|||
|
||||
// http://slps.github.io/zoo/cpp/iso-n2723.html
|
||||
|
||||
extern const Grammar cpp = Grammar({
|
||||
extern const Grammar cpp{{
|
||||
{ "translation_unit", repeat(sym("_declaration")) },
|
||||
|
||||
{ "_declaration", choice({
|
||||
|
|
@ -211,13 +211,13 @@ extern const Grammar cpp = Grammar({
|
|||
{ "number", pattern("\\d+(\\.\\d+)?") },
|
||||
|
||||
{ "comment", pattern("//[^\n]*") },
|
||||
}).extra_tokens({
|
||||
}, {
|
||||
sym("comment"),
|
||||
pattern("[ \t\r\n]"),
|
||||
}).expected_conflicts({
|
||||
}, {
|
||||
{ "type_specifier", "_expression" },
|
||||
{ "template_call", "_expression" },
|
||||
{ "template_call", "relational_expression" },
|
||||
});
|
||||
}};
|
||||
|
||||
} // namespace tree_sitter_examples
|
||||
|
|
|
|||
6
spec/fixtures/grammars/golang.cc
vendored
6
spec/fixtures/grammars/golang.cc
vendored
|
|
@ -9,7 +9,7 @@ static rule_ptr terminated(rule_ptr rule) {
|
|||
str(";") }) });
|
||||
}
|
||||
|
||||
extern const Grammar golang = Grammar({
|
||||
extern const Grammar golang{{
|
||||
{ "program", seq({
|
||||
sym("package_directive"),
|
||||
repeat(sym("imports_block")),
|
||||
|
|
@ -203,10 +203,10 @@ extern const Grammar golang = Grammar({
|
|||
|
||||
{ "comment", pattern("//[^\n]*") },
|
||||
|
||||
}).extra_tokens({
|
||||
}, {
|
||||
sym("comment"),
|
||||
sym("_line_break"),
|
||||
pattern("[ \t\r]"),
|
||||
});
|
||||
}, {}};
|
||||
|
||||
} // namespace tree_sitter_examples
|
||||
|
|
|
|||
8
spec/fixtures/grammars/javascript.cc
vendored
8
spec/fixtures/grammars/javascript.cc
vendored
|
|
@ -30,7 +30,7 @@ enum {
|
|||
PREC_ARGS = 16,
|
||||
};
|
||||
|
||||
extern const Grammar javascript = Grammar({
|
||||
extern const Grammar javascript{{
|
||||
{ "program", repeat(sym("_statement")) },
|
||||
|
||||
/*
|
||||
|
|
@ -349,13 +349,13 @@ extern const Grammar javascript = Grammar({
|
|||
str(")"),
|
||||
sym("statement_block") }) },
|
||||
|
||||
}).extra_tokens({
|
||||
}, {
|
||||
sym("comment"),
|
||||
sym("_line_break"),
|
||||
pattern("[ \t\r]"),
|
||||
}).expected_conflicts({
|
||||
}, {
|
||||
{ "for_in_statement", "_expression" },
|
||||
{ "method_definition", "_expression" },
|
||||
});
|
||||
}};
|
||||
|
||||
} // namespace tree_sitter_examples
|
||||
|
|
|
|||
6
spec/fixtures/grammars/json.cc
vendored
6
spec/fixtures/grammars/json.cc
vendored
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
namespace tree_sitter_examples {
|
||||
|
||||
extern const Grammar json = Grammar({
|
||||
extern const Grammar json{{
|
||||
{ "_value", choice({
|
||||
sym("object"),
|
||||
sym("array"),
|
||||
|
|
@ -22,8 +22,8 @@ extern const Grammar json = Grammar({
|
|||
{ "null", str("null") },
|
||||
{ "true", str("true") },
|
||||
{ "false", str("false") },
|
||||
}).extra_tokens({
|
||||
}, {
|
||||
pattern("\\s"),
|
||||
});
|
||||
}, {}};
|
||||
|
||||
} // namespace tree_sitter_examples
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
#include "tree_sitter/compiler.h"
|
||||
#include "compiler/rule.h"
|
||||
|
||||
namespace tree_sitter {
|
||||
|
||||
using std::ostream;
|
||||
using std::pair;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
Grammar::Grammar(const vector<pair<string, rule_ptr>> &rules)
|
||||
: rules_(rules), extra_tokens_({}) {}
|
||||
|
||||
const vector<pair<string, rule_ptr>> &Grammar::rules() const {
|
||||
return rules_;
|
||||
}
|
||||
|
||||
const vector<rule_ptr> &Grammar::extra_tokens() const {
|
||||
return extra_tokens_;
|
||||
}
|
||||
|
||||
const vector<vector<string>> &Grammar::expected_conflicts() const {
|
||||
return expected_conflicts_;
|
||||
}
|
||||
|
||||
Grammar &Grammar::extra_tokens(const vector<rule_ptr> &extra_tokens) {
|
||||
extra_tokens_ = extra_tokens;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Grammar &Grammar::expected_conflicts(
|
||||
const vector<vector<string>> &expected_conflicts) {
|
||||
expected_conflicts_ = expected_conflicts;
|
||||
return *this;
|
||||
}
|
||||
|
||||
GrammarError::GrammarError(GrammarErrorType type, string message)
|
||||
: type(type), message(message) {}
|
||||
|
||||
bool GrammarError::operator==(const GrammarError &other) const {
|
||||
return type == other.type && message == other.message;
|
||||
}
|
||||
|
||||
} // namespace tree_sitter
|
||||
|
|
@ -31,8 +31,8 @@ class InternSymbols : public rules::IdentityRuleFn {
|
|||
|
||||
public:
|
||||
std::shared_ptr<rules::Symbol> symbol_for_rule_name(string rule_name) {
|
||||
for (size_t i = 0; i < grammar.rules().size(); i++)
|
||||
if (grammar.rules()[i].first == rule_name)
|
||||
for (size_t i = 0; i < grammar.rules.size(); i++)
|
||||
if (grammar.rules[i].first == rule_name)
|
||||
return make_shared<rules::Symbol>(i);
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -51,7 +51,7 @@ pair<InternedGrammar, const GrammarError *> intern_symbols(const Grammar &gramma
|
|||
InternedGrammar result;
|
||||
InternSymbols interner(grammar);
|
||||
|
||||
for (auto &pair : grammar.rules()) {
|
||||
for (auto &pair : grammar.rules) {
|
||||
auto new_rule = interner.apply(pair.second);
|
||||
if (!interner.missing_rule_name.empty())
|
||||
return { result, missing_rule_error(interner.missing_rule_name) };
|
||||
|
|
@ -61,14 +61,14 @@ pair<InternedGrammar, const GrammarError *> intern_symbols(const Grammar &gramma
|
|||
new_rule));
|
||||
}
|
||||
|
||||
for (auto &rule : grammar.extra_tokens()) {
|
||||
for (auto &rule : grammar.extra_tokens) {
|
||||
auto new_rule = interner.apply(rule);
|
||||
if (!interner.missing_rule_name.empty())
|
||||
return { result, missing_rule_error(interner.missing_rule_name) };
|
||||
result.extra_tokens.push_back(new_rule);
|
||||
}
|
||||
|
||||
for (auto &names : grammar.expected_conflicts()) {
|
||||
for (auto &names : grammar.expected_conflicts) {
|
||||
set<rules::Symbol> entry;
|
||||
for (auto &name : names) {
|
||||
auto symbol = interner.symbol_for_rule_name(name);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace tree_sitter {
|
||||
|
||||
class Grammar;
|
||||
struct Grammar;
|
||||
class GrammarError;
|
||||
|
||||
namespace prepare_grammar {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue