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
|
#include "all.h"
#include "ivec.h"
#include "node_vec.h"
#include <stdint.h>
#include <stdlib.h>
static inline lex_tok_e peek(parser_t *p) {
return iv_get(&p->lx->tokens, p->pos);
}
static inline lex_tok_e advance(parser_t *p) {
return iv_get(&p->lx->tokens, p->pos++);
}
static ast_node_t *new_node(ast_type_e type, int val) {
ast_node_t *n = malloc(sizeof(ast_node_t));
n->type = type;
n->val = val;
n->next = NULL;
n->children = (node_vec){0};
return n;
}
static ast_node_t *parse_block(parser_t *p);
static ast_node_t *parse_single(parser_t *p) {
lex_tok_e t = peek(p);
switch (t) {
case LEX_PINC: {
int count = 0;
while (peek(p) == LEX_PINC) {
advance(p);
count++;
}
return new_node(AST_INC, count);
}
case LEX_PDEC: {
int count = 0;
while (peek(p) == LEX_PDEC) {
advance(p);
count++;
}
return new_node(AST_DEC, count);
}
case LEX_VINC: {
int count = 0;
while (peek(p) == LEX_VINC) {
advance(p);
count++;
}
return new_node(AST_PTR_INC, count);
}
case LEX_VDEC: {
int count = 0;
while (peek(p) == LEX_VDEC) {
advance(p);
count++;
}
return new_node(AST_PTR_DEC, count);
}
case LEX_OUT:
advance(p);
return new_node(AST_OUT, 1);
case LEX_IN:
advance(p);
return new_node(AST_IN, 1);
case LEX_LB:
advance(p); // consume '['
return parse_block(p);
case LEX_RB:
return NULL;
case LEX_EOF:
return NULL;
default:
advance(p);
return NULL;
}
}
static ast_node_t *parse_block(parser_t *p) {
ast_node_t *loop = new_node(AST_LOOP, 1);
while (1) {
lex_tok_e t = peek(p);
if (t == LEX_EOF) {
break;
}
if (t == LEX_RB) {
advance(p); // consume ']'
break;
}
ast_node_t *child = parse_single(p);
if (child) {
node_vec_push(&loop->children, child);
}
}
return loop;
}
parser_t parser_init(lexer_t *lx) { return (parser_t){.lx = lx, .pos = 0}; }
ast_node_t *parse_program(parser_t *p) {
ast_node_t *head = NULL;
ast_node_t *tail = NULL;
while (peek(p) != LEX_EOF) {
ast_node_t *node = parse_single(p);
if (!node)
continue;
if (!head) {
head = tail = node;
} else {
tail->next = node;
tail = node;
}
}
return head;
}
void ast_free(ast_node_t *node) {
if (!node)
return;
if (node->next)
ast_free(node->next);
for (size_t i = 0; i < node->children.len; i++) {
ast_free(node->children._data[i]);
}
node_vec_free(&node->children);
free(node);
}
|