· 6 years ago · May 23, 2019, 01:34 PM
1#include "table.h"
2
3rootNode* globalRoot;
4
5rootNode* newRoot(){
6 rootNode* newNode = malloc(sizeof(rootNode));
7 if(newNode == NULL){
8 printf("Error newRoot allocating space");
9 return NULL;
10 }
11 newNode->decl = NULL;
12 return newNode;
13}
14declNode* newDecl2(){
15 declNode* newNode = malloc(sizeof(declNode));
16 if(newNode == NULL){
17 printf("Error newDecl allocating space");
18 return NULL;
19 }
20 newNode->nextDecl = malloc(sizeof(declNode));
21 return newNode;
22}
23declNode* newDecl(char* type, char* id, bool isField){
24 declNode* newNode = malloc(sizeof(declNode));
25 if(newNode == NULL){
26 printf("Error newDecl allocating space");
27 return NULL;
28 }
29 newNode->nextDecl = NULL;
30 newNode->firstVar = NULL;
31 newNode->id = (char*)malloc((strlen(id)+1)*sizeof(char));
32 strcpy(newNode->id, id);
33 newNode->type = (char*)malloc((strlen(type)+1)*sizeof(char));
34 strcpy(newNode->type, type);
35 newNode->isField = isField;
36 newNode->nParams = 0;
37
38 return newNode;
39
40}
41
42varNode* newVar(char* type, char* id, bool isVar){
43 varNode* newNode = malloc(sizeof(varNode));
44 if(newNode == NULL){
45 printf("Error newVar allocating space");
46 return NULL;
47 }
48 newNode->nextVar = NULL;
49 newNode->id = (char*)malloc((strlen(id)+1)*sizeof(char));
50 strcpy(newNode->id, id);
51 newNode->type = (char*)malloc((strlen(type)+1)*sizeof(char));
52 strcpy(newNode->type, type);
53 newNode->isVar = isVar;
54 return newNode;
55}
56
57param* newParam(char* type){
58 param* newNode = malloc(sizeof(param));
59 if(newNode == NULL){
60 printf("Error newParam allocating space");
61 return NULL;
62 }
63 newNode->next = NULL;
64 newNode->type = (char*)malloc((strlen(type)+1)*sizeof(char));
65 strcpy(newNode->type, type);
66 return newNode;
67}
68
69// "Main"
70void symbolTable(node* astRoot){
71 //aux = id of Class
72 node* aux = astRoot->child;
73 //create root of symbol table
74 globalRoot = newRoot();
75 rootNode* root = globalRoot;
76 //root->decl = malloc(sizeof(newDecl));
77 //in case tree is not empty, creates symbol table
78 if(aux!=NULL){
79 root->decl = recursive(aux);
80 }
81 //addNotes, using symbol table. If tree is empty returns null;
82 recursiveNotes(aux, root->decl);
83 //printf("fsdfsdfsdgfsdfgsfhsdf%s\n",root->decl->type);
84 printTable(root);
85 clearTable(root);
86}
87
88// create Symbol Table
89declNode* recursive(node* current){
90 declNode* aux = malloc(sizeof(declNode*));
91 //printf("\n1%s\n",current->child->node_type);
92 //printf("\n----------%s\n",current->child->brother->value);
93 //printf("current->node_Type: %s, l93\n", current->node_type);
94 if(strcmp(current->node_type, "VarDecl") == 0){
95 //printf("child: %s\tchild->brother:%s\n", current->child->node_type, current->child->brother->value);
96 aux = newDecl(current->child->node_type, current->child->brother->value, TRUE);
97 }
98 else if(strcmp(current->node_type, "FuncDecl") == 0){
99//printf("current->child:%s\n", current->child->node_type);
100 aux = createMethod(current->child);
101 }
102
103 if(current->brother != NULL){
104 //printf("current brother: %s\n", current->brother->node_type);
105 aux->nextDecl = recursive(current->brother);
106 }
107 return aux;
108}
109
110// ignores VarDecl, treats MethodDecl
111void recursiveNotes(node* tree, declNode* table){
112 if(tree == NULL)
113 return;
114 //printf("\npop2\n");
115 node* auxTree = tree;
116 node* auxMethod = NULL;
117 declNode* auxTable = table;
118
119 // pass global variables
120 while(auxTable->isField && auxTable->nextDecl != NULL){
121 auxTree = auxTree->brother;
122 auxTable = auxTable->nextDecl;
123 }
124
125 // MethodDecl -> MethodHeader -> MethodBody -> (1st var decl / statement / NULL)
126 auxMethod = auxTree;
127
128 while(auxMethod != NULL){
129 // pass local declaration of variables
130 //printf("auxMethod: %s\n", auxMethod->node_type);
131 while(strcmp(auxMethod->node_type, "VarDecl") == 0 && auxMethod->brother != NULL){
132 auxMethod = auxMethod->brother;
133 }
134 //printf("auxMethod2: %s\n", auxMethod->node_type);
135 // if not a variable, it's a statement. Deals with it
136 if(strcmp(auxMethod->child->node_type, "FuncDecl") != 0){
137 recStatement(auxMethod, auxTable);
138 }
139
140 auxMethod = auxMethod->brother;
141 }
142
143 // goes to next MethodDecl/VarDecl (if exists, auxTable also has it, if not returns NULL)
144 if(auxTable->nextDecl!=NULL)
145 recursiveNotes(auxTree->brother, auxTable->nextDecl);
146}
147
148declNode* createMethod(node* current){
149 // current = MethodHeader
150 // aux = type
151 // aux2 = MethodBody
152 node* aux = current->child;
153 node* aux2 = current->brother;
154 declNode* decl = newDecl2();
155 if(strcmp(aux->brother->node_type,"FuncParams")==0){
156 if(aux->brother->child==NULL)
157 decl = newDecl("none", aux->value, FALSE);
158 else
159 decl = newDecl(aux->node_type, aux->value, FALSE);
160
161 // MethodParams
162 aux = aux->brother;
163
164 decl->firstVar = addVar(aux->child, FALSE);
165 // goes to the first var, skiping the params
166 if(decl->firstVar == NULL){
167 decl->firstVar = addVar(aux2->child->child, TRUE);}
168 else{
169 varNode* varAux = decl->firstVar;
170 while(varAux->nextVar != NULL)
171 varAux = varAux->nextVar;
172 varAux->nextVar = addVar(aux2->child->child, TRUE);
173 }
174
175 // counts params
176 varNode* vars = decl->firstVar;
177 while(vars != NULL){
178 if(!vars->isVar)
179 decl->nParams++;
180 vars = vars->nextVar;
181 }
182
183 }
184 else{
185
186 decl = newDecl(aux->brother->node_type, aux->value, FALSE);
187 // MethodParams
188 aux = aux->brother->brother;
189 //printf("auxchild: %s\n", aux->child->node_type);
190 //printf("auxchild2: %s\n", aux2->child->node_type);
191 // param or null
192 if(aux->child !=NULL) {
193 decl->firstVar = addVar(aux->child, FALSE);
194
195 // goes to the first var, skiping the params
196 //printf("aux2->child: %s\n", aux->child->node_type);
197 if(decl->firstVar == NULL)
198 {
199 if(aux2->child->child != NULL) decl->firstVar = addVar(aux2->child->child, TRUE);
200
201
202 }
203
204 else{
205 varNode* varAux = decl->firstVar;
206 while(varAux->nextVar != NULL)
207 varAux = varAux->nextVar;
208 varAux->nextVar = addVar(aux2->child->child, TRUE);
209 }
210
211 // counts params
212 varNode* vars = decl->firstVar;
213 while(vars != NULL){
214 if(!vars->isVar)
215 decl->nParams++;
216 vars = vars->nextVar;
217 }
218 }
219 }
220 return decl;
221}
222
223// isVar ? var : param
224// receives the first Var/Param and adds all it's brothers
225varNode* addVar(node* current, bool isVar){
226 if(current == NULL){
227 return NULL;
228 }
229
230 varNode* aux = NULL;
231 // in case it's a statement moves to the next brother (statement/var/null)
232 if(strcmp(current->node_type, "VarDecl") != 0 && strcmp(current->node_type, "ParamDecl") != 0){
233 aux = addVar(current->child, isVar);
234
235 // goes through all var/param brothers
236 if(aux == NULL)
237 aux = addVar(current->brother, isVar);
238 else{
239 varNode* varAux = aux;
240 while(varAux->nextVar != NULL)
241 varAux = varAux->nextVar;
242 varAux->nextVar = addVar(current->brother, isVar);
243 }
244 return aux;
245 }
246
247 // adds Var and moves to the next brother
248 aux = newVar(current->child->node_type, current->child->brother->value, isVar);
249 aux->nextVar = addVar(current->brother, isVar);
250 return aux;
251}
252//
253void recStatement(node* tree, declNode* table){
254 if(tree == NULL)
255 return;
256 //printf("tree->value: %s\n", tree->node_type);
257 // goes to the last child, and does down up
258 if(strcmp(tree->node_type, "VarDecl") != 0)
259 recStatement(tree->child, table);
260 // goes to the last brother (and childs, etc.), does right left
261 recStatement(tree->brother, table);
262
263 // ID
264 //printf("tree->value: %s\n", tree->node_type);
265 if(strcmp(tree->node_type, "Id") == 0){
266 // checks if value(id) exists (not well implemented)
267 char* auxText = searchVar(tree, table);
268 //printf("auxText: %s\n", auxText);
269 if(auxText != NULL){
270 addNote(tree, printType(auxText));}
271 }
272 //else if(strcmp(tree->value, "Id") != 0)
273 // ASSIGN
274 else if(strcmp(tree->node_type, "Assign") == 0){
275 recAssign(tree, 0);
276 }
277 // CALL
278 else if(strcmp(tree->node_type, "Call") == 0){
279 searchMethod(tree);
280 }
281 // should have else for the rest of the nodes, which are having the notes added in yacc,
282}
283
284
285//necessário alterar de modo a não aceitar variáveis que sejam declaradas depois (localmente)
286// checks if id exists in the table
287char* searchVar(node* tree, declNode* table){
288 char* text = tree->value;
289 //printf("text: %s\n",text);
290 varNode* aux = table->firstVar;
291 char* nextSt = nextStuff(tree);
292 // searches in local variables
293 while(aux != NULL){
294 printf("aux->id:%s\ttext:%s\n",aux->id, text);
295 if(strcmp(text, aux->id) == 0){
296 return aux->type;
297 }
298 // if it finds the next variable in the tree it means it's not declared,
299 // since the order of the table is the same as the order of the tree
300 if(strcmp(nextSt, "") != 0)
301 if(strcmp(aux->nextVar->id, nextSt) == 0)
302 break;
303 aux = aux->nextVar;
304 }
305 //procurar variaveis globais
306 // searches in global variables
307 declNode* aux2 = globalRoot->decl;
308 while(aux2 != NULL){
309 if(aux2->isField){
310 if(strcmp(text, aux2->id) == 0){
311 return aux2->type;
312 }
313 }
314 aux2 = aux2->nextDecl;
315 }
316 //print erro var não declarada
317 return NULL;
318}
319
320// searches for the next var in the tree
321char* nextStuff(node* tree){
322 node* aux = tree;
323 char* temp = NULL;
324 if(strcmp(aux->node_type, "VarDecl") == 0){
325 return aux->child->value;
326 }
327 if(aux->child != NULL){
328 temp = nextStuff(aux->child);
329 if(strcmp(temp, "") != 0){
330 return temp;
331 }
332 }
333 if(aux->brother != NULL){
334 temp = nextStuff(aux->brother);
335 if(strcmp(temp, "") != 0){
336 return temp;
337 }
338 }
339 return "";
340}
341
342// Assign
343int recAssign(node* tree, int depth){
344 if(tree->child != NULL){
345 if(strcmp(tree->child->node_type, "Call") != 0){
346 if(tree->child->brother != NULL)
347 if(recAssign(tree->child, depth+1))
348 return 1;
349 }
350 if(tree->child != NULL){
351 if(tree->child->brother == NULL){
352 if(strcmp(tree->child->node_type, "Minus") == 0 || strcmp(tree->child->node_type, "Plus") == 0){
353 node* auxMinus = tree->child;
354 while(auxMinus->child != NULL){
355 auxMinus = auxMinus->child;
356 }
357 char* auxPlus = (char*)malloc((strlen(auxMinus->note)+1)*sizeof(char));
358 strcpy(auxPlus, auxMinus->note);
359 auxMinus = tree;
360 while(auxMinus->child != NULL){
361 auxMinus->note = (char*)malloc((strlen(auxPlus)+1)*sizeof(char));
362 strcpy(auxMinus->note, auxPlus);
363 auxMinus = auxMinus->child;
364 }
365 }
366 else
367 return 0;
368 }
369 else if(strcmp(tree->child->brother->node_type, "Call") != 0){
370 if(recAssign(tree->child->brother, depth+1))
371 return 1;
372 }
373 }
374 }
375 else{
376 return 0;}
377 if(tree->child->brother!=NULL){
378 if(tree->child->note != NULL && tree->child->brother->note != NULL){
379 if(strcmp(tree->child->note, tree->child->brother->note) == 0){
380 addNote(tree, tree->child->note);
381
382 }
383 else if(strcmp(tree->child->note, "double") == 0 && depth == 0){
384 if(strcmp(tree->child->brother->note, "int") == 0){
385 addNote(tree, "double");
386 }
387 }
388 else if(strcmp(tree->child->note, "double") == 0){
389 if(strcmp(tree->child->brother->note, "int") == 0)
390 addNote(tree, "double");
391 }
392 else if(strcmp(tree->child->brother->note, "double") == 0 && depth != 0){
393 if(strcmp(tree->child->note, "int") == 0)
394 addNote(tree, "double");
395 }
396 else if(strcmp(tree->child->note, "String") == 0 && strcmp(tree->node_type, "ParseArgs") == 0){
397 addNote(tree, tree->child->brother->note);
398 }
399 else{
400 return 1;
401 }
402 }
403 else
404 return 1;
405 }
406 return 0;
407}
408
409// call
410void searchMethod(node* tree){
411 //caso argumento seja int, uma função com os argumentos double também aceita (caso não exista com int)
412 //guarda o tipo de argumentos que tem
413 node* aux = tree->child;
414 param* first = NULL;
415 param* aux2 = NULL;
416 varNode* auxVar = NULL;
417 declNode* auxDecl = NULL;
418 declNode* auxNote = NULL;
419 int nParams = 0;
420 int nVars = 0;
421 bool check = TRUE;
422 int nMatches = 0;
423 int paramMatches = 0;
424 int firstTime = 0;
425
426 //caso exista pelo menos 1 param
427 // counts number of params to only check methods with same number of params
428 //printf("brother->nodetype: %s\n", aux->brother->node_type);
429 while(aux->brother != NULL){
430 //printf("dsadsads:%s\n", tree->node_type);
431 if(aux->brother->note != NULL){
432 //printf("aux->brother->note: %s\n",aux->brother->note);
433 if(firstTime == 0){
434 first = newParam(aux->brother->note);
435 firstTime++;
436 nParams++;
437 aux2 = first;
438 }
439 else{
440 aux2->next = newParam(aux->brother->note);
441
442 nParams++;
443 aux2 = aux2->next;
444 }
445 }
446 aux = aux->brother;
447 }
448
449 aux2 = first;
450
451 //procura um método que tenha o mesmo tipo de parametros (único),
452 //só é preciso percorrer a tabela de simbolos global
453 auxDecl = globalRoot->decl;
454 while(auxDecl != NULL){
455
456 if(!auxDecl->isField){
457
458 if(strcmp(auxDecl->id, tree->child->value) == 0){
459 if(auxDecl->nParams == nParams){
460 //verifica tipos de params
461 auxVar = auxDecl->firstVar;
462 nVars = 0;
463 check = TRUE;
464 paramMatches = 0;
465 while(auxVar != NULL){
466 if(nVars == auxDecl->nParams)
467 break;
468
469 if(!auxVar->isVar){
470 if(aux2 != NULL){
471 // if the types are equal
472 if(strcmp(printType(auxVar->type), aux2->type) == 0){
473 paramMatches++;
474 }
475 // if the types are compatible, saves method but keeps looking
476 else if(strcmp(aux2->type, "int") == 0){
477 if(strcmp(printType(auxVar->type), "double") == 0){
478 paramMatches++;
479 check = FALSE;
480 }
481 }
482 nVars++;
483 aux2 = aux2->next;
484 }
485 }
486 auxVar = auxVar->nextVar;
487 }
488 if(paramMatches == nParams){
489
490 // perfect match
491 if(check){
492 //printf("linha 489: %s\n", auxDecl);
493 addNote(tree->child, formatParams(auxDecl));
494 addNote(tree, printType(auxDecl->type));
495 return;
496 }
497 // compatible match, keeps looking for perfect match.
498 // if it doesn't find any perfect the first compatible one is "the one".
499 else if(nMatches == 0){
500 nMatches++;
501 auxNote = auxDecl;
502 }
503 else{
504 //error
505 }
506 }
507 }
508 }
509 }
510 auxDecl = auxDecl->nextDecl;
511 }
512 if(nMatches == 1){
513 //printf("linha 510: %s\n", auxNote);
514 addNote(tree->child, formatParams(auxNote));
515 addNote(tree, printType(auxNote->type));
516
517 }
518 else{
519 //error
520 }
521}
522
523void printTable(rootNode* root){
524 declNode* aux = root->decl;
525
526 if(root == NULL)
527 return;
528
529 printf("===== Global Symbol Table =====\n");
530
531 printClassTable(aux);
532 printMethodTable(aux);
533
534}
535
536void printClassTable(declNode* aux){
537 while(aux != NULL){
538 printf("%s\t", aux->id);
539 if(!aux->isField){
540 printf("%s", formatParams(aux));
541 }
542 printf("\t%s", printType(aux->type));
543
544 printf("\n");
545 aux = aux->nextDecl;
546 }
547 printf("\n");
548}
549
550void printMethodTable(declNode* aux){
551 varNode* aux2;
552 while(aux != NULL){
553 if(!aux->isField){
554 printf("===== Function %s", aux->id);
555 printf("%s", formatParams(aux));
556 printf(" Symbol Table =====\n");
557 printf("return\t\t%s\n", printType(aux->type));
558
559 aux2 = aux->firstVar;
560 while(aux2 != NULL){
561 printf("%s\t\t%s", aux2->id, printType(aux2->type));
562 if(!aux2->isVar)
563 printf("\tparam");
564 printf("\n");
565 aux2 = aux2->nextVar;
566 }
567 printf("\n");
568 }
569 aux = aux->nextDecl;
570 }
571}
572
573// print auxiliar
574char* formatParams(declNode* aux){
575 bool first = TRUE;
576 varNode* aux2 = aux->firstVar;
577 char* str1;
578 char* str2;
579 char* new_str;
580
581
582 new_str = malloc(strlen("(")+1);
583 new_str[0] = '\0';
584 strcat(new_str, "(");
585
586 while(aux2 != NULL){
587 if(!aux2->isVar){
588 if(first){
589 first = FALSE;
590 str1 = new_str;
591 str2 = printType(aux2->type);
592 new_str = malloc(strlen(str1)+strlen(str2)+1);
593 strcat(new_str, str1);
594 strcat(new_str, str2);
595 }
596 else{
597 str1 = new_str;
598 str2 = printType(aux2->type);
599 new_str = malloc(strlen(str1)+strlen(str2)+2);
600 strcat(new_str, str1);
601 strcat(new_str, ",");
602 strcat(new_str, str2);
603 }
604 }
605 else
606 break;
607 aux2 = aux2->nextVar;
608 }
609 str1 = new_str;
610 str2 = ")";
611 new_str = malloc(strlen(str1)+strlen(str2)+1);
612 strcat(new_str, str1);
613 strcat(new_str, str2);
614 return new_str;
615}
616
617char* printType(char* text){
618 if(strcmp(text, "Bool") == 0){
619 return "bool";
620 }
621 else if(strcmp(text, "String") == 0){
622 return "string";
623 }
624 else{
625 text[0] = tolower(text[0]);
626 return text;
627 }
628}
629
630void clearTable(rootNode* root){
631 if(root->decl != NULL)
632 clearDecl(root->decl);
633 free(root);
634}
635
636void clearDecl(declNode* current){
637 if(current->firstVar != NULL)
638 clearVar(current->firstVar);
639 if(current->nextDecl != NULL)
640 clearDecl(current->nextDecl);
641 free(current);
642}
643
644void clearVar(varNode* current){
645 if(current->nextVar != NULL)
646 clearVar(current->nextVar);
647 free(current);
648}