diff options
author | Johnny Richard <johnny@johnnyrichard.com> | 2023-04-30 01:48:18 +0200 |
---|---|---|
committer | Johnny Richard <johnny@johnnyrichard.com> | 2023-04-30 01:55:29 +0200 |
commit | ef07fab261cce781ca750c1288574d4001f14bcf (patch) | |
tree | 9b4da44aee7cc64cec448adeee31b38e12d29e6d /src | |
parent | 88a08db927629032d6d4c662e00f0dce2c112ce4 (diff) |
parser: Registry identifiers on scope
We are parsing variables/functions and checking if they are defined on
scope. Otherwise we fail the parsing with a nice message.
Signed-off-by: Johnny Richard <johnny@johnnyrichard.com>
Co-authored-by: Carlos Maniero <carlosmaniero@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/ast.c | 7 | ||||
-rw-r--r-- | src/ast.h | 11 | ||||
-rw-r--r-- | src/gas_assembly_generator.c | 3 | ||||
-rw-r--r-- | src/parser.c | 27 | ||||
-rw-r--r-- | src/parser.h | 4 | ||||
-rw-r--r-- | src/pipac.c | 5 | ||||
-rw-r--r-- | src/scope.c | 6 | ||||
-rw-r--r-- | src/scope.h | 7 |
8 files changed, 58 insertions, 12 deletions
@@ -108,6 +108,13 @@ ast_node_init_variable_declaration(ast_node_t *node, string_view_t variable_name } void +ast_node_init_variable(ast_node_t *node, ast_identifier_t *identifier) +{ + node->kind = AST_VARIABLE; + node->data = (ast_node_data_t){ .variable_ex = { .identifier = identifier } }; +} + +void ast_node_init_identifier(ast_node_t *node, string_view_t name) { node->kind = AST_IDENTIFIER; @@ -37,6 +37,11 @@ typedef struct ast_identifier_t string_view_t name; } ast_identifier_t; +typedef struct ast_variable_t +{ + ast_identifier_t *identifier; +} ast_variable_t; + typedef struct ast_function_declaration_t { ast_identifier_t identifier; @@ -91,6 +96,7 @@ typedef enum AST_RETURN_STMT, AST_UNKOWN_NODE, AST_VARIABLE_DECLARATION, + AST_VARIABLE } ast_node_kind_t; typedef union @@ -99,8 +105,9 @@ typedef union ast_function_declaration_t function; ast_literal_t literal; ast_return_stmt_t return_stmt; - ast_variable_declaration_t variable; + ast_variable_declaration_t variable; // FIXME: Rename to variable_declaration ast_identifier_t identifier; + ast_variable_t variable_ex; // FIXME: Rename to variable } ast_node_data_t; typedef struct ast_node_t @@ -127,5 +134,7 @@ ast_node_init_variable_declaration(ast_node_t *node, string_view_t variable_name // FIXME: use the naming convention void ast_literal_integer_create(ast_node_t *node, uint32_t number); +void +ast_node_init_variable(ast_node_t *node, ast_identifier_t *identifier); #endif /* AST_H */ diff --git a/src/gas_assembly_generator.c b/src/gas_assembly_generator.c index ea76c5f..f09b60d 100644 --- a/src/gas_assembly_generator.c +++ b/src/gas_assembly_generator.c @@ -61,6 +61,9 @@ gas_assembly_generator_compile(gas_assembly_generator_t *gen, ast_node_t *ast) case AST_VARIABLE_DECLARATION: assert(false && "TODO: ast variable declaration not implemented yet"); break; + case AST_VARIABLE: + assert(false && "TODO: ast variable not implemented yet"); + break; case AST_UNKOWN_NODE: assert(false && "unreachable"); } diff --git a/src/parser.c b/src/parser.c index 6b954c2..469fa99 100644 --- a/src/parser.c +++ b/src/parser.c @@ -24,14 +24,16 @@ #include "ast.h" #include "lexer.h" #include "parser.h" +#include "scope.h" #include "vector.h" void -parser_init(parser_t *parser, lexer_t *lexer) +parser_init(parser_t *parser, lexer_t *lexer, scope_t *scope) { assert(parser && "parser must be defined"); assert(lexer && "lexer must be defined"); parser->lexer = lexer; + parser->scope = scope; parser->errors_len = 0; } @@ -134,8 +136,16 @@ parser_parse_factor(parser_t *parser, ast_node_t *node) return false; return true; case TOKEN_NAME: - /// FIXME: Check if the identifier is defined ast_node_init_identifier(node, token.value); + // TODO: Check node kind, today accepts only variables + if (scope_get(parser->scope, token.value) == NULL) { + parser_error_t error; + error.token = token; + sprintf(error.message, "identifier '" SVFMT "' not defined", SVARG(&token.value)); + parser->errors[parser->errors_len++] = error; + return false; + } + return true; default: { parser_error_t error; @@ -143,7 +153,7 @@ parser_parse_factor(parser_t *parser, ast_node_t *node) sprintf(error.message, "unexpected '%s (" SVFMT ")' token", token_kind_to_str(token.kind), SVARG(&token.value)); parser->errors[parser->errors_len++] = error; return false; - } + } } } @@ -247,6 +257,7 @@ parser_parse_variable_definition(parser_t *parser, string_view_t variable_name, } ast_node_init_variable_declaration(node, variable_name, type, expression); + scope_push(parser->scope, &node->data.variable.identifier, node); return true; } @@ -333,11 +344,17 @@ parser_parse_function_declaration(parser_t *parser, ast_node_t *node) return false; vector_t *body = vector_new(); + ast_node_init_function_declaration(node, func_name_token.value, return_type, body); + scope_push(parser->scope, &node->data.function.identifier, node); + + scope_enter(parser->scope); - if (!parser_parse_block_declarations(parser, body)) + if (!parser_parse_block_declarations(parser, body)) { + scope_leave(parser->scope); return false; + } - ast_node_init_function_declaration(node, func_name_token.value, return_type, body); + scope_leave(parser->scope); return true; } diff --git a/src/parser.h b/src/parser.h index bdf0c5a..d3e1431 100644 --- a/src/parser.h +++ b/src/parser.h @@ -19,6 +19,7 @@ #include "ast.h" #include "lexer.h" +#include "scope.h" #include "string_view.h" typedef struct parser_error_t @@ -30,13 +31,14 @@ typedef struct parser_error_t typedef struct parser_t { lexer_t *lexer; + scope_t *scope; int errors_len; // FIXME: replace with vector parser_error_t errors[1]; } parser_t; void -parser_init(parser_t *parser, lexer_t *lexer); +parser_init(parser_t *parser, lexer_t *lexer, scope_t *scope); bool parser_parse_function_declaration(parser_t *parser, ast_node_t *node); diff --git a/src/pipac.c b/src/pipac.c index b31b8b5..2041218 100644 --- a/src/pipac.c +++ b/src/pipac.c @@ -22,6 +22,7 @@ #include "gas_assembly_generator.h" #include "lexer.h" #include "parser.h" +#include "scope.h" #include "string_view.h" static void @@ -62,8 +63,9 @@ main(int argc, char **argv) lexer_t lexer; lexer_init(&lexer, filepath); + scope_t *scope = scope_new(); parser_t parser; - parser_init(&parser, &lexer); + parser_init(&parser, &lexer, scope); ast_node_t *func = ast_node_new(); @@ -74,6 +76,7 @@ main(int argc, char **argv) generate_gas_x86_64_linux(func); + scope_destroy(scope); ast_node_destroy(func); return EXIT_SUCCESS; } diff --git a/src/scope.c b/src/scope.c index 5b696ad..662e59c 100644 --- a/src/scope.c +++ b/src/scope.c @@ -54,7 +54,7 @@ scope_new(void) void scope_destroy(scope_t *scope) { - if (scope->stack->size) { + if (scope->stack->size != 1) { fprintf(stderr, "Stack not cleaned before destroying. This may lead to memory leaks.\n" "Please make sure to call the leave function before destroying it."); @@ -97,7 +97,7 @@ scope_leave(scope_t *scope) } ast_node_t * -scope_get(scope_t *scope, ast_identifier_t *identifier) +scope_get(scope_t *scope, string_view_t name) { for (size_t i = scope->stack->size; i > 0; i--) { vector_t *current_level = vector_at(scope->stack, i - 1); @@ -105,7 +105,7 @@ scope_get(scope_t *scope, ast_identifier_t *identifier) for (size_t j = 0; j < current_level->size; j++) { scope_item_t *item = vector_at(current_level, j); - if (string_view_eq(identifier->name, item->identifier->name)) { + if (string_view_eq(name, item->identifier->name)) { return item->node; } } diff --git a/src/scope.h b/src/scope.h index c221703..2636990 100644 --- a/src/scope.h +++ b/src/scope.h @@ -14,6 +14,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ +#ifndef SCOPE_H +#define SCOPE_H + #include "ast.h" #include "string_view.h" #include "vector.h" @@ -41,6 +44,8 @@ void scope_leave(scope_t *scope); ast_node_t * -scope_get(scope_t *scope, ast_identifier_t *identifier); +scope_get(scope_t *scope, string_view_t name); void scope_push(scope_t *scope, ast_identifier_t *identifier, ast_node_t *node); + +#endif /* SCOPE_H */ |