diff options
Diffstat (limited to 'src/parser.c')
-rw-r--r-- | src/parser.c | 743 |
1 files changed, 463 insertions, 280 deletions
diff --git a/src/parser.c b/src/parser.c index 90adaf3..05a00e7 100644 --- a/src/parser.c +++ b/src/parser.c | |||
@@ -9,6 +9,7 @@ | |||
9 | // | 9 | // |
10 | 10 | ||
11 | typedef enum NodeKind { | 11 | typedef enum NodeKind { |
12 | NODE_ERR, | ||
12 | // Arithmetic. | 13 | // Arithmetic. |
13 | NODE_ADD, | 14 | NODE_ADD, |
14 | NODE_SUB, | 15 | NODE_SUB, |
@@ -29,6 +30,7 @@ typedef enum NodeKind { | |||
29 | NODE_BITNOT, | 30 | NODE_BITNOT, |
30 | NODE_BITAND, | 31 | NODE_BITAND, |
31 | NODE_BITOR, | 32 | NODE_BITOR, |
33 | NODE_BITXOR, | ||
32 | NODE_BITLSHIFT, | 34 | NODE_BITLSHIFT, |
33 | NODE_BITRSHIFT, | 35 | NODE_BITRSHIFT, |
34 | // Literals. | 36 | // Literals. |
@@ -60,15 +62,18 @@ typedef enum NodeKind { | |||
60 | NODE_FUNCALL, | 62 | NODE_FUNCALL, |
61 | NODE_RETURN, | 63 | NODE_RETURN, |
62 | // Helpers. | 64 | // Helpers. |
63 | NODE_SYMBOL_IDX, | ||
64 | NODE_TYPE, | 65 | NODE_TYPE, |
65 | NODE_COMPOUND_TYPE, | 66 | NODE_COMPOUND_TYPE, |
66 | NODE_ARR_TYPE, | ||
67 | NODE_FIELD, | 67 | NODE_FIELD, |
68 | NODE_BLOCK, | 68 | NODE_BLOCK, |
69 | NODE_PTR, | ||
70 | NODE_DEREF, | ||
71 | NODE_ARR, | ||
72 | NODE_INDEX, | ||
69 | } NodeKind; | 73 | } NodeKind; |
70 | 74 | ||
71 | Str node_str[] = { | 75 | Str node_str[] = { |
76 | [NODE_ERR] = cstr("ERR"), | ||
72 | // Arithmetic. | 77 | // Arithmetic. |
73 | [NODE_ADD] = cstr("ADD"), | 78 | [NODE_ADD] = cstr("ADD"), |
74 | [NODE_SUB] = cstr("SUB"), | 79 | [NODE_SUB] = cstr("SUB"), |
@@ -89,6 +94,7 @@ Str node_str[] = { | |||
89 | [NODE_BITNOT] = cstr("BITNOT"), | 94 | [NODE_BITNOT] = cstr("BITNOT"), |
90 | [NODE_BITAND] = cstr("BITAND"), | 95 | [NODE_BITAND] = cstr("BITAND"), |
91 | [NODE_BITOR] = cstr("BITOR"), | 96 | [NODE_BITOR] = cstr("BITOR"), |
97 | [NODE_BITXOR] = cstr("BITXOR"), | ||
92 | [NODE_BITLSHIFT] = cstr("BITLSHIFT"), | 98 | [NODE_BITLSHIFT] = cstr("BITLSHIFT"), |
93 | [NODE_BITRSHIFT] = cstr("BITRSHIFT"), | 99 | [NODE_BITRSHIFT] = cstr("BITRSHIFT"), |
94 | // Literals. | 100 | // Literals. |
@@ -122,81 +128,137 @@ Str node_str[] = { | |||
122 | // Helpers. | 128 | // Helpers. |
123 | [NODE_TYPE] = cstr("TYPE"), | 129 | [NODE_TYPE] = cstr("TYPE"), |
124 | [NODE_COMPOUND_TYPE] = cstr("COMPOUND TYPE"), | 130 | [NODE_COMPOUND_TYPE] = cstr("COMPOUND TYPE"), |
125 | [NODE_ARR_TYPE] = cstr("TYPE (ARR)"), | ||
126 | [NODE_SYMBOL_IDX] = cstr("SYMBOL[IDX]"), | ||
127 | [NODE_FIELD] = cstr("FIELD"), | 131 | [NODE_FIELD] = cstr("FIELD"), |
128 | [NODE_BLOCK] = cstr("BLOCK"), | 132 | [NODE_BLOCK] = cstr("BLOCK"), |
133 | [NODE_PTR] = cstr("@"), | ||
134 | [NODE_DEREF] = cstr("DEREF"), | ||
135 | [NODE_ARR] = cstr("ARR"), | ||
136 | [NODE_INDEX] = cstr("INDEX"), | ||
129 | }; | 137 | }; |
130 | 138 | ||
139 | typedef union NodeLit { | ||
140 | f64 d; | ||
141 | sz i; | ||
142 | u64 u; | ||
143 | Str str; | ||
144 | Str sym; | ||
145 | } NodeLit; | ||
146 | |||
147 | typedef struct NodeBinary { | ||
148 | struct Node *left; | ||
149 | struct Node *right; | ||
150 | } NodeBinary; | ||
151 | |||
152 | typedef struct NodeUnary { | ||
153 | struct Node *left; | ||
154 | } NodeUnary; | ||
155 | |||
156 | typedef struct NodeVariable { | ||
157 | struct Node *name; | ||
158 | struct Node *type; | ||
159 | struct Node *val; | ||
160 | } NodeVariable; | ||
161 | |||
162 | typedef struct NodeLoop { | ||
163 | struct Node *cond; | ||
164 | struct Node *expr; | ||
165 | } NodeLoop; | ||
166 | |||
167 | typedef struct NodeIf { | ||
168 | struct Node *cond; | ||
169 | struct Node *expr_true; | ||
170 | struct Node *expr_else; | ||
171 | } NodeIf; | ||
172 | |||
173 | typedef struct NodeField { | ||
174 | struct Node *type; | ||
175 | struct Node *val; | ||
176 | } NodeField; | ||
177 | |||
178 | typedef struct NodeParam { | ||
179 | struct Node *name; | ||
180 | struct Node *type; | ||
181 | } NodeParam; | ||
182 | |||
183 | typedef struct NodeMatch { | ||
184 | struct Node *expr; | ||
185 | struct Node **cases; | ||
186 | } NodeMatch; | ||
187 | |||
188 | typedef struct NodeCase { | ||
189 | struct Node *cond; | ||
190 | struct Node *expr; | ||
191 | } NodeCase; | ||
192 | |||
193 | typedef struct NodeFunction { | ||
194 | struct Node *name; | ||
195 | struct Node **params; | ||
196 | struct Node **ret; | ||
197 | struct Node *body; | ||
198 | } NodeFunction; | ||
199 | |||
200 | typedef struct NodeSymbol { | ||
201 | struct Node *next; | ||
202 | } NodeSymbol; | ||
203 | |||
204 | typedef struct NodeIndex { | ||
205 | struct Node *next; | ||
206 | struct Node *value; | ||
207 | } NodeIndex; | ||
208 | |||
209 | typedef struct NodeType { | ||
210 | struct Node *next; | ||
211 | } NodeType; | ||
212 | |||
213 | typedef struct NodeDeref { | ||
214 | struct Node *next; | ||
215 | } NodeDeref; | ||
216 | |||
217 | typedef enum { | ||
218 | NODE_ARR_STATIC, | ||
219 | NODE_ARR_DYNAMIC, | ||
220 | NODE_ARR_SLICE, | ||
221 | } NodeArrKind; | ||
222 | |||
223 | typedef struct NodeArr { | ||
224 | struct Node *next; | ||
225 | struct Node *size; | ||
226 | NodeArrKind kind; | ||
227 | } NodeArr; | ||
228 | |||
131 | typedef struct Node { | 229 | typedef struct Node { |
132 | sz id; | 230 | sz id; |
133 | sz line; | 231 | sz line; |
134 | sz col; | 232 | sz col; |
233 | struct Node *parent; | ||
135 | 234 | ||
136 | NodeKind kind; | 235 | NodeKind kind; |
236 | NodeLit value; | ||
137 | union { | 237 | union { |
138 | f64 d; | 238 | NodeBinary binary; |
139 | sz i; | 239 | NodeUnary unary; |
140 | u64 u; | 240 | NodeVariable var; |
141 | Str str; | 241 | NodeSymbol sym; |
142 | Str sym; | 242 | NodeLoop loop; |
143 | } value; | 243 | NodeIf ifelse; |
144 | union { | 244 | NodeField field; |
145 | struct { | 245 | NodeParam param; |
146 | struct Node *left; | 246 | NodeMatch match; |
147 | struct Node *right; | 247 | NodeCase case_entry; |
148 | }; | 248 | NodeFunction func; |
149 | struct { | 249 | NodeType t; |
150 | struct Node *next; | 250 | NodeIndex idx; |
151 | struct Node *arr_size; | 251 | NodeDeref deref; |
152 | }; | 252 | NodeArr array; |
153 | struct { | ||
154 | struct Node *var_name; | ||
155 | struct Node *var_type; | ||
156 | struct Node *var_val; | ||
157 | }; | ||
158 | struct { | ||
159 | struct Node *while_cond; | ||
160 | struct Node *while_expr; | ||
161 | }; | ||
162 | struct { | ||
163 | struct Node *cond_if; | ||
164 | struct Node *cond_expr; | ||
165 | struct Node *cond_else; | ||
166 | }; | ||
167 | struct { | ||
168 | struct Node *field_type; | ||
169 | struct Node *field_val; | ||
170 | }; | ||
171 | struct { | ||
172 | struct Node *param_name; | ||
173 | struct Node *param_type; | ||
174 | }; | ||
175 | struct { | ||
176 | struct Node *match_expr; | ||
177 | struct Node **match_cases; | ||
178 | }; | ||
179 | struct { | ||
180 | struct Node *case_value; | ||
181 | struct Node *case_expr; | ||
182 | }; | ||
183 | struct Node **struct_field; | 253 | struct Node **struct_field; |
184 | struct Node **elements; | 254 | struct Node **elements; |
185 | struct Node **statements; | 255 | struct Node **statements; |
186 | struct Node **expressions; | 256 | struct Node **expressions; |
187 | struct Node **arguments; | 257 | struct Node **arguments; |
188 | struct { | ||
189 | struct Node *func_name; | ||
190 | struct Node **func_params; | ||
191 | struct Node **func_ret; | ||
192 | struct Node *func_body; | ||
193 | }; | ||
194 | }; | 258 | }; |
195 | bool is_ptr; | ||
196 | struct Scope *scope; | ||
197 | Str type; | 259 | Str type; |
198 | Str fun_params; | 260 | Str type_params; |
199 | Str fun_return; | 261 | Str type_returns; |
200 | Str unique_name; | 262 | Str unique_name; |
201 | } Node; | 263 | } Node; |
202 | 264 | ||
@@ -286,6 +348,7 @@ ParseRule parse_rules[] = { | |||
286 | [TOK_BITNOT] = {parse_unary, NULL, PREC_NONE}, | 348 | [TOK_BITNOT] = {parse_unary, NULL, PREC_NONE}, |
287 | [TOK_BITAND] = {NULL, parse_binary, PREC_BITLOGIC}, | 349 | [TOK_BITAND] = {NULL, parse_binary, PREC_BITLOGIC}, |
288 | [TOK_BITOR] = {NULL, parse_binary, PREC_BITLOGIC}, | 350 | [TOK_BITOR] = {NULL, parse_binary, PREC_BITLOGIC}, |
351 | [TOK_BITXOR] = {NULL, parse_binary, PREC_BITLOGIC}, | ||
289 | [TOK_BITLSHIFT] = {NULL, parse_binary, PREC_BITSHIFT}, | 352 | [TOK_BITLSHIFT] = {NULL, parse_binary, PREC_BITSHIFT}, |
290 | [TOK_BITRSHIFT] = {NULL, parse_binary, PREC_BITSHIFT}, | 353 | [TOK_BITRSHIFT] = {NULL, parse_binary, PREC_BITSHIFT}, |
291 | 354 | ||
@@ -308,6 +371,7 @@ ParseRule parse_rules[] = { | |||
308 | [TOK_MATCH] = {parse_keyword, NULL, PREC_NONE}, | 371 | [TOK_MATCH] = {parse_keyword, NULL, PREC_NONE}, |
309 | [TOK_COND] = {parse_keyword, NULL, PREC_NONE}, | 372 | [TOK_COND] = {parse_keyword, NULL, PREC_NONE}, |
310 | [TOK_WHILE] = {parse_keyword, NULL, PREC_NONE}, | 373 | [TOK_WHILE] = {parse_keyword, NULL, PREC_NONE}, |
374 | [TOK_FOR] = {parse_keyword, NULL, PREC_NONE}, | ||
311 | [TOK_CONTINUE] = {parse_keyword, NULL, PREC_NONE}, | 375 | [TOK_CONTINUE] = {parse_keyword, NULL, PREC_NONE}, |
312 | [TOK_BREAK] = {parse_keyword, NULL, PREC_NONE}, | 376 | [TOK_BREAK] = {parse_keyword, NULL, PREC_NONE}, |
313 | [TOK_FUN] = {parse_keyword, NULL, PREC_NONE}, | 377 | [TOK_FUN] = {parse_keyword, NULL, PREC_NONE}, |
@@ -318,7 +382,6 @@ ParseRule parse_rules[] = { | |||
318 | 382 | ||
319 | Node * | 383 | Node * |
320 | node_alloc(Parser *parser, NodeKind kind, Token tok) { | 384 | node_alloc(Parser *parser, NodeKind kind, Token tok) { |
321 | if (parser->panic) return NULL; | ||
322 | static sz id = 0; | 385 | static sz id = 0; |
323 | Node *node = arena_calloc((sz)sizeof(Node), parser->storage); | 386 | Node *node = arena_calloc((sz)sizeof(Node), parser->storage); |
324 | node->id = id++; | 387 | node->id = id++; |
@@ -388,20 +451,44 @@ parse_block(Parser *parser) { | |||
388 | print_token(parser->previous); | 451 | print_token(parser->previous); |
389 | #endif | 452 | #endif |
390 | Node *block = node_alloc(parser, NODE_BLOCK, parser->previous); | 453 | Node *block = node_alloc(parser, NODE_BLOCK, parser->previous); |
391 | if (!block) return; | ||
392 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | 454 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { |
393 | parse_expr(parser, PREC_LOW); | 455 | parse_expr(parser, PREC_LOW); |
394 | Node *next = array_pop(parser->nodes); | 456 | Node *next = array_pop(parser->nodes); |
457 | next->parent = block; | ||
395 | array_push(block->statements, next, parser->storage); | 458 | array_push(block->statements, next, parser->storage); |
396 | } | 459 | } |
397 | array_push(parser->nodes, block, parser->storage); | 460 | array_push(parser->nodes, block, parser->storage); |
398 | } | 461 | } |
399 | 462 | ||
400 | void | 463 | void |
464 | parser_sync(Parser *parser) { | ||
465 | parser->panic = false; | ||
466 | while (parser->current.kind != TOK_EOF) { | ||
467 | switch (parser->current.kind) { | ||
468 | case TOK_FUN: | ||
469 | case TOK_LET: | ||
470 | case TOK_SET: | ||
471 | case TOK_STRUCT: | ||
472 | case TOK_ENUM: | ||
473 | case TOK_FOR: | ||
474 | case TOK_IF: | ||
475 | case TOK_WHILE: | ||
476 | case TOK_BREAK: | ||
477 | case TOK_CONTINUE: | ||
478 | case TOK_COND: | ||
479 | case TOK_MATCH: | ||
480 | case TOK_CASE: | ||
481 | case TOK_RETURN: return; | ||
482 | default: break; | ||
483 | } | ||
484 | parse_advance(parser); | ||
485 | } | ||
486 | } | ||
487 | |||
488 | void | ||
401 | parse_expr(Parser *parser, ParsePrecedence precedence) { | 489 | parse_expr(Parser *parser, ParsePrecedence precedence) { |
402 | parse_advance(parser); | 490 | parse_advance(parser); |
403 | // TODO: synchronize panic mode on keywords. | 491 | if (parser->panic) parser_sync(parser); |
404 | if (parser->panic) return; | ||
405 | ParseFn prefix = parse_rules[parser->previous.kind].prefix; | 492 | ParseFn prefix = parse_rules[parser->previous.kind].prefix; |
406 | if (prefix == NULL) { | 493 | if (prefix == NULL) { |
407 | parse_emit_err(parser, parser->previous, cstr("expected expression")); | 494 | parse_emit_err(parser, parser->previous, cstr("expected expression")); |
@@ -436,8 +523,8 @@ parse_unary(Parser *parser) { | |||
436 | case TOK_BITNOT: node = node_alloc(parser, NODE_BITNOT, prev); break; | 523 | case TOK_BITNOT: node = node_alloc(parser, NODE_BITNOT, prev); break; |
437 | default: break; // Unreachable. | 524 | default: break; // Unreachable. |
438 | } | 525 | } |
439 | if (!node) return; | 526 | node->unary.left = array_pop(parser->nodes); |
440 | node->left = array_pop(parser->nodes); | 527 | node->unary.left->parent = node; |
441 | array_push(parser->nodes, node, parser->storage); | 528 | array_push(parser->nodes, node, parser->storage); |
442 | } | 529 | } |
443 | 530 | ||
@@ -459,7 +546,6 @@ parse_literal(Parser *parser) { | |||
459 | case TOK_NIL: node = node_alloc(parser, NODE_NIL, prev); break; | 546 | case TOK_NIL: node = node_alloc(parser, NODE_NIL, prev); break; |
460 | default: return; // Unreachable. | 547 | default: return; // Unreachable. |
461 | } | 548 | } |
462 | if (!node) return; | ||
463 | array_push(parser->nodes, node, parser->storage); | 549 | array_push(parser->nodes, node, parser->storage); |
464 | } | 550 | } |
465 | 551 | ||
@@ -471,21 +557,50 @@ parse_type(Parser *parser) { | |||
471 | print_token(prev); | 557 | print_token(prev); |
472 | #endif | 558 | #endif |
473 | Node *node = node_alloc(parser, NODE_TYPE, prev); | 559 | Node *node = node_alloc(parser, NODE_TYPE, prev); |
474 | if (!node) return; | 560 | Node *child = node; |
475 | if (parse_match(parser, TOK_AT)) { | 561 | while (parse_match(parser, TOK_AT) || parse_match(parser, TOK_LSQUARE)) { |
476 | node->is_ptr = true; | 562 | switch (parser->previous.kind) { |
563 | case TOK_AT: { | ||
564 | Node *ptr_node = node_alloc(parser, NODE_PTR, parser->previous); | ||
565 | ptr_node->parent = child; | ||
566 | child->t.next = ptr_node; | ||
567 | child = ptr_node; | ||
568 | } break; | ||
569 | case TOK_LSQUARE: { | ||
570 | Node *ptr_node = node_alloc(parser, NODE_ARR, parser->previous); | ||
571 | if (parse_match(parser, TOK_NUM_INT)) { | ||
572 | // Static array. | ||
573 | parse_number(parser); | ||
574 | ptr_node->array.size = array_pop(parser->nodes); | ||
575 | ptr_node->array.kind = NODE_ARR_STATIC; | ||
576 | ptr_node->array.size->parent = ptr_node; | ||
577 | parse_consume(parser, TOK_RSQUARE, | ||
578 | cstr("unmatched brackets ']' in array type")); | ||
579 | } else if (parse_match(parser, TOK_RSQUARE)) { | ||
580 | // Slice. | ||
581 | ptr_node->array.kind = NODE_ARR_SLICE; | ||
582 | } else { | ||
583 | // Dynamic array. | ||
584 | parse_consume(parser, TOK_DOT, cstr("invalid array type")); | ||
585 | parse_consume(parser, TOK_DOT, cstr("invalid array type")); | ||
586 | parse_consume(parser, TOK_DOT, cstr("invalid array type")); | ||
587 | parse_consume(parser, TOK_RSQUARE, | ||
588 | cstr("unmatched brackets ']' in array type")); | ||
589 | ptr_node->array.kind = NODE_ARR_DYNAMIC; | ||
590 | } | ||
591 | ptr_node->parent = child; | ||
592 | child->t.next = ptr_node; | ||
593 | child = ptr_node; | ||
594 | } break; | ||
595 | default: { | ||
596 | parse_emit_err(parser, prev, cstr("unimplemented")); | ||
597 | } break; | ||
598 | } | ||
477 | } | 599 | } |
478 | parse_consume(parser, TOK_SYMBOL, cstr("no type given for struct field")); | 600 | // TODO: maps |
601 | // TODO: function pointer syntax: : (T T : R) | ||
602 | parse_consume(parser, TOK_SYMBOL, cstr("expected type name")); | ||
479 | node->value.sym = parser->previous.val; | 603 | node->value.sym = parser->previous.val; |
480 | // Optional array value? | ||
481 | if (parse_match(parser, TOK_LSQUARE)) { | ||
482 | node->kind = NODE_ARR_TYPE, | ||
483 | parse_consume(parser, TOK_NUM_INT, cstr("no array size given")); | ||
484 | parse_number(parser); | ||
485 | node->arr_size = array_pop(parser->nodes); | ||
486 | parse_consume(parser, TOK_RSQUARE, | ||
487 | cstr("unmatched brackets ']' in array type")); | ||
488 | } | ||
489 | array_push(parser->nodes, node, parser->storage); | 604 | array_push(parser->nodes, node, parser->storage); |
490 | } | 605 | } |
491 | 606 | ||
@@ -497,29 +612,31 @@ parse_struct_field(Parser *parser) { | |||
497 | print_token(parser->previous); | 612 | print_token(parser->previous); |
498 | #endif | 613 | #endif |
499 | Node *field = node_alloc(parser, NODE_FIELD, parser->current); | 614 | Node *field = node_alloc(parser, NODE_FIELD, parser->current); |
500 | if (!field) return; | ||
501 | parse_consume(parser, TOK_SYMBOL, | 615 | parse_consume(parser, TOK_SYMBOL, |
502 | cstr("expected symbol name on struct field")); | 616 | cstr("expected symbol name on struct field")); |
503 | field->value.sym = parser->previous.val; | 617 | field->value.sym = parser->previous.val; |
504 | parse_consume(parser, TOK_COLON, cstr("expected type in struct field")); | 618 | parse_consume(parser, TOK_COLON, cstr("expected type in struct field")); |
505 | if (parse_match(parser, TOK_LCURLY)) { | 619 | if (parse_match(parser, TOK_LCURLY)) { |
506 | Node *type = node_alloc(parser, NODE_COMPOUND_TYPE, parser->current); | 620 | Node *type = node_alloc(parser, NODE_COMPOUND_TYPE, parser->current); |
507 | if (!type) return; | 621 | type->parent = field; |
508 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | 622 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { |
509 | parse_struct_field(parser); | 623 | parse_struct_field(parser); |
510 | Node *subfield = array_pop(parser->nodes); | 624 | Node *subfield = array_pop(parser->nodes); |
625 | subfield->parent = type; | ||
511 | array_push(type->elements, subfield, parser->storage); | 626 | array_push(type->elements, subfield, parser->storage); |
512 | } | 627 | } |
513 | field->field_type = type; | 628 | field->field.type = type; |
514 | } else { | 629 | } else { |
515 | parse_type(parser); | 630 | parse_type(parser); |
516 | field->field_type = array_pop(parser->nodes); | 631 | field->field.type = array_pop(parser->nodes); |
632 | field->field.type->parent = field; | ||
517 | } | 633 | } |
518 | 634 | ||
519 | // Optional assignment. | 635 | // Optional assignment. |
520 | if (parse_match(parser, TOK_ASSIGN)) { | 636 | if (parse_match(parser, TOK_ASSIGN)) { |
521 | parse_expr(parser, PREC_LOW); | 637 | parse_expr(parser, PREC_LOW); |
522 | field->field_val = array_pop(parser->nodes); | 638 | field->field.val = array_pop(parser->nodes); |
639 | field->field.val->parent = field; | ||
523 | } | 640 | } |
524 | array_push(parser->nodes, field, parser->storage); | 641 | array_push(parser->nodes, field, parser->storage); |
525 | } | 642 | } |
@@ -532,7 +649,6 @@ parse_struct_lit_field(Parser *parser) { | |||
532 | print_token(parser->previous); | 649 | print_token(parser->previous); |
533 | #endif | 650 | #endif |
534 | Node *field = node_alloc(parser, NODE_FIELD, parser->current); | 651 | Node *field = node_alloc(parser, NODE_FIELD, parser->current); |
535 | if (!field) return; | ||
536 | parse_consume(parser, TOK_SYMBOL, | 652 | parse_consume(parser, TOK_SYMBOL, |
537 | cstr("expected symbol name on struct field")); | 653 | cstr("expected symbol name on struct field")); |
538 | field->value.sym = parser->previous.val; | 654 | field->value.sym = parser->previous.val; |
@@ -540,16 +656,18 @@ parse_struct_lit_field(Parser *parser) { | |||
540 | cstr("expected field value on struct literal")); | 656 | cstr("expected field value on struct literal")); |
541 | if (parse_match(parser, TOK_LCURLY)) { | 657 | if (parse_match(parser, TOK_LCURLY)) { |
542 | Node *type = node_alloc(parser, NODE_COMPOUND_TYPE, parser->current); | 658 | Node *type = node_alloc(parser, NODE_COMPOUND_TYPE, parser->current); |
543 | if (!type) return; | 659 | type->parent = field; |
544 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | 660 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { |
545 | parse_struct_lit_field(parser); | 661 | parse_struct_lit_field(parser); |
546 | Node *subfield = array_pop(parser->nodes); | 662 | Node *subfield = array_pop(parser->nodes); |
663 | subfield->parent = type; | ||
547 | array_push(type->elements, subfield, parser->storage); | 664 | array_push(type->elements, subfield, parser->storage); |
548 | } | 665 | } |
549 | field->field_val = type; | 666 | field->field.val = type; |
550 | } else { | 667 | } else { |
551 | parse_expr(parser, PREC_LOW); | 668 | parse_expr(parser, PREC_LOW); |
552 | field->field_val = array_pop(parser->nodes); | 669 | field->field.val = array_pop(parser->nodes); |
670 | field->field.val->parent = field; | ||
553 | } | 671 | } |
554 | array_push(parser->nodes, field, parser->storage); | 672 | array_push(parser->nodes, field, parser->storage); |
555 | } | 673 | } |
@@ -566,12 +684,12 @@ parse_keyword(Parser *parser) { | |||
566 | switch (prev.kind) { | 684 | switch (prev.kind) { |
567 | case TOK_LET: { | 685 | case TOK_LET: { |
568 | node = node_alloc(parser, NODE_LET, prev); | 686 | node = node_alloc(parser, NODE_LET, prev); |
569 | if (!node) return; | ||
570 | parse_consume(parser, TOK_SYMBOL, | 687 | parse_consume(parser, TOK_SYMBOL, |
571 | cstr("expected symbol name on let expression")); | 688 | cstr("expected symbol name on let expression")); |
572 | parse_symbol(parser); | 689 | parse_symbol(parser); |
573 | node->var_name = array_pop(parser->nodes); | 690 | node->var.name = array_pop(parser->nodes); |
574 | if (node->var_name->next) { | 691 | node->var.name->parent = node; |
692 | if (node->var.name->sym.next) { | ||
575 | parse_emit_err(parser, prev, | 693 | parse_emit_err(parser, prev, |
576 | cstr("invalid symbol name in let expression")); | 694 | cstr("invalid symbol name in let expression")); |
577 | return; | 695 | return; |
@@ -580,16 +698,18 @@ parse_keyword(Parser *parser) { | |||
580 | // Optional type declaration. | 698 | // Optional type declaration. |
581 | if (parse_match(parser, TOK_COLON)) { | 699 | if (parse_match(parser, TOK_COLON)) { |
582 | parse_type(parser); | 700 | parse_type(parser); |
583 | node->var_type = array_pop(parser->nodes); | 701 | node->var.type = array_pop(parser->nodes); |
702 | node->var.type->parent = node; | ||
584 | } | 703 | } |
585 | 704 | ||
586 | // Optional assignment. | 705 | // Optional assignment. |
587 | if (parse_match(parser, TOK_ASSIGN)) { | 706 | if (parse_match(parser, TOK_ASSIGN)) { |
588 | parse_expr(parser, PREC_LOW); | 707 | parse_expr(parser, PREC_LOW); |
589 | node->var_val = array_pop(parser->nodes); | 708 | node->var.val = array_pop(parser->nodes); |
709 | node->var.val->parent = node; | ||
590 | } | 710 | } |
591 | 711 | ||
592 | if (node->var_type == NULL && node->var_val == NULL) { | 712 | if (node->var.type == NULL && node->var.val == NULL) { |
593 | parse_emit_err(parser, prev, | 713 | parse_emit_err(parser, prev, |
594 | cstr("variable declaration must include type or " | 714 | cstr("variable declaration must include type or " |
595 | "value information")); | 715 | "value information")); |
@@ -597,19 +717,58 @@ parse_keyword(Parser *parser) { | |||
597 | } break; | 717 | } break; |
598 | case TOK_SET: { | 718 | case TOK_SET: { |
599 | node = node_alloc(parser, NODE_SET, prev); | 719 | node = node_alloc(parser, NODE_SET, prev); |
600 | if (!node) return; | ||
601 | parse_consume(parser, TOK_SYMBOL, | 720 | parse_consume(parser, TOK_SYMBOL, |
602 | cstr("expected symbol name on let expression")); | 721 | cstr("expected symbol name on set expression")); |
603 | parse_symbol(parser); | 722 | parse_symbol(parser); |
604 | node->var_name = array_pop(parser->nodes); | 723 | node->var.name = array_pop(parser->nodes); |
605 | parse_consume(parser, TOK_ASSIGN, | 724 | node->var.name->parent = node; |
606 | cstr("expected assignment on set expression")); | 725 | |
607 | parse_expr(parser, PREC_LOW); | 726 | if (parse_match(parser, TOK_ADD_ASSIGN) || |
608 | node->var_val = array_pop(parser->nodes); | 727 | parse_match(parser, TOK_ADD_ASSIGN) || |
728 | parse_match(parser, TOK_SUB_ASSIGN) || | ||
729 | parse_match(parser, TOK_MUL_ASSIGN) || | ||
730 | parse_match(parser, TOK_DIV_ASSIGN) || | ||
731 | parse_match(parser, TOK_MOD_ASSIGN) || | ||
732 | parse_match(parser, TOK_BITAND_ASSIGN) || | ||
733 | parse_match(parser, TOK_BITOR_ASSIGN) || | ||
734 | parse_match(parser, TOK_BITXOR_ASSIGN) || | ||
735 | parse_match(parser, TOK_BITLSHIFT_ASSIGN) || | ||
736 | parse_match(parser, TOK_BITRSHIFT_ASSIGN)) { | ||
737 | NodeKind kind = NODE_ERR; | ||
738 | switch (parser->previous.kind) { | ||
739 | case TOK_ADD_ASSIGN: kind = NODE_ADD; break; | ||
740 | case TOK_SUB_ASSIGN: kind = NODE_SUB; break; | ||
741 | case TOK_MUL_ASSIGN: kind = NODE_MUL; break; | ||
742 | case TOK_DIV_ASSIGN: kind = NODE_DIV; break; | ||
743 | case TOK_MOD_ASSIGN: kind = NODE_MOD; break; | ||
744 | case TOK_BITAND_ASSIGN: kind = NODE_BITAND; break; | ||
745 | case TOK_BITOR_ASSIGN: kind = NODE_BITOR; break; | ||
746 | case TOK_BITXOR_ASSIGN: kind = NODE_BITXOR; break; | ||
747 | case TOK_BITLSHIFT_ASSIGN: kind = NODE_BITLSHIFT; break; | ||
748 | case TOK_BITRSHIFT_ASSIGN: kind = NODE_BITRSHIFT; break; | ||
749 | default: break; | ||
750 | } | ||
751 | parse_expr(parser, PREC_LOW); | ||
752 | Node *value = array_pop(parser->nodes); | ||
753 | Node *sym = node_alloc(parser, NODE_SYMBOL, prev); | ||
754 | Node *op = node_alloc(parser, kind, prev); | ||
755 | op->binary.left = sym; | ||
756 | op->binary.right = value; | ||
757 | sym->parent = op; | ||
758 | value->parent = op; | ||
759 | node->var.val = op; | ||
760 | node->var.val->parent = node; | ||
761 | sym->value = node->var.name->value; | ||
762 | sym->kind = node->var.name->kind; | ||
763 | } else { | ||
764 | parse_consume(parser, TOK_ASSIGN, | ||
765 | cstr("expected assignment on set expression")); | ||
766 | parse_expr(parser, PREC_LOW); | ||
767 | node->var.val = array_pop(parser->nodes); | ||
768 | } | ||
609 | } break; | 769 | } break; |
610 | case TOK_STRUCT: { | 770 | case TOK_STRUCT: { |
611 | node = node_alloc(parser, NODE_STRUCT, prev); | 771 | node = node_alloc(parser, NODE_STRUCT, prev); |
612 | if (!node) return; | ||
613 | parse_consume(parser, TOK_SYMBOL, | 772 | parse_consume(parser, TOK_SYMBOL, |
614 | cstr("expected symbol name on struct definition")); | 773 | cstr("expected symbol name on struct definition")); |
615 | // Just consume this to avoid conflicts with struct literals. | 774 | // Just consume this to avoid conflicts with struct literals. |
@@ -621,54 +780,53 @@ parse_keyword(Parser *parser) { | |||
621 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | 780 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { |
622 | parse_struct_field(parser); | 781 | parse_struct_field(parser); |
623 | Node *field = array_pop(parser->nodes); | 782 | Node *field = array_pop(parser->nodes); |
624 | 783 | field->parent = node; | |
625 | array_push(node->struct_field, field, parser->storage); | 784 | array_push(node->struct_field, field, parser->storage); |
626 | } | 785 | } |
627 | } break; | 786 | } break; |
628 | case TOK_IF: { | 787 | case TOK_IF: { |
629 | node = node_alloc(parser, NODE_IF, prev); | 788 | node = node_alloc(parser, NODE_IF, prev); |
630 | if (!node) return; | ||
631 | parse_expr(parser, PREC_LOW); | 789 | parse_expr(parser, PREC_LOW); |
632 | node->cond_if = array_pop(parser->nodes); | 790 | node->ifelse.cond = array_pop(parser->nodes); |
791 | node->ifelse.cond->parent = node; | ||
633 | parse_expr(parser, PREC_LOW); | 792 | parse_expr(parser, PREC_LOW); |
634 | node->cond_expr = array_pop(parser->nodes); | 793 | node->ifelse.expr_true = array_pop(parser->nodes); |
794 | node->ifelse.expr_true->parent = node; | ||
635 | if (parse_match(parser, TOK_ELSE)) { | 795 | if (parse_match(parser, TOK_ELSE)) { |
636 | parse_expr(parser, PREC_LOW); | 796 | parse_expr(parser, PREC_LOW); |
637 | node->cond_else = array_pop(parser->nodes); | 797 | node->ifelse.expr_else = array_pop(parser->nodes); |
798 | node->ifelse.expr_else->parent = node; | ||
638 | } | 799 | } |
639 | } break; | 800 | } break; |
640 | case TOK_MATCH: { | 801 | case TOK_MATCH: { |
641 | node = node_alloc(parser, NODE_MATCH, prev); | 802 | node = node_alloc(parser, NODE_MATCH, prev); |
642 | if (!node) return; | ||
643 | parse_expr(parser, PREC_LOW); | 803 | parse_expr(parser, PREC_LOW); |
644 | node->match_expr = array_pop(parser->nodes); | 804 | node->match.expr = array_pop(parser->nodes); |
805 | node->match.expr->parent = node; | ||
645 | parse_consume(parser, TOK_LCURLY, | 806 | parse_consume(parser, TOK_LCURLY, |
646 | cstr("expected block of match cases")); | 807 | cstr("expected block of match cases")); |
647 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | 808 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { |
648 | Node *tmp = | 809 | Node *tmp = |
649 | node_alloc(parser, NODE_CASE_MATCH, parser->previous); | 810 | node_alloc(parser, NODE_CASE_MATCH, parser->previous); |
650 | if (!tmp) return; | 811 | tmp->parent = node; |
651 | // Are we on the default case. | 812 | // Are we on the default case. |
652 | if (!parse_match(parser, TOK_ELSE)) { | 813 | if (!parse_match(parser, TOK_ELSE)) { |
653 | parse_consume(parser, TOK_CASE, | 814 | parse_consume(parser, TOK_CASE, |
654 | cstr("expected case statement")); | 815 | cstr("expected case statement")); |
655 | parse_expr(parser, PREC_LOW); | 816 | parse_expr(parser, PREC_LOW); |
656 | tmp->case_value = array_pop(parser->nodes); | 817 | tmp->case_entry.cond = array_pop(parser->nodes); |
818 | tmp->case_entry.cond->parent = tmp; | ||
657 | } | 819 | } |
658 | parse_consume(parser, TOK_ASSIGN, | 820 | parse_consume(parser, TOK_ASSIGN, |
659 | cstr("malformed case statement")); | 821 | cstr("malformed case statement")); |
660 | parse_expr(parser, PREC_LOW); | 822 | parse_expr(parser, PREC_LOW); |
661 | tmp->case_expr = array_pop(parser->nodes); | 823 | tmp->case_entry.expr = array_pop(parser->nodes); |
662 | array_push(node->match_cases, tmp, parser->storage); | 824 | tmp->case_entry.expr->parent = tmp; |
825 | array_push(node->match.cases, tmp, parser->storage); | ||
663 | } | 826 | } |
664 | // TODO: Check that we only have literals on the match case, | ||
665 | // this could be done on the analysis step, but also here... | ||
666 | // TODO: Check that there are no multiple default or duplicated | ||
667 | // cases. | ||
668 | } break; | 827 | } break; |
669 | case TOK_ENUM: { | 828 | case TOK_ENUM: { |
670 | node = node_alloc(parser, NODE_ENUM, prev); | 829 | node = node_alloc(parser, NODE_ENUM, prev); |
671 | if (!node) return; | ||
672 | parse_consume(parser, TOK_SYMBOL, | 830 | parse_consume(parser, TOK_SYMBOL, |
673 | cstr("expected symbol name on enum definition")); | 831 | cstr("expected symbol name on enum definition")); |
674 | // Just consume this to avoid conflicts with struct literals. | 832 | // Just consume this to avoid conflicts with struct literals. |
@@ -677,13 +835,14 @@ parse_keyword(Parser *parser) { | |||
677 | cstr("expected '{' on enum definition")); | 835 | cstr("expected '{' on enum definition")); |
678 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | 836 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { |
679 | Node *field = node_alloc(parser, NODE_FIELD, parser->current); | 837 | Node *field = node_alloc(parser, NODE_FIELD, parser->current); |
680 | if (!field) return; | 838 | field->parent = node; |
681 | parse_consume(parser, TOK_SYMBOL, | 839 | parse_consume(parser, TOK_SYMBOL, |
682 | cstr("expected symbol name on enum definition")); | 840 | cstr("expected symbol name on enum definition")); |
683 | field->value.sym = parser->previous.val; | 841 | field->value.sym = parser->previous.val; |
684 | if (parse_match(parser, TOK_ASSIGN)) { | 842 | if (parse_match(parser, TOK_ASSIGN)) { |
685 | parse_expr(parser, PREC_LOW); | 843 | parse_expr(parser, PREC_LOW); |
686 | field->field_val = array_pop(parser->nodes); | 844 | field->field.val = array_pop(parser->nodes); |
845 | field->field.val->parent = field; | ||
687 | } | 846 | } |
688 | array_push(node->struct_field, field, parser->storage); | 847 | array_push(node->struct_field, field, parser->storage); |
689 | } | 848 | } |
@@ -693,144 +852,133 @@ parse_keyword(Parser *parser) { | |||
693 | } break; | 852 | } break; |
694 | case TOK_COND: { | 853 | case TOK_COND: { |
695 | node = node_alloc(parser, NODE_COND, prev); | 854 | node = node_alloc(parser, NODE_COND, prev); |
696 | if (!node) return; | ||
697 | parse_consume(parser, TOK_LCURLY, | 855 | parse_consume(parser, TOK_LCURLY, |
698 | cstr("expected '{' on cond expression")); | 856 | cstr("expected '{' on cond expression")); |
699 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | 857 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { |
700 | Node *tmp = | 858 | Node *tmp = |
701 | node_alloc(parser, NODE_CASE_COND, parser->previous); | 859 | node_alloc(parser, NODE_CASE_COND, parser->previous); |
702 | if (!tmp) return; | 860 | tmp->parent = node; |
703 | // Are we on the default case. | 861 | // Are we on the default case. |
704 | if (!parse_match(parser, TOK_ELSE)) { | 862 | if (!parse_match(parser, TOK_ELSE)) { |
705 | parse_expr(parser, PREC_LOW); | 863 | parse_expr(parser, PREC_LOW); |
706 | tmp->case_value = array_pop(parser->nodes); | 864 | tmp->case_entry.cond = array_pop(parser->nodes); |
865 | tmp->case_entry.cond->parent = tmp; | ||
707 | } | 866 | } |
708 | parse_consume(parser, TOK_ASSIGN, | 867 | parse_consume(parser, TOK_ASSIGN, |
709 | cstr("malformed case statement")); | 868 | cstr("malformed case statement")); |
710 | parse_expr(parser, PREC_LOW); | 869 | parse_expr(parser, PREC_LOW); |
711 | tmp->case_expr = array_pop(parser->nodes); | 870 | tmp->case_entry.expr = array_pop(parser->nodes); |
712 | array_push(node->match_cases, tmp, parser->storage); | 871 | tmp->case_entry.expr->parent = tmp; |
872 | array_push(node->match.cases, tmp, parser->storage); | ||
713 | } | 873 | } |
714 | } break; | 874 | } break; |
715 | case TOK_BREAK: { | 875 | case TOK_BREAK: { |
716 | node = node_alloc(parser, NODE_BREAK, prev); | 876 | node = node_alloc(parser, NODE_BREAK, prev); |
717 | if (!node) return; | ||
718 | } break; | 877 | } break; |
719 | case TOK_CONTINUE: { | 878 | case TOK_CONTINUE: { |
720 | node = node_alloc(parser, NODE_CONTINUE, prev); | 879 | node = node_alloc(parser, NODE_CONTINUE, prev); |
721 | if (!node) return; | 880 | } break; |
881 | case TOK_FOR: { | ||
882 | node = node_alloc(parser, NODE_BLOCK, prev); | ||
883 | |||
884 | Node *node_while = node_alloc(parser, NODE_WHILE, prev); | ||
885 | node_while->parent = node; | ||
886 | Node *block = node_alloc(parser, NODE_BLOCK, prev); | ||
887 | block->parent = node_while; | ||
888 | |||
889 | parse_expr(parser, PREC_LOW); | ||
890 | Node *pre = array_pop(parser->nodes); | ||
891 | pre->parent = node; | ||
892 | |||
893 | parse_expr(parser, PREC_LOW); | ||
894 | Node *cond = array_pop(parser->nodes); | ||
895 | cond->parent = node_while; | ||
896 | |||
897 | parse_expr(parser, PREC_LOW); | ||
898 | Node *post = array_pop(parser->nodes); | ||
899 | post->parent = block; | ||
900 | |||
901 | // Body. | ||
902 | parse_consume(parser, TOK_LCURLY, | ||
903 | cstr("expected '{' on for loop statement")); | ||
904 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | ||
905 | parse_expr(parser, PREC_LOW); | ||
906 | Node *next = array_pop(parser->nodes); | ||
907 | next->parent = block; | ||
908 | array_push(block->statements, next, parser->storage); | ||
909 | } | ||
910 | array_push(block->statements, post, parser->storage); | ||
911 | |||
912 | // Put everything together | ||
913 | node_while->loop.cond = cond; | ||
914 | node_while->loop.expr = block; | ||
915 | array_push(node->statements, pre, parser->storage); | ||
916 | array_push(node->statements, node_while, parser->storage); | ||
722 | } break; | 917 | } break; |
723 | case TOK_WHILE: { | 918 | case TOK_WHILE: { |
724 | node = node_alloc(parser, NODE_WHILE, prev); | 919 | node = node_alloc(parser, NODE_WHILE, prev); |
725 | if (!node) return; | ||
726 | parse_expr(parser, PREC_LOW); | 920 | parse_expr(parser, PREC_LOW); |
727 | node->while_cond = array_pop(parser->nodes); | 921 | node->loop.cond = array_pop(parser->nodes); |
922 | node->loop.cond->parent = node; | ||
728 | parse_expr(parser, PREC_LOW); | 923 | parse_expr(parser, PREC_LOW); |
729 | node->while_expr = array_pop(parser->nodes); | 924 | node->loop.expr = array_pop(parser->nodes); |
925 | node->loop.expr->parent = node; | ||
730 | } break; | 926 | } break; |
731 | case TOK_FUN: { | 927 | case TOK_FUN: { |
732 | node = node_alloc(parser, NODE_FUN, prev); | 928 | node = node_alloc(parser, NODE_FUN, prev); |
733 | if (!node) return; | ||
734 | parse_consume(parser, TOK_SYMBOL, cstr("expected function name")); | 929 | parse_consume(parser, TOK_SYMBOL, cstr("expected function name")); |
735 | Node *name = node_alloc(parser, NODE_SYMBOL, prev); | 930 | Node *name = node_alloc(parser, NODE_SYMBOL, prev); |
736 | if (!name) return; | 931 | name->parent = node; |
737 | name->value.sym = parser->previous.val; | 932 | name->value.sym = parser->previous.val; |
738 | node->func_name = name; | 933 | node->func.name = name; |
739 | parse_consume(parser, TOK_LPAREN, | 934 | parse_consume(parser, TOK_LPAREN, |
740 | cstr("expected '(' on function definition")); | 935 | cstr("expected '(' on function definition")); |
741 | // Parameters. | 936 | // Parameters. |
742 | while (!parse_match(parser, TOK_RPAREN) && !parser->panic) { | 937 | while (!parse_match(parser, TOK_RPAREN) && !parser->panic) { |
743 | Node *param = | 938 | Node *param = |
744 | node_alloc(parser, NODE_FUN_PARAM, parser->current); | 939 | node_alloc(parser, NODE_FUN_PARAM, parser->current); |
745 | if (!param) return; | 940 | param->parent = node; |
941 | |||
942 | // Name. | ||
746 | Node *name = node_alloc(parser, NODE_SYMBOL, prev); | 943 | Node *name = node_alloc(parser, NODE_SYMBOL, prev); |
747 | if (!name) return; | ||
748 | parse_consume(parser, TOK_SYMBOL, cstr("expected symbol name")); | 944 | parse_consume(parser, TOK_SYMBOL, cstr("expected symbol name")); |
749 | name->value.sym = parser->previous.val; | 945 | name->value.sym = parser->previous.val; |
750 | param->param_name = name; | ||
751 | 946 | ||
752 | Node *type = node_alloc(parser, NODE_TYPE, prev); | 947 | // Type. |
753 | if (!type) return; | ||
754 | parse_consume(parser, TOK_COLON, cstr("expected param type")); | 948 | parse_consume(parser, TOK_COLON, cstr("expected param type")); |
755 | if (parse_match(parser, TOK_AT)) { | 949 | parse_type(parser); |
756 | type->is_ptr = true; | 950 | |
757 | } | 951 | // Put everything together. |
758 | parse_consume(parser, TOK_SYMBOL, cstr("expected param type")); | 952 | param->param.name = name; |
759 | type->value.sym = parser->previous.val; | 953 | param->param.type = array_pop(parser->nodes); |
760 | param->param_type = type; | 954 | param->param.name->parent = param; |
761 | if (parse_match(parser, TOK_LSQUARE)) { | 955 | param->param.type->parent = param; |
762 | type->kind = NODE_ARR_TYPE, | 956 | array_push(node->func.params, param, parser->storage); |
763 | parse_consume(parser, TOK_NUM_INT, | ||
764 | cstr("no array size given")); | ||
765 | parse_number(parser); | ||
766 | type->arr_size = array_pop(parser->nodes); | ||
767 | parse_consume(parser, TOK_RSQUARE, | ||
768 | cstr("unmatched brackets ']' in array type")); | ||
769 | } | ||
770 | array_push(node->func_params, param, parser->storage); | ||
771 | } | 957 | } |
772 | parse_consume(parser, TOK_COLON, cstr("expected param type")); | ||
773 | 958 | ||
774 | // Return type(s). | 959 | // Return type(s). |
775 | if (!parse_match(parser, TOK_NIL)) { | 960 | // NOTE: We are setup here for multiple return values, but we are |
776 | if (parse_match(parser, TOK_LPAREN)) { | 961 | // currently only considering a single one for simplicity. |
777 | while (!parse_match(parser, TOK_RPAREN) && !parser->panic) { | 962 | if (parse_match(parser, TOK_COLON)) { |
778 | Node *ret = node_alloc(parser, NODE_TYPE, prev); | 963 | parse_type(parser); |
779 | if (!ret) return; | 964 | Node *ret = array_pop(parser->nodes); |
780 | if (parse_match(parser, TOK_AT)) { | 965 | ret->parent = node; |
781 | ret->is_ptr = true; | 966 | array_push(node->func.ret, ret, parser->storage); |
782 | } | ||
783 | parse_consume(parser, TOK_SYMBOL, | ||
784 | cstr("expected type name")); | ||
785 | ret->value.sym = parser->previous.val; | ||
786 | if (parse_match(parser, TOK_LSQUARE)) { | ||
787 | ret->kind = NODE_ARR_TYPE, | ||
788 | parse_consume(parser, TOK_NUM_INT, | ||
789 | cstr("no array size given")); | ||
790 | parse_number(parser); | ||
791 | ret->arr_size = array_pop(parser->nodes); | ||
792 | parse_consume(parser, TOK_RSQUARE, | ||
793 | cstr("unmatched brackets ']' in " | ||
794 | "array type")); | ||
795 | } | ||
796 | array_push(node->func_ret, ret, parser->storage); | ||
797 | } | ||
798 | } else { | ||
799 | Node *ret = node_alloc(parser, NODE_TYPE, prev); | ||
800 | if (!ret) return; | ||
801 | if (parse_match(parser, TOK_AT)) { | ||
802 | ret->is_ptr = true; | ||
803 | } | ||
804 | parse_consume(parser, TOK_SYMBOL, | ||
805 | cstr("expected type name")); | ||
806 | ret->value.sym = parser->previous.val; | ||
807 | if (parse_match(parser, TOK_LSQUARE)) { | ||
808 | ret->kind = NODE_ARR_TYPE, | ||
809 | parse_consume(parser, TOK_NUM_INT, | ||
810 | cstr("no array size given")); | ||
811 | parse_number(parser); | ||
812 | ret->arr_size = array_pop(parser->nodes); | ||
813 | parse_consume( | ||
814 | parser, TOK_RSQUARE, | ||
815 | cstr("unmatched brackets ']' in array type")); | ||
816 | } | ||
817 | array_push(node->func_ret, ret, parser->storage); | ||
818 | } | ||
819 | } | 967 | } |
820 | 968 | ||
821 | // Body. | 969 | // Body. |
822 | parse_expr(parser, PREC_LOW); | 970 | parse_expr(parser, PREC_LOW); |
823 | node->func_body = array_pop(parser->nodes); | 971 | node->func.body = array_pop(parser->nodes); |
824 | } break; | 972 | } break; |
825 | case TOK_RETURN: { | 973 | case TOK_RETURN: { |
826 | node = node_alloc(parser, NODE_RETURN, prev); | 974 | node = node_alloc(parser, NODE_RETURN, prev); |
827 | if (!node) return; | ||
828 | parse_consume(parser, TOK_LPAREN, | 975 | parse_consume(parser, TOK_LPAREN, |
829 | cstr("expected '(' after return")); | 976 | cstr("expected '(' after return")); |
830 | while (!parse_match(parser, TOK_RPAREN) && !parser->panic) { | 977 | while (!parse_match(parser, TOK_RPAREN) && !parser->panic) { |
831 | parse_expr(parser, PREC_LOW); | 978 | parse_expr(parser, PREC_LOW); |
832 | array_push(node->expressions, array_pop(parser->nodes), | 979 | Node *val = array_pop(parser->nodes); |
833 | parser->storage); | 980 | val->parent = node; |
981 | array_push(node->expressions, val, parser->storage); | ||
834 | } | 982 | } |
835 | } break; | 983 | } break; |
836 | default: return; // Unreachable. | 984 | default: return; // Unreachable. |
@@ -870,6 +1018,9 @@ parse_binary(Parser *parser) { | |||
870 | case TOK_BITOR: { | 1018 | case TOK_BITOR: { |
871 | node = node_alloc(parser, NODE_BITOR, prev); | 1019 | node = node_alloc(parser, NODE_BITOR, prev); |
872 | } break; | 1020 | } break; |
1021 | case TOK_BITXOR: { | ||
1022 | node = node_alloc(parser, NODE_BITXOR, prev); | ||
1023 | } break; | ||
873 | case TOK_BITLSHIFT: { | 1024 | case TOK_BITLSHIFT: { |
874 | node = node_alloc(parser, NODE_BITLSHIFT, prev); | 1025 | node = node_alloc(parser, NODE_BITLSHIFT, prev); |
875 | } break; | 1026 | } break; |
@@ -881,9 +1032,10 @@ parse_binary(Parser *parser) { | |||
881 | return; | 1032 | return; |
882 | } | 1033 | } |
883 | } | 1034 | } |
884 | if (!node) return; | 1035 | node->binary.right = array_pop(parser->nodes); |
885 | node->right = array_pop(parser->nodes); | 1036 | node->binary.left = array_pop(parser->nodes); |
886 | node->left = array_pop(parser->nodes); | 1037 | node->binary.right->parent = node; |
1038 | node->binary.left->parent = node; | ||
887 | array_push(parser->nodes, node, parser->storage); | 1039 | array_push(parser->nodes, node, parser->storage); |
888 | } | 1040 | } |
889 | 1041 | ||
@@ -901,22 +1053,18 @@ parse_number(Parser *parser) { | |||
901 | if (str_has_prefix(prev.val, cstr("0x")) || | 1053 | if (str_has_prefix(prev.val, cstr("0x")) || |
902 | str_has_prefix(prev.val, cstr("0b"))) { | 1054 | str_has_prefix(prev.val, cstr("0b"))) { |
903 | node = node_alloc(parser, NODE_NUM_UINT, prev); | 1055 | node = node_alloc(parser, NODE_NUM_UINT, prev); |
904 | if (!node) return; | ||
905 | node->value.u = str_to_uint(prev.val); | 1056 | node->value.u = str_to_uint(prev.val); |
906 | } else { | 1057 | } else { |
907 | node = node_alloc(parser, NODE_NUM_INT, prev); | 1058 | node = node_alloc(parser, NODE_NUM_INT, prev); |
908 | if (!node) return; | ||
909 | node->value.i = str_to_int(prev.val); | 1059 | node->value.i = str_to_int(prev.val); |
910 | } | 1060 | } |
911 | } break; | 1061 | } break; |
912 | case TOK_NUM_FLOAT: { | 1062 | case TOK_NUM_FLOAT: { |
913 | node = node_alloc(parser, NODE_NUM_FLOAT, prev); | 1063 | node = node_alloc(parser, NODE_NUM_FLOAT, prev); |
914 | if (!node) return; | ||
915 | node->value.d = str_to_float(prev.val); | 1064 | node->value.d = str_to_float(prev.val); |
916 | } break; | 1065 | } break; |
917 | case TOK_CHAR: { | 1066 | case TOK_CHAR: { |
918 | node = node_alloc(parser, NODE_NUM_INT, prev); | 1067 | node = node_alloc(parser, NODE_NUM_INT, prev); |
919 | if (!node) return; | ||
920 | node->value.i = prev.val.mem[1]; | 1068 | node->value.i = prev.val.mem[1]; |
921 | } break; | 1069 | } break; |
922 | default: break; | 1070 | default: break; |
@@ -933,7 +1081,6 @@ parse_string(Parser *parser) { | |||
933 | print_token(prev); | 1081 | print_token(prev); |
934 | #endif | 1082 | #endif |
935 | Node *node = node_alloc(parser, NODE_STRING, prev); | 1083 | Node *node = node_alloc(parser, NODE_STRING, prev); |
936 | if (!node) return; | ||
937 | node->value.str = str_remove_prefix(prev.val, cstr("\"")); | 1084 | node->value.str = str_remove_prefix(prev.val, cstr("\"")); |
938 | node->value.str = str_remove_suffix(node->value.str, cstr("\"")); | 1085 | node->value.str = str_remove_suffix(node->value.str, cstr("\"")); |
939 | array_push(parser->nodes, node, parser->storage); | 1086 | array_push(parser->nodes, node, parser->storage); |
@@ -947,25 +1094,27 @@ parse_symbol(Parser *parser) { | |||
947 | print("parsing symbol "); | 1094 | print("parsing symbol "); |
948 | print_token(prev); | 1095 | print_token(prev); |
949 | #endif | 1096 | #endif |
1097 | // Dereference operators. | ||
950 | if (prev.kind == TOK_AT) { | 1098 | if (prev.kind == TOK_AT) { |
1099 | Node *node = node_alloc(parser, NODE_PTR, parser->previous); | ||
951 | parse_consume(parser, TOK_SYMBOL, | 1100 | parse_consume(parser, TOK_SYMBOL, |
952 | cstr("expected symbol after '.' operator")); | 1101 | cstr("expected symbol after '@' operator")); |
953 | parse_symbol(parser); | 1102 | parse_symbol(parser); |
954 | Node *node = array_pop(parser->nodes); | 1103 | node->t.next = array_pop(parser->nodes); |
955 | if (node) { | 1104 | node->t.next->parent = node; |
956 | node->is_ptr = true; | 1105 | array_push(parser->nodes, node, parser->storage); |
957 | array_push(parser->nodes, node, parser->storage); | ||
958 | } | ||
959 | return; | 1106 | return; |
960 | } | 1107 | } |
1108 | |||
961 | Node *node = node_alloc(parser, NODE_SYMBOL, prev); | 1109 | Node *node = node_alloc(parser, NODE_SYMBOL, prev); |
962 | if (!node) return; | 1110 | node->value.sym = prev.val; |
963 | if (parse_match(parser, TOK_DOT)) { | 1111 | if (parse_match(parser, TOK_DOT)) { |
964 | // Symbol chain. | 1112 | // Symbol chain. |
965 | parse_consume(parser, TOK_SYMBOL, | 1113 | parse_consume(parser, TOK_SYMBOL, |
966 | cstr("expected symbol after '.' operator")); | 1114 | cstr("expected symbol after '.' operator")); |
967 | parse_symbol(parser); | 1115 | parse_symbol(parser); |
968 | node->next = array_pop(parser->nodes); | 1116 | node->sym.next = array_pop(parser->nodes); |
1117 | node->sym.next->parent = node; | ||
969 | } else if (parser->current.kind == TOK_COLON && | 1118 | } else if (parser->current.kind == TOK_COLON && |
970 | parse_peek(parser) == TOK_LCURLY) { | 1119 | parse_peek(parser) == TOK_LCURLY) { |
971 | parse_advance(parser); | 1120 | parse_advance(parser); |
@@ -976,37 +1125,62 @@ parse_symbol(Parser *parser) { | |||
976 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | 1125 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { |
977 | parse_struct_lit_field(parser); | 1126 | parse_struct_lit_field(parser); |
978 | Node *field = array_pop(parser->nodes); | 1127 | Node *field = array_pop(parser->nodes); |
1128 | field->parent = node; | ||
979 | array_push(node->elements, field, parser->storage); | 1129 | array_push(node->elements, field, parser->storage); |
980 | } | 1130 | } |
981 | } else if (parse_match(parser, TOK_LSQUARE)) { | 1131 | } else if (parse_match(parser, TOK_LSQUARE)) { |
982 | node->kind = NODE_SYMBOL_IDX; | 1132 | Node *index = node_alloc(parser, NODE_INDEX, prev); |
1133 | Node *start = index; | ||
983 | parse_expr(parser, PREC_LOW); | 1134 | parse_expr(parser, PREC_LOW); |
984 | node->arr_size = array_pop(parser->nodes); | ||
985 | parse_consume(parser, TOK_RSQUARE, | 1135 | parse_consume(parser, TOK_RSQUARE, |
986 | cstr("unmatched brackets ']' in array type")); | 1136 | cstr("unmatched brackets ']' in array type")); |
987 | if (parse_match(parser, TOK_DOT)) { | 1137 | index->idx.value = array_pop(parser->nodes); |
988 | // Symbol chain. | 1138 | index->idx.value->parent = start; |
989 | parse_consume(parser, TOK_SYMBOL, | 1139 | while (parse_match(parser, TOK_LSQUARE)) { |
990 | cstr("expected symbol after '.' operator")); | 1140 | Node *next = node_alloc(parser, NODE_INDEX, prev); |
991 | parse_symbol(parser); | 1141 | parse_expr(parser, PREC_LOW); |
992 | node->next = array_pop(parser->nodes); | 1142 | parse_consume(parser, TOK_RSQUARE, |
1143 | cstr("unmatched brackets ']' in array type")); | ||
1144 | next->idx.value = array_pop(parser->nodes); | ||
1145 | next->parent = index; | ||
1146 | index->idx.next = next; | ||
1147 | index = next; | ||
993 | } | 1148 | } |
1149 | |||
1150 | index->idx.next = node; | ||
1151 | index->idx.next->parent = index; | ||
1152 | array_push(parser->nodes, start, parser->storage); | ||
1153 | return; | ||
994 | } else if (parse_match(parser, TOK_LPAREN)) { | 1154 | } else if (parse_match(parser, TOK_LPAREN)) { |
995 | node->kind = NODE_FUNCALL; | 1155 | node->kind = NODE_FUNCALL; |
996 | while (!parse_match(parser, TOK_RPAREN) && !parser->panic) { | 1156 | while (!parse_match(parser, TOK_RPAREN) && !parser->panic) { |
997 | parse_expr(parser, PREC_LOW); | 1157 | parse_expr(parser, PREC_LOW); |
998 | array_push(node->arguments, array_pop(parser->nodes), | 1158 | Node *arg = array_pop(parser->nodes); |
999 | parser->storage); | 1159 | arg->parent = node; |
1160 | array_push(node->arguments, arg, parser->storage); | ||
1000 | } | 1161 | } |
1001 | if (parse_match(parser, TOK_DOT)) { | 1162 | if (parse_match(parser, TOK_DOT)) { |
1002 | // Symbol chain. | 1163 | // Symbol chain. |
1003 | parse_consume(parser, TOK_SYMBOL, | 1164 | parse_consume(parser, TOK_SYMBOL, |
1004 | cstr("expected symbol after '.' operator")); | 1165 | cstr("expected symbol after '.' operator")); |
1005 | parse_symbol(parser); | 1166 | parse_symbol(parser); |
1006 | node->next = array_pop(parser->nodes); | 1167 | node->sym.next = array_pop(parser->nodes); |
1168 | node->sym.next->parent = node; | ||
1169 | } | ||
1170 | } else if (parse_match(parser, TOK_AT)) { | ||
1171 | Node *deref = node_alloc(parser, NODE_DEREF, prev); | ||
1172 | Node *start = deref; | ||
1173 | while (parse_match(parser, TOK_AT)) { | ||
1174 | Node *next = node_alloc(parser, NODE_DEREF, prev); | ||
1175 | next->parent = deref; | ||
1176 | deref->deref.next = next; | ||
1177 | deref = next; | ||
1007 | } | 1178 | } |
1179 | deref->deref.next = node; | ||
1180 | deref->deref.next->parent = deref; | ||
1181 | array_push(parser->nodes, start, parser->storage); | ||
1182 | return; | ||
1008 | } | 1183 | } |
1009 | node->value.sym = prev.val; | ||
1010 | array_push(parser->nodes, node, parser->storage); | 1184 | array_push(parser->nodes, node, parser->storage); |
1011 | } | 1185 | } |
1012 | 1186 | ||
@@ -1032,62 +1206,71 @@ graph_node(Node *node) { | |||
1032 | case NODE_NUM_UINT: print("| Value: %x", node->value.u); break; | 1206 | case NODE_NUM_UINT: print("| Value: %x", node->value.u); break; |
1033 | case NODE_NUM_FLOAT: print("| Value: %f{2}", node->value.d); break; | 1207 | case NODE_NUM_FLOAT: print("| Value: %f{2}", node->value.d); break; |
1034 | case NODE_STRING: print("| Value: %s", node->value.str); break; | 1208 | case NODE_STRING: print("| Value: %s", node->value.str); break; |
1035 | case NODE_SYMBOL_IDX: | ||
1036 | case NODE_STRUCT: | 1209 | case NODE_STRUCT: |
1037 | case NODE_STRUCT_LIT: print("| Name: %s", node->value.sym); break; | 1210 | case NODE_STRUCT_LIT: print("| Name: %s", node->value.sym); break; |
1038 | case NODE_SYMBOL: | 1211 | case NODE_SYMBOL: |
1039 | case NODE_FUNCALL: | 1212 | case NODE_FUNCALL: |
1040 | case NODE_ARR_TYPE: | ||
1041 | case NODE_FIELD: | 1213 | case NODE_FIELD: |
1042 | case NODE_TYPE: { | 1214 | case NODE_TYPE: { |
1043 | if (node->is_ptr) { | 1215 | print("| Name: %s", node->value.sym); |
1044 | print("| Name: @%s", node->value.sym); | 1216 | } break; |
1045 | } else { | 1217 | case NODE_ARR: { |
1046 | print("| Name: %s", node->value.sym); | 1218 | if (node->array.kind == NODE_ARR_STATIC) { |
1219 | print("| Static [%d]", node->array.size->value.i); | ||
1220 | } else if (node->array.kind == NODE_ARR_SLICE) { | ||
1221 | print("| Slice []"); | ||
1222 | } else if (node->array.kind == NODE_ARR_DYNAMIC) { | ||
1223 | print("| Dynamic [...]"); | ||
1047 | } | 1224 | } |
1048 | } break; | 1225 | } break; |
1049 | default: break; | 1226 | default: break; |
1050 | } | 1227 | } |
1228 | if (node->unique_name.size > 0) { | ||
1229 | print("| Unique Name: %s", node->unique_name); | ||
1230 | } | ||
1051 | if (node->type.size > 0) { | 1231 | if (node->type.size > 0) { |
1052 | print("| Type: %s", node->type); | 1232 | print("| Type: %s", node->type); |
1053 | } | 1233 | } |
1054 | if (node->fun_params.size > 0) { | 1234 | if (node->type_params.size > 0) { |
1055 | print("| Params: %s", node->fun_params); | 1235 | print("| Params: %s", node->type_params); |
1056 | } | 1236 | } |
1057 | if (node->fun_return.size > 0) { | 1237 | if (node->type_returns.size > 0) { |
1058 | print("| Return: %s", node->fun_return); | 1238 | print("| Return: %s", node->type_returns); |
1059 | } | 1239 | } |
1060 | println("\"];"); | 1240 | println("\"];"); |
1061 | 1241 | ||
1242 | if (node->parent) { | ||
1243 | println("%d:w->%d:e;", node->id, node->parent->id); | ||
1244 | } | ||
1062 | switch (node->kind) { | 1245 | switch (node->kind) { |
1063 | case NODE_FUN: { | 1246 | case NODE_FUN: { |
1064 | for (sz i = 0; i < array_size(node->func_params); i++) { | 1247 | for (sz i = 0; i < array_size(node->func.params); i++) { |
1065 | Node *next = node->func_params[i]; | 1248 | Node *next = node->func.params[i]; |
1066 | println("%d:e->%d:w;", node->id, next->id); | 1249 | println("%d:e->%d:w;", node->id, next->id); |
1067 | graph_node(next); | 1250 | graph_node(next); |
1068 | } | 1251 | } |
1069 | for (sz i = 0; i < array_size(node->func_ret); i++) { | 1252 | for (sz i = 0; i < array_size(node->func.ret); i++) { |
1070 | Node *next = node->func_ret[i]; | 1253 | Node *next = node->func.ret[i]; |
1071 | println("%d:e->%d:w;", node->id, next->id); | 1254 | println("%d:e->%d:w;", node->id, next->id); |
1072 | graph_node(next); | 1255 | graph_node(next); |
1073 | } | 1256 | } |
1074 | if (node->func_name) { | 1257 | if (node->func.name) { |
1075 | println("%d:e->%d:w;", node->id, node->func_name->id); | 1258 | println("%d:e->%d:w;", node->id, node->func.name->id); |
1076 | graph_node(node->func_name); | 1259 | graph_node(node->func.name); |
1077 | } | 1260 | } |
1078 | if (node->func_body) { | 1261 | if (node->func.body) { |
1079 | println("%d:e->%d:w;", node->id, node->func_body->id); | 1262 | println("%d:e->%d:w;", node->id, node->func.body->id); |
1080 | graph_node(node->func_body); | 1263 | graph_node(node->func.body); |
1081 | } | 1264 | } |
1082 | } break; | 1265 | } break; |
1083 | case NODE_COND: | 1266 | case NODE_COND: |
1084 | case NODE_MATCH: { | 1267 | case NODE_MATCH: { |
1085 | if (node->match_expr) { | 1268 | if (node->match.expr) { |
1086 | println("%d:e->%d:w;", node->id, node->match_expr->id); | 1269 | println("%d:e->%d:w;", node->id, node->match.expr->id); |
1087 | graph_node(node->match_expr); | 1270 | graph_node(node->match.expr); |
1088 | } | 1271 | } |
1089 | for (sz i = 0; i < array_size(node->match_cases); i++) { | 1272 | for (sz i = 0; i < array_size(node->match.cases); i++) { |
1090 | Node *next = node->match_cases[i]; | 1273 | Node *next = node->match.cases[i]; |
1091 | println("%d:e->%d:w;", node->id, next->id); | 1274 | println("%d:e->%d:w;", node->id, next->id); |
1092 | graph_node(next); | 1275 | graph_node(next); |
1093 | } | 1276 | } |
@@ -1112,43 +1295,43 @@ graph_node(Node *node) { | |||
1112 | } | 1295 | } |
1113 | } break; | 1296 | } break; |
1114 | case NODE_IF: { | 1297 | case NODE_IF: { |
1115 | if (node->cond_if) { | 1298 | if (node->ifelse.cond) { |
1116 | println("%d:e->%d:w;", node->id, node->cond_if->id); | 1299 | println("%d:e->%d:w;", node->id, node->ifelse.cond->id); |
1117 | graph_node(node->cond_if); | 1300 | graph_node(node->ifelse.cond); |
1118 | } | 1301 | } |
1119 | if (node->cond_expr) { | 1302 | if (node->ifelse.expr_true) { |
1120 | println("%d:e->%d:w;", node->id, node->cond_expr->id); | 1303 | println("%d:e->%d:w;", node->id, node->ifelse.expr_true->id); |
1121 | graph_node(node->cond_expr); | 1304 | graph_node(node->ifelse.expr_true); |
1122 | } | 1305 | } |
1123 | if (node->cond_else) { | 1306 | if (node->ifelse.expr_else) { |
1124 | println("%d:e->%d:w;", node->id, node->cond_else->id); | 1307 | println("%d:e->%d:w;", node->id, node->ifelse.expr_else->id); |
1125 | graph_node(node->cond_else); | 1308 | graph_node(node->ifelse.expr_else); |
1126 | } | 1309 | } |
1127 | } break; | 1310 | } break; |
1128 | case NODE_FIELD: | 1311 | case NODE_FIELD: |
1129 | case NODE_SET: | 1312 | case NODE_SET: |
1130 | case NODE_LET: { | 1313 | case NODE_LET: { |
1131 | if (node->var_name) { | 1314 | if (node->var.name) { |
1132 | println("%d:e->%d:w;", node->id, node->var_name->id); | 1315 | println("%d:e->%d:w;", node->id, node->var.name->id); |
1133 | graph_node(node->var_name); | 1316 | graph_node(node->var.name); |
1134 | } | 1317 | } |
1135 | if (node->var_type) { | 1318 | if (node->var.type) { |
1136 | println("%d:e->%d:w;", node->id, node->var_type->id); | 1319 | println("%d:e->%d:w;", node->id, node->var.type->id); |
1137 | graph_node(node->var_type); | 1320 | graph_node(node->var.type); |
1138 | } | 1321 | } |
1139 | if (node->var_val) { | 1322 | if (node->var.val) { |
1140 | println("%d:e->%d:w;", node->id, node->var_val->id); | 1323 | println("%d:e->%d:w;", node->id, node->var.val->id); |
1141 | graph_node(node->var_val); | 1324 | graph_node(node->var.val); |
1142 | } | 1325 | } |
1143 | } break; | 1326 | } break; |
1144 | default: { | 1327 | default: { |
1145 | if (node->left) { | 1328 | if (node->binary.left) { |
1146 | println("%d:e->%d:w;", node->id, node->left->id); | 1329 | println("%d:e->%d:w;", node->id, node->binary.left->id); |
1147 | graph_node(node->left); | 1330 | graph_node(node->binary.left); |
1148 | } | 1331 | } |
1149 | if (node->right) { | 1332 | if (node->binary.right) { |
1150 | println("%d:e->%d:w;", node->id, node->right->id); | 1333 | println("%d:e->%d:w;", node->id, node->binary.right->id); |
1151 | graph_node(node->right); | 1334 | graph_node(node->binary.right); |
1152 | } | 1335 | } |
1153 | } break; | 1336 | } break; |
1154 | } | 1337 | } |