diff options
author | Bad Diode <bd@badd10de.dev> | 2021-10-12 17:25:08 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-10-12 17:25:08 +0200 |
commit | ab7d5d484b911f454f35567ed2f1a1a2dac167f7 (patch) | |
tree | 315733c643b7d9bce50e25f91ed59ce39272a1f6 /src/bootstrap/parser.c | |
parent | d90018ed10267dbf1f4c6f746b9f70460e1424a6 (diff) | |
download | bdl-ab7d5d484b911f454f35567ed2f1a1a2dac167f7.tar.gz bdl-ab7d5d484b911f454f35567ed2f1a1a2dac167f7.zip |
Add new error values
Diffstat (limited to 'src/bootstrap/parser.c')
-rw-r--r-- | src/bootstrap/parser.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/src/bootstrap/parser.c b/src/bootstrap/parser.c new file mode 100644 index 0000000..c84c6c6 --- /dev/null +++ b/src/bootstrap/parser.c | |||
@@ -0,0 +1,149 @@ | |||
1 | typedef struct Visitor { | ||
2 | Tokens tokens; | ||
3 | size_t current; | ||
4 | } Visitor; | ||
5 | |||
6 | Token | ||
7 | peek_token(const Visitor *visitor) { | ||
8 | return visitor->tokens.buf[visitor->current]; | ||
9 | } | ||
10 | |||
11 | Token | ||
12 | next_token(Visitor *visitor) { | ||
13 | return visitor->tokens.buf[visitor->current++]; | ||
14 | } | ||
15 | |||
16 | bool | ||
17 | has_next_token(const Visitor *visitor) { | ||
18 | return visitor->current < visitor->tokens.size; | ||
19 | } | ||
20 | |||
21 | Object * | ||
22 | parse_fixnum(Token tok) { | ||
23 | ssize_t num = 0; | ||
24 | int sign = 1; | ||
25 | for (size_t i = 0; i < tok.value.n; i++) { | ||
26 | char c = tok.value.start[i]; | ||
27 | if (c == '-') { | ||
28 | sign = -1; | ||
29 | continue; | ||
30 | } | ||
31 | num = num * 10 + (c - '0'); | ||
32 | } | ||
33 | return make_fixnum(num * sign); | ||
34 | } | ||
35 | |||
36 | Object * parse_tree(Visitor *vs); | ||
37 | |||
38 | Object * | ||
39 | parse_list(Visitor *vs) { | ||
40 | Token tok = peek_token(vs); | ||
41 | if (tok.type == TOKEN_EOF) { | ||
42 | error_push((Error){ | ||
43 | .type = ERR_TYPE_PARSER, | ||
44 | .value = ERR_UNBALANCED_PAREN, | ||
45 | .line = tok.line, | ||
46 | .col = tok.column, | ||
47 | }); | ||
48 | return obj_err; | ||
49 | } | ||
50 | Object *next_obj = parse_tree(vs); | ||
51 | if (next_obj == obj_err) { | ||
52 | return obj_err; | ||
53 | } | ||
54 | Object *root = make_pair(next_obj, obj_nil); | ||
55 | Object *list = root; | ||
56 | while (has_next_token(vs)) { | ||
57 | Token tok = peek_token(vs); | ||
58 | if (tok.type == TOKEN_RPAREN) { | ||
59 | next_token(vs); | ||
60 | break; | ||
61 | } | ||
62 | if (tok.type == TOKEN_EOF) { | ||
63 | error_push((Error){ | ||
64 | .type = ERR_TYPE_PARSER, | ||
65 | .value = ERR_UNBALANCED_PAREN, | ||
66 | .line = tok.line, | ||
67 | .col = tok.column, | ||
68 | }); | ||
69 | free_objects(root); | ||
70 | return obj_err; | ||
71 | } | ||
72 | next_obj = parse_tree(vs); | ||
73 | if (next_obj == obj_err) { | ||
74 | free_objects(root); | ||
75 | return obj_err; | ||
76 | } | ||
77 | list->cdr = make_pair(next_obj, obj_nil); | ||
78 | list = list->cdr; | ||
79 | } | ||
80 | return root; | ||
81 | } | ||
82 | |||
83 | Object * | ||
84 | parse_tree(Visitor *vs) { | ||
85 | Token tok = next_token(vs); | ||
86 | switch (tok.type) { | ||
87 | case TOKEN_FIXNUM: { | ||
88 | return parse_fixnum(tok); | ||
89 | } break; | ||
90 | case TOKEN_TRUE: { | ||
91 | return obj_true; | ||
92 | } break; | ||
93 | case TOKEN_FALSE: { | ||
94 | return obj_false; | ||
95 | } break; | ||
96 | case TOKEN_RPAREN: { | ||
97 | error_push((Error){ | ||
98 | .type = ERR_TYPE_PARSER, | ||
99 | .value = ERR_UNBALANCED_PAREN, | ||
100 | .line = tok.line, | ||
101 | .col = tok.column, | ||
102 | }); | ||
103 | return obj_err; | ||
104 | } break; | ||
105 | case TOKEN_QUOTE: { | ||
106 | // TODO: Implement. | ||
107 | error_push((Error){ | ||
108 | .type = ERR_TYPE_PARSER, | ||
109 | .value = ERR_NOT_IMPLEMENTED, | ||
110 | .line = tok.line, | ||
111 | .col = tok.column, | ||
112 | }); | ||
113 | return obj_err; | ||
114 | } break; | ||
115 | case TOKEN_LPAREN: { | ||
116 | return parse_list(vs); | ||
117 | } break; | ||
118 | case TOKEN_STRING: { | ||
119 | Object *obj = make_string(); | ||
120 | append_string(obj, tok.value); | ||
121 | return obj; | ||
122 | } break; | ||
123 | case TOKEN_SYMBOL: { | ||
124 | return make_symbol(tok.value); | ||
125 | } break; | ||
126 | case TOKEN_EOF: { | ||
127 | error_push((Error){ | ||
128 | .type = ERR_TYPE_PARSER, | ||
129 | .value = ERR_EOF_REACHED, | ||
130 | .line = tok.line, | ||
131 | .col = tok.column, | ||
132 | }); | ||
133 | return obj_err; | ||
134 | } break; | ||
135 | case TOKEN_NIL: { | ||
136 | return obj_nil; | ||
137 | } break; | ||
138 | default: { | ||
139 | break; | ||
140 | } break; | ||
141 | } | ||
142 | error_push((Error){ | ||
143 | .type = ERR_TYPE_PARSER, | ||
144 | .value = ERR_EOF_REACHED, | ||
145 | .line = tok.line, | ||
146 | .col = tok.column, | ||
147 | }); | ||
148 | return obj_err; | ||
149 | } | ||