-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSymbolTable.c
More file actions
351 lines (297 loc) · 11.2 KB
/
SymbolTable.c
File metadata and controls
351 lines (297 loc) · 11.2 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
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
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include "stack.c"
#include "Structs.h"
#define HASH_SIZE 60
bool ScopesArray[100];
union Value {
int MyintValue; /* integer value */
float MyfloatValue; /* float value */
char* MycharValue; /* char value */
char* MystringValue; /* string value*/
char* Myidentifier; /* identifier name */
/*char* Myarrayidentifier;*/
char* Mycomment;
nodeType* nPtr;
};
struct SymbolInfo {
char * Sym_Name;
int Sym_Type;
int Sym_Scope;
union Value Sym_Value;
PermissionEnum Sym_Perm;
bool Sym_Init;
struct SymbolInfo *Next;
}*HashTable[HASH_SIZE];
//we have a hash table of size HASH_SIZE to point to different symbol tables
//HashFun to return the index of new symbol table in the hash table
//HashFun takes the name of the symbol and add its ASCII code % HASH_SIZE to get its index
int HashFun(char *Name){
int index= 0;
for (int i=0; Name[i]; ++i){
index += Name[i];
}
return (index % HASH_SIZE);
}
//Search Hash Table to check whether the exact info exists before or not
//that is return true only if a symbol having the same name, same type, same scope exists
struct SymbolInfo * SearchTable(char *Name, int Type, int Scope){
//get index
int HashIndex = HashFun(Name);
struct SymbolInfo *symbolEntry = HashTable[HashIndex];
//strcmp compares 2 strings (2 *char) and return 0 if they are identical
while (symbolEntry != NULL){
if (!strcmp(symbolEntry->Sym_Name, Name) && symbolEntry->Sym_Type==Type && symbolEntry->Sym_Scope == Scope){
return symbolEntry; //found
}
symbolEntry = symbolEntry->Next;
}
return NULL; //not found
}
//Search Symbol Table to check whether a name is already declared in the same scope
struct SymbolInfo * AlreadyDeclaredInScope(char *Name, int Scope){
int HashIndex = HashFun(Name);
struct SymbolInfo *symbolEntry = HashTable[HashIndex];
while (symbolEntry != NULL){
if (!strcmp(symbolEntry->Sym_Name, Name) && symbolEntry->Sym_Scope == Scope){
return symbolEntry; //found
}
symbolEntry = symbolEntry->Next;
}
return NULL; //not found
}
//return symbol having name with most recent scope
struct SymbolInfo * SearchByName(char *Name){
int HashIndex = HashFun(Name);
struct SymbolInfo *symbolEntry = HashTable[HashIndex];
while (symbolEntry != NULL){
if (!strcmp(symbolEntry->Sym_Name, Name) && ScopesArray[symbolEntry->Sym_Scope] == true){
return symbolEntry; //found
}
symbolEntry = symbolEntry->Next;
}
return NULL; //not found
}
//insert in hash table, return false if insertion failed as the symbol already exists
//or return true if insertion was successful
bool InsertTable(struct SymbolInfo *newEntry){
char *newName = newEntry->Sym_Name;
int index= HashFun(newName);
if(SearchTable(newName, newEntry->Sym_Type, newEntry->Sym_Scope)){
printf("Symbol with name %s is already declared in this scope\n", newName);
return false;
}
//by here, symbol wasn't found in hash table, so we will add a new one
//if HashTable[index]==NULL, then we insert newEntry immediately
//otherwise we resolve collision by chaining, we put new node at first and make it point to the rest of the symbols having same index
if (HashTable[index] == NULL){
HashTable[index] = newEntry;
HashTable[index]->Next = NULL;
return true;
}
else {
struct SymbolInfo *temp = HashTable[index];
HashTable[index] = newEntry;
HashTable[index]->Next = temp;
return true;
}
}
//same as SearchTable but returns the Value if found and Found is true
//otherwise Found = false
union Value SearchTableVal(char *Name, int Type, int Scope, bool *Found){
//get index
int HashIndex = HashFun(Name);
struct SymbolInfo *symbolEntry = HashTable[HashIndex];
//strcmp compares 2 strings (2 *char) and return 0 if they are identical
while (symbolEntry != NULL){
if (!strcmp(symbolEntry->Sym_Name, Name) && symbolEntry->Sym_Type== Type && symbolEntry->Sym_Scope == Scope){
(*Found) = true;
return symbolEntry->Sym_Value; //found
}
symbolEntry = symbolEntry->Next;
}
(*Found) = false;
union Value result;
result.MycharValue = '#';
return result; //not found
}
void PrintSymbolTable(){
FILE * fp = fopen ("SymbolTable.txt","w");
for (int HashIndex=0; HashIndex< HASH_SIZE; HashIndex++){
printf("HashIndex= %d", HashIndex);
printf("\n---------------------------\n");
fprintf(fp, "HashIndex= %d", HashIndex);
fprintf(fp, "\n---------------------------\n");
struct SymbolInfo *temp= HashTable[HashIndex];
while (temp != NULL){
printf("Name= %s Type=%d Scope=%d Value= %d Permission= %d Initi= %d\n", temp->Sym_Name, temp->Sym_Type, temp->Sym_Scope, temp->Sym_Value, temp->Sym_Perm, temp->Sym_Init);
fprintf(fp, "Name= %s Type=%d Scope=%d Value= %d Permission= %d Initi= %d\n", temp->Sym_Name, temp->Sym_Type, temp->Sym_Scope, temp->Sym_Value, temp->Sym_Perm, temp->Sym_Init);
temp= temp->Next;
}
printf("\n\n");
fprintf(fp, "\n\n");
}
}
bool DeleteHash(char *Name, int Type, int Scope){
int HashIndex = HashFun(Name);
struct SymbolInfo *symbolEntry = HashTable[HashIndex];
if (symbolEntry == NULL) //not found
return false;
//found at head and has no next
if (symbolEntry->Next == NULL && !strcmp(symbolEntry->Sym_Name, Name) && symbolEntry->Sym_Type== Type && symbolEntry->Sym_Scope == Scope){
free(symbolEntry);
HashTable[HashIndex] = NULL;
return true;
}
//at head and has followers
else if (!strcmp(symbolEntry->Sym_Name, Name) && symbolEntry->Sym_Type== Type && symbolEntry->Sym_Scope == Scope){
HashTable[HashIndex] = symbolEntry->Next;
free(symbolEntry);
return true;
}
else {
//not found at head, search in chain
while (symbolEntry->Next != NULL){
if (!strcmp(symbolEntry->Next->Sym_Name, Name) && symbolEntry->Next->Sym_Type== Type && symbolEntry->Next->Sym_Scope == Scope){
//found
break;
}
symbolEntry = symbolEntry->Next;
}
}
if (symbolEntry != NULL){
struct SymbolInfo * found = symbolEntry->Next;
symbolEntry->Next = found->Next;
free(found);
return true;
}
return false;
}
bool Delete(struct SymbolInfo *symbolEntry){
return DeleteHash(symbolEntry->Sym_Name, symbolEntry->Sym_Type, symbolEntry->Sym_Scope);
}
bool UpdateHash(char *Name, int Type, int Scope, union Value newVal){
struct SymbolInfo *symbolEntry = SearchTable(Name, Type, Scope);
if (symbolEntry == NULL)
return false;
if (symbolEntry->Sym_Perm == 1 && symbolEntry->Sym_Init == false) {//is const and not assigned before
symbolEntry->Sym_Value = newVal;
symbolEntry->Sym_Init = true;
return true;
}
else if (symbolEntry->Sym_Perm != 1){//not const
symbolEntry->Sym_Value = newVal;
symbolEntry->Sym_Init = true;
return true;
}
return false;
}
bool UpdateHash2(char *Name, int Scope, int newVal){
struct SymbolInfo *symbolEntry = AlreadyDeclaredInScope(Name, Scope);
if (symbolEntry == NULL)
return false;
if (symbolEntry->Sym_Perm == 1 && symbolEntry->Sym_Init == false) {//is const and not assigned before
symbolEntry->Sym_Value.MyintValue = newVal;
symbolEntry->Sym_Init = true;
return true;
}
else if (symbolEntry->Sym_Perm != 1){
symbolEntry->Sym_Value.MyintValue = newVal;
symbolEntry->Sym_Init = true;
return true;
}
return false;
}
bool UpdateHash3(char *Name, int newVal){
struct SymbolInfo *symbolEntry = SearchByName(Name);
if (symbolEntry == NULL)
return false;
if (symbolEntry->Sym_Perm == 1 && symbolEntry->Sym_Init == false) {//is const and not assigned before
symbolEntry->Sym_Value.MyintValue = newVal;
symbolEntry->Sym_Init = true;
return true;
}
else if (symbolEntry->Sym_Perm != 1){
symbolEntry->Sym_Value.MyintValue = newVal;
symbolEntry->Sym_Init = true;
return true;
}
return false;
}
bool UpdateHash4(char *Name, bool newVal){
struct SymbolInfo *symbolEntry = SearchByName(Name);
if (symbolEntry == NULL)
return false;
if (symbolEntry->Sym_Perm == 1 && symbolEntry->Sym_Init == false) {//is const and not assigned before
symbolEntry->Sym_Value.MyintValue = newVal;
symbolEntry->Sym_Init = true;
return true;
}
else if (symbolEntry->Sym_Perm != 1){
symbolEntry->Sym_Value.MyintValue = newVal;
symbolEntry->Sym_Init = true;
return true;
}
return false;
}
//return 1 if variable found and updated
//return 0 if variable not found but updated for test
struct SymbolInfo * UpdateAnyway(char *Name, int newVal, bool*Found, int Scope_, struct SymbolInfo **Virtual){
struct SymbolInfo *symbolEntry = AlreadyDeclaredInScope(Name, Scope_);
*Virtual = malloc(sizeof(struct SymbolInfo));
//struct SymbolInfo *symbolEntry = SearchByName(Name);
if (symbolEntry == NULL){ //symbol with this name and scope not found
symbolEntry = SearchByName(Name); //check other scopes
if (symbolEntry == NULL){ //if name not found in other scopes too, set found b false, and create new node
(*Found) = false;
(*Virtual)->Sym_Name = Name;
(*Virtual)->Sym_Type = -1;
(*Virtual)->Sym_Scope = Scope_;
(*Virtual)->Sym_Perm = -1;
(*Virtual)->Sym_Init = true;
(*Virtual)->Sym_Value.MyintValue = newVal;
InsertTable(*Virtual);
return NULL;
}
}
//node found in current scope or previous scopes
(*Found)= true;
(*Virtual)->Sym_Name = Name;
(*Virtual)->Sym_Type = -1;
(*Virtual)->Sym_Scope = Scope_;
(*Virtual)->Sym_Perm = 2; //not declared
(*Virtual)->Sym_Init = true;
(*Virtual)->Sym_Value.MyintValue = newVal;
InsertTable(*Virtual);
if (symbolEntry->Sym_Perm == 1 && symbolEntry->Sym_Init == false) {//is const and not assigned before
//symbolEntry->Sym_Value.MyintValue = newVal;
//symbolEntry->Sym_Init = true;
return symbolEntry;
}
else if (symbolEntry->Sym_Perm != 1){//is not const
//symbolEntry->Sym_Value.MyintValue = newVal;
//symbolEntry->Sym_Init = true;
return symbolEntry;
}
else //is const
return symbolEntry;
}
int checkPerm(char *Name){
struct SymbolInfo *symbolEntry = SearchByName(Name);
if (symbolEntry == NULL)
return -1;
return symbolEntry->Sym_Perm;
}
bool UpdatePermAndType(char*Name, int Per, int Type){
struct SymbolInfo *symbolEntry = SearchByName(Name);
if (symbolEntry == NULL){
return false;
}
symbolEntry->Sym_Perm = Per;
symbolEntry->Sym_Type = Type;
return true;
}