-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsemantics.cpp
More file actions
186 lines (161 loc) · 5.7 KB
/
semantics.cpp
File metadata and controls
186 lines (161 loc) · 5.7 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
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#include "semantics.h"
#include "errors.h"
#include "utils.h"
const char* FILE_NAME;
extern std::string code;
static SymbolTable symbols;
static Stack<int> scopes;
std::string context = "";
void init(const char* file, std::string& c)
{
FILE_NAME = file;
scopes.push(0);
}
static void print_symbols() {
if (symbols.size() == 0) return;
cout << "{";
for (Symbol& i : symbols) {
cout << i.name.value << ", ";
}
cout << "\b\b}";
}
Symbol::Symbol(Token& t, bool is_c, bool is_i, bool is_f, int s)
: name(t), is_const(is_c), is_initialized(is_i), is_file(is_f), scope(s) {}
// =========================================================================== ALL CHECKS:
void valid_file(SyntaxTreeNode& node)
{
// no need to do anything here...
}
void in_global_scope(SyntaxTreeNode& node)
{
if (scopes.access() != 0) {
ERROR(error_type::NOT_IN_GLOBAL_SCOPE,
"Import statement not in global scope."
, node.children[1].name.pos, FILE_NAME, code);
}
}
void is_defined(SyntaxTreeNode& node)
{
node.traverse_left_right([](SyntaxTreeNode& x) {
if (x.name.type != IDENTIFIER) return; // dont check since its not an identifier
for (Symbol& i : symbols) {
if (x.name == i.name && i.name.scope >= x.name.scope) return; // it is defined somewhere
}
const std::string message = "Token \"" + x.name.value + "\" not found.";
ERROR(error_type::TOKEN_NOT_DEFINED, message.c_str(), x.name.pos, FILE_NAME, code);
});
}
void inc_scope(SyntaxTreeNode& node)
{
scopes.push(scopes.access() + 1);
}
void no_rep(SyntaxTreeNode& node)
{
node.traverse_left_right([](SyntaxTreeNode& x) {
if (x.name.type != IDENTIFIER) return; // dont check since its not an identifier
for (Symbol& i : symbols) {
if (x.name.pos == i.name.pos) return; // already checked, dont check again
if (x.name.value == i.name.value && i.name.scope == x.name.scope) {
const std::string message = "Token \"" + x.name.value + "\" has already been defined in the same scope.";
ERROR(error_type::REPEATED_DEFINITION, message.c_str(), x.name.pos, FILE_NAME, code);
}
}
});
}
void add_to_symbols(SyntaxTreeNode& node)
{
// CAN ONLY ADD RAW DECLARATIONS AS NEW SYMBOLS!
if (node.name.value != "~decl") return;
if (node.children.size() < 2) return;
Symbol s;
// find id to store:
Token store = node.get_farthest_token();
s.name = store;
s.is_const = (node.father->get_closest_token().value == "const") ? true : false;
s.is_file = (node.father->name.value == "~import") ? true : false;
s.is_initialized = (node.father->name.value == "~assign" || node.father->name.value == "~var"
|| node.father->name.value == "~fundef" || node.father->name.value == "~class") ? true : false;
s.scope = scopes.access();
symbols.push_back(s);
}
void valid_math(SyntaxTreeNode& node)
{
}
void type_mismatch(SyntaxTreeNode& node)
{
}
void reserved_name(SyntaxTreeNode& node)
{
node.traverse_left_right([](SyntaxTreeNode& x) {
if (x.name.type != IDENTIFIER) return; // dont check since its not an identifier
for (Symbol& i : symbols) {
if (x.name.value == "super") {
const std::string message = "Token \"" + x.name.value + "\" is a reserved identifier";
ERROR(error_type::RESERVED_NAME, message.c_str(), x.name.pos, FILE_NAME, code);
}
if (x.name.value == "this") {
const std::string message = "Token \"" + x.name.value + "\" is a reserved identifier";
ERROR(error_type::RESERVED_NAME, message.c_str(), x.name.pos, FILE_NAME, code);
}
}
});
}
void context_not_oop(SyntaxTreeNode& node)
{
if (context != "oop") {
const std::string message = "Token used in a non-OOP context.";
ERROR(error_type::INVALID_CONTEXT, message.c_str(), node.name.pos, FILE_NAME, code);
}
}
void correct_decl_type(SyntaxTreeNode& node)
{
}
void const_violation(SyntaxTreeNode& node)
{
// only checking with assignments:
if (node.name.value != "~assign") return;
for (Symbol& i : symbols) {
if (i.name.value == node.children[0].name.value && i.is_const) {
// throw error:
const std::string message = "Attempting to change token \"" + i.name.value + "\", which is a constant.";
ERROR(error_type::CONST_VIOLATION, message.c_str(), node.name.pos, FILE_NAME, code);
}
}
}
void correct_params(SyntaxTreeNode& node)
{
}
void expr_not_bool(SyntaxTreeNode& node)
{
}
void not_bool_context(SyntaxTreeNode& node)
{
}
void not_function_context(SyntaxTreeNode& node)
{
if (context != "function") {
const std::string message = "Token used in a non-functional context.";
ERROR(error_type::INVALID_CONTEXT, message.c_str(), node.name.pos, FILE_NAME, code);
}
}
void bad_use_of_tokens(SyntaxTreeNode& node)
{
if (node.name.value != "~speddecl") return;
node.traverse_left_right([](SyntaxTreeNode& x) {
if (x.name.value == "~speddecl") {
const std::string message = "Special initialization is used badly.";
ERROR(error_type::REPEATED_DEFINITION, message.c_str(), x.children[0].name.pos, FILE_NAME, code);
}
});
}
void update_context(SyntaxTreeNode& node)
{
if (node.name.value == "~class") context = "oop";
else if (node.name.value == "~fund") context = "function";
else if (node.name.value == "~funstart") context = "function";
else if (node.name.value == "~ifhead" ||
node.name.value == "~whilehead" ||
node.name.value == "~forhead2"
) context = "boolean";
else context = "";
}