From 009bdcf281a807da597ca9dc4dcf06a383f220af Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Sun, 15 Feb 2026 21:31:57 -0500 Subject: [PATCH] parser: Add function parsing groundwork Signed-off-by: Ian Moffett --- core/parser.c | 194 ++++++++++++++++++++++++++++++++++++++++++++- inc/rifle/ast.h | 4 + inc/rifle/symbol.h | 4 +- sample/func.rifle | 3 +- sample/op.rifle | 1 - 5 files changed, 201 insertions(+), 5 deletions(-) delete mode 100644 sample/op.rifle diff --git a/core/parser.c b/core/parser.c index acd0a14..aa18404 100644 --- a/core/parser.c +++ b/core/parser.c @@ -6,6 +6,9 @@ #include "rifle/lexer.h" #include "rifle/state.h" #include "rifle/symbol.h" +#include "rifle/types.h" +#include "rifle/ast.h" +#include "rifle/scope.h" /* Symbolic token */ #define symtok(tok) \ @@ -30,6 +33,13 @@ "unexpected end of file\n" \ ); +#define utok1(state, tok) \ + trace_error( \ + (state), \ + "unexpected token %s\n", \ + tokstr(tok) \ + ) + /* Unexpected token */ #define utok(state, expt, got) \ trace_error( \ @@ -321,13 +331,195 @@ parse_preprocess(struct rifle_state *state) return 0; } +/* + * Parse a type definition + * + * @state: Compiler state + * @tok: Last token + * @res: Data type result + * + * Returns zero on success + */ +static int +parse_type(struct rifle_state *state, struct token *tok, struct data_type *res) +{ + + if (state == NULL || tok == NULL){ + return -1; + } + + res->ptr_depth = 0; + res->type = token_to_data_type(tok->type); + + if (res->type == DATA_TYPE_BAD) { + utok(state, "TYPE", tokstr(tok)); + return -1; + } + + return 0; +} + +/* + * Parse a lbrace + * + * @state: Compiler state + * @scope: Scope token type + * @tok: Last token + * + * Returns zero on success + */ +static int +parse_lbrace(struct rifle_state *state, tt_t scope, struct token *tok) +{ + if (state == NULL || tok == NULL) { + return -1; + } + + /* EXPECT '{' */ + if (parse_expect(state, TT_LBRACE, tok) < 0) { + return -1; + } + + if (scope_push(state, scope) < 0) { + return -1; + } + + return 0; +} + +/* + * Parse a function + * + * @state: Compiler state + * @tok: Last token + * @res: AST node + * + * Returns zero on success + */ +static int +parse_func(struct rifle_state *state, struct token *tok, struct ast_node **res) +{ + struct ast_node *root; + struct symbol *symbol; + int error; + + if (state == NULL || tok == NULL) { + return -1; + } + + if (res == NULL) { + return -1; + } + + if (tok->type != TT_F) { + return -1; + } + + /* EXPECT */ + if (parse_expect(state, TT_IDENT, tok) < 0) { + return -1; + } + + error = symbol_new( + &state->symtab, + tok->s, + SYMBOL_FUNC, + &symbol + ); + + if (error < 0) { + trace_error(state, "failed to create symbol '%s'\n", tok->s); + return error; + } + + if (ast_alloc_node(state, AST_FUNC, &root) < 0) { + trace_error(state, "failed to allocate AST_FUNC\n"); + return -1; + } + + /* EXPECT '(' */ + if (parse_expect(state, TT_LPAREN, tok) < 0) { + return -1; + } + + /* EXPECT ')' : TODO: ARGUMENTS */ + if (parse_expect(state, TT_RPAREN, tok) < 0) { + return -1; + } + + /* EXPECT ':' */ + if (parse_expect(state, TT_COLON, tok) < 0) { + return -1; + } + + if (parse_scan(state, tok) < 0) { + ueof(state); + return -1; + } + + /* Parse the return type */ + if (parse_type(state, tok, &root->dtype) < 0) { + return -1; + } + + /* Expect '{' */ + if (parse_lbrace(state, TT_F, tok) < 0) { + return -1; + } + + return 0; +} + +/* + * Parse a '{' token + * + * @state: Compiler state + * @tok: Last token + * @res: AST result + */ +static int +parse_rbrace(struct rifle_state *state, struct token *tok, struct ast_node **res) +{ + if (state == NULL || tok == NULL) { + return -1; + } + + if (res == NULL) { + return -1; + } + + if (tok->type != TT_RBRACE) { + return -1; + } + + scope_pop(state); + return 0; +} + static int parse_begin(struct rifle_state *state) { struct token tok; + struct ast_node *root; while (parse_scan(state, &tok) == 0) { - printf("got token %s\n", tokstr(&tok)); + switch (tok.type) { + case TT_F: + if (parse_func(state, &tok, &root) < 0) { + return -1; + } + + break; + case TT_RBRACE: + if (parse_rbrace(state, &tok, &root) < 0) { + return -1; + } + + break; + default: + utok1(state, &tok); + return -1; + } } return 0; diff --git a/inc/rifle/ast.h b/inc/rifle/ast.h index ae4ce69..b12ba4e 100644 --- a/inc/rifle/ast.h +++ b/inc/rifle/ast.h @@ -4,6 +4,7 @@ #include #include #include "rifle/state.h" +#include "rifle/types.h" /* * Represents valid types for AST nodes @@ -13,17 +14,20 @@ */ typedef enum { AST_NONE, + AST_FUNC } ast_type_t; /* * Represents an abstract syntax tree node * * @type: Node type + * @dtype: Data type * @left: Left leaf * @right: Right leaf */ struct ast_node { ast_type_t type; + struct data_type dtype; struct ast_node *left; struct ast_node *right; }; diff --git a/inc/rifle/symbol.h b/inc/rifle/symbol.h index ebe7d0c..bae1bf4 100644 --- a/inc/rifle/symbol.h +++ b/inc/rifle/symbol.h @@ -9,10 +9,12 @@ * * @SYMBOL_NONE: This symbol has no associated type * @SYMBOL_MACRO: This symbol is a macro + * @SYMBOL_FUNC: This symbol is a function */ typedef enum { SYMBOL_NONE, - SYMBOL_MACRO + SYMBOL_MACRO, + SYMBOL_FUNC } symtype_t; /* diff --git a/sample/func.rifle b/sample/func.rifle index 788a6a3..8f57571 100644 --- a/sample/func.rifle +++ b/sample/func.rifle @@ -1,4 +1,3 @@ -.pub .f main() : u32 +.f main() : u32 { - return 0; } diff --git a/sample/op.rifle b/sample/op.rifle deleted file mode 100644 index bc11bac..0000000 --- a/sample/op.rifle +++ /dev/null @@ -1 +0,0 @@ -+-*/