#define _POSIX_C_SOURCE 200809L #include "parser.h" #include "../utils/safe_alloc.h" #include #include #include RavaASTNode_t* rava_ast_node_create(RavaASTNodeType_e type, int line, int column) { RavaASTNode_t *node = calloc(1, sizeof(RavaASTNode_t)); if (!node) return NULL; node->type = type; node->line = line; node->column = column; node->parent = NULL; node->children = NULL; node->children_count = 0; node->children_capacity = 0; return node; } void rava_ast_node_destroy(RavaASTNode_t *node) { if (!node) return; for (size_t i = 0; i < node->children_count; i++) { rava_ast_node_destroy(node->children[i]); } free(node->children); switch (node->type) { case RAVA_AST_IDENTIFIER_EXPR: free(node->data.identifier.name); break; case RAVA_AST_CLASS_DECL: free(node->data.class_decl.name); free(node->data.class_decl.modifiers); rava_ast_node_destroy(node->data.class_decl.type); break; case RAVA_AST_ENUM_DECL: free(node->data.enum_decl.name); free(node->data.enum_decl.modifiers); for (size_t i = 0; i < node->data.enum_decl.constants_count; i++) { free(node->data.enum_decl.constants[i]); } free(node->data.enum_decl.constants); break; case RAVA_AST_METHOD_DECL: free(node->data.method_decl.name); free(node->data.method_decl.modifiers); rava_ast_node_destroy(node->data.method_decl.return_type); break; case RAVA_AST_VAR_DECL: free(node->data.var_decl.name); rava_ast_node_destroy(node->data.var_decl.type); rava_ast_node_destroy(node->data.var_decl.initializer); break; case RAVA_AST_TYPE: free(node->data.type.type_name); break; case RAVA_AST_MEMBER_ACCESS_EXPR: free(node->data.member_access.member); rava_ast_node_destroy(node->data.member_access.object); break; case RAVA_AST_CALL_EXPR: rava_ast_node_destroy(node->data.call.callee); for (size_t i = 0; i < node->data.call.arguments_count; i++) { rava_ast_node_destroy(node->data.call.arguments[i]); } free(node->data.call.arguments); break; case RAVA_AST_NEW_EXPR: rava_ast_node_destroy(node->data.new_expr.type); for (size_t i = 0; i < node->data.new_expr.arguments_count; i++) { rava_ast_node_destroy(node->data.new_expr.arguments[i]); } free(node->data.new_expr.arguments); break; case RAVA_AST_LITERAL_EXPR: if (node->data.literal.literal_type == RAVA_TOKEN_LITERAL_STRING) { free(node->data.literal.value.string_value); } break; default: break; } free(node); } void rava_ast_node_add_child(RavaASTNode_t *parent, RavaASTNode_t *child) { if (!parent || !child) return; if (parent->children_count >= parent->children_capacity) { size_t new_capacity = parent->children_capacity == 0 ? 4 : parent->children_capacity * 2; RavaASTNode_t **new_children = rava_safe_realloc(parent->children, sizeof(RavaASTNode_t*) * new_capacity); if (!new_children) return; parent->children = new_children; parent->children_capacity = new_capacity; } parent->children[parent->children_count++] = child; child->parent = parent; } RavaParser_t* rava_parser_create(RavaLexer_t *lexer) { RavaParser_t *parser = malloc(sizeof(RavaParser_t)); if (!parser) return NULL; parser->lexer = lexer; parser->current_token = rava_lexer_next_token(lexer); parser->peek_token = rava_lexer_next_token(lexer); parser->error_message = NULL; parser->had_error = false; return parser; } void rava_parser_destroy(RavaParser_t *parser) { if (!parser) return; rava_token_destroy(parser->current_token); rava_token_destroy(parser->peek_token); free(parser->error_message); free(parser); } void _rava_parser_advance(RavaParser_t *parser) { rava_token_destroy(parser->current_token); parser->current_token = parser->peek_token; parser->peek_token = rava_lexer_next_token(parser->lexer); } bool _rava_parser_check(RavaParser_t *parser, RavaTokenType_e type) { return parser->current_token->type == type; } bool _rava_parser_match(RavaParser_t *parser, RavaTokenType_e type) { if (_rava_parser_check(parser, type)) { _rava_parser_advance(parser); return true; } return false; } bool _rava_parser_expect(RavaParser_t *parser, RavaTokenType_e type, const char *message) { if (_rava_parser_check(parser, type)) { _rava_parser_advance(parser); return true; } parser->had_error = true; if (parser->error_message) free(parser->error_message); parser->error_message = malloc(RAVA_ERROR_BUFFER_SIZE); if (parser->error_message) { snprintf(parser->error_message, RAVA_ERROR_BUFFER_SIZE, "%s at line %d, column %d", message, parser->current_token->line, parser->current_token->column); } return false; } extern RavaASTNode_t* _rava_parser_parse_type(RavaParser_t *parser); extern RavaASTNode_t* _rava_parser_parse_expression(RavaParser_t *parser); extern RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser); extern RavaASTNode_t* _rava_parser_parse_block(RavaParser_t *parser); static RavaModifier_e _rava_token_to_modifier(RavaTokenType_e type) { switch (type) { case RAVA_TOKEN_KEYWORD_PUBLIC: return RAVA_MODIFIER_PUBLIC; case RAVA_TOKEN_KEYWORD_PRIVATE: return RAVA_MODIFIER_PRIVATE; case RAVA_TOKEN_KEYWORD_PROTECTED: return RAVA_MODIFIER_PROTECTED; case RAVA_TOKEN_KEYWORD_STATIC: return RAVA_MODIFIER_STATIC; case RAVA_TOKEN_KEYWORD_FINAL: return RAVA_MODIFIER_FINAL; case RAVA_TOKEN_KEYWORD_ABSTRACT: return RAVA_MODIFIER_ABSTRACT; case RAVA_TOKEN_KEYWORD_NATIVE: return RAVA_MODIFIER_NATIVE; case RAVA_TOKEN_KEYWORD_SYNCHRONIZED: return RAVA_MODIFIER_SYNCHRONIZED; case RAVA_TOKEN_KEYWORD_TRANSIENT: return RAVA_MODIFIER_TRANSIENT; case RAVA_TOKEN_KEYWORD_VOLATILE: return RAVA_MODIFIER_VOLATILE; case RAVA_TOKEN_KEYWORD_STRICTFP: return RAVA_MODIFIER_STRICTFP; default: return RAVA_MODIFIER_PUBLIC; } } static bool _rava_is_modifier(RavaTokenType_e type) { return type == RAVA_TOKEN_KEYWORD_PUBLIC || type == RAVA_TOKEN_KEYWORD_PRIVATE || type == RAVA_TOKEN_KEYWORD_PROTECTED || type == RAVA_TOKEN_KEYWORD_STATIC || type == RAVA_TOKEN_KEYWORD_FINAL || type == RAVA_TOKEN_KEYWORD_ABSTRACT || type == RAVA_TOKEN_KEYWORD_NATIVE || type == RAVA_TOKEN_KEYWORD_SYNCHRONIZED || type == RAVA_TOKEN_KEYWORD_TRANSIENT || type == RAVA_TOKEN_KEYWORD_VOLATILE || type == RAVA_TOKEN_KEYWORD_STRICTFP; } void _rava_parser_parse_modifiers(RavaParser_t *parser, RavaModifier_e **modifiers, size_t *count) { size_t capacity = 4; *modifiers = malloc(sizeof(RavaModifier_e) * capacity); *count = 0; while (_rava_is_modifier(parser->current_token->type)) { if (*count >= capacity) { capacity *= 2; *modifiers = realloc(*modifiers, sizeof(RavaModifier_e) * capacity); } (*modifiers)[(*count)++] = _rava_token_to_modifier(parser->current_token->type); _rava_parser_advance(parser); } } RavaASTNode_t* _rava_parser_parse_type(RavaParser_t *parser) { RavaASTNode_t *type_node = rava_ast_node_create(RAVA_AST_TYPE, parser->current_token->line, parser->current_token->column); if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER) || _rava_parser_check(parser, RAVA_TOKEN_KEYWORD_INT) || _rava_parser_check(parser, RAVA_TOKEN_KEYWORD_BOOLEAN) || _rava_parser_check(parser, RAVA_TOKEN_KEYWORD_CHAR) || _rava_parser_check(parser, RAVA_TOKEN_KEYWORD_BYTE) || _rava_parser_check(parser, RAVA_TOKEN_KEYWORD_SHORT) || _rava_parser_check(parser, RAVA_TOKEN_KEYWORD_LONG) || _rava_parser_check(parser, RAVA_TOKEN_KEYWORD_FLOAT) || _rava_parser_check(parser, RAVA_TOKEN_KEYWORD_DOUBLE) || _rava_parser_check(parser, RAVA_TOKEN_KEYWORD_VOID)) { type_node->data.type.type_name = strdup(parser->current_token->lexeme); type_node->data.type.is_array = false; type_node->data.type.array_dimensions = 0; _rava_parser_advance(parser); while (_rava_parser_check(parser, RAVA_TOKEN_LBRACKET)) { if (parser->peek_token && parser->peek_token->type == RAVA_TOKEN_RBRACKET) { _rava_parser_advance(parser); _rava_parser_advance(parser); type_node->data.type.is_array = true; type_node->data.type.array_dimensions++; } else { break; } } } else { parser->had_error = true; if (parser->error_message) free(parser->error_message); parser->error_message = strdup("Expected type name"); rava_ast_node_destroy(type_node); return NULL; } return type_node; } RavaASTNode_t* rava_parser_parse(RavaParser_t *parser);