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
|
#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<std::string> Lex(std::string s)
{
return split(s);
}
BNF Reverse(BNF bnf){
return {}; // TODO
}
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
}
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 Top{"program"};
BNF bnf{
{"program", {{"statement-list"}}},
{"statement-list", {{"statement", "statement-list"}}},
{"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);
auto Program = Compile(tokens, Top, bnf, Terminals);
}
int main(int argc, char* argv[]) {
::testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}
|