-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser_extension_test.cpp
More file actions
115 lines (105 loc) · 3.78 KB
/
Copy pathparser_extension_test.cpp
File metadata and controls
115 lines (105 loc) · 3.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/**
* @brief Staging for a potential customizable grammar extension
* to the parser. I'm writing this here rather than in
* parser.hpp so as not to get that file any dirtier.
*/
#include "src/ast.hpp"
#include "src/parse.hpp"
#include <cassert>
#include <iostream>
#include <map>
/// Manages grammars, but only LR(1) recursive-descent ones. No
/// shift-reduce allowed, and grammars must be disambiguated by
/// their first literal tokens.
class GrammarController {
public:
ASTNode parse(TokenStream &_ts,
const ASTNode &_grammar_fragment) {
if (_grammar_fragment.text == "TOKEN") {
return _ts.cur_next();
} else if (_grammar_fragment.text == "LITERAL") {
// (LITERAL raw_expected_text)
_ts.expect({_grammar_fragment.children.at(0).text.text});
return _grammar_fragment.children.at(0);
} else if (_grammar_fragment.text == "GRAMMAR") {
// (GRAMMAR grammar_name)
const auto grammar_name =
_grammar_fragment.children.at(0).text;
const auto g = grammars.at(grammar_name.text);
ASTNode out(grammar_name, {parse(_ts, g)});
if (out.children.size() == 1 &&
out.children.at(0).text == "_") {
out.children = out.children.at(0).children;
}
return out;
} else if (_grammar_fragment.text == "_") {
// (_ any number of arguments ...)
ASTNode out(_grammar_fragment.text);
for (const auto &arg : _grammar_fragment.children) {
const auto to_add = parse(_ts, arg);
if (to_add != "NULL") {
out.children.push_back(to_add);
}
}
return out;
} else if (_grammar_fragment.text == "OR") {
std::map<std::string, size_t> starting_toks;
for (size_t i = 0;
i + 1 < _grammar_fragment.children.size(); ++i) {
const auto meta_arg = _grammar_fragment.children.at(i);
assert(meta_arg.text == "_");
const auto arg = meta_arg.children.at(0);
assert(arg.text == "LITERAL");
const auto starting_tok = arg.children.at(0).text.text;
assert(!starting_toks.contains(starting_tok));
starting_toks[starting_tok] = i;
}
const auto t = _ts.cur().text;
if (starting_toks.contains(t)) {
return parse(_ts, _grammar_fragment.children.at(
starting_toks.at(t)));
} else {
return parse(_ts, _grammar_fragment.children.back());
}
}
return ASTNode("PARSE_FAILURE");
}
std::map<std::string, ASTNode> grammars;
};
int main() {
GrammarController gc;
gc.grammars["FORMULA"] = ASTNode(
"OR",
{
ASTNode("_",
{
ASTNode("LITERAL", {ASTNode("not")}),
ASTNode("GRAMMAR", {ASTNode("FORMULA")}),
}),
ASTNode("_",
{
ASTNode("LITERAL", {ASTNode("or")}),
ASTNode("GRAMMAR", {ASTNode("FORMULA")}),
ASTNode("GRAMMAR", {ASTNode("FORMULA")}),
}),
ASTNode("_",
{
ASTNode("LITERAL", {ASTNode("and")}),
ASTNode("GRAMMAR", {ASTNode("FORMULA")}),
ASTNode("GRAMMAR", {ASTNode("FORMULA")}),
}),
ASTNode("_",
{
ASTNode("LITERAL", {ASTNode("[")}),
ASTNode("GRAMMAR", {ASTNode("FORMULA")}),
ASTNode("LITERAL", {ASTNode("]")}),
}),
ASTNode("_", {ASTNode("TOKEN")}),
});
TokenStream ts(lex_text("not or a and b and or c not d not a",
"NULL_FP"));
const auto parsed =
gc.parse(ts, ASTNode("GRAMMAR", {ASTNode("FORMULA")}));
std::cout << "Parsed " << parsed << "\n";
return 0;
}