diff options
author | Bad Diode <bd@badd10de.dev> | 2021-10-30 08:51:46 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-10-30 08:51:46 +0200 |
commit | c0520617a974abd27c413fb21ecd64ca2d11d135 (patch) | |
tree | c284b450c7532303c1eb138bcf6fb45a8540603f | |
parent | f17b11003fe384b49a7bf844824f23167b6095e0 (diff) | |
download | bdl-c0520617a974abd27c413fb21ecd64ca2d11d135.tar.gz bdl-c0520617a974abd27c413fb21ecd64ca2d11d135.zip |
Add parsing for def/set! expressions
-rwxr-xr-x | src/lexer.c | 4 | ||||
-rwxr-xr-x | src/lexer.h | 2 | ||||
-rw-r--r-- | src/parser.c | 97 | ||||
-rwxr-xr-x | src/parser.h | 11 |
4 files changed, 99 insertions, 15 deletions
diff --git a/src/lexer.c b/src/lexer.c index cbcc175..704ee66 100755 --- a/src/lexer.c +++ b/src/lexer.c | |||
@@ -13,6 +13,8 @@ static const char* token_str[] = { | |||
13 | [TOKEN_FALSE] = "TOKEN_FALSE", | 13 | [TOKEN_FALSE] = "TOKEN_FALSE", |
14 | [TOKEN_LAMBDA] = "TOKEN_LAMBDA", | 14 | [TOKEN_LAMBDA] = "TOKEN_LAMBDA", |
15 | [TOKEN_IF] = "TOKEN_IF", | 15 | [TOKEN_IF] = "TOKEN_IF", |
16 | [TOKEN_DEF] = "TOKEN_DEF", | ||
17 | [TOKEN_SET] = "TOKEN_SET", | ||
16 | [TOKEN_EOF] = "TOKEN_EOF", | 18 | [TOKEN_EOF] = "TOKEN_EOF", |
17 | }; | 19 | }; |
18 | 20 | ||
@@ -128,6 +130,8 @@ find_primitive_type(const StringView value) { | |||
128 | if (TOKEN_IS_KEYWORD(value, "false")) { return TOKEN_FALSE; } | 130 | if (TOKEN_IS_KEYWORD(value, "false")) { return TOKEN_FALSE; } |
129 | if (TOKEN_IS_KEYWORD(value, "lambda")) { return TOKEN_LAMBDA; } | 131 | if (TOKEN_IS_KEYWORD(value, "lambda")) { return TOKEN_LAMBDA; } |
130 | if (TOKEN_IS_KEYWORD(value, "if")) { return TOKEN_IF; } | 132 | if (TOKEN_IS_KEYWORD(value, "if")) { return TOKEN_IF; } |
133 | if (TOKEN_IS_KEYWORD(value, "def")) { return TOKEN_DEF; } | ||
134 | if (TOKEN_IS_KEYWORD(value, "set!")) { return TOKEN_SET; } | ||
131 | 135 | ||
132 | return TOKEN_SYMBOL; | 136 | return TOKEN_SYMBOL; |
133 | } | 137 | } |
diff --git a/src/lexer.h b/src/lexer.h index 4798a2b..f187526 100755 --- a/src/lexer.h +++ b/src/lexer.h | |||
@@ -21,6 +21,8 @@ typedef enum TokenType { | |||
21 | // Keywords. | 21 | // Keywords. |
22 | TOKEN_LAMBDA, | 22 | TOKEN_LAMBDA, |
23 | TOKEN_IF, | 23 | TOKEN_IF, |
24 | TOKEN_DEF, | ||
25 | TOKEN_SET, | ||
24 | 26 | ||
25 | // End of file. | 27 | // End of file. |
26 | TOKEN_EOF, | 28 | TOKEN_EOF, |
diff --git a/src/parser.c b/src/parser.c index 5551dd2..f831e50 100644 --- a/src/parser.c +++ b/src/parser.c | |||
@@ -122,7 +122,7 @@ parse_lambda(Parser *parser, Errors *errors) { | |||
122 | Object * | 122 | Object * |
123 | parse_if(Parser *parser, Errors *errors) { | 123 | parse_if(Parser *parser, Errors *errors) { |
124 | Token start = next_token(parser); | 124 | Token start = next_token(parser); |
125 | Object *obj_if = object_alloc(start, OBJ_TYPE_IF); | 125 | Object *ret = object_alloc(start, OBJ_TYPE_IF); |
126 | 126 | ||
127 | Token tok = peek_token(parser); | 127 | Token tok = peek_token(parser); |
128 | if (tok.type == TOKEN_RPAREN) { | 128 | if (tok.type == TOKEN_RPAREN) { |
@@ -134,7 +134,7 @@ parse_if(Parser *parser, Errors *errors) { | |||
134 | }); | 134 | }); |
135 | return NULL; | 135 | return NULL; |
136 | } | 136 | } |
137 | obj_if->condition = parse_tree(parser, errors); | 137 | ret->condition = parse_tree(parser, errors); |
138 | 138 | ||
139 | tok = peek_token(parser); | 139 | tok = peek_token(parser); |
140 | if (tok.type == TOKEN_RPAREN) { | 140 | if (tok.type == TOKEN_RPAREN) { |
@@ -146,16 +146,16 @@ parse_if(Parser *parser, Errors *errors) { | |||
146 | }); | 146 | }); |
147 | return NULL; | 147 | return NULL; |
148 | } | 148 | } |
149 | obj_if->expr_true = parse_tree(parser, errors); | 149 | ret->expr_true = parse_tree(parser, errors); |
150 | 150 | ||
151 | // Optional else expression. | 151 | // Optional else expression. |
152 | tok = peek_token(parser); | 152 | tok = peek_token(parser); |
153 | if (tok.type == TOKEN_RPAREN) { | 153 | if (tok.type == TOKEN_RPAREN) { |
154 | next_token(parser); | 154 | next_token(parser); |
155 | obj_if->expr_false = NULL; | 155 | ret->expr_false = NULL; |
156 | return obj_if; | 156 | return ret; |
157 | } | 157 | } |
158 | obj_if->expr_false = parse_tree(parser, errors); | 158 | ret->expr_false = parse_tree(parser, errors); |
159 | 159 | ||
160 | tok = peek_token(parser); | 160 | tok = peek_token(parser); |
161 | if (tok.type != TOKEN_RPAREN) { | 161 | if (tok.type != TOKEN_RPAREN) { |
@@ -168,7 +168,62 @@ parse_if(Parser *parser, Errors *errors) { | |||
168 | return NULL; | 168 | return NULL; |
169 | } | 169 | } |
170 | next_token(parser); | 170 | next_token(parser); |
171 | return obj_if; | 171 | return ret; |
172 | } | ||
173 | |||
174 | Object * | ||
175 | parse_var(Parser *parser, Errors *errors) { | ||
176 | Token start = next_token(parser); | ||
177 | ObjectType type = start.type == TOKEN_DEF ? OBJ_TYPE_DEF : OBJ_TYPE_SET; | ||
178 | Object *ret = object_alloc(start, type); | ||
179 | |||
180 | // Variable name. | ||
181 | Token tok = peek_token(parser); | ||
182 | if (tok.type == TOKEN_RPAREN) { | ||
183 | error_push(errors, (Error){ | ||
184 | .type = ERR_TYPE_PARSER, | ||
185 | .value = ERR_NOT_ENOUGH_ARGS, | ||
186 | .line = tok.line, | ||
187 | .col = tok.col, | ||
188 | }); | ||
189 | return NULL; | ||
190 | } | ||
191 | if (tok.type != TOKEN_SYMBOL) { | ||
192 | error_push(errors, (Error){ | ||
193 | .type = ERR_TYPE_PARSER, | ||
194 | .value = ERR_WRONG_ARG_TYPE, | ||
195 | .line = tok.line, | ||
196 | .col = tok.col, | ||
197 | }); | ||
198 | return NULL; | ||
199 | } | ||
200 | ret->var_name = parse_tree(parser, errors); | ||
201 | |||
202 | // Variable value (expression). | ||
203 | tok = peek_token(parser); | ||
204 | if (tok.type == TOKEN_RPAREN) { | ||
205 | error_push(errors, (Error){ | ||
206 | .type = ERR_TYPE_PARSER, | ||
207 | .value = ERR_NOT_ENOUGH_ARGS, | ||
208 | .line = tok.line, | ||
209 | .col = tok.col, | ||
210 | }); | ||
211 | return NULL; | ||
212 | } | ||
213 | ret->var_expr = parse_tree(parser, errors); | ||
214 | |||
215 | tok = peek_token(parser); | ||
216 | if (tok.type != TOKEN_RPAREN) { | ||
217 | error_push(errors, (Error){ | ||
218 | .type = ERR_TYPE_PARSER, | ||
219 | .value = ERR_TOO_MANY_ARGS, | ||
220 | .line = tok.line, | ||
221 | .col = tok.col, | ||
222 | }); | ||
223 | return NULL; | ||
224 | } | ||
225 | next_token(parser); | ||
226 | return ret; | ||
172 | } | 227 | } |
173 | 228 | ||
174 | Object * | 229 | Object * |
@@ -188,12 +243,10 @@ parse_list(Parser *parser, Errors *errors) { | |||
188 | }); | 243 | }); |
189 | return NULL; | 244 | return NULL; |
190 | } break; | 245 | } break; |
191 | case TOKEN_LAMBDA: { | 246 | case TOKEN_LAMBDA: { return parse_lambda(parser, errors); } break; |
192 | return parse_lambda(parser, errors); | 247 | case TOKEN_IF: { return parse_if(parser, errors); } break; |
193 | } break; | 248 | case TOKEN_DEF: { return parse_var(parser, errors); } break; |
194 | case TOKEN_IF: { | 249 | case TOKEN_SET: { return parse_var(parser, errors); } break; |
195 | return parse_if(parser, errors); | ||
196 | } break; | ||
197 | default: break; | 250 | default: break; |
198 | } | 251 | } |
199 | 252 | ||
@@ -386,7 +439,7 @@ object_display(Object *obj) { | |||
386 | printf(")"); | 439 | printf(")"); |
387 | } break; | 440 | } break; |
388 | case OBJ_TYPE_LAMBDA: { | 441 | case OBJ_TYPE_LAMBDA: { |
389 | printf("#{ lambda( "); | 442 | printf("#{ lambda ( "); |
390 | for (size_t i = 0; i < array_size(obj->params); i++) { | 443 | for (size_t i = 0; i < array_size(obj->params); i++) { |
391 | object_display(obj->params[i]); | 444 | object_display(obj->params[i]); |
392 | printf(" "); | 445 | printf(" "); |
@@ -408,7 +461,21 @@ object_display(Object *obj) { | |||
408 | object_display(obj->expr_false); | 461 | object_display(obj->expr_false); |
409 | } | 462 | } |
410 | printf(" }"); | 463 | printf(" }"); |
411 | }; | 464 | } break; |
465 | case OBJ_TYPE_DEF: { | ||
466 | printf("#{ def "); | ||
467 | object_display(obj->var_name); | ||
468 | printf(" "); | ||
469 | object_display(obj->var_expr); | ||
470 | printf(" }"); | ||
471 | } break; | ||
472 | case OBJ_TYPE_SET: { | ||
473 | printf("#{ set! "); | ||
474 | object_display(obj->var_name); | ||
475 | printf(" "); | ||
476 | object_display(obj->var_expr); | ||
477 | printf(" }"); | ||
478 | } break; | ||
412 | } | 479 | } |
413 | return; | 480 | return; |
414 | } | 481 | } |
diff --git a/src/parser.h b/src/parser.h index b2b07c8..14d9df5 100755 --- a/src/parser.h +++ b/src/parser.h | |||
@@ -13,6 +13,8 @@ typedef enum ObjectType { | |||
13 | OBJ_TYPE_PAIR, | 13 | OBJ_TYPE_PAIR, |
14 | OBJ_TYPE_LAMBDA, | 14 | OBJ_TYPE_LAMBDA, |
15 | OBJ_TYPE_IF, | 15 | OBJ_TYPE_IF, |
16 | OBJ_TYPE_DEF, | ||
17 | OBJ_TYPE_SET, | ||
16 | } ObjectType; | 18 | } ObjectType; |
17 | 19 | ||
18 | typedef struct Object { | 20 | typedef struct Object { |
@@ -43,6 +45,13 @@ typedef struct Object { | |||
43 | struct Object *expr_true; | 45 | struct Object *expr_true; |
44 | struct Object *expr_false; | 46 | struct Object *expr_false; |
45 | }; | 47 | }; |
48 | |||
49 | // OBJ_TYPE_DEF | ||
50 | // OBJ_TYPE_SET | ||
51 | struct { | ||
52 | struct Object *var_name; | ||
53 | struct Object *var_expr; | ||
54 | }; | ||
46 | }; | 55 | }; |
47 | 56 | ||
48 | size_t line; | 57 | size_t line; |
@@ -71,6 +80,8 @@ Object * parse_bool(Token tok); | |||
71 | Object * parse_fixnum(Token tok); | 80 | Object * parse_fixnum(Token tok); |
72 | Object * parse_list(Parser *parser, Errors *errors); | 81 | Object * parse_list(Parser *parser, Errors *errors); |
73 | Object * parse_lambda(Parser *parser, Errors *errors); | 82 | Object * parse_lambda(Parser *parser, Errors *errors); |
83 | Object * parse_if(Parser *parser, Errors *errors); | ||
84 | Object * parse_var(Parser *parser, Errors *errors); | ||
74 | Root * parse(Token *tokens, Errors *errors); | 85 | Root * parse(Token *tokens, Errors *errors); |
75 | 86 | ||
76 | // Object operations. | 87 | // Object operations. |