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
|
#include "types.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
static char next_char(FILE* file) {
char c;
if (fread(&c, 1, 1, file) != 1) {
return EOF;
} else {
return c;
}
}
static Symbol next_symbol(FILE* file) {
char c = next_char(file);
retest:
switch (c) {
case '<':
return MoveLeft;
case '>':
return MoveRight;
case '+':
return Increment;
case '-':
return Decrement;
case '[':
return StartLoop;
case ']':
return EndLoop;
case '.':
return PutChar;
case ',':
return GetChar;
case '*':
return Allocate;
case '!':
return Free;
case '(':
return EnterTape;
case ')':
return LeaveTape;
case '`':
return PutString;
case '~':
return GetString;
case '%':
return Clear;
case '\n':
case '\t':
case ' ':
while(c = next_char(file), c == '\n' || c == '\t' || c == ' ');
goto retest;
case '/':
while(c = next_char(file), c != '\n' && c != EOF);
goto retest;
case EOF:
return Eof;
default:
c = next_char(file);
goto retest;
}
}
void program_init(Program* program, FILE* file) {
uint32_t capacity = 8;
program->data = malloc(capacity * sizeof(struct instruction));
program->len = 0;
program->index = 0;
Stack stack;
stack_init(&stack, 8);
Symbol s;
while(true) {
s = next_symbol(file);
if (program->len == capacity) {
capacity *= 2;
program->data = realloc(program->data, capacity * sizeof(struct instruction));
}
program->data[program->len].s = s;
program->data[program->len].j = 0;
if (s == StartLoop) {
stack_pushi(&stack, program->len);
} else if (s == EndLoop) {
uint32_t i = stack_popi(&stack);
program->data[program->len].j = i;
if (i != 0 || program->data[i].j == 0) {
program->data[i].j = program->len;
}
}
program->len++;
if (s == Eof) break;
}
stack_free(&stack);
fclose(file);
}
void program_get(Program* program, Symbol* symbol) {
if (program->index >= program->len) {
*symbol = Eof;
return;
}
*symbol = program->data[program->index].s;
}
uint32_t program_get_jump(Program* program) {
if (program->index >= program->len) {
return 0;
}
return program->data[program->index].j;
}
void program_next(Program* program) {
program->index++;
}
void program_seek(Program* program, uint32_t index) {
program->index = index;
}
void program_free(Program* program) {
free(program->data);
}
|