ag: even more refactored
[uebersetzerbau-ss10.git] / ag / symtable.c
1 #include <string.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include "symtable.h"
5
6 struct symbol *new_tab(void)
7 {
8         return SYMNULL;
9 }
10
11 struct symbol *clone_tab(struct symbol *tab)
12 {
13         struct symbol *elm;
14         struct symbol *new_tabx;
15
16         elm = tab;
17         new_tabx = new_tab();
18         while(elm != SYMNULL) {
19                 new_tabx = tab_add_symbol(new_tabx, elm->ident, elm->type, 0);
20                 elm = elm->next;
21         }
22
23         return new_tabx;
24 }
25
26 struct symbol *tab_add_symbol(struct symbol *tab, char *ident, short type, short check)
27 {
28         struct symbol *elm;
29         struct symbol *new_elm;
30
31         if(tab_lookup(tab, ident) != SYMNULL) {
32                 if(check) {
33                         fprintf(stderr, "Feld doppelt vorhanden: \"%s\"\n", ident);
34                         exit(3);
35                 } else {
36                         tab = tab_remove_symbol(tab, ident);
37                 }
38         }
39         
40         new_elm = (struct symbol *) malloc(sizeof(struct symbol));
41         new_elm->next = SYMNULL;
42         new_elm->ident = strdup(ident);
43         new_elm->type = type;
44
45         if(tab == SYMNULL) {
46                 return new_elm;
47         }
48
49         elm = tab;
50         while(elm->next != SYMNULL) {
51                 elm = elm->next;
52         }
53         elm->next = new_elm;
54         
55         return tab;
56 }
57
58 struct symbol *tab_lookup(struct symbol *tab, char *ident)
59 {
60         struct symbol *elm = tab;
61
62         if(tab == SYMNULL) {
63                 return SYMNULL;
64         }
65
66         do {
67                 if(strcmp(elm->ident, ident) == 0) {
68                         return elm;
69                 }
70                 elm = elm->next;
71         } while(elm != SYMNULL);
72
73         return SYMNULL;
74 }
75
76 struct symbol *tab_merge(struct symbol *tab, struct symbol *to_add, short check)
77 {
78         struct symbol *elm = to_add;
79         struct symbol *new_tab = clone_tab(tab);
80         
81         while(elm != SYMNULL) {
82                 new_tab = tab_add_symbol(new_tab, elm->ident, elm->type, check);
83                 elm = elm->next;
84         }
85
86         return new_tab;
87 }
88
89 struct symbol *tab_remove_symbol(struct symbol *tab, char *ident)
90 {
91         struct symbol *elm = tab;
92         struct symbol *previous_elm = SYMNULL;
93
94         while(elm != SYMNULL) {
95                 if(strcmp(elm->ident, ident) == 0) {
96                         if(previous_elm == SYMNULL) {
97                                 tab = elm->next;
98                         } else {
99                                 previous_elm->next = elm->next;
100                         }
101                         (void)free(elm->ident);
102                         (void)free(elm);
103                         break;
104                 }
105                 previous_elm = elm;
106                 elm = elm->next;
107         }
108
109         return tab;
110 }
111
112 void check_variable(struct symbol *tab, char *ident)
113 {
114         struct symbol *elm = tab_lookup(tab, ident);
115         if(elm != SYMNULL) {
116                 if(elm->type != S_VAR) {
117                         fprintf(stderr, "Identifier ist keine Variable: \"%s\"\n", ident);
118                         exit(3);
119                 }
120         } else {
121                 fprintf(stderr, "Unbekannter Identifier: \"%s\"\n", ident);
122                 exit(3);
123         }
124 }
125
126 void check_field(struct symbol *tab, char *ident)
127 {
128         struct symbol *elm = tab_lookup(tab, ident);
129         if(elm != SYMNULL) {
130                 if(elm->type != S_FIELD) {
131                         fprintf(stderr, "Identifier ist kein Feld: \"%s\"\n", ident);
132                         exit(3);
133                 }
134         } else {
135                 fprintf(stderr, "Unbekannter Identifier: \"%s\"\n", ident);
136                 exit(3);
137         }
138 }
139