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
|
typedef struct {
Location where;
Identifier var;
bool is_const;
bool has_expr;
} Declaration;
arr_declaration(Declarations, Declaration, decls_)
typedef enum {
STMT_DECLS
} StatementKind;
typedef struct {
StatementKind kind;
Location where;
union {
Declarations decls;
};
} Statement;
arr_declaration(Statements, Statement, stmts_)
typedef struct {
Statements stmts;
} ParsedFile;
/* TODO: Add newline tokens back in; give tokens pointer to text */
static bool parse_decls(Declarations *ds, Tokenizer *t) {
decls_create(ds);
while (1) {
Declaration decl = {0};
if (t->token->kind != TOKEN_IDENT) {
tokr_err(t, "Cannot declare non-identifier.");
return false;
}
decl.where = t->token->where;
decl.var = t->token->ident;
t->token++;
if (!token_is_kw(t->token, KW_COLON)) {
tokr_err(t, "Expected ':' in declaration.");
return false;
}
/* TODO: type */
t->token++;
if (token_is_kw(t->token, KW_SEMICOLON)) {
} else if (token_is_kw(t->token, KW_EQ)) {
t->token++;
decl.has_expr = true;
} else if (token_is_kw(t->token, KW_MINUS)) {
t->token++;
decl.has_expr = true;
decl.is_const = true;
}
decls_add(ds, &decl);
if (token_is_kw(t->token, KW_SEMICOLON)) {
t->token++;
break;
}
if (!token_is_kw(t->token, KW_COMMA)) {
tokr_err(t, "Expected ';' or ',' to finish or continue declaration.");
return false;
}
t->token++; /* move past comma */
}
return true;
}
static bool parse_stmt(Statement *s, Tokenizer *t) {
if (token_is_kw(t->token + 1, KW_COLON)) {
return parse_decls(&s->decls, t);
} else {
tokr_err(t, "Unreocgnized statement.");
return false;
}
}
static bool parse_file(ParsedFile *f, Tokenizer *t) {
stmts_create(&f->stmts);
bool ret = true;
while (t->token->kind != TOKEN_EOF) {
Statement stmt = {0};
if (!parse_stmt(&stmt, t))
ret = false;
stmts_add(&f->stmts, &stmt);
}
return ret;
}
static void decl_fprint(FILE *out, Declaration *d) {
fprintf(out, "l%lu:", (unsigned long)d->where.line);
ident_fprint(out, d->var);
if (d->is_const) {
fprintf(out, "[const]");
}
if (d->has_expr) {
fprintf(out, "=");
}
}
static void stmt_fprint(FILE *out, Statement *s) {
switch (s->kind) {
case STMT_DECLS:
arr_foreach(s->decls, Declaration, decl) {
if (decl != s->decls.data) {
fprintf(out, ", ");
}
decl_fprint(out, decl);
}
fprintf(out, ";\n");
break;
}
}
static void parsed_file_fprint(FILE *out, ParsedFile *f) {
arr_foreach(f->stmts, Statement, stmt) {
stmt_fprint(out, stmt);
}
}
|