r/o
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
5
#include "parser.h"
6
7
/* ast_expr_t */
8
9
ast_expr_t *ast_string_alloc(char const *value) {
10
ast_expr_t *expr = malloc(sizeof(*expr));
11
memset(expr, 0, sizeof(*expr));
12
expr->type = EXPR_STRING;
13
expr->string = strdup(value);
14
15
int len = strlen(expr->string);
16
if (len > 0 && expr->string[len - 1] == '"') {
17
expr->string[len - 1] = 0;
18
}
19
20
return expr;
21
}
22
23
ast_expr_t *ast_binary_alloc(char op, ast_expr_t *a, ast_expr_t *b) {
24
ast_expr_t *expr = malloc(sizeof(*expr));
25
memset(expr, 0, sizeof(*expr));
26
expr->type = EXPR_BINARY;
27
expr->binary.op = op;
28
expr->binary.a = a;
29
expr->binary.b = b;
30
31
return expr;
32
}
33
34
ast_expr_t *ast_integer_alloc(int i) {
35
ast_expr_t *expr = malloc(sizeof(*expr));
36
memset(expr, 0, sizeof(*expr));
37
expr->type = EXPR_INTEGER;
38
expr->integer = i;
39
40
return expr;
41
}
42
43
static int get_precedence(char op) {
44
switch (op) {
45
case '+': return 1;
46
case '-': return 1;
47
case '*': return 2;
48
case '/': return 2;
49
default: return 0;
50
}
51
}
52
53
static char get_associativity(char op) {
54
switch (op) {
55
case '+': return 'L';
56
case '-': return 'L';
57
case '*': return 'L';
58
case '/': return 'L';
59
default: return 'N';
60
}
61
}
62
63
static void print_subexpr(ast_expr_t *outer, ast_expr_t *inner, char assoc) {
64
int outerp = get_precedence(outer->binary.op);
65
int innerp = inner->type == EXPR_BINARY ? get_precedence(inner->binary.op) : 0;
66
67
if (outerp > innerp && innerp != 0) {
68
printf("(");
69
ast_expr_pp(inner);
70
printf(")");
71
} else if (outerp != innerp) {
72
ast_expr_pp(inner);
73
} else {
74
char outera = get_associativity(outer->binary.op);
75
char innera = inner->type == EXPR_BINARY ? get_precedence(inner->binary.op) : 'N';
76
if (outera == 'N' || innera == 'N') {
77
ast_expr_pp(inner);
78
} else if (outera != assoc) {
79
printf("(");
80
ast_expr_pp(inner);
81
printf(")");
82
} else {
83
ast_expr_pp(inner);
84
}
85
}
86
}
87
88
void ast_expr_pp(ast_expr_t *expr) {
89
switch (expr->type) {
90
case EXPR_STRING:
91
printf("\"%s\"", expr->string);
92
break;
93
94
case EXPR_BINARY:
95
print_subexpr(expr, expr->binary.a, 'L');
96
printf(" %c ", expr->binary.op);
97
print_subexpr(expr, expr->binary.b, 'R');
98
break;
99
100
case EXPR_INTEGER:
101
printf("%d", expr->integer);
102
break;
103
104
default:
105
fprintf(stderr, "UNKNOWN EXPR TYPE %d\n", expr->type);
106
}
107
}
108
109
void ast_expr_free(ast_expr_t *expr) {
110
switch (expr->type) {
111
case EXPR_STRING:
112
free(expr->string);
113
break;
114
115
case EXPR_BINARY:
116
ast_expr_free(expr->binary.a);
117
ast_expr_free(expr->binary.b);
118
break;
119
120
case EXPR_INTEGER:
121
/* empty */
122
break;
123
124
default:
125
fprintf(stderr, "UNKNOWN EXPR TYPE %d\n", expr->type);
126
}
127
free(expr);
128
}
129
130
void ast_expr_free_list(ast_expr_t *expr) {
131
while (expr) {
132
ast_expr_t *next = expr->next;
133
ast_expr_free(expr);
134
expr = next;
135
}
136
}
137
138
/* ast_comment_t */
139
140
ast_comment_t *ast_comment_alloc(char const *value, int is_rem) {
141
ast_comment_t *comment = malloc(sizeof(*comment));
142
memset(comment, 0, sizeof(*comment));
143
comment->value = strdup(value);
144
comment->is_rem = is_rem;
145
return comment;
146
}
147
148
void ast_comment_free(ast_comment_t *comment) {
149
free(comment->value);
150
free(comment);
151
}
152
153
/* ast_token_t */
154
155
ast_token_t *ast_token_alloc(char const *value) {
156
ast_token_t *token = malloc(sizeof(*token));
157
memset(token, 0, sizeof(*token));
158
token->value = strdup(value);
159
return token;
160
}
161
162
void ast_token_free(ast_token_t *token) {
163
free(token->value);
164
free(token);
165
}
166
167
/* ast_stmt_t */
168
169
ast_stmt_t *ast_stmt_alloc(ast_stmt_type_t type) {
170
ast_stmt_t *stmt = malloc(sizeof(*stmt));
171
memset(stmt, 0, sizeof(*stmt));
172
stmt->type = type;
173
return stmt;
174
}
175
176
void ast_stmt_pp(ast_stmt_t *stmt) {
177
switch (stmt->type) {
178
case STMT_CALL:
179
printf("%s", stmt->call.target->value);
180
181
ast_expr_t *args = stmt->call.args;
182
while (args) {
183
printf(" ");
184
ast_expr_pp(args);
185
if (args->next) {
186
printf("%c", args->nexttype);
187
}
188
args = args->next;
189
}
190
191
printf("\n");
192
break;
193
194
case STMT_COMMENT:
195
printf("%s%s\n", stmt->comment->is_rem ? "REM" : "'", stmt->comment->value);
196
break;
197
198
default:
199
fprintf(stderr, "UNKNOWN STMT TYPE %d\n", stmt->type);
200
break;
201
}
202
}
203
204
void ast_stmt_free(ast_stmt_t *stmt) {
205
switch (stmt->type) {
206
case STMT_CALL:
207
ast_token_free(stmt->call.target);
208
ast_expr_free_list(stmt->call.args);
209
break;
210
211
case STMT_COMMENT:
212
ast_comment_free(stmt->comment);
213
break;
214
215
default:
216
fprintf(stderr, "UNKNOWN STMT TYPE %d\n", stmt->type);
217
break;
218
}
219
free(stmt);
220
}
221
222
void ast_stmt_free_list(ast_stmt_t *stmt) {
223
while (stmt) {
224
ast_stmt_t *next = stmt->next;
225
ast_stmt_free(stmt);
226
stmt = next;
227
}
228
}
229
230
/* ast_t */
231
232
ast_t *ast_alloc(void) {
233
ast_t *ast = malloc(sizeof(*ast));
234
memset(ast, 0, sizeof(*ast));
235
return ast;
236
}
237
238
void ast_append_stmt(ast_t *ast, ast_stmt_t *stmt) {
239
ast_stmt_t **writer = &ast->stmts;
240
while (*writer) {
241
writer = &(*writer)->next;
242
}
243
*writer = stmt;
244
}
245
246
void ast_pp(ast_t *ast) {
247
ast_stmt_t *stmt = ast->stmts;
248
while (stmt) {
249
ast_stmt_pp(stmt);
250
stmt = stmt->next;
251
}
252
}
253
254
void ast_free(ast_t *ast) {
255
ast_stmt_free_list(ast->stmts);
256
free(ast);
257
}
258
259
/* flex/bison */
260
261
int yywrap(void) {
262
return 1;
263
}
264
265
void yyerror(ast_t *ast, char const *s) {
266
fprintf(stderr, "parse error: %s\n", s);
267
}
268
269
int parser_test(void) {
270
ast_t *ast = ast_alloc();
271
272
begin_scan(
273
"PRINT \"Hello\"; \"there\", \"pals\" \"!\"\n"
274
"REM 1 + 2 * 3\n"
275
"PRINT 1 + 2 * 3\n"
276
277
"REM (1 + 2) * 3\n"
278
"PRINT (1 + 2) * 3\n"
279
280
"REM 1 * (2 + 3)\n"
281
"PRINT 1 * (2 + 3)\n"
282
283
"REM (1 * 2) * (3 * 4) + 1 + (2 + 3)\n"
284
"PRINT (1 * 2) * (3 * 4) + 1 + (2 + 3)\n"
285
286
"GOTO\n"
287
"\n"
288
"REM Okay, sure thing.\n"
289
"'I guess.\n");
290
yyparse(ast);
291
finish_scan();
292
293
ast_pp(ast);
294
295
free(ast);
296
297
return 0;
298
}
299
300
/* vim: set sw=4 et: */
301