From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0.migadu.com ([2001:41d0:403:58f0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms5.migadu.com with LMTPS id 4DEaBq/Q4GbdSgEAqHPOHw:P1 (envelope-from ) for ; Wed, 11 Sep 2024 01:05:19 +0200 Received: from aspmx1.migadu.com ([2001:41d0:403:58f0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0.migadu.com with LMTPS id 4DEaBq/Q4GbdSgEAqHPOHw (envelope-from ) for ; Wed, 11 Sep 2024 01:05:19 +0200 X-Envelope-To: patches@johnnyrichard.com Authentication-Results: aspmx1.migadu.com; none Received: from mail-a.sr.ht (mail-a.sr.ht [46.23.81.152]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 09BD46D898 for ; Wed, 11 Sep 2024 01:05:19 +0200 (CEST) DKIM-Signature: a=rsa-sha256; bh=ynBrCd875jmUXGI+62M5jIe6BV5Gxvzm6rJpGtp2DlA=; c=simple/simple; d=lists.sr.ht; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-Unsubscribe:List-Subscribe:List-Archive:List-Post:List-ID; q=dns/txt; s=20240113; t=1726009518; v=1; b=qcL2wf3pEh3xdaYgMUyIniVbQROgpEpRPcvpPhPH2oZhxv3AqPpW7At+GKXP6ukTWx5uonc7 URWT6DgEm8c6QdC+PyTrKFHRYSCezcRh7KegILI033o3RV1xvWmwEKcAvOZ6K0TffAM7qgHt3zQ jTn1mzfubj6XiCj64JbKQPuAIt00o5fYh61L9gWX2yzs4P4YDZ2t0qG48ABtRTkEns+EVfT+kmP PNZP9BxdB0wkm5aywC7E6+6laNtJwy7BHNxsJpqMvSugbJm2DhsYME/b8Rkm2ZnnDFXeVt6xQx8 vxNpOiRKtGurFAJbT+KhopXpA8pxTdNpEKk5syH74lS+Q== Received: from lists.sr.ht (unknown [46.23.81.154]) by mail-a.sr.ht (Postfix) with ESMTPSA id A1CE72028D for ; Tue, 10 Sep 2024 23:05:18 +0000 (UTC) Received: from out-186.mta1.migadu.com (out-186.mta1.migadu.com [95.215.58.186]) by mail-a.sr.ht (Postfix) with ESMTPS id E774B20286 for <~johnnyrichard/olang-devel@lists.sr.ht>; Tue, 10 Sep 2024 23:05:17 +0000 (UTC) X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=johnnyrichard.com; s=key1; t=1726009517; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cPC64hzo74wajAQkDp98AXVSWjTTqtSCkzF0jf+gaFk=; b=2CQ2EIVVgjHhUII/Wn4wJKjqG/Sce8Vky2pvuzJnV+Dv9uObmG3zkd3uQxEUCQ2UxOuFpl CRuBbUE3YZXwIZPMMGqECuQSLHRDxc1+QXIIxRUh8izfDti18hnbNND6B8CyJfh3ezdYT0 xUIc07wLvZ4GXNYJOIMA47x2w4aeejkg55VM4lMM2wkW/c9gTbxJ90Gyis606GqQjTAsN/ tQ1Y1hyXhHk0XEVdjBva9kDthqcKjuXty43JoNPY84VK9QWVVQ+PWctyEsGjoO7naO9BBY XFMFwIRoN0BFiZD66Q7KkL6LRv/V1WlxQVDLVPpFBkNvYTGlH1KpIo5vkOwjPQ== From: Johnny Richard To: ~johnnyrichard/olang-devel@lists.sr.ht Cc: Johnny Richard Subject: [PATCH olang v1 2/2] parser: add var definition and reference support Date: Wed, 11 Sep 2024 03:03:47 +0200 Message-ID: <20240911010517.196175-3-johnny@johnnyrichard.com> In-Reply-To: <20240911010517.196175-1-johnny@johnnyrichard.com> References: <20240911010517.196175-1-johnny@johnnyrichard.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Sourcehut-Patchset-Status: PROPOSED List-Unsubscribe: List-Subscribe: List-Archive: Archived-At: List-Post: List-ID: ~johnnyrichard/olang-devel <~johnnyrichard/olang-devel.lists.sr.ht> Sender: ~johnnyrichard/olang-devel <~johnnyrichard/olang-devel@lists.sr.ht> X-Migadu-Flow: FLOW_IN X-Migadu-Country: NL X-Migadu-Spam-Score: -4.00 X-Spam-Score: -4.00 X-Migadu-Queue-Id: 09BD46D898 X-Migadu-Scanner: mx11.migadu.com X-TUID: Tq2Md3Y6D92w In order to get the var definition parsed we also introduce the reference node to get a functional ast test. This first implementation assumes that all variables will be of type u32 and we don't allow variable definitions without assignment, this assignment issue will be addressed in the future. Signed-off-by: Johnny Richard --- src/ast.c | 28 ++++++++++ src/ast.h | 22 ++++++++ src/parser.c | 52 +++++++++++++++++++ src/pretty_print_ast.c | 25 +++++++++ .../integration/tests/0024_var_definition.ol | 14 ++++- 5 files changed, 139 insertions(+), 2 deletions(-) diff --git a/src/ast.c b/src/ast.c index 4b252ae..d2fd2fa 100644 --- a/src/ast.c +++ b/src/ast.c @@ -52,6 +52,22 @@ ast_new_node_fn_def(arena_t *arena, string_view_t identifier, type_t return_type return node_fn_def; } +ast_node_t * +ast_new_node_var_def(arena_t *arena, string_view_t identifier, type_t type, ast_node_t *value) +{ + ast_node_t *node_var_def = (ast_node_t *)arena_alloc(arena, sizeof(ast_node_t)); + assert(node_var_def); + + node_var_def->kind = AST_NODE_VAR_DEF; + ast_var_definition_t *var_def = &node_var_def->as_var_def; + + var_def->identifier = identifier; + var_def->type = type; + var_def->value = value; + + return node_var_def; +} + ast_node_t * ast_new_node_bin_op(arena_t *arena, ast_binary_op_kind_t kind, ast_node_t *lhs, ast_node_t *rhs) { @@ -79,6 +95,18 @@ ast_new_node_literal_u32(arena_t *arena, uint32_t value) return node_literal; } +ast_node_t * +ast_new_node_ref(arena_t *arena, string_view_t identifier) +{ + ast_node_t *node_ref = (ast_node_t *)arena_alloc(arena, sizeof(ast_node_t)); + assert(node_ref); + + node_ref->kind = AST_NODE_REF; + node_ref->as_ref.identifier = identifier; + + return node_ref; +} + ast_node_t * ast_new_node_return_stmt(arena_t *arena) { diff --git a/src/ast.h b/src/ast.h index 9bf3723..94ee6b4 100644 --- a/src/ast.h +++ b/src/ast.h @@ -30,10 +30,12 @@ typedef enum AST_NODE_PROGRAM, AST_NODE_BLOCK, AST_NODE_FN_DEF, + AST_NODE_VAR_DEF, AST_NODE_BINARY_OP, AST_NODE_RETURN_STMT, AST_NODE_IF_STMT, AST_NODE_LITERAL, + AST_NODE_REF, AST_NODE_UNKNOWN } ast_node_kind_t; @@ -59,6 +61,13 @@ typedef struct ast_fn_definition ast_node_t *block; } ast_fn_definition_t; +typedef struct ast_var_definition +{ + string_view_t identifier; + type_t type; + ast_node_t *value; +} ast_var_definition_t; + typedef enum { AST_LITERAL_U32 @@ -73,6 +82,11 @@ typedef struct ast_literal }; } ast_literal_t; +typedef struct ast_ref +{ + string_view_t identifier; +} ast_ref_t; + typedef enum ast_binary_op_kind { AST_BINOP_ADDITION, @@ -121,8 +135,10 @@ typedef struct ast_node { ast_program_t as_program; ast_fn_definition_t as_fn_def; + ast_var_definition_t as_var_def; ast_binary_op_t as_bin_op; ast_literal_t as_literal; + ast_ref_t as_ref; ast_block_t as_block; ast_return_stmt_t as_return_stmt; ast_if_stmt_t as_if_stmt; @@ -135,12 +151,18 @@ ast_new_program(arena_t *arena, ast_node_t *fn_def); ast_node_t * ast_new_node_fn_def(arena_t *arena, string_view_t identifier, type_t return_type, ast_node_t *block); +ast_node_t * +ast_new_node_var_def(arena_t *arena, string_view_t identifier, type_t type, ast_node_t *value); + ast_node_t * ast_new_node_bin_op(arena_t *arena, ast_binary_op_kind_t kind, ast_node_t *lhs, ast_node_t *rhs); ast_node_t * ast_new_node_literal_u32(arena_t *arena, uint32_t value); +ast_node_t * +ast_new_node_ref(arena_t *arena, string_view_t identifier); + ast_node_t * ast_new_node_return_stmt(arena_t *arena); diff --git a/src/parser.c b/src/parser.c index 8f49f5e..d71500f 100644 --- a/src/parser.c +++ b/src/parser.c @@ -45,6 +45,9 @@ parser_parse_return_stmt(parser_t *parser); static ast_node_t * parser_parse_if_stmt(parser_t *parser); +static ast_node_t * +parser_parse_var_def(parser_t *parser); + ast_node_t * parser_parse_fn_definition(parser_t *parser); @@ -233,6 +236,9 @@ parser_parse_factor(parser_t *parser) case TOKEN_NUMBER: return ast_new_node_literal_u32(parser->arena, string_view_to_u32(token.value)); + case TOKEN_IDENTIFIER: + return ast_new_node_ref(parser->arena, token.value); + case TOKEN_OPAREN: { ast_node_t *expr = parser_parse_expr(parser); if (expr == NULL) { @@ -348,7 +354,15 @@ StartLoop: node = parser_parse_if_stmt(parser); break; } + case TOKEN_VAR: { + node = parser_parse_var_def(parser); + break; + } + case TOKEN_CCURLY: { + goto EndLoop; + } default: { + // FIXME: write a better error message goto EndLoop; } } @@ -443,6 +457,44 @@ parser_parse_if_stmt(parser_t *parser) return node_if_stmt; } +static ast_node_t * +parser_parse_var_def(parser_t *parser) +{ + if (!skip_expected_token(parser, TOKEN_VAR)) { + return NULL; + } + + token_t identifier_token; + if (!expected_next_token(parser, &identifier_token, TOKEN_IDENTIFIER)) { + return NULL; + } + + if (!skip_expected_token(parser, TOKEN_COLON)) { + return NULL; + } + + type_t var_type; + if (!parser_parse_type(parser, &var_type)) { + return NULL; + } + + // FIXME: assignment must be optional according to the spec + if (!skip_expected_token(parser, TOKEN_EQ)) { + return NULL; + } + + ast_node_t *expr = parser_parse_expr(parser); + if (expr == NULL) { + return NULL; + } + + ast_node_t *var_node = ast_new_node_var_def(parser->arena, identifier_token.value, var_type, expr); + + skip_line_feeds(parser->lexer); + + return var_node; +} + static bool skip_expected_token(parser_t *parser, token_kind_t expected_kind) { diff --git a/src/pretty_print_ast.c b/src/pretty_print_ast.c index 3c12716..d6eef67 100644 --- a/src/pretty_print_ast.c +++ b/src/pretty_print_ast.c @@ -198,6 +198,31 @@ ast_node_to_pretty_print_node(ast_node_t *ast, arena_t *arena) return node; } + case AST_NODE_VAR_DEF: { + pretty_print_node_t *node = pretty_print_node_new(arena); + ast_var_definition_t var = ast->as_var_def; + + char name[256]; + sprintf(name, "Var_Definition ", SV_ARG(var.identifier)); + node->name = (char *)arena_alloc(arena, sizeof(char) * (strlen(name) + 1)); + strcpy(node->name, name); + + pretty_print_node_t *child = ast_node_to_pretty_print_node(var.value, arena); + list_append(node->children, child); + + return node; + } + case AST_NODE_REF: { + pretty_print_node_t *node = pretty_print_node_new(arena); + ast_ref_t ref = ast->as_ref; + + char name[256]; + sprintf(name, "Reference ", SV_ARG(ref.identifier)); + node->name = (char *)arena_alloc(arena, sizeof(char) * (strlen(name) + 1)); + strcpy(node->name, name); + + return node; + } case AST_NODE_BINARY_OP: { pretty_print_node_t *node = pretty_print_node_new(arena); ast_binary_op_t binop = ast->as_bin_op; diff --git a/tests/integration/tests/0024_var_definition.ol b/tests/integration/tests/0024_var_definition.ol index d0b68da..241fc1a 100644 --- a/tests/integration/tests/0024_var_definition.ol +++ b/tests/integration/tests/0024_var_definition.ol @@ -14,10 +14,20 @@ # along with this program. If not, see . fn main(): u32 { - var code: u32 = 0; - return code; + var code: u32 = 0 + return code } # TEST test_contains_tokens WITH # ./tests/0024_var_definition.ol:17:3: # END + +# TEST test_ast WITH +# Translation_Unit +# `-Function_Definition +# `-Block +# |-Var_Definition +# | `-Literal +# `-Return_Statement +# `-Reference +# END -- 2.46.0