From c0520617a974abd27c413fb21ecd64ca2d11d135 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sat, 30 Oct 2021 08:51:46 +0200 Subject: Add parsing for def/set! expressions --- src/parser.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 15 deletions(-) (limited to 'src/parser.c') diff --git a/src/parser.c b/src/parser.c index 5551dd2..f831e50 100644 --- a/src/parser.c +++ b/src/parser.c @@ -122,7 +122,7 @@ parse_lambda(Parser *parser, Errors *errors) { Object * parse_if(Parser *parser, Errors *errors) { Token start = next_token(parser); - Object *obj_if = object_alloc(start, OBJ_TYPE_IF); + Object *ret = object_alloc(start, OBJ_TYPE_IF); Token tok = peek_token(parser); if (tok.type == TOKEN_RPAREN) { @@ -134,7 +134,7 @@ parse_if(Parser *parser, Errors *errors) { }); return NULL; } - obj_if->condition = parse_tree(parser, errors); + ret->condition = parse_tree(parser, errors); tok = peek_token(parser); if (tok.type == TOKEN_RPAREN) { @@ -146,16 +146,16 @@ parse_if(Parser *parser, Errors *errors) { }); return NULL; } - obj_if->expr_true = parse_tree(parser, errors); + ret->expr_true = parse_tree(parser, errors); // Optional else expression. tok = peek_token(parser); if (tok.type == TOKEN_RPAREN) { next_token(parser); - obj_if->expr_false = NULL; - return obj_if; + ret->expr_false = NULL; + return ret; } - obj_if->expr_false = parse_tree(parser, errors); + ret->expr_false = parse_tree(parser, errors); tok = peek_token(parser); if (tok.type != TOKEN_RPAREN) { @@ -168,7 +168,62 @@ parse_if(Parser *parser, Errors *errors) { return NULL; } next_token(parser); - return obj_if; + return ret; +} + +Object * +parse_var(Parser *parser, Errors *errors) { + Token start = next_token(parser); + ObjectType type = start.type == TOKEN_DEF ? OBJ_TYPE_DEF : OBJ_TYPE_SET; + Object *ret = object_alloc(start, type); + + // Variable name. + Token tok = peek_token(parser); + if (tok.type == TOKEN_RPAREN) { + error_push(errors, (Error){ + .type = ERR_TYPE_PARSER, + .value = ERR_NOT_ENOUGH_ARGS, + .line = tok.line, + .col = tok.col, + }); + return NULL; + } + if (tok.type != TOKEN_SYMBOL) { + error_push(errors, (Error){ + .type = ERR_TYPE_PARSER, + .value = ERR_WRONG_ARG_TYPE, + .line = tok.line, + .col = tok.col, + }); + return NULL; + } + ret->var_name = parse_tree(parser, errors); + + // Variable value (expression). + tok = peek_token(parser); + if (tok.type == TOKEN_RPAREN) { + error_push(errors, (Error){ + .type = ERR_TYPE_PARSER, + .value = ERR_NOT_ENOUGH_ARGS, + .line = tok.line, + .col = tok.col, + }); + return NULL; + } + ret->var_expr = parse_tree(parser, errors); + + tok = peek_token(parser); + if (tok.type != TOKEN_RPAREN) { + error_push(errors, (Error){ + .type = ERR_TYPE_PARSER, + .value = ERR_TOO_MANY_ARGS, + .line = tok.line, + .col = tok.col, + }); + return NULL; + } + next_token(parser); + return ret; } Object * @@ -188,12 +243,10 @@ parse_list(Parser *parser, Errors *errors) { }); return NULL; } break; - case TOKEN_LAMBDA: { - return parse_lambda(parser, errors); - } break; - case TOKEN_IF: { - return parse_if(parser, errors); - } break; + case TOKEN_LAMBDA: { return parse_lambda(parser, errors); } break; + case TOKEN_IF: { return parse_if(parser, errors); } break; + case TOKEN_DEF: { return parse_var(parser, errors); } break; + case TOKEN_SET: { return parse_var(parser, errors); } break; default: break; } @@ -386,7 +439,7 @@ object_display(Object *obj) { printf(")"); } break; case OBJ_TYPE_LAMBDA: { - printf("#{ lambda( "); + printf("#{ lambda ( "); for (size_t i = 0; i < array_size(obj->params); i++) { object_display(obj->params[i]); printf(" "); @@ -408,7 +461,21 @@ object_display(Object *obj) { object_display(obj->expr_false); } printf(" }"); - }; + } break; + case OBJ_TYPE_DEF: { + printf("#{ def "); + object_display(obj->var_name); + printf(" "); + object_display(obj->var_expr); + printf(" }"); + } break; + case OBJ_TYPE_SET: { + printf("#{ set! "); + object_display(obj->var_name); + printf(" "); + object_display(obj->var_expr); + printf(" }"); + } break; } return; } -- cgit v1.2.1