diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-19 08:43:17 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-19 08:51:00 +0200 |
commit | eed58fa9d2bccf9df9128e6eff08fcd08b6fa95e (patch) | |
tree | 67ac983d04880a6ac80d8b0cb71e05ebb0cc5ea0 | |
parent | faf69726d4fc619bc55a2c1105bd542673cce342 (diff) | |
download | bdl-eed58fa9d2bccf9df9128e6eff08fcd08b6fa95e.tar.gz bdl-eed58fa9d2bccf9df9128e6eff08fcd08b6fa95e.zip |
Change a few syntax constructs for consistency
-rw-r--r-- | src/lexer.c | 19 | ||||
-rw-r--r-- | src/main.c | 16 | ||||
-rw-r--r-- | tests/conditionals.bad | 14 | ||||
-rw-r--r-- | tests/loops.bad | 18 |
4 files changed, 50 insertions, 17 deletions
diff --git a/src/lexer.c b/src/lexer.c index 2d2b6fc..2feba2a 100644 --- a/src/lexer.c +++ b/src/lexer.c | |||
@@ -1,3 +1,6 @@ | |||
1 | #ifndef LEXER_C | ||
2 | #define LEXER_C | ||
3 | |||
1 | #include "badlib.h" | 4 | #include "badlib.h" |
2 | 5 | ||
3 | #define LEXER_MEM GB(2) | 6 | #define LEXER_MEM GB(2) |
@@ -610,3 +613,19 @@ scan_token(Scanner *scanner) { | |||
610 | } | 613 | } |
611 | return emit_token(current, scanner, TOK_SYMBOL); | 614 | return emit_token(current, scanner, TOK_SYMBOL); |
612 | } | 615 | } |
616 | |||
617 | void | ||
618 | print_token(Token tok) { | ||
619 | println("%d:%d\t%s %s", tok.line, tok.col, token_str[tok.kind], tok.val); | ||
620 | } | ||
621 | |||
622 | void | ||
623 | print_tokens(Str path, Token *tokens) { | ||
624 | for (sz i = 0; i < array_size(tokens); i++) { | ||
625 | Token tok = tokens[i]; | ||
626 | print("%s:", path); | ||
627 | print_token(tok); | ||
628 | } | ||
629 | } | ||
630 | |||
631 | #endif // LEXER_C | ||
@@ -584,8 +584,12 @@ parse_keyword(Parser *parser) { | |||
584 | case TOK_IF: { | 584 | case TOK_IF: { |
585 | node = node_alloc(parser, NODE_IF, prev); | 585 | node = node_alloc(parser, NODE_IF, prev); |
586 | if (!node) return; | 586 | if (!node) return; |
587 | parse_consume(parser, TOK_LPAREN, | ||
588 | cstr("expected '(' on if expression")); | ||
587 | parse_expr(parser, PREC_LOW); | 589 | parse_expr(parser, PREC_LOW); |
588 | node->cond_if = array_pop(parser->nodes); | 590 | node->cond_if = array_pop(parser->nodes); |
591 | parse_consume(parser, TOK_RPAREN, | ||
592 | cstr("expected ')' on if expression")); | ||
589 | parse_expr(parser, PREC_LOW); | 593 | parse_expr(parser, PREC_LOW); |
590 | node->cond_expr = array_pop(parser->nodes); | 594 | node->cond_expr = array_pop(parser->nodes); |
591 | if (parse_match(parser, TOK_ELSE)) { | 595 | if (parse_match(parser, TOK_ELSE)) { |
@@ -596,10 +600,12 @@ parse_keyword(Parser *parser) { | |||
596 | case TOK_MATCH: { | 600 | case TOK_MATCH: { |
597 | node = node_alloc(parser, NODE_MATCH, prev); | 601 | node = node_alloc(parser, NODE_MATCH, prev); |
598 | if (!node) return; | 602 | if (!node) return; |
603 | parse_consume(parser, TOK_LPAREN, | ||
604 | cstr("expected '(' on if expression")); | ||
599 | parse_expr(parser, PREC_LOW); | 605 | parse_expr(parser, PREC_LOW); |
600 | node->match_expr = array_pop(parser->nodes); | 606 | node->match_expr = array_pop(parser->nodes); |
601 | parse_consume(parser, TOK_ASSIGN, | 607 | parse_consume(parser, TOK_RPAREN, |
602 | cstr("malformed match statement")); | 608 | cstr("expected ')' on if expression")); |
603 | parse_consume(parser, TOK_LCURLY, | 609 | parse_consume(parser, TOK_LCURLY, |
604 | cstr("expected block of match cases")); | 610 | cstr("expected block of match cases")); |
605 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | 611 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { |
@@ -686,10 +692,12 @@ parse_keyword(Parser *parser) { | |||
686 | case TOK_WHILE: { | 692 | case TOK_WHILE: { |
687 | node = node_alloc(parser, NODE_WHILE, prev); | 693 | node = node_alloc(parser, NODE_WHILE, prev); |
688 | if (!node) return; | 694 | if (!node) return; |
695 | parse_consume(parser, TOK_LPAREN, | ||
696 | cstr("expected '(' on while expression")); | ||
689 | parse_expr(parser, PREC_LOW); | 697 | parse_expr(parser, PREC_LOW); |
690 | node->while_cond = array_pop(parser->nodes); | 698 | node->while_cond = array_pop(parser->nodes); |
691 | parse_consume(parser, TOK_ASSIGN, | 699 | parse_consume(parser, TOK_RPAREN, |
692 | cstr("malformed while expression")); | 700 | cstr("expected ')' on while expression")); |
693 | parse_expr(parser, PREC_LOW); | 701 | parse_expr(parser, PREC_LOW); |
694 | node->while_expr = array_pop(parser->nodes); | 702 | node->while_expr = array_pop(parser->nodes); |
695 | } break; | 703 | } break; |
diff --git a/tests/conditionals.bad b/tests/conditionals.bad index 856ac8a..e1a456e 100644 --- a/tests/conditionals.bad +++ b/tests/conditionals.bad | |||
@@ -1,26 +1,26 @@ | |||
1 | ; Basic if expressions. | 1 | ; Basic if expressions. |
2 | if true "hello" | 2 | if (true) "hello" |
3 | 3 | ||
4 | ; These can produce values and the result bound to a name. | 4 | ; These can produce values and the result bound to a name. |
5 | let a = if (2 + 2 >= 4) 42 | 5 | let a = if (2 + 2 >= 4) 42 |
6 | 6 | ||
7 | ; We support a single if expression. | 7 | ; We support a single if expression. |
8 | let b = if 0xff == 255 "hello" else "world" | 8 | let b = if (0xff == 255) "hello" else "world" |
9 | 9 | ||
10 | ; ... but these can compound on each other | 10 | ; ... but these can compound on each other |
11 | if 1 < 2 6 | 11 | if (1 < 2) 6 |
12 | else if 1 > 2 7 | 12 | else if (1 > 2) 7 |
13 | else 8 | 13 | else 8 |
14 | 14 | ||
15 | ; A block is an expression, and if raise the scope level regardless if a block | 15 | ; A block is an expression, and if raise the scope level regardless if a block |
16 | ; is used or not. | 16 | ; is used or not. |
17 | if true != false { | 17 | if (true != false) { |
18 | let a = "yo" | 18 | let a = "yo" |
19 | } | 19 | } |
20 | 20 | ||
21 | ; Match cases should only apply to literal values, for example `case 1 + 2` | 21 | ; Match cases should only apply to literal values, for example `case 1 + 2` |
22 | ; isn't allowed. They should generally convert to a lookup table. | 22 | ; isn't allowed. They should generally convert to a lookup table. |
23 | match a = { | 23 | match (a) { |
24 | case 8 = "hello" | 24 | case 8 = "hello" |
25 | case 9 = "world" | 25 | case 9 = "world" |
26 | else = "what" | 26 | else = "what" |
@@ -37,7 +37,7 @@ enum flags { | |||
37 | let a:flags = flags.node_add | 37 | let a:flags = flags.node_add |
38 | 38 | ||
39 | ; No need to qualify enum fields inside match-case. | 39 | ; No need to qualify enum fields inside match-case. |
40 | match a = { | 40 | match (a) { |
41 | case node_add = "adding something..." | 41 | case node_add = "adding something..." |
42 | case node_add = "subbing something..." | 42 | case node_add = "subbing something..." |
43 | else = "default case" | 43 | else = "default case" |
diff --git a/tests/loops.bad b/tests/loops.bad index 5221844..45c9712 100644 --- a/tests/loops.bad +++ b/tests/loops.bad | |||
@@ -1,18 +1,24 @@ | |||
1 | ; The most basic loop is the while loop. | 1 | ; The most basic loop is the while loop. |
2 | while abc = "heelo" | 2 | while (abc) "heelo" |
3 | 3 | ||
4 | while 1 + 2 == 3 = { | 4 | while (1 + 2 == 3) { |
5 | "hello" | 5 | "hello" |
6 | } | 6 | } |
7 | 7 | ||
8 | while symbol = { | 8 | while (symbol) { |
9 | "hello" | 9 | "hello" |
10 | } | 10 | } |
11 | 11 | ||
12 | |||
13 | ; We could use some sugar for this. | 12 | ; We could use some sugar for this. |
14 | let i = 0 | 13 | let i = 0 |
15 | while i < 10 = { | 14 | while (i < 10) { |
16 | "hello" | 15 | "hello" |
17 | set i = i + 1 | 16 | ; --i |
18 | } | 17 | } |
18 | ; TODO: add post/pre increment tokens | ||
19 | ; TODO: add functions | ||
20 | ; TODO: add function calls | ||
21 | |||
22 | ; for let i = 1, 1 < 10, i++ { | ||
23 | |||
24 | ; } | ||