Start work on recording parse action conflicts
This commit is contained in:
parent
1da9f1fdfd
commit
3982b73ed6
12 changed files with 278 additions and 26 deletions
89
spec/compiler/build_tables/conflict_manager_spec.cc
Normal file
89
spec/compiler/build_tables/conflict_manager_spec.cc
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#include "compiler_spec_helper.h"
|
||||
#include "compiler/build_tables/conflict_manager.h"
|
||||
|
||||
using namespace rules;
|
||||
using namespace build_tables;
|
||||
|
||||
START_TEST
|
||||
|
||||
describe("resolving parse conflicts", []() {
|
||||
LexAction lex_action;
|
||||
ParseAction parse_action;
|
||||
ConflictManager *manager;
|
||||
|
||||
PreparedGrammar parse_grammar({
|
||||
{ "rule1", seq({ sym("rule2"), sym("token2") }) },
|
||||
{ "rule2", sym("token1") },
|
||||
}, {});
|
||||
|
||||
PreparedGrammar lex_grammar({
|
||||
{ "token1", pattern("[a-c]") },
|
||||
{ "token2", pattern("[b-d]") },
|
||||
}, {});
|
||||
|
||||
before_each([&]() {
|
||||
manager = new ConflictManager(parse_grammar, lex_grammar);
|
||||
});
|
||||
|
||||
after_each([&]() {
|
||||
delete manager;
|
||||
});
|
||||
|
||||
describe("lexical conflicts", [&]() {
|
||||
Symbol sym1("token1");
|
||||
Symbol sym2("token2");
|
||||
|
||||
it("favors non-errors over lexical errors", [&]() {
|
||||
lex_action = manager->resolve_lex_action(LexAction::Error(), LexAction::Advance(2));
|
||||
AssertThat(lex_action, Equals(LexAction::Advance(2)));
|
||||
|
||||
lex_action = manager->resolve_lex_action(LexAction::Advance(2), LexAction::Error());
|
||||
AssertThat(lex_action, Equals(LexAction::Advance(2)));
|
||||
});
|
||||
|
||||
it("prefers tokens that are listed earlier in the grammar", [&]() {
|
||||
lex_action = manager->resolve_lex_action(LexAction::Accept(sym1), LexAction::Accept(sym2));
|
||||
AssertThat(lex_action, Equals(LexAction::Accept(sym1)));
|
||||
|
||||
lex_action = manager->resolve_lex_action(LexAction::Accept(sym2), LexAction::Accept(sym1));
|
||||
AssertThat(lex_action, Equals(LexAction::Accept(sym1)));
|
||||
});
|
||||
});
|
||||
|
||||
describe("syntactic conflicts", [&]() {
|
||||
Symbol sym1("rule1");
|
||||
Symbol sym2("rule2");
|
||||
|
||||
it("favors non-errors over parse errors", [&]() {
|
||||
parse_action = manager->resolve_parse_action(sym1, ParseAction::Error(), ParseAction::Shift(2));
|
||||
AssertThat(parse_action, Equals(ParseAction::Shift(2)));
|
||||
|
||||
parse_action = manager->resolve_parse_action(sym1, ParseAction::Shift(2), ParseAction::Error());
|
||||
AssertThat(parse_action, Equals(ParseAction::Shift(2)));
|
||||
});
|
||||
|
||||
describe("shift/reduce conflicts", [&]() {
|
||||
it("records shift/reduce conflicts, favoring the shift", [&]() {
|
||||
manager->resolve_parse_action(sym1, ParseAction::Reduce(sym2, 1), ParseAction::Shift(2));
|
||||
manager->resolve_parse_action(sym1, ParseAction::Shift(2), ParseAction::Reduce(sym2, 1));
|
||||
|
||||
AssertThat(manager->conflicts()[0], Equals(Conflict("rule1: shift / reduce rule2")));
|
||||
AssertThat(manager->conflicts()[1], Equals(Conflict("rule1: shift / reduce rule2")));
|
||||
});
|
||||
|
||||
it("favors the shift", [&]() {
|
||||
parse_action = manager->resolve_parse_action(sym1, ParseAction::Reduce(sym2, 1), ParseAction::Shift(2));
|
||||
AssertThat(parse_action, Equals(ParseAction::Shift(2)));
|
||||
|
||||
parse_action = manager->resolve_parse_action(sym1, ParseAction::Shift(2), ParseAction::Reduce(sym2, 1));
|
||||
AssertThat(parse_action, Equals(ParseAction::Shift(2)));
|
||||
});
|
||||
});
|
||||
|
||||
it("records reduce/reduce conflicts, favoring the symbol listed earlier in the grammar", [&]() {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
END_TEST
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
#include "compiler_spec_helper.h"
|
||||
#include <fstream>
|
||||
|
||||
#include "stream_methods.h"
|
||||
|
||||
static string src_dir() {
|
||||
const char * dir = getenv("TREESITTER_DIR");
|
||||
if (!dir) dir = getenv("PWD");
|
||||
|
|
@ -22,7 +24,11 @@ describe("compiling the example grammars", []() {
|
|||
auto compile_grammar = [&](const Grammar &grammar, string language) {
|
||||
it(("compiles the " + language + " grammar").c_str(), [&]() {
|
||||
ofstream file(example_parser_dir + language + ".c");
|
||||
file << compile(grammar, language);
|
||||
auto result = compile(grammar, language);
|
||||
|
||||
// cout << "\n conflicts for " << language << "\n:" << result.second;
|
||||
|
||||
file << result.first;
|
||||
file.close();
|
||||
});
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue