-
Notifications
You must be signed in to change notification settings - Fork 0
/
canon.c
90 lines (78 loc) · 1.5 KB
/
canon.c
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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ast.h"
static void canon_decl(struct decl *);
static void canon_stmt(struct stmt *);
static void canon_expr(struct expr *);
static struct prog *prog;
void ast_canon(struct prog *p, struct config *cfg)
{
prog = p;
canon_decl(prog->ast);
}
void canon_decl(struct decl *d)
{
if (!d) {
return;
}
canon_expr(d->value);
canon_stmt(d->code);
canon_decl(d->next);
if (!d->value) {
char *name;
switch (d->type->kind) {
case TYPE_INT:
d->value = expr_make(EXPR_INT, NULL, NULL, NULL, 0);
break;
case TYPE_CHAR:
d->value = expr_make(EXPR_CHAR, NULL, NULL, NULL, 0);
break;
case TYPE_BOOLEAN:
d->value = expr_make(EXPR_BOOLEAN, NULL, NULL, NULL, 0);
break;
case TYPE_STRING:
name = malloc(3);
strcpy(name, "\"\"");
d->value = expr_make(EXPR_STRING, NULL, NULL, name, 0);
prog_add_string(prog, "\"\"");
break;
default:
break;
}
}
}
#define WRAP(body) do { \
if (!body || (body->kind != STMT_BLOCK)) { \
body = stmt_make(STMT_BLOCK, NULL, NULL, body, NULL); \
} } while (0)
void canon_stmt(struct stmt *s)
{
if (!s) {
return;
}
canon_decl(s->decl);
canon_expr(s->expr);
canon_stmt(s->body);
canon_stmt(s->ebody);
canon_stmt(s->next);
switch (s->kind) {
case STMT_WHILE:
WRAP(s->body);
break;
case STMT_IF_ELSE:
WRAP(s->body);
WRAP(s->ebody);
break;
default:
break;
}
}
void canon_expr(struct expr *e)
{
if (!e) {
return;
}
canon_expr(e->left);
canon_expr(e->right);
}