This repository was archived by the owner on Jan 6, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinterpreter.c
More file actions
399 lines (325 loc) · 12 KB
/
interpreter.c
File metadata and controls
399 lines (325 loc) · 12 KB
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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
// simple-basic-script-interpreter
// (c) 2019 Renee Waverly Sonntag
// Licensed under Apache 2.0
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define NUMBER_OF_VARIABLES 50
#define VARIABLE_NAME_LENGTH 100+1
// Here's the place where the variables will exist when they're defined.
// Dynamic memory allocation would complicate things, so there's a maximum number of variables, and a maximum
// length for variable names.
char variableNames[NUMBER_OF_VARIABLES][VARIABLE_NAME_LENGTH];
int variableValues[NUMBER_OF_VARIABLES];
int numberOfVariables = 0;
// Function Prototypes
int getIndexFromVariableName(char*);
int resolveStringToValue(char*);
// loop pointers (not c pointers, stream pointers)
long int doStart;
/*
* This program takes one argument, with an optional flag argument.
* Opens a file, and treats lines within as "basic" code to execute.
* Will exit with error upon fault in the lines of code.
*
* flag of "v", after the filename, will enter "verbose" mode.
* This prints all lines of code as they are processed.
*/
int main(int argc, char** argv) {
char* fileName = argv[1];
char* flags = argv[2];
char lineOfCode[256] = "";
// Open the file.
FILE* sourceFile = fopen(fileName, "r");
// check for error
if (sourceFile == NULL) {
printf("[ERROR] Source File Not Provided.\n");
return 1;
}
// Loop, getting each line in the file and processing it.
while(fgets(lineOfCode, 256, sourceFile) != NULL) {
// Print the line of code for debugging purposes!
if (flags != NULL) {
if (flags[0] == 'v') {
printf("\tLine of Code: %s", lineOfCode);
}
}
// Get first part of string, ending at the first space character.
// This is the "keyword", or the thing that tells us what the line wants to do
char* keyword = strtok(lineOfCode, " \r\n");
if (keyword == NULL) continue; // safety against emtpy lines
// Check the keyword against our known commands
//-------------------------------
// #
//-------------------------------
if (strcmp(keyword, "#") == 0) {
// Do nothing, it's a comment
}
//-------------------------------
// LET
//-------------------------------
else if (strcmp(keyword, "LET") == 0) {
// It's a variable! Let's Figure out how to make a variable on the fly.
// get the variable name
char* vName = strtok(NULL, " \r\n");
// copy the variable name into the variable name array
strcpy(variableNames[numberOfVariables], vName);
// check for a value after it
char* vValue = strtok(NULL, " \r\n");
if (vValue != NULL) {
// Convert the string to an int.
int iValue = atoi(vValue);
// Place the int in the variable value array.
variableValues[numberOfVariables] = iValue;
} else {
// if nothing is provided, default to 0
// that way there's no garbage.
variableValues[numberOfVariables] = 0;
}
// increment the number of variables
numberOfVariables++;
}
//-------------------------------
// PRINT
//-------------------------------
else if (strcmp(keyword, "PRINT") == 0) {
// It's a print line! Because this language has integers only,
// we can use a very simple block of code.
// get the variable name
char* vName = strtok(NULL, " \r\n");
// get variable index
int i = getIndexFromVariableName(vName);
// Now we can print!
printf("%i\n", variableValues[i]);
}
//-------------------------------
// SET
//-------------------------------
else if (strcmp(keyword, "SET") == 0) {
// get the variable name
char* vName = strtok(NULL, " \r\n");
// get variable index
int i = getIndexFromVariableName(vName);
// Now we can get the value
char* vValue = strtok(NULL, " \r\n");
int iValue = 0;
if (vValue != NULL) {
// get the value, whether it's an integer or a variable name
iValue = resolveStringToValue(vValue);
// Finally, we can set the value!
variableValues[i] = iValue;
} else {
printf("[WARNING] Missing argument to SET\n");
}
}
//-------------------------------
// ADD
//-------------------------------
else if (strcmp(keyword, "ADD") == 0) {
// It's time to do addition!
// get the variable name
char* vName = strtok(NULL, " \r\n");
// get variable index
int i = getIndexFromVariableName(vName);
// Now we can get the value
char* vValue = strtok(NULL, " \r\n");
int iValue = 0;
if (vValue != NULL) {
// get the value, whether it's an integer or a variable name
iValue = resolveStringToValue(vValue);
// Finally, we can add!
variableValues[i] += iValue;
} else {
printf("[WARNING] Missing argument to ADD\n");
}
}
//-------------------------------
// SUB
// (copy paste of ADD, but the "Finally" line does subtraction)
//-------------------------------
else if (strcmp(keyword, "SUB") == 0) {
// It's time to do subtraction!
// get the variable name
char* vName = strtok(NULL, " \r\n");
// get variable index
int i = getIndexFromVariableName(vName);
// Now we can get the value
char* vValue = strtok(NULL, " \r\n");
int iValue = 0;
if (vValue != NULL) {
// get the value, whether it's an integer or a variable name
iValue = resolveStringToValue(vValue);
// Finally, we can subtract!
variableValues[i] -= iValue;
} else {
printf("[WARNING] Missing argument to SUB\n");
}
}
//-------------------------------
// MUL
// (copy paste of ADD, but the "Finally" line does multiplication)
//-------------------------------
else if (strcmp(keyword, "MUL") == 0) {
// It's time to do subtraction!
// get the variable name
char* vName = strtok(NULL, " \r\n");
// get variable index
int i = getIndexFromVariableName(vName);
// Now we can get the value
char* vValue = strtok(NULL, " \r\n");
int iValue = 0;
if (vValue != NULL) {
// get the value, whether it's an integer or a variable name
iValue = resolveStringToValue(vValue);
// Finally, we can multiply!
variableValues[i] *= iValue;
} else {
printf("[WARNING] Missing argument to MUL\n");
}
}
//-------------------------------
// DIV
// (copy paste of ADD, but the "Finally" line does division)
//-------------------------------
else if (strcmp(keyword, "DIV") == 0) {
// It's time to do subtraction!
// get the variable name
char* vName = strtok(NULL, " \r\n");
// get variable index
int i = getIndexFromVariableName(vName);
// Now we can get the value
char* vValue = strtok(NULL, " \r\n");
int iValue = 0;
if (vValue != NULL) {
// get the value, whether it's an integer or a variable name
iValue = resolveStringToValue(vValue);
// Finally, we can divide!
variableValues[i] /= iValue;
} else {
printf("[WARNING] Missing argument to DIV\n");
}
}
//-------------------------------
// MOD
// (copy paste of ADD, but the "Finally" line does modulus)
//-------------------------------
else if (strcmp(keyword, "MOD") == 0) {
// It's time to do subtraction!
// get the variable name
char* vName = strtok(NULL, " \r\n");
// get variable index
int i = getIndexFromVariableName(vName);
// Now we can get the value
char* vValue = strtok(NULL, " \r\n");
int iValue = 0;
if (vValue != NULL) {
// get the value, whether it's an integer or a variable name
iValue = resolveStringToValue(vValue);
// Finally, we can do modulus!
variableValues[i] %= iValue;
} else {
printf("[WARNING] Missing argument to MOD\n");
}
}
//-------------------------------
// INPUT
//-------------------------------
else if (strcmp(keyword, "INPUT") == 0) {
// It's time to use the standard input
// get the variable name
char* vName = strtok(NULL, " \r\n");
// get variable index
int i = getIndexFromVariableName(vName);
// Display prompt
printf("? ");
// Read from stdin
char numbery[100];
fgets(numbery, 100, stdin);
// convert to an integer
int iValue = atoi(numbery);
// place value at variable
variableValues[i] = iValue;
}
//-------------------------------
// DO
//-------------------------------
else if (strcmp(keyword, "DO") == 0) {
// get the address of the current line, save it in memory
doStart = ftell(sourceFile);
// we now know the start of the do-while loop
}
//-------------------------------
// WHILE_NEQ
//-------------------------------
else if (strcmp(keyword, "WHILE_NEQ") == 0) {
// get the variable name
char* vName = strtok(NULL, " \r\n");
// get variable index
int i = getIndexFromVariableName(vName);
// Now we can get the value
char* vValue = strtok(NULL, " \r\n");
int iValue = 0;
if (vValue != NULL) {
// get the value, whether it's an integer or a variable name
iValue = resolveStringToValue(vValue);
// Finally, we can do the comparison!
if (variableValues[i] == iValue) {
continue;
}
} else {
printf("[ERROR] Missing argument to WHILE_NEQ\n");
return 1;
}
// go to the start of the loop, by adjusting the stream pointer.
fseek(sourceFile, doStart, SEEK_SET);
}
//-------------------------------
// (fallthrough)
//-------------------------------
else {
printf("[WARNING] The keyword is not valid: %s\n", keyword);
}
}
}
/*
* Returns the index of the string containing a variable name.
* Program will terminate with an error if the variable name does not exist.
* This was mainly done to simplify error checking, as this is purely an
* example of a simple interpreter.
*/
int getIndexFromVariableName(char* vName) {
// figure out which index corresponds to the variable name, if at all.
int i;
for (i = 0; i < numberOfVariables; i++) {
if (strcmp(vName, variableNames[i]) == 0) {
// This is the one, break out.
break;
}
}
// check if i isn't valid
if (i == numberOfVariables) {
printf("[ERROR] Variable to index does not exist: %s\n", vName);
exit(1);
}
return i;
}
/*
* Returns the numeric value associated with the input string.
* If the string starts with a digit, it is presumed an integer literal.
* All other strings are interpreted as variable names.
* This can terminate the program, as it calls getIndexFromVariableName.
*/
int resolveStringToValue(char* sValue) {
// Is it a variable name or an integer?
// pattern matching, if the first character is a number, it's an integer.
if (sValue[0] >= '0' && sValue[0] <= '9') {
// The string is an integer
// Convert the string to an int.
return atoi(sValue);
} else {
// The string is a variable name.
// get index of second variable
int j = getIndexFromVariableName(sValue);
return variableValues[j];
}
}