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
153
154
155
156
157
158
159
160
161
162
|
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "lex.h"
/* node graph */
typedef enum {
N_START,
N_STOP,
N_LIT_INT,
N_OP_ADD,
N_OP_SUB,
N_OP_MUL,
N_OP_DIV,
N_OP_NEG,
} NodeType;
typedef struct Node {
NodeType type;
struct Node **inputs, **outputs;
} Node;
typedef struct {
Node *start, *stop;
} ProcGraph;
/* parsing */
void parse_expr(Lexer *l);
void parse_stmt_let(Lexer *l) {
lex_expect(l, TMASK(TOK_IDENT));
Str name = l->ident;
lex_expect(l, TMASK(TOK_EQUALS) | TMASK(TOK_COLON));
lex_next(l);
parse_expr(l);
printf("name_bind %.*s\n", (int)name.n, name.s);
}
void parse_stmt(Lexer *l) {
/* TODO */
(void)l;
switch (l->tok) {
case TOK_LET:
parse_stmt_let(l);
break;
case TOK_RETURN:
lex_next(l);
parse_expr(l);
puts("return");
break;
default:
lex_expected(l, TMASK(TOK_RBRACE));
}
}
void parse_proc(Lexer *l) {
lex_expect(l, TMASK(TOK_IDENT));
lex_expect(l, TMASK(TOK_LBRACE));
lex_next(l);
while (l->tok != TOK_RBRACE) {
lex_expected_not(l, TMASK(TOK_EOF));
parse_stmt(l);
}
lex_expected(l, TMASK(TOK_RBRACE));
lex_next(l);
}
void parse_term(Lexer *l) {
int negate_after = l->tok == TOK_MINUS;
if (TMASK(l->tok) & (TMASK(TOK_MINUS) | TMASK(TOK_PLUS))) {
lex_next(l);
}
if (l->tok == TOK_LPAREN) {
lex_next(l);
parse_expr(l);
lex_expected(l, TMASK(TOK_RPAREN));
lex_next(l);
} else {
lex_expected(l, TMASK(TOK_LIT_NUM) | TMASK(TOK_LIT_STR) | TMASK(TOK_LIT_CHAR) | TMASK(TOK_IDENT));
switch (l->tok) {
case TOK_IDENT:
printf("var %.*s\n", (int)l->ident.n, l->ident.s);
break;
case TOK_LIT_STR:
printf("lit_str %.*s\n", (int)l->ident.n, l->ident.s);
break;
case TOK_LIT_CHAR:
printf("lit_char %.*s\n", (int)l->ident.n, l->ident.s);
break;
case TOK_LIT_NUM:
printf("lit_num %.*s\n", (int)l->ident.n, l->ident.s);
break;
default:
break;
}
lex_next(l);
}
if (negate_after) puts("negate");
}
void parse_expr(Lexer *l) {
parse_term(l);
if (l->tok == TOK_LPAREN) {
lex_next(l);
puts("args_start");
for (;;) {
parse_expr(l);
lex_expected(l, TMASK(TOK_COMMA) | TMASK(TOK_RPAREN));
if (l->tok == TOK_RPAREN) break;
lex_next(l);
}
lex_next(l);
puts("args_end");
puts("func_call");
}
if (TMASK(l->tok) & (TMASK(TOK_PLUS) | TMASK(TOK_MINUS) | TMASK(TOK_ASTERISK) | TMASK(TOK_SLASH))) {
Token t = l->tok;
lex_next(l);
parse_expr(l);
switch (t) {
case TOK_PLUS: puts("add"); break;
case TOK_MINUS: puts("subtract"); break;
case TOK_ASTERISK: puts("multiply"); break;
case TOK_SLASH: puts("divide"); break;
default: break;
}
}
}
void parse_toplevel(Lexer *l) {
switch (l->tok) {
case TOK_PROC:
parse_proc(l);
break;
default:
lex_expected(l, TMASK(TOK_PROC));
break;
}
}
void parse_unit(Lexer *l) {
while (l->tok != TOK_EOF) {
parse_toplevel(l);
}
}
int main(int argc, const char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s FILE\n", argv[0]);
return 1;
}
Lexer l = { 0 };
lex_start(&l, argv[1]);
parse_unit(&l);
lex_free(&l);
return 0;
}
|