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
116
117
118
119
|
#include <boost/algorithm/string.hpp>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <deque>
#include <map>
#include <string>
#include <utility>
#include <vector>
using namespace std::string_literals;
using BNF = std::map<std::string, std::vector<std::vector<std::string>>>;
using Terminals = std::set<std::string>;
using ProgramNode = std::deque<std::string>;
using PathElement = std::pair<std::string, size_t>; // Name, Index
std::vector<std::string> split(std::string s)
{
std::vector<std::string> result;
boost::algorithm::split(result, s, boost::algorithm::is_any_of(s), boost::algorithm::token_compress_on);
while (result.size() > 0 && result.back() == ""s)
result.pop_back();
return result;
}
std::vector<PathElement> GetPath(std::string Token, BNF ReverseBNF, std::string Top, Terminals terminals = {}, std::vector<PathElement> PreviousPath = {})
{
throw std::runtime_error("Compile error");
return {}; // TODO
}
BNF Reverse(BNF bnf){
return {}; // TODO
}
std::vector<std::string> Lex(std::string s, std::string Top, BNF bnf)
{
BNF ReverseBNF{ Reverse(bnf)};
size_t pos{0};
while (pos < s.size()) {
char c{s[pos]};
auto Path = GetPath(std::string{1, c}, ReverseBNF, Top);
pos++;
}
return {};
}
ProgramNode Compile(std::vector<std::string> Tokens, std::string Top, BNF bnf, Terminals terminals)
{
BNF ReverseBNF{ Reverse(bnf)};
if (Tokens.size()){
std::string Token = Tokens[0];
auto Path = GetPath(Token, ReverseBNF, Top, terminals);
if (Path.size()) {
size_t Index{1};
while (Index < Tokens.size()) {
Path = GetPath(Token, ReverseBNF, Top, terminals, Path);
Index++;
}
} else
throw std::runtime_error("Invalid token: "s + Token);
} else
throw std::runtime_error("No tokens!");
return {};
}
class Test: public ::testing::Test {
protected:
Test(){}
~Test() override {}
};
TEST_F(Test, BNF) {
std::string LexTop{"preprocessing-token"};
BNF LexBNF{
{"preprocessing-token", {{"identifier"},
{"preprocessing-op-or-punc"},
{"pp-number"}}},
{"identifier", {{"identifier-nondigit"},
{"identifier", "identifier-nondigit"},
{"identifier", "digit"}}},
{"digit", {{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }}},
{"identifier-nondigit", {{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "_"}}},
{"preprocessing-op-or-punc", {{";"}}},
{"pp-number", {{"digit"},
{"pp-number", "digit"}}}
};
std::string Top{"program"};
BNF bnf{
{"program", {{"statement-list"}}},
{"statement-list", {{"statement", "statement-list"},
{}, }},
{"statement", {{"assigmnent", ";"}}},
{"assignment", {{"identifier", "=", "identifier"}}}
};
std::set<std::string> Terminals{"identifier", "=", ";"};
std::string Code{"a = b ; c = d ; e = f ;"};
auto tokens = Lex(Code, LexTop, LexBNF);
auto Program = Compile(tokens, Top, bnf, Terminals);
}
int main(int argc, char* argv[]) {
::testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}
|