summaryrefslogtreecommitdiff
path: root/parse.c
blob: 775eac3918b73d24983f2d71af30255297b5cf63 (plain)
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);
	}
}