diff options
author | Bad Diode <bd@badd10de.dev> | 2022-04-06 08:02:52 -0300 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2022-04-06 08:02:52 -0300 |
commit | 11df0f4556f526189234be216fa16a2fcb8c308b (patch) | |
tree | d9459ebf0b99ef1ecadf4101da147d60935e916f /src | |
parent | 77b309ba82d090094f5f753342c3aa401cbf657d (diff) | |
download | bdl-11df0f4556f526189234be216fa16a2fcb8c308b.tar.gz bdl-11df0f4556f526189234be216fa16a2fcb8c308b.zip |
Add parsing of if statements
Diffstat (limited to 'src')
-rw-r--r-- | src/lexer.c | 10 | ||||
-rw-r--r-- | src/lexer.h | 5 | ||||
-rw-r--r-- | src/nodes.c | 14 | ||||
-rw-r--r-- | src/nodes.h | 8 | ||||
-rw-r--r-- | src/parser.c | 51 |
5 files changed, 86 insertions, 2 deletions
diff --git a/src/lexer.c b/src/lexer.c index 729ea14..b4dcaf5 100644 --- a/src/lexer.c +++ b/src/lexer.c | |||
@@ -29,6 +29,11 @@ static const char* token_str[] = { | |||
29 | [TOKEN_NOT] = "TOKEN_NOT", | 29 | [TOKEN_NOT] = "TOKEN_NOT", |
30 | [TOKEN_AND] = "TOKEN_AND", | 30 | [TOKEN_AND] = "TOKEN_AND", |
31 | [TOKEN_OR] = "TOKEN_OR", | 31 | [TOKEN_OR] = "TOKEN_OR", |
32 | [TOKEN_EQ] = "TOKEN_EQ", | ||
33 | [TOKEN_LT] = "TOKEN_LT", | ||
34 | [TOKEN_GT] = "TOKEN_GT", | ||
35 | [TOKEN_LE] = "TOKEN_LE", | ||
36 | [TOKEN_GE] = "TOKEN_GE", | ||
32 | [TOKEN_COLON] = "TOKEN_COLON", | 37 | [TOKEN_COLON] = "TOKEN_COLON", |
33 | [TOKEN_DOT] = "TOKEN_DOT", | 38 | [TOKEN_DOT] = "TOKEN_DOT", |
34 | [TOKEN_AT] = "TOKEN_AT", | 39 | [TOKEN_AT] = "TOKEN_AT", |
@@ -61,6 +66,11 @@ static const Keyword keywords[] = { | |||
61 | KEYWORD("not", TOKEN_NOT), | 66 | KEYWORD("not", TOKEN_NOT), |
62 | KEYWORD("and", TOKEN_AND), | 67 | KEYWORD("and", TOKEN_AND), |
63 | KEYWORD("or", TOKEN_OR), | 68 | KEYWORD("or", TOKEN_OR), |
69 | KEYWORD("=", TOKEN_EQ), | ||
70 | KEYWORD("<", TOKEN_LT), | ||
71 | KEYWORD(">", TOKEN_GT), | ||
72 | KEYWORD("<=", TOKEN_LE), | ||
73 | KEYWORD(">=", TOKEN_GE), | ||
64 | }; | 74 | }; |
65 | 75 | ||
66 | void | 76 | void |
diff --git a/src/lexer.h b/src/lexer.h index fa43ebb..949abaf 100644 --- a/src/lexer.h +++ b/src/lexer.h | |||
@@ -41,6 +41,11 @@ typedef enum TokenType { | |||
41 | TOKEN_NOT, | 41 | TOKEN_NOT, |
42 | TOKEN_AND, | 42 | TOKEN_AND, |
43 | TOKEN_OR, | 43 | TOKEN_OR, |
44 | TOKEN_EQ, | ||
45 | TOKEN_LT, | ||
46 | TOKEN_GT, | ||
47 | TOKEN_LE, | ||
48 | TOKEN_GE, | ||
44 | 49 | ||
45 | // Special operators. | 50 | // Special operators. |
46 | TOKEN_COLON, | 51 | TOKEN_COLON, |
diff --git a/src/nodes.c b/src/nodes.c index 3a63246..af3b772 100644 --- a/src/nodes.c +++ b/src/nodes.c | |||
@@ -11,6 +11,9 @@ alloc_node(NodeType type) { | |||
11 | 11 | ||
12 | void | 12 | void |
13 | print_node(Node *node) { | 13 | print_node(Node *node) { |
14 | if (node == NULL) { | ||
15 | return; | ||
16 | } | ||
14 | switch (node->type) { | 17 | switch (node->type) { |
15 | case NODE_NUMBER: { | 18 | case NODE_NUMBER: { |
16 | if (node->number.negative) { | 19 | if (node->number.negative) { |
@@ -73,6 +76,17 @@ print_node(Node *node) { | |||
73 | } | 76 | } |
74 | printf(" }"); | 77 | printf(" }"); |
75 | } break; | 78 | } break; |
79 | case NODE_IF: { | ||
80 | printf("(if "); | ||
81 | print_node(node->ifexpr.cond); | ||
82 | printf(" "); | ||
83 | print_node(node->ifexpr.expr_true); | ||
84 | if (node->ifexpr.expr_false != NULL) { | ||
85 | printf(" "); | ||
86 | print_node(node->ifexpr.expr_false); | ||
87 | } | ||
88 | printf(")"); | ||
89 | } break; | ||
76 | case NODE_FUN: { | 90 | case NODE_FUN: { |
77 | printf("(fun "); | 91 | printf("(fun "); |
78 | print_node(node->fun.name); | 92 | print_node(node->fun.name); |
diff --git a/src/nodes.h b/src/nodes.h index c1520b3..4fb48a1 100644 --- a/src/nodes.h +++ b/src/nodes.h | |||
@@ -12,6 +12,7 @@ typedef enum NodeType { | |||
12 | NODE_SET, | 12 | NODE_SET, |
13 | NODE_FUN, | 13 | NODE_FUN, |
14 | NODE_BLOCK, | 14 | NODE_BLOCK, |
15 | NODE_IF, | ||
15 | } NodeType; | 16 | } NodeType; |
16 | 17 | ||
17 | typedef struct Node { | 18 | typedef struct Node { |
@@ -63,6 +64,13 @@ typedef struct Node { | |||
63 | struct { | 64 | struct { |
64 | struct Node **expr; | 65 | struct Node **expr; |
65 | } block; | 66 | } block; |
67 | |||
68 | // If statement. | ||
69 | struct { | ||
70 | struct Node *cond; | ||
71 | struct Node *expr_true; | ||
72 | struct Node *expr_false; | ||
73 | } ifexpr; | ||
66 | }; | 74 | }; |
67 | } Node; | 75 | } Node; |
68 | 76 | ||
diff --git a/src/parser.c b/src/parser.c index 58ad722..b76e32f 100644 --- a/src/parser.c +++ b/src/parser.c | |||
@@ -291,7 +291,46 @@ parse_fun(Parser *parser) { | |||
291 | return NULL; | 291 | return NULL; |
292 | } | 292 | } |
293 | node->fun.body = body; | 293 | node->fun.body = body; |
294 | consume_rparen(parser); | 294 | if (!consume_rparen(parser)) { |
295 | return NULL; | ||
296 | } | ||
297 | |||
298 | return node; | ||
299 | } | ||
300 | |||
301 | Node * | ||
302 | parse_if(Parser *parser) { | ||
303 | next_token(parser); // Skip keyword. | ||
304 | |||
305 | Node *node = alloc_node(NODE_IF); | ||
306 | node->ifexpr.cond = NULL; | ||
307 | node->ifexpr.expr_true = NULL; | ||
308 | node->ifexpr.expr_false = NULL; | ||
309 | |||
310 | Node *cond = parse_next(parser); | ||
311 | if (cond == NULL) { | ||
312 | return NULL; | ||
313 | } | ||
314 | Node *expr_true = parse_next(parser); | ||
315 | if (expr_true == NULL) { | ||
316 | return NULL; | ||
317 | } | ||
318 | node->ifexpr.cond = cond; | ||
319 | node->ifexpr.expr_true = expr_true; | ||
320 | Token tok = peek_token(parser); | ||
321 | |||
322 | // Optional else statement. | ||
323 | if (tok.type != TOKEN_RPAREN) { | ||
324 | Node *expr_false = parse_next(parser); | ||
325 | if (expr_false == NULL) { | ||
326 | return NULL; | ||
327 | } | ||
328 | node->ifexpr.expr_false = expr_false; | ||
329 | } | ||
330 | |||
331 | if (!consume_rparen(parser)) { | ||
332 | return NULL; | ||
333 | } | ||
295 | 334 | ||
296 | return node; | 335 | return node; |
297 | } | 336 | } |
@@ -299,6 +338,7 @@ parse_fun(Parser *parser) { | |||
299 | Node * | 338 | Node * |
300 | parse_paren(Parser *parser) { | 339 | parse_paren(Parser *parser) { |
301 | next_token(parser); // Skip paren. | 340 | next_token(parser); // Skip paren. |
341 | |||
302 | Token tok = peek_token(parser); | 342 | Token tok = peek_token(parser); |
303 | 343 | ||
304 | switch (tok.type) { | 344 | switch (tok.type) { |
@@ -310,11 +350,17 @@ parse_paren(Parser *parser) { | |||
310 | case TOKEN_MOD: | 350 | case TOKEN_MOD: |
311 | case TOKEN_NOT: | 351 | case TOKEN_NOT: |
312 | case TOKEN_AND: | 352 | case TOKEN_AND: |
313 | case TOKEN_OR: { return parse_builtin(parser); } break; | 353 | case TOKEN_OR: |
354 | case TOKEN_EQ: | ||
355 | case TOKEN_LT: | ||
356 | case TOKEN_GT: | ||
357 | case TOKEN_LE: | ||
358 | case TOKEN_GE: { return parse_builtin(parser); } break; | ||
314 | // Special functions. | 359 | // Special functions. |
315 | case TOKEN_DEF: { return parse_def(parser); } break; | 360 | case TOKEN_DEF: { return parse_def(parser); } break; |
316 | case TOKEN_SET: { return parse_set(parser); } break; | 361 | case TOKEN_SET: { return parse_set(parser); } break; |
317 | case TOKEN_FUN: { return parse_fun(parser); } break; | 362 | case TOKEN_FUN: { return parse_fun(parser); } break; |
363 | case TOKEN_IF: { return parse_if(parser); } break; | ||
318 | default: break; | 364 | default: break; |
319 | } | 365 | } |
320 | 366 | ||
@@ -326,6 +372,7 @@ parse_paren(Parser *parser) { | |||
326 | Node * | 372 | Node * |
327 | parse_block(Parser *parser) { | 373 | parse_block(Parser *parser) { |
328 | next_token(parser); // Skip paren. | 374 | next_token(parser); // Skip paren. |
375 | |||
329 | Node *node = alloc_node(NODE_BLOCK); | 376 | Node *node = alloc_node(NODE_BLOCK); |
330 | array_init(node->block.expr, 0); | 377 | array_init(node->block.expr, 0); |
331 | while (true) { | 378 | while (true) { |