From 496ec36c8002a85dc0c3bb62de6d176e369b40af Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sun, 3 Apr 2022 17:16:26 -0300 Subject: Add parsing for (set ...) statements --- src/lexer.c | 2 +- src/nodes.c | 7 +++++++ src/nodes.h | 6 ++++++ src/parser.c | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lexer.c b/src/lexer.c index 2ccd577..729ea14 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -50,7 +50,7 @@ static const Keyword keywords[] = { KEYWORD("lambda", TOKEN_LAMBDA), KEYWORD("if", TOKEN_IF), KEYWORD("def", TOKEN_DEF), - KEYWORD("set!", TOKEN_SET), + KEYWORD("set", TOKEN_SET), KEYWORD("fun", TOKEN_FUN), KEYWORD("struct", TOKEN_STRUCT), KEYWORD("+", TOKEN_ADD), diff --git a/src/nodes.c b/src/nodes.c index 63e9b1f..855d186 100644 --- a/src/nodes.c +++ b/src/nodes.c @@ -56,6 +56,13 @@ print_node(Node *node) { print_node(node->def.value); printf(")"); } break; + case NODE_SET: { + printf("(set "); + print_node(node->def.symbol); + printf(" "); + print_node(node->def.value); + printf(")"); + } break; default: { printf("{#unknown#}"); } break; } } diff --git a/src/nodes.h b/src/nodes.h index e6ceb50..566d6d3 100644 --- a/src/nodes.h +++ b/src/nodes.h @@ -8,6 +8,7 @@ typedef enum NodeType { NODE_STRING, NODE_SYMBOL, NODE_DEF, + NODE_SET, } NodeType; typedef struct Node { @@ -39,6 +40,11 @@ typedef struct Node { struct Node *value; StringView type; } def; + + struct { + struct Node *symbol; + struct Node *value; + } set; }; } Node; diff --git a/src/parser.c b/src/parser.c index cc94fd2..b36ddc9 100644 --- a/src/parser.c +++ b/src/parser.c @@ -177,6 +177,33 @@ parse_def(Parser *parser) { return node; } +Node * +parse_set(Parser *parser) { + Token op = next_token(parser); + Node *symbol = parse_next(parser); + if (symbol == NULL || symbol->type != NODE_SYMBOL) { + push_error(ERR_TYPE_PARSER, ERR_MALFORMED_EXPR, op.line, op.col); + return NULL; + } + + Node *value = parse_next(parser); + if (value == NULL) { + push_error(ERR_TYPE_PARSER, ERR_MALFORMED_EXPR, op.line, op.col); + return NULL; + } + + Token end = next_token(parser); + if (end.type != TOKEN_RPAREN) { + push_error(ERR_TYPE_PARSER, ERR_MALFORMED_EXPR, op.line, op.col); + return NULL; + } + + Node *node = alloc_node(NODE_SET); + node->set.symbol = symbol; + node->set.value = value; + return node; +} + Node * parse_paren(Parser *parser) { next_token(parser); // Skip paren. @@ -194,6 +221,7 @@ parse_paren(Parser *parser) { case TOKEN_OR: { return parse_builtin(parser); } break; // Special functions. case TOKEN_DEF: { return parse_def(parser); } break; + case TOKEN_SET: { return parse_set(parser); } break; default: break; } @@ -202,6 +230,11 @@ parse_paren(Parser *parser) { return NULL; } + +// TODO: Parse if: (def ...) shouldn't be allowed for now on if statements. In +// the future, an if can create a new block and thus a fresh scope which would +// make the decision of what variables are active trivial. + Node * parse_next(Parser *parser) { Token tok = peek_token(parser); -- cgit v1.2.1