-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPTemp2.c
206 lines (158 loc) · 6.47 KB
/
PTemp2.c
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
#include "PTemp.h"
// Global Variables
symbol symbol_Table[MAX_SYMBOL_TABLE_SIZE]; // Creates the symbol table as a global array
lexeme *lex_Array;
instruction VM_Instructions[MAX_SYMBOL_TABLE_SIZE];
int symbol_Table_Size = 0;
int lex_Array_Size = 0;
int VM_Instruct_Size = 0;
int prodecureCount = 0;
int token = -1; // Token is used to get the next token in the token list
// HELPER FUNCTIONS
void Emit(int OP_Code, int L, int M) {
instruction newInstruction; // Creates a new instruction of type instructon
newInstruction.opcode = OP_Code; // Assigns the given opcode to the new opcode
newInstruction.l = L; // Assigns the given l to the new l
newInstruction.m = M; // Assigns the given m to the new m
VM_Instructions[VM_Instruct_Size++] = newInstruction; // Adds the new Instruction to Virtual Machine Instructions and increments VM Size
}
void Add_To_SymTable(int kind, char *name, int number, int level, int address, int mark, int param) {
symbol newSybol; // Creates a new Sybol
newSybol.kind = kind;
strcpy(newSybol.name, name);
newSybol.val = number;
newSybol.level = level;
newSybol.addr = address;
newSybol.mark = mark;
newSybol.param = param;
symbol_Table[symbol_Table_Size++] = newSybol; // Adds the new symbol to the symbol table and increments the symbol table size
}
int Get_Token() {
int token = lex_Array[lex_Array_Size++].tokenType; // Retrieves the token from the lex Array. Increments the lex_Array_Size also.
return token; // Returns token
}
int Find_Procedure(int prodecureIndex) {
for(int i = 0; i < symbol_Table_Size; i++) {
if(symbol_Table[i].kind == 3 && symbol_Table[i].val == prodecureIndex) return i;
}
return -1;
}
void Mark(int count) {
for(int i = symbol_Table_Size; i != -1; i--) {
if(symbol_Table[i].mark == 0) {
symbol_Table[i].mark = 1;
count--;
} else {
continue;
}
}
}
int Symbol_Table_Check(char *checkName, int checkLevel) {
for(int i = 0; i < symbol_Table_Size; i++) {
// Checks the level, name, and mark status of each entry in the symbol table. If the requirements are met, the index is returned.
if(symbol_Table[i].level == checkLevel && strcmp(symbol_Table[i].name, checkName) == 0 && symbol_Table[i].mark == 0) return i;
}
return -1;
}
int Const_Declaration(int lex_Level) {
int num_Constants = 0;
token = Get_Token(); // Gets the next token
if(token == 28) { // If the token is a Constant
do {
num_Constants++; // Increases the number of constants
token = Get_Token(); // Gets the next token
if(token != 2) { // Checks to see if there is an identifier after the constant, if not then an error is thrown.
printf("Error: const, var, and read keywords must be followed by identifier\n");
exit(-1);
}
if(Symbol_Table_Check(token, lex_Level) != -1){
printf("symbol has already been declared\n");
exit(-1);
}
int name_index = lex_Array_Size - 1;
token = Get_Token();
if(token != 9){
printf("constants must be assigned with =\n");
exit(-1);
}
token = Get_Token();
if(toke != 3){
printf("constants must be assigned an integer value\n");
exit(-1);
}
Add_To_SymTable(1, lexeme_Array[name_index].lexeme, num_Constants, lex_Level, 0, 0, 0);
token = Get_Token();
} while (token == 17);
if(token != 18){
printf("constant and variable declarations must be followed by a semicolon\n");
exit(-1);
}
token = Get_Token();
}
return -1;
}
int Variable_Declaration(int lex_Level, int param) {
int numVars;
token = Get_Token();
if(param == 1)
numVars = 1;
else
numVars = 0;
if(token == 29) {
do{
numVars++;
token = Get_Token();
if(token != 2){
printf("Error: const, var, and read keywords must be followed by identifier\n");
exit(-1);
}
if(Symbol_Table_Check(token, lex_Level) != -1)
{
printf("symbol has already been declared\n");
exit(-1);
}
int name_index = lex_Array_Size - 1;
Add_To_SymTable(2, lexeme_Array[name_index].lexeme, 0, lex_Level, numVars + 3, 0, 0);
token = Get_Token();
} while(token == 17);
if(token != 18) {
printf("constant and variable declarations must be followed by a semicolon\n");
exit(-1);
}
token = Get_Token();
return numVars;
}
}
void Block(int lexLevel, int param, int prodedureIndex) {
int c = Const_Declaration(lexLevel);
int v = Variable_Declaration(lexLevel);
int p = Procedure_Declaration(lexLevel);
symbol_Table[prodedureIndex].addr = VM_Instruct_Size; // COULD BE WRONG
emit(6, 0, 4 + v); // Emits INC, Increases by 4 plus the number of variables
Statement(lexLevel);
Mark(c + v + p);
}
void Program() {
int num_Procedures = 1;
Emit(7, 0, 10); // Create a filler JMP, the M value is not important right now
for(int i = 0; i < sizeof(lex_Array) / sizeof(lex_Array[0]); i++) { // Loops through the entire Lex_Array
if(lex_Array[i].tokenType == 30) { // Checks to see if the tokentype is a Procedure
num_Procedures++;
Emit(7, 0, 10); // Another filler JMP, with a random M
}
}
Add_To_SymTable(3, "main", 0, 0, 0, 0, 0); // Adds the MAIN function to the symbol Table
prodecureCount++;
//Block(0, 0, 0);
if(token != 19) {
printf("Error: program must end with period\n");
exit(-1);
}
for(int i = 0; i < num_Procedures; i++) {
VM_Instructions[i].m = symbol_Table[Find_Procedure(i)].addr;
}
Emit(9, 0, 3); // HALT
}
void ParserCodegenMain(lexeme *Lex_Token_Array, int A_Directive) {
lex_Array = Lex_Token_Array; // Copies the Lexeme Token Array into the Lex Array
}