1
+ #include < iostream>
2
+ #include < cmath>
3
+ #include " utils.cpp"
4
+
5
+ using namespace std ;
6
+
7
+ void getSymbolTable (TreeNode* syntax_tree,SymbolTable &symbol_table){
8
+ // insert the id nodes in the symbol table
9
+ if (syntax_tree->node_kind ==READ_NODE || syntax_tree->node_kind ==ASSIGN_NODE || syntax_tree->node_kind ==ID_NODE){
10
+ symbol_table.Insert (syntax_tree->id , syntax_tree->line_num );
11
+ }
12
+ // traverse the tree in preorder to get the symbol table
13
+ for (int i = 0 ; i < MAX_CHILDREN; ++i) {
14
+ if (syntax_tree->child [i]){
15
+ getSymbolTable (syntax_tree->child [i],symbol_table);
16
+ }
17
+ }
18
+ if (syntax_tree->sibling ){
19
+ getSymbolTable (syntax_tree->sibling ,symbol_table);
20
+ }
21
+ }
22
+
23
+
24
+ void replaceNonVoid (TreeNode* syntax_tree,bool &ok){
25
+
26
+ // replace the non-void nodes
27
+ if (syntax_tree->node_kind == NUM_NODE || syntax_tree->node_kind ==ID_NODE){
28
+ syntax_tree->expr_data_type =INTEGER;
29
+ }else if (syntax_tree->node_kind == OPER_NODE && (syntax_tree->oper ==EQUAL || syntax_tree->oper ==LESS_THAN)){
30
+ syntax_tree->expr_data_type =BOOLEAN;
31
+ }else if (syntax_tree->node_kind == OPER_NODE) {
32
+ syntax_tree->expr_data_type = INTEGER;
33
+ }
34
+
35
+ // recursively traverse the tree to replace the non-void nodes and validate nodes
36
+ for (int i = 0 ; i < MAX_CHILDREN; ++i) {
37
+ if (syntax_tree->child [i]){
38
+ replaceNonVoid (syntax_tree->child [i],ok);
39
+ }
40
+ }
41
+ // after traversing children and validating nodes we traverse the sibling
42
+ if (syntax_tree->sibling ){
43
+ replaceNonVoid (syntax_tree->sibling ,ok);
44
+ }
45
+
46
+
47
+ // match IF_NODE have Boolean type after it
48
+ if (syntax_tree->node_kind == IF_NODE && syntax_tree->child [0 ]->expr_data_type !=BOOLEAN){
49
+ printf (" error: if should be followed by a Boolean on line %d\n " ,syntax_tree->line_num );
50
+ ok = false ;
51
+ }
52
+ // match REPEAT_NODE have Boolean type after it
53
+ else if (syntax_tree->node_kind == REPEAT_NODE && syntax_tree->child [1 ]->expr_data_type !=BOOLEAN) {
54
+ printf (" error: repeat should be followed by a Boolean on line %d\n " ,syntax_tree->line_num );
55
+ ok = false ;
56
+ }
57
+ // match OPER_NODE have Integer type after and before it
58
+ else if (syntax_tree->node_kind == OPER_NODE){
59
+ if (syntax_tree->child [0 ]->expr_data_type !=INTEGER || syntax_tree->child [1 ]->expr_data_type !=INTEGER) {
60
+ printf (" error: operand should be followed and preceded by Integer on line %d\n " ,syntax_tree->line_num );
61
+ ok = false ;
62
+ }
63
+ }
64
+ // match ASSIGN_NODE have Integer type after it
65
+ else if (syntax_tree->node_kind == ASSIGN_NODE && syntax_tree->child [0 ]->expr_data_type !=INTEGER){
66
+ printf (" error: assign should be followed by an Integer on line %d\n " ,syntax_tree->line_num );
67
+ ok = false ;
68
+ }
69
+ // match WRITE_NODE have Integer type after it
70
+ else if (syntax_tree->node_kind == WRITE_NODE && syntax_tree->child [0 ]->expr_data_type !=INTEGER){
71
+ printf (" error: write should be followed by an Integer on line %d\n " ,syntax_tree->line_num );
72
+ ok = false ;
73
+ }
74
+
75
+ }
76
+
77
+ int getVariableValue (char *name,SymbolTable* symbol_table,int * variables){
78
+ return variables[symbol_table->Find (name)->memloc ];
79
+ }
80
+
81
+ int getValue (TreeNode* syntax_tree,SymbolTable* symbol_table,int * variables){
82
+ if (syntax_tree->node_kind ==NUM_NODE){
83
+ return syntax_tree->num ;
84
+ }else if (syntax_tree->node_kind ==ID_NODE){
85
+ return getVariableValue (syntax_tree->id , symbol_table, variables);
86
+ }
87
+
88
+ int num1 = getValue (syntax_tree->child [0 ], symbol_table, variables);
89
+ int num2 = getValue (syntax_tree->child [1 ], symbol_table, variables);
90
+ TokenType oper = syntax_tree->oper ;
91
+
92
+ switch (oper) {
93
+ case PLUS:
94
+ return num1+num2;
95
+ case MINUS:
96
+ return num1-num2;
97
+ case TIMES:
98
+ return num1*num2;
99
+ case DIVIDE:
100
+ return num1/num2;
101
+ case POWER:
102
+ return (int )pow (num1,num2);
103
+ case EQUAL:
104
+ return num1==num2;
105
+ case LESS_THAN:
106
+ return num1<num2;
107
+ default :
108
+ return -1 ;
109
+ }
110
+ }
111
+
112
+ void RunProgram (TreeNode* syntax_tree,SymbolTable* symbol_table,int * variables){
113
+
114
+ // code generation for the if statement
115
+ if (syntax_tree->node_kind == IF_NODE){
116
+ int cond = getValue (syntax_tree->child [0 ], symbol_table, variables);
117
+ if (cond) {
118
+ RunProgram (syntax_tree->child [1 ], symbol_table, variables);
119
+ }else {
120
+ if (syntax_tree->child [2 ]){
121
+ RunProgram (syntax_tree->child [2 ], symbol_table, variables);
122
+ }
123
+ }
124
+
125
+ // code generation for the repeat statement
126
+ }else if (syntax_tree->node_kind == REPEAT_NODE){
127
+ do {
128
+ RunProgram (syntax_tree->child [0 ], symbol_table, variables);
129
+ } while (!getValue (syntax_tree->child [1 ], symbol_table, variables));
130
+
131
+ // code generation for the assign, read and write statements
132
+ }else if (syntax_tree->node_kind == ASSIGN_NODE){
133
+ int val = getValue (syntax_tree->child [0 ], symbol_table, variables);
134
+ variables[symbol_table->Find (syntax_tree->id )->memloc ] = val;
135
+
136
+ // code generation for the read statement
137
+ }else if (syntax_tree->node_kind == READ_NODE){
138
+ cout<<" Enter " <<syntax_tree->id <<" : " ;
139
+ cin>>variables[symbol_table->Find (syntax_tree->id )->memloc ];
140
+
141
+ // code generation for the write statement
142
+ }else if (syntax_tree->node_kind == WRITE_NODE){
143
+ cout<<" Val: " <<getValue (syntax_tree->child [0 ], symbol_table, variables)<<endl;
144
+ }
145
+
146
+ // traverse the tree in preorder to generate the code
147
+ if (syntax_tree->sibling ){
148
+ RunProgram (syntax_tree->sibling , symbol_table, variables);
149
+ }
150
+ }
151
+
152
+ int main (int argc, char **argv)
153
+ {
154
+ char *input_file_name = argv[1 ];
155
+ if (!input_file_name)
156
+ {
157
+ printf (" error: no input file\n " );
158
+ return 1 ;
159
+ }
160
+ FILE *input_file = fopen (input_file_name, " r" );
161
+ if (!input_file)
162
+ {
163
+ printf (" error: file %s does not exist\n " , input_file_name);
164
+ return 1 ;
165
+ }
166
+ fclose (input_file);
167
+ if (strcmp (input_file_name + strlen (input_file_name) - 2 , " .m" ))
168
+ {
169
+ printf (" error: input file should have .m extension\n " );
170
+ return 1 ;
171
+ }
172
+ CompilerInfo compiler_info (input_file_name, " output.txt" , " debug.txt" );
173
+
174
+ TreeNode* syntax_tree = Parse (&compiler_info);
175
+ SymbolTable symbol_table;
176
+ getSymbolTable (syntax_tree,symbol_table);
177
+ bool ok = true ;
178
+ replaceNonVoid (syntax_tree,ok);
179
+
180
+ // arr to store the values of the variables in the symbol table
181
+ int * variables=new int [symbol_table.num_vars ];
182
+ memset (variables, 0 , sizeof (int )*symbol_table.num_vars );
183
+
184
+ if (ok){
185
+ RunProgram (syntax_tree, &symbol_table, variables);
186
+ }
187
+ return 0 ;
188
+ }
0 commit comments