2013-12-27 17:31:08 -08:00
|
|
|
#include "spec_helper.h"
|
2013-12-28 15:09:52 -08:00
|
|
|
#include <functional>
|
2014-01-11 15:14:17 -08:00
|
|
|
#include "build_tables/perform.h"
|
2013-12-27 17:31:08 -08:00
|
|
|
|
2014-01-11 17:08:32 -08:00
|
|
|
using build_tables::perform;
|
|
|
|
|
using namespace rules;
|
2014-01-03 22:42:05 -08:00
|
|
|
|
2014-01-08 18:35:16 -08:00
|
|
|
typedef unordered_set<ParseAction> parse_actions;
|
|
|
|
|
typedef unordered_set<LexAction> lex_actions;
|
2013-12-27 17:31:08 -08:00
|
|
|
|
2014-01-27 12:40:06 -08:00
|
|
|
static unordered_set<Symbol> keys(const unordered_map<Symbol, parse_actions> &map) {
|
|
|
|
|
unordered_set<Symbol> result;
|
2014-01-23 13:10:37 -08:00
|
|
|
for (auto pair : map) {
|
|
|
|
|
result.insert(pair.first);
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-29 19:18:21 -08:00
|
|
|
static unordered_set<Character> keys(const unordered_map<Character, lex_actions> &map) {
|
|
|
|
|
unordered_set<Character> result;
|
2014-01-23 13:10:37 -08:00
|
|
|
for (auto pair : map) {
|
|
|
|
|
result.insert(pair.first);
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-28 15:09:52 -08:00
|
|
|
START_TEST
|
|
|
|
|
|
|
|
|
|
describe("building parse and lex tables", []() {
|
2014-01-03 22:42:05 -08:00
|
|
|
Grammar grammar({
|
|
|
|
|
{ "expression", choice({
|
|
|
|
|
seq({
|
|
|
|
|
sym("term"),
|
2014-01-08 18:35:16 -08:00
|
|
|
sym("plus"),
|
2014-01-03 22:42:05 -08:00
|
|
|
sym("term") }),
|
|
|
|
|
sym("term") }) },
|
|
|
|
|
{ "term", choice({
|
|
|
|
|
sym("variable"),
|
|
|
|
|
sym("number"),
|
|
|
|
|
seq({
|
2014-01-08 18:35:16 -08:00
|
|
|
sym("left-paren"),
|
2014-01-03 22:42:05 -08:00
|
|
|
sym("expression"),
|
2014-01-08 18:35:16 -08:00
|
|
|
sym("right-paren")
|
|
|
|
|
}) }) }
|
2014-01-03 22:42:05 -08:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Grammar lex_grammar({
|
2014-01-08 18:35:16 -08:00
|
|
|
{ "plus", str("+") },
|
|
|
|
|
{ "variable", pattern("\\w+") },
|
|
|
|
|
{ "number", pattern("\\d+") },
|
|
|
|
|
{ "left-paren", str("(") },
|
|
|
|
|
{ "right-paren", str(")") }
|
2014-01-03 22:42:05 -08:00
|
|
|
});
|
2014-01-21 23:33:26 -08:00
|
|
|
|
|
|
|
|
ParseTable table;
|
|
|
|
|
LexTable lex_table;
|
|
|
|
|
|
|
|
|
|
before_each([&]() {
|
|
|
|
|
pair<ParseTable, LexTable> tables = perform(grammar, lex_grammar);
|
|
|
|
|
table = tables.first;
|
|
|
|
|
lex_table = tables.second;
|
|
|
|
|
});
|
2013-12-27 17:31:08 -08:00
|
|
|
|
2013-12-28 15:09:52 -08:00
|
|
|
function<ParseState(size_t)> parse_state = [&](size_t index) {
|
2013-12-27 17:31:08 -08:00
|
|
|
return table.states[index];
|
2013-12-28 15:09:52 -08:00
|
|
|
};
|
2013-12-27 17:31:08 -08:00
|
|
|
|
2013-12-28 15:09:52 -08:00
|
|
|
function<LexState(size_t)> lex_state = [&](size_t parse_state_index) {
|
2014-01-21 23:33:26 -08:00
|
|
|
long index = table.states[parse_state_index].lex_state_index;
|
2013-12-27 17:31:08 -08:00
|
|
|
return lex_table.states[index];
|
2013-12-28 15:09:52 -08:00
|
|
|
};
|
2013-12-27 17:31:08 -08:00
|
|
|
|
2013-12-28 15:09:52 -08:00
|
|
|
it("has the right starting state", [&]() {
|
2014-01-27 12:40:06 -08:00
|
|
|
AssertThat(keys(parse_state(0).actions), Equals(unordered_set<Symbol>({
|
|
|
|
|
Symbol("expression"),
|
|
|
|
|
Symbol("term"),
|
|
|
|
|
Symbol("number"),
|
|
|
|
|
Symbol("variable"),
|
|
|
|
|
Symbol("left-paren"),
|
2013-12-27 17:31:08 -08:00
|
|
|
})));
|
|
|
|
|
|
2014-01-29 19:18:21 -08:00
|
|
|
AssertThat(keys(lex_state(0).actions), Equals(unordered_set<Character>({
|
|
|
|
|
Character('('),
|
|
|
|
|
Character(CharClassDigit),
|
|
|
|
|
Character(CharClassWord),
|
2013-12-27 17:31:08 -08:00
|
|
|
})));
|
2014-01-08 18:35:16 -08:00
|
|
|
|
2014-01-29 19:18:21 -08:00
|
|
|
AssertThat(lex_state(0).expected_inputs(), Equals(unordered_set<Character>({
|
|
|
|
|
Character('('),
|
|
|
|
|
Character(CharClassDigit),
|
|
|
|
|
Character(CharClassWord),
|
2014-01-08 18:35:16 -08:00
|
|
|
})));
|
2013-12-28 15:09:52 -08:00
|
|
|
});
|
2013-12-27 17:31:08 -08:00
|
|
|
|
2013-12-28 15:09:52 -08:00
|
|
|
it("accepts when the start symbol is reduced", [&]() {
|
2014-01-27 12:40:06 -08:00
|
|
|
AssertThat(parse_state(1).actions, Equals(unordered_map<Symbol, parse_actions>({
|
|
|
|
|
{ Symbol("__END__"), parse_actions({ ParseAction::Accept() }) }
|
2013-12-27 17:31:08 -08:00
|
|
|
})));
|
2013-12-28 15:09:52 -08:00
|
|
|
});
|
2013-12-27 17:31:08 -08:00
|
|
|
|
2013-12-28 15:09:52 -08:00
|
|
|
it("has the right next states", [&]() {
|
2014-01-27 12:40:06 -08:00
|
|
|
AssertThat(parse_state(2).actions, Equals(unordered_map<Symbol, parse_actions>({
|
|
|
|
|
{ Symbol("plus"), parse_actions({ ParseAction::Shift(3) }) },
|
2014-01-28 22:09:37 -08:00
|
|
|
{ Symbol("__END__"), parse_actions({ ParseAction::Reduce(Symbol("expression"), { false }) }) },
|
2013-12-27 17:31:08 -08:00
|
|
|
})));
|
2013-12-28 15:09:52 -08:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
END_TEST
|