summaryrefslogtreecommitdiffhomepage
path: root/test-lexer.cpp
blob: b0706dfc857b81723b86bc91a980696e2a5af96b (plain)
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "bnf.h"
#include "cpp.h"
#include "lexer.h"
#include "grammer.h"
#include "minicc.h"
#include "debug.h"

#include <boost/algorithm/string.hpp>

#include "gmock/gmock.h"
#include "gtest/gtest.h"

#include <algorithm>
#include <cctype>
#include <deque>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

class Test: public ::testing::Test {
protected:
 Test(){
  debug = false;
 }
 ~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"},
                     }},
  {"statement", {{"assignment", ";"}}},
  {"assignment", {{"identifier", "=", "identifier"},
                  {"identifier", "=", "pp-number"}}}
 };

 // implicit?
 //std::set<std::string> Terminals{"identifier", "=", ";"};

 std::string Code{"a = bc ; c = 123 ; esd = Ff ; 1 = XYZ ; "};
 std::vector<Token> tokens_reference{
  {"identifier", "a", { 1, 1} },
  {"preprocessing-op-or-punc", "=", { 1, 3}},
  {"identifier", "bc", { 1, 5}},
  {"preprocessing-op-or-punc", ";", { 1, 8}},
  {"identifier", "c", { 1, 10}},
  {"preprocessing-op-or-punc", "=", { 1, 12}},
  {"pp-number", "123", { 1, 14}},
  {"preprocessing-op-or-punc", ";", { 1, 18}},
  {"identifier", "esd", { 1, 20}},
  {"preprocessing-op-or-punc", "=", { 1, 24}},
  {"identifier", "Ff", { 1, 26}},
  {"preprocessing-op-or-punc", ";", { 1, 29}},
  {"pp-number", "1", { 1, 31}},
  {"preprocessing-op-or-punc", "=", { 1, 33}},
  {"identifier", "XYZ", { 1, 35}},
  {"preprocessing-op-or-punc", ";", { 1, 39}},
 };

 Lex::Lexer lexer(LexBNF, LexTop);
 auto tokens = lexer.Lex(Code);

 ASSERT_EQ(tokens, tokens_reference);
#if 1
 std::cout << "=== Tokens =================================" << std::endl;
 for (const auto& i: tokens) {
  std::cout << i.type << ": " << i.value << std::endl;
 }
#endif

 CPP::PreprocessorTokensToTokens(tokens);
 Gram::Compiler compiler(bnf, Top);
 auto Tree = compiler.compile(tokens);

 compiler.DumpTree();

 //----------------------------------------------------------------
 
 std::string Code2{"a = bc ; c = 123 ; esd = Ff ; 1 = XYZ "};
 std::vector<Token> tokens_reference2{
  {"identifier", "a", { 1, 1} },
  {"preprocessing-op-or-punc", "=", { 1, 3}},
  {"identifier", "bc", { 1, 5}},
  {"preprocessing-op-or-punc", ";", { 1, 8}},
  {"identifier", "c", { 1, 10}},
  {"preprocessing-op-or-punc", "=", { 1, 12}},
  {"pp-number", "123", { 1, 14}},
  {"preprocessing-op-or-punc", ";", { 1, 18}},
  {"identifier", "esd", { 1, 20}},
  {"preprocessing-op-or-punc", "=", { 1, 24}},
  {"identifier", "Ff", { 1, 26}},
  {"preprocessing-op-or-punc", ";", { 1, 29}},
  {"pp-number", "1", { 1, 31}},
  {"preprocessing-op-or-punc", "=", { 1, 33}},
  {"identifier", "XYZ", { 1, 35}},
  //{"preprocessing-op-or-punc", ";", { 1, 39}},
 };

 tokens = lexer.Lex(Code2);
 ASSERT_EQ(tokens, tokens_reference2);
 CPP::PreprocessorTokensToTokens(tokens);
 try {
  Tree = compiler.compile(tokens);
  FAIL() << "compile() was expected to throw."s;
 } catch (const std::runtime_error& ex) {
  ASSERT_EQ(std::string{ex.what()}, "Compile error: Invalid program.");
 }
}

int main(int argc, char* argv[]) {
 ::testing::InitGoogleMock(&argc, argv);
 return RUN_ALL_TESTS();
}