diff options
Diffstat (limited to 'src/parser.c')
-rw-r--r-- | src/parser.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/parser.c b/src/parser.c new file mode 100644 index 0000000..5d2a734 --- /dev/null +++ b/src/parser.c @@ -0,0 +1,102 @@ +/* +* Copyright (C) 2023 Johnny Richard +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "lexer.h" +#include "parser.h" + +void +parser_init(parser_t *parser, lexer_t *lexer) +{ + assert(parser && "parser must be defined"); + assert(lexer && "lexer must be defined"); + parser->lexer = lexer; +} + +static token_t +expected_token(parser_t *parser, token_kind_t kind) +{ + token_t token; + lexer_next_token(parser->lexer, &token); + + if (token.kind == TOKEN_EOF) { + fprintf(stderr, "[ERROR]: expected '%s' but got end of file\n", token_kind_to_str(kind)); + exit(EXIT_FAILURE); + } + + if (token.kind != kind) { + fprintf(stderr, "[ERROR]: expected '%s' but got '%s'\n", token_kind_to_str(kind), token_kind_to_str(token.kind)); + exit(EXIT_FAILURE); + } + + return token; +} + +static type_t +parser_parse_type(parser_t *parser) +{ + token_t token = expected_token(parser, TOKEN_NAME); + + if (strcmp(token.value, "i32") == 0) { + return TYPE_I32; + } + + fprintf(stderr, "[ERROR]: expected type 'i32' but got '%s'\n", token.value); + exit(EXIT_FAILURE); +} + +static ast_return_stmt_t +parser_parse_return_stmt(parser_t *parser) +{ + expected_token(parser, TOKEN_OCURLY); + token_t return_keyword_token = expected_token(parser, TOKEN_NAME); + + if (strcmp(return_keyword_token.value, "return") != 0) { + // TODO: Add filename:row:col prefix to expected token exceptions + fprintf(stderr, "[ERROR]: expected 'return' keyword but got '%s'\n", return_keyword_token.value); + exit(EXIT_FAILURE); + } + + token_t number_token = expected_token(parser, TOKEN_NUMBER); + expected_token(parser, TOKEN_SEMICOLON); + expected_token(parser, TOKEN_CCURLY); + + return (ast_return_stmt_t) { + .number = atoi(number_token.value) + }; +} + +ast_function_t +parser_parse_function(parser_t *parser) +{ + token_t func_name_token = expected_token(parser, TOKEN_NAME); + expected_token(parser, TOKEN_OPAREN); + expected_token(parser, TOKEN_CPAREN); + expected_token(parser, TOKEN_COLON); + type_t return_type = parser_parse_type(parser); + + return (ast_function_t) { + // FIXME: alloc memory for the ast_function.name, it's not a good idea to use the token.value + .name = func_name_token.value, + .return_type = return_type, + .body = parser_parse_return_stmt(parser) + }; +} |