-
Notifications
You must be signed in to change notification settings - Fork 0
/
symbolTable.cpp
430 lines (337 loc) · 12.1 KB
/
symbolTable.cpp
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
#include "symbolTable.h"
// // // // // // // // // // // // // // // // // // // //
//
// Introduction
//
// This symbol table library supplies basic insert and lookup for
// symbols linked to void * pointers of data. The is expected to use
// ONLY the SymbolTable class and NOT the Scope class. The Scope class
// is used by SymbolTable in its implementation.
//
// Plenty of room for improvement inlcuding: better debugging setup,
// passing of refs rather than values and purpose built char *
// routines, and C support.
//
// WARNING: lookup will return NULL pointer if key is not in table.
// This means the void * cannot have zero as a legal value! Attempting
// to save a NULL pointer will get a error.
//
// A main() is commented out and has testing code in it.
//
// Robert Heckendorn Apr 3, 2021
//
// // // // // // // // // // // // // // // // // // // //
//
// Some sample void * printing routines. User shoud supply their own.
// The print routine will print the name of the symbol and then
// use a user supplied function to print the pointer.
//
// print nothing about the pointer
void pointerPrintNothing(void *data)
{
}
// print the pointer as a hex address
void pointerPrintAddr(void *data)
{
printf("0x%016llx ", (unsigned long long int)(data));
}
// print the pointer as a long long int
void pointerPrintLongInteger(void *data)
{
printf("%18lld ", (unsigned long long int)(data));
}
// print the pointer as a char * string
void pointerPrintStr(void *data)
{
printf("%s ", (char *)(data));
}
// // // // // // // // // // // // // // // // // // // //
//
// Class: Scope
//
// Helper class for SymbolTable
//
class SymbolTable::Scope {
private:
static bool debugFlg; // turn on tedious debugging
std::string name; // name of scope
std::map<std::string , void *> symbols; // use an ordered map (not as fast as unordered)
public:
Scope(std::string newname);
~Scope();
std::string scopeName(); // returns name of scope
void debug(bool state); // sets the debug flag to state
void print(void (*printData)(void *)); // prints the table using the supplied function to print the void *
void applyToAll(void (*action)(std::string , void *)); // applies func to all symbol/data pairs
bool insert(std::string sym, void *ptr); // inserts a new ptr associated with symbol sym
// returns false if already defined
void *lookup(std::string sym); // returns the ptr associated with sym
// returns NULL if symbol not found
//void *firstSym(); //returns the first symbol of the scope
};
SymbolTable::Scope::Scope(std::string newname) {
name = newname;
debugFlg = false;
}
SymbolTable::Scope::~Scope() {
}
// returns char *name of scope
std::string SymbolTable::Scope::scopeName() {
return name;
}
// set scope debugging
void SymbolTable::Scope::debug(bool state) {
debugFlg = state;
}
// print the scope
void SymbolTable::Scope::print(void (*printData)(void *)) {
printf("Scope: %-15s -----------------\n", name.c_str());
for (std::map<std::string , void *>::iterator it=symbols.begin(); it!=symbols.end(); it++) {
printf("%20s: ", (it->first).c_str());
printData(it->second);
printf("\n");
}
}
// apply the function to each symbol in this scope
void SymbolTable::Scope::applyToAll(void (*action)(std::string , void *)) {
for (std::map<std::string , void *>::iterator it=symbols.begin(); it!=symbols.end(); it++) {
action(it->first, it->second);
}
}
// returns true if insert was successful and false if symbol already in this scope
bool SymbolTable::Scope::insert(std::string sym, void *ptr) {
if (symbols.find(sym) == symbols.end()) {
if (debugFlg) printf("DEBUG(Scope): insert in \"%s\" the symbol \"%s\".\n",
name.c_str(),
sym.c_str());
if (ptr==NULL) {
printf("ERROR(SymbolTable): Attempting to save a NULL pointer for the symbol '%s'.\n",
sym.c_str());
}
symbols[sym] = ptr;
return true;
}
else {
if (debugFlg) printf("DEBUG(Scope): insert in \"%s\" the symbol \"%s\" but symbol already there!\n", name.c_str(), sym.c_str());
return false;
}
}
void *SymbolTable::Scope::lookup(std::string sym) {
if (symbols.find(sym) != symbols.end()) {
if (debugFlg) printf("DEBUG(Scope): lookup in \"%s\" for the symbol \"%s\" and found it.\n", name.c_str(), sym.c_str());
return symbols[sym];
}
else {
if (debugFlg) printf("DEBUG(Scope): lookup in \"%s\" for the symbol \"%s\" and did NOT find it.\n", name.c_str(), sym.c_str());
return NULL;
}
}
bool SymbolTable::Scope::debugFlg;
// // // // // // // // // // // // // // // // // // // //
//
// Class: SymbolTable
//
// This is a stack of scopes that represents a symbol table
//
SymbolTable::SymbolTable()
{
debugFlg = false;
enter((std::string )"Global");
scopeStart = NULL;
activeFunction = NULL;
loopNum = 0;
}
void SymbolTable::debug(bool state)
{
debugFlg = state;
}
// Returns the number of scopes in the symbol table
int SymbolTable::depth()
{
return stack.size();
}
// print all scopes using data printing func
void SymbolTable::print(void (*printData)(void *))
{
printf("=========== Symbol Table ===========\n");
for (std::vector<Scope *>::iterator it=stack.begin(); it!=stack.end(); it++) {
(*it)->print(printData);
}
printf("=========== ============ ===========\n");
}
// Enter a scope
void SymbolTable::enter(std::string name)
{
if (debugFlg) printf("DEBUG(SymbolTable): enter scope \"%s\".\n", name.c_str());
stack.push_back(new Scope(name));
}
// Leave a scope (not allowed to leave global)
void SymbolTable::leave()
{
if (debugFlg) printf("DEBUG(SymbolTable): leave scope \"%s\".\n", (stack.back()->scopeName()).c_str());
if (stack.size()>1) {
delete stack.back();
stack.pop_back();
}
else {
printf("ERROR(SymbolTable): You cannot leave global scope. Number of scopes: %d.\n", (int)stack.size());
}
}
// Lookup a symbol anywhere in the stack of scopes
// Returns NULL if symbol not found, otherwise it returns the stored void * associated with the symbol
void * SymbolTable::lookup(std::string sym)
{
void *data;
std::string name;
data = NULL; // set even though the scope stack should never be empty
for (std::vector<Scope *>::reverse_iterator it=stack.rbegin(); it!=stack.rend(); it++) {
data = (*it)->lookup(sym);
name = (*it)->scopeName();
if (data!=NULL) break;
}
if (debugFlg) {
printf("DEBUG(SymbolTable): lookup the symbol \"%s\" and ", sym.c_str());
if (data) printf("found it in the scope named \"%s\".\n", name.c_str());
else printf("did NOT find it!\n");
}
return data;
}
// Lookup a symbol in the global scope
// returns NULL if symbol not found, otherwise it returns the stored void * associated with the symbol
void * SymbolTable::lookupGlobal(std::string sym)
{
void *data;
data = stack[0]->lookup(sym);
if (debugFlg) printf("DEBUG(SymbolTable): lookup the symbol \"%s\" in the Globals and %s.\n", sym.c_str(),
(data ? "found it" : "did NOT find it"));
return data;
}
// Insert a symbol into the most recent scope
// Returns true if insert was successful and false if symbol already in the most recent scope
bool SymbolTable::insert(std::string sym, void *ptr)
{
if (debugFlg) {
printf("DEBUG(symbolTable): insert in scope \"%s\" the symbol \"%s\"",
(stack.back()->scopeName()).c_str(), sym.c_str());
if(ptr==NULL) printf(" WARNING: The inserted pointer is NULL!!");
printf("\n");
}
return (stack.back())->insert(sym, ptr);
}
// Insert a symbol into the global scope
// Returns true is insert was successful and false if symbol already in the global scope
bool SymbolTable::insertGlobal(std::string sym, void *ptr)
{
if (debugFlg) {
printf("DEBUG(Scope): insert the global symbol \"%s\"", sym.c_str());
if(ptr==NULL) printf(" WARNING: The inserted pointer is NULL!!");
printf("\n");
}
return stack[0]->insert(sym, ptr);
}
// Apply function to each simple in the local scope. The function gets both the
// string and the associated pointer.
void SymbolTable::applyToAll(void (*action)(std::string , void *))
{
stack[stack.size()-1]->applyToAll(action);
}
// Apply function to each simple in the global scope. The function gets both the
// string and the associated pointer.
void SymbolTable::applyToAllGlobal(void (*action)(std::string , void *))
{
stack[0]->applyToAll(action);
}
bool SymbolTable::getDebug() {
return debugFlg;
}
void SymbolTable::addToLoopNum(int val) {
loopNum += val;
}
int SymbolTable::getLoopNum() {
return loopNum;
}
// // // // // // // // // // // // // // // // // // // //
//
// Some tests
//
std::string words[] = {"alfa", "bravo", "charlie", "dog", "echo", "foxtrot", "golf"};
int wordsLen = 7;
int counter;
void countSymbols(std::string sym, void *ptr) {
counter++;
printf("%d %20s: ", counter, sym.c_str());
pointerPrintAddr(ptr);
printf("\n");
}
bool SymbolTable::test()
{
Scope s("global");
s.debug(true);
s.insert("dog", (char *)"woof");
s.insert("cat", (char *)"meow");
printf("%s\n", (char *)(s.lookup("cat")));
printf("%s\n", (char *)(s.lookup("dog")));
if (s.lookup("fox")==NULL) printf("not found\n");
else printf("found\n");
s.print(pointerPrintAddr);
s.print(pointerPrintStr);
SymbolTable st;
st.debug(true);
printf("Print symbol table.\n");
st.print(pointerPrintStr);
st.insert("alfa", (char *)"ant");
st.insert("bravo", (char *)"bat");
st.insert("charlie", (char *)"cob");
st.enter("First");
st.insert("charlie", (char *)"cow");
st.enter((std::string )"Second");
st.insert("delta", (char *)"dog");
st.insertGlobal("echo", (char *)"elk");
printf("Print symbol table.\n");
st.print(pointerPrintStr);
printf("This is how you might use insert and lookup in your compiler.\n");
st.leave(); // second no longer exists
st.enter((std::string )"Third");
if (st.insert("charlie", (char *)"cat")) printf("success\n"); else printf("FAIL\n");
if (st.insert("charlie", (char *)"pig")) printf("success\n"); else printf("FAIL\n");
if (st.lookup("charlie")) printf("success\n"); else printf("FAIL\n");
if (st.lookup("mirage")) printf("success\n"); else printf("FAIL\n");
printf("Print symbol table.\n");
st.print(pointerPrintStr);
fflush(stdout);
printf("\nGeneral Lookup\n");
for (int i=0; i<wordsLen; i++) {
void *data;
if ((data = st.lookup(words[i]))==NULL) printf("%s: %s\n", words[i].c_str(), (char *)"NULL");
else printf("%s: %s\n", words[i].c_str(), (char *)data);
}
printf("\nGlobal Lookup\n");
for (int i=0; i<wordsLen; i++) {
void *data;
if ((data = st.lookupGlobal(words[i]))==NULL) printf("%s: %s\n", words[i].c_str(), (char *)"NULL");
else printf("%s: %s\n", words[i].c_str(), (char *)data);
}
printf("Test that apply works.\n");
counter = 0;
st.applyToAllGlobal(countSymbols);
printf("Number of global symbols: %d\n", counter);
st.insert((char *)"gnu", (char *)"goat");
st.lookup((char *)"gnu");
st.insertGlobal((char *)"gnu", (char *)"grebe");
st.lookup((char *)"gnu");
st.lookupGlobal((char *)"gnu");
return true;
}
//getter and setter functions for the new variables, the first symbol of the current scope and the symbol of the current function
void* SymbolTable::getScopeStart() {
return scopeStart;
}
void SymbolTable::setScopeStart(void *start) {
scopeStart = start;
}
void *SymbolTable::getCurrentFunction(){
return activeFunction;
}
void SymbolTable::setCurrentFunction(void *funct){
activeFunction = funct;
}