tree-sitter/spec/compiler/prepare_grammar_spec.cc
2014-04-09 18:41:43 -07:00

106 lines
No EOL
3.8 KiB
C++

#include "compiler_spec_helper.h"
#include "compiler/prepared_grammar.h"
#include "compiler/prepare_grammar/prepare_grammar.h"
#include "compiler/rules/symbol.h"
START_TEST
using namespace rules;
using prepare_grammar::prepare_grammar;
describe("preparing a grammar", []() {
describe("extracting tokens", []() {
it("moves strings and patterns into a separate 'lexical' grammar", [&]() {
pair<PreparedGrammar, PreparedGrammar> result = prepare_grammar(Grammar({
{ "rule1", seq({
str("ab"),
seq({
sym("rule2"),
sym("rule3") }),
str("ab") }) }
}));
AssertThat(result.first, Equals(PreparedGrammar({
{ "rule1", seq({
make_shared<Symbol>("token1", SymbolTypeAuxiliary),
seq({
sym("rule2"),
sym("rule3") }),
make_shared<Symbol>("token1", SymbolTypeAuxiliary) }) }
}, {})));
AssertThat(result.second, Equals(PreparedGrammar({}, {
{ "token1", str("ab") },
})));
});
it("moves entire rules into the lexical grammar when possible, preserving their names", [&]() {
auto result = prepare_grammar(Grammar({
{ "rule1", sym("rule2") },
{ "rule2", pattern("a|b") }
}));
AssertThat(result.first, Equals(PreparedGrammar({
{ "rule1", sym("rule2") }
}, {})));
AssertThat(result.second, Equals(PreparedGrammar({
{ "rule2", pattern("a|b") },
}, {})));
});
it("does not extract blanks into tokens", [&]() {
pair<PreparedGrammar, PreparedGrammar> result = prepare_grammar(Grammar({
{ "rule1", choice({ sym("rule2"), blank() }) },
}));
AssertThat(result.first, Equals(PreparedGrammar({
{ "rule1", choice({ sym("rule2"), blank() }) },
}, {})));
AssertThat(result.second, Equals(PreparedGrammar({}, {})));
});
});
describe("expanding repeats", []() {
it("replaces repeat rules with pairs of recursive rules", [&]() {
PreparedGrammar result = prepare_grammar(Grammar({
{ "rule1", seq({
sym("x"),
repeat(seq({ sym("a"), sym("b") })),
repeat(sym("a")),
sym("y")
}) },
{ "rule2", repeat(sym("b")) },
})).first;
AssertThat(result, Equals(PreparedGrammar({
{ "rule1", seq({
sym("x"),
make_shared<Symbol>("rule1_repeat1", SymbolTypeAuxiliary),
make_shared<Symbol>("rule1_repeat2", SymbolTypeAuxiliary),
sym("y") }) },
{ "rule2", make_shared<Symbol>("rule2_repeat1", SymbolTypeAuxiliary) },
}, {
{ "rule1_repeat1", choice({
seq({
seq({ sym("a"), sym("b") }),
make_shared<Symbol>("rule1_repeat1", SymbolTypeAuxiliary),
}),
blank() }) },
{ "rule1_repeat2", choice({
seq({
sym("a"),
make_shared<Symbol>("rule1_repeat2", SymbolTypeAuxiliary) }),
blank() }) },
{ "rule2_repeat1", choice({
seq({
sym("b"),
make_shared<Symbol>("rule2_repeat1", SymbolTypeAuxiliary) }),
blank() }) }
})));
});
});
});
END_TEST