Skip to content

Commit b26b7e2

Browse files
build complete complier
1 parent 4bf51b6 commit b26b7e2

File tree

6 files changed

+1065
-0
lines changed

6 files changed

+1065
-0
lines changed

complete/debug.txt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Start StmtSeq
2+
Start Stmt
3+
Start ReadStmt
4+
Start Match
5+
[1] x (ID)
6+
Start Match
7+
[1] ; (SemiColon)
8+
End ReadStmt
9+
End Stmt
10+
Start Match
11+
[2] write (Write)
12+
Start Stmt
13+
Start WriteStmt
14+
Start Match
15+
[2] x (ID)
16+
Start Expr
17+
Start MathExpr
18+
Start Term
19+
Start Factor
20+
Start NewExpr
21+
Start Match
22+
[2] (EndFile)
23+
End NewExpr
24+
End Factor
25+
End Term
26+
End MathExpr
27+
End Expr
28+
End WriteStmt
29+
End Stmt
30+
End StmtSeq

complete/input.m

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{ Sample program
2+
in TINY language
3+
compute factorial
4+
}
5+
6+
read x; {input an integer}
7+
if 0<x then {compute only if x>=1}
8+
fact:=1;
9+
repeat
10+
fact := fact * x;
11+
x:=x-1
12+
until x=0;
13+
write fact {output factorial}
14+
end

complete/output.txt

Whitespace-only changes.

complete/tiny_compiler.cpp

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
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+
}

complete/tiny_compiler.exe

66.9 KB
Binary file not shown.

0 commit comments

Comments
 (0)