diff options
-rw-r--r-- | src/nodes.c | 18 | ||||
-rw-r--r-- | src/nodes.h | 8 | ||||
-rw-r--r-- | src/parser.c | 42 |
3 files changed, 43 insertions, 25 deletions
diff --git a/src/nodes.c b/src/nodes.c index fc39d8e..3a63246 100644 --- a/src/nodes.c +++ b/src/nodes.c | |||
@@ -64,6 +64,15 @@ print_node(Node *node) { | |||
64 | print_node(node->def.value); | 64 | print_node(node->def.value); |
65 | printf(")"); | 65 | printf(")"); |
66 | } break; | 66 | } break; |
67 | case NODE_BLOCK: { | ||
68 | size_t n_expr = array_size(node->block.expr); | ||
69 | printf("{"); | ||
70 | for (size_t i = 0; i < n_expr; ++i) { | ||
71 | printf(" "); | ||
72 | print_node(node->block.expr[i]); | ||
73 | } | ||
74 | printf(" }"); | ||
75 | } break; | ||
67 | case NODE_FUN: { | 76 | case NODE_FUN: { |
68 | printf("(fun "); | 77 | printf("(fun "); |
69 | print_node(node->fun.name); | 78 | print_node(node->fun.name); |
@@ -80,13 +89,8 @@ print_node(Node *node) { | |||
80 | printf(")"); | 89 | printf(")"); |
81 | printf(": "); | 90 | printf(": "); |
82 | print_node(node->fun.return_type); | 91 | print_node(node->fun.return_type); |
83 | 92 | printf(" "); | |
84 | size_t n_expr = array_size(node->fun.body); | 93 | print_node(node->fun.body); |
85 | for (size_t i = 0; i < n_expr; ++i) { | ||
86 | printf(" "); | ||
87 | print_node(node->fun.body[i]); | ||
88 | } | ||
89 | |||
90 | printf(")"); | 94 | printf(")"); |
91 | } break; | 95 | } break; |
92 | default: { printf("{#unknown#}"); } break; | 96 | default: { printf("{#unknown#}"); } break; |
diff --git a/src/nodes.h b/src/nodes.h index 2e24ea5..c1520b3 100644 --- a/src/nodes.h +++ b/src/nodes.h | |||
@@ -11,6 +11,7 @@ typedef enum NodeType { | |||
11 | NODE_DEF, | 11 | NODE_DEF, |
12 | NODE_SET, | 12 | NODE_SET, |
13 | NODE_FUN, | 13 | NODE_FUN, |
14 | NODE_BLOCK, | ||
14 | } NodeType; | 15 | } NodeType; |
15 | 16 | ||
16 | typedef struct Node { | 17 | typedef struct Node { |
@@ -55,8 +56,13 @@ typedef struct Node { | |||
55 | struct Node **param_names; | 56 | struct Node **param_names; |
56 | struct Node **param_types; | 57 | struct Node **param_types; |
57 | struct Node *return_type; | 58 | struct Node *return_type; |
58 | struct Node **body; | 59 | struct Node *body; |
59 | } fun; | 60 | } fun; |
61 | |||
62 | // Block statements. | ||
63 | struct { | ||
64 | struct Node **expr; | ||
65 | } block; | ||
60 | }; | 66 | }; |
61 | } Node; | 67 | } Node; |
62 | 68 | ||
diff --git a/src/parser.c b/src/parser.c index cfbefaf..58ad722 100644 --- a/src/parser.c +++ b/src/parser.c | |||
@@ -258,7 +258,6 @@ parse_fun(Parser *parser) { | |||
258 | node->fun.name = name; | 258 | node->fun.name = name; |
259 | array_init(node->fun.param_names, 0); | 259 | array_init(node->fun.param_names, 0); |
260 | array_init(node->fun.param_types, 0); | 260 | array_init(node->fun.param_types, 0); |
261 | array_init(node->fun.body, 0); | ||
262 | 261 | ||
263 | // Parse parameter list and return type. | 262 | // Parse parameter list and return type. |
264 | if (!consume_lparen(parser)) { | 263 | if (!consume_lparen(parser)) { |
@@ -287,19 +286,12 @@ parse_fun(Parser *parser) { | |||
287 | } | 286 | } |
288 | node->fun.return_type = ret_type; | 287 | node->fun.return_type = ret_type; |
289 | 288 | ||
290 | // Parse body. | 289 | Node *body = parse_next(parser); |
291 | while (true) { | 290 | if (body == NULL) { |
292 | Token next = peek_token(parser); | 291 | return NULL; |
293 | if (next.type == TOKEN_RPAREN) { | ||
294 | next_token(parser); | ||
295 | break; | ||
296 | } | ||
297 | Node *expr = parse_next(parser); | ||
298 | if (expr == NULL) { | ||
299 | return NULL; | ||
300 | } | ||
301 | array_push(node->fun.body, expr); | ||
302 | } | 292 | } |
293 | node->fun.body = body; | ||
294 | consume_rparen(parser); | ||
303 | 295 | ||
304 | return node; | 296 | return node; |
305 | } | 297 | } |
@@ -331,10 +323,25 @@ parse_paren(Parser *parser) { | |||
331 | return NULL; | 323 | return NULL; |
332 | } | 324 | } |
333 | 325 | ||
334 | 326 | Node * | |
335 | // TODO: Parse if: (def ...) shouldn't be allowed for now on if statements. In | 327 | parse_block(Parser *parser) { |
336 | // the future, an if can create a new block and thus a fresh scope which would | 328 | next_token(parser); // Skip paren. |
337 | // make the decision of what variables are active trivial. | 329 | Node *node = alloc_node(NODE_BLOCK); |
330 | array_init(node->block.expr, 0); | ||
331 | while (true) { | ||
332 | Token next = peek_token(parser); | ||
333 | if (next.type == TOKEN_RCURLY) { | ||
334 | next_token(parser); | ||
335 | break; | ||
336 | } | ||
337 | Node *expr = parse_next(parser); | ||
338 | if (expr == NULL) { | ||
339 | return NULL; | ||
340 | } | ||
341 | array_push(node->block.expr, expr); | ||
342 | } | ||
343 | return node; | ||
344 | } | ||
338 | 345 | ||
339 | Node * | 346 | Node * |
340 | parse_next(Parser *parser) { | 347 | parse_next(Parser *parser) { |
@@ -347,6 +354,7 @@ parse_next(Parser *parser) { | |||
347 | case TOKEN_FALSE: { return parse_bool(parser); } break; | 354 | case TOKEN_FALSE: { return parse_bool(parser); } break; |
348 | case TOKEN_LPAREN: { return parse_paren(parser); } break; | 355 | case TOKEN_LPAREN: { return parse_paren(parser); } break; |
349 | case TOKEN_EOF: { return NULL; } break; | 356 | case TOKEN_EOF: { return NULL; } break; |
357 | case TOKEN_LCURLY: { return parse_block(parser); } break; | ||
350 | default: { | 358 | default: { |
351 | push_error(ERR_TYPE_PARSER, ERR_UNKNOWN_TOK_TYPE, tok.line, tok.col); | 359 | push_error(ERR_TYPE_PARSER, ERR_UNKNOWN_TOK_TYPE, tok.line, tok.col); |
352 | return NULL; | 360 | return NULL; |