include stdio include ctype include string include stdlib define OVERL

 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
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define OVERLOW 1000000
struct stack {
char value[8];
stack *prev;
};
// Чтение очередной инструкции из файла
stack * read_next_instruction (FILE *f) {
if ( feof (f))
return NULL;
char buf[8];
stack * instruction = new stack;
instruction->prev = NULL;
for ( fscanf (f, "%s ", buf); *buf != ';'; fscanf (f, "%s ", buf)) {
stack * lex = new stack;
lex->prev = instruction;
strcpy (lex->value, buf);
instruction = lex;
}
return instruction;
}
// Загрузка значения переменной
int load (int vars[], char var) {
int index = toupper (var) - 'A'; // Регистр имен переменных игнорируется
if (vars[index] >= OVERLOW) {
printf ("Ошибка: переменная %c не инициализирована!\n", var);
exit (1);
}
return vars[index];
}
// Сохранение значения переменной
void store (int vars[], char var, int val) {
if (abs(val) >= OVERLOW) {
printf ("Ошибка: переполнение в переменной %c!\n", var);
exit (1);
}
int index = toupper (var) - 'A';
vars[index] = val;
}
int main ( int argc, char **argv) {
FILE *source = fopen (argv[1],"rt");
int * variables = new int[26]; // Значения переменных
for (int i = 0; i < 26; i++)
variables[i] = OVERLOW; // Считать все переменные неинициализированными
stack * instruction = NULL;
while (instruction = read_next_instruction (source)) { // Пока инструкции не кончились
int res = 0; // Текущее значение правой части
char op = 0; // Знак операции
stack * unused; // Элемент, готовый к удалению
for (; instruction->prev != NULL; unused = instruction, instruction = instruction->prev, delete unused) {
char *lex = instruction->value;
if (isalpha (*lex)) // Если переменная
switch (op) {
// Текущее значение правой части загружается из переменной
case 0: res = load (variables, *lex); break;
// Текущее значение правой части вычисляется, в зависимости от знака операции
case '+': res += load (variables, *lex); break;
case '-': res = load (variables, *lex) -res; break;
case '*': res *= load (variables, *lex); break;
// Текущее значение правой части сохраняется в переменной
case ':': store (variables, *lex, res); break;
}
else
if (isdigit (*lex)) // Если константа (требуется для инициализации переменных)
res = atoi (instruction->value); // Текущее значение правой части равно константе
else // Если знак операции
op = *lex;
}
delete instruction;
}
fclose (source);
char * output_name = new char[256];
strcpy (output_name, argv[1]);
strcat (output_name, ".out");
FILE *output = fopen (output_name,"wt");
for (int i = 0; i < 26; i++)
if (variables[i] < OVERLOW)
fprintf (output,"%c = %d\n", i+'A', variables[i]);
fclose (output);
return 0;
}