#define _POSIX_C_SOURCE 200809L #include "parser.h" #include #include extern void _rava_parser_advance(RavaParser_t *parser); extern bool _rava_parser_check(RavaParser_t *parser, RavaTokenType_e type); extern bool _rava_parser_match(RavaParser_t *parser, RavaTokenType_e type); extern bool _rava_parser_expect(RavaParser_t *parser, RavaTokenType_e type, const char *message); 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_block(RavaParser_t *parser); extern void _rava_parser_parse_modifiers(RavaParser_t *parser, RavaModifier_e **modifiers, size_t *count); static RavaASTNode_t* _rava_parser_parse_method_declaration(RavaParser_t *parser, RavaModifier_e *modifiers, size_t modifiers_count, RavaASTNode_t *return_type) { RavaASTNode_t *method = rava_ast_node_create(RAVA_AST_METHOD_DECL, parser->current_token->line, parser->current_token->column); method->data.method_decl.modifiers = modifiers; method->data.method_decl.modifiers_count = modifiers_count; method->data.method_decl.return_type = return_type; if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) { method->data.method_decl.name = strdup(parser->current_token->lexeme); _rava_parser_advance(parser); } _rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after method name"); while (!_rava_parser_check(parser, RAVA_TOKEN_RPAREN) && !_rava_parser_check(parser, RAVA_TOKEN_EOF)) { RavaASTNode_t *param_type = _rava_parser_parse_type(parser); RavaASTNode_t *param = rava_ast_node_create(RAVA_AST_PARAM_DECL, parser->current_token->line, parser->current_token->column); param->data.var_decl.type = param_type; if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) { param->data.var_decl.name = strdup(parser->current_token->lexeme); _rava_parser_advance(parser); } rava_ast_node_add_child(method, param); if (!_rava_parser_match(parser, RAVA_TOKEN_COMMA)) { break; } } _rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after parameters"); if (_rava_parser_check(parser, RAVA_TOKEN_LBRACE)) { RavaASTNode_t *body = _rava_parser_parse_block(parser); rava_ast_node_add_child(method, body); } else { _rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' or '{' after method declaration"); } return method; } RavaASTNode_t* _rava_parser_parse_class_declaration(RavaParser_t *parser) { RavaModifier_e *modifiers = NULL; size_t modifiers_count = 0; _rava_parser_parse_modifiers(parser, &modifiers, &modifiers_count); _rava_parser_expect(parser, RAVA_TOKEN_KEYWORD_CLASS, "Expected 'class' keyword"); RavaASTNode_t *class_decl = rava_ast_node_create(RAVA_AST_CLASS_DECL, parser->current_token->line, parser->current_token->column); class_decl->data.class_decl.modifiers = modifiers; class_decl->data.class_decl.modifiers_count = modifiers_count; class_decl->data.class_decl.superclass = NULL; class_decl->data.class_decl.interfaces = NULL; class_decl->data.class_decl.interfaces_count = 0; if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) { class_decl->data.class_decl.name = strdup(parser->current_token->lexeme); _rava_parser_advance(parser); } if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_EXTENDS)) { if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) { class_decl->data.class_decl.superclass = strdup(parser->current_token->lexeme); _rava_parser_advance(parser); } } if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_IMPLEMENTS)) { size_t capacity = 4; class_decl->data.class_decl.interfaces = malloc(capacity * sizeof(char*)); do { if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) { if (class_decl->data.class_decl.interfaces_count >= capacity) { capacity *= 2; class_decl->data.class_decl.interfaces = realloc( class_decl->data.class_decl.interfaces, capacity * sizeof(char*)); } class_decl->data.class_decl.interfaces[class_decl->data.class_decl.interfaces_count++] = strdup(parser->current_token->lexeme); _rava_parser_advance(parser); } } while (_rava_parser_match(parser, RAVA_TOKEN_COMMA)); } _rava_parser_expect(parser, RAVA_TOKEN_LBRACE, "Expected '{' after class name"); while (!_rava_parser_check(parser, RAVA_TOKEN_RBRACE) && !_rava_parser_check(parser, RAVA_TOKEN_EOF)) { RavaModifier_e *member_modifiers = NULL; size_t member_modifiers_count = 0; _rava_parser_parse_modifiers(parser, &member_modifiers, &member_modifiers_count); if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER) && strcmp(parser->current_token->lexeme, class_decl->data.class_decl.name) == 0) { RavaASTNode_t *constructor = rava_ast_node_create(RAVA_AST_CONSTRUCTOR_DECL, parser->current_token->line, parser->current_token->column); _rava_parser_advance(parser); _rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after constructor name"); while (!_rava_parser_check(parser, RAVA_TOKEN_RPAREN) && !_rava_parser_check(parser, RAVA_TOKEN_EOF)) { RavaASTNode_t *param_type = _rava_parser_parse_type(parser); RavaASTNode_t *param = rava_ast_node_create(RAVA_AST_PARAM_DECL, parser->current_token->line, parser->current_token->column); param->data.var_decl.type = param_type; if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) { param->data.var_decl.name = strdup(parser->current_token->lexeme); _rava_parser_advance(parser); } rava_ast_node_add_child(constructor, param); if (!_rava_parser_match(parser, RAVA_TOKEN_COMMA)) { break; } } _rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after constructor parameters"); if (_rava_parser_check(parser, RAVA_TOKEN_LBRACE)) { RavaASTNode_t *body = _rava_parser_parse_block(parser); rava_ast_node_add_child(constructor, body); } rava_ast_node_add_child(class_decl, constructor); free(member_modifiers); continue; } RavaASTNode_t *member_type = _rava_parser_parse_type(parser); if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) { char *name = strdup(parser->current_token->lexeme); _rava_parser_advance(parser); if (_rava_parser_check(parser, RAVA_TOKEN_LPAREN)) { RavaASTNode_t *method = _rava_parser_parse_method_declaration(parser, member_modifiers, member_modifiers_count, member_type); method->data.method_decl.name = name; rava_ast_node_add_child(class_decl, method); } else { RavaASTNode_t *field = rava_ast_node_create(RAVA_AST_FIELD_DECL, parser->current_token->line, parser->current_token->column); field->data.field_decl.type = member_type; field->data.field_decl.name = name; field->data.field_decl.modifiers = member_modifiers; field->data.field_decl.modifiers_count = member_modifiers_count; if (_rava_parser_match(parser, RAVA_TOKEN_ASSIGN)) { field->data.field_decl.initializer = _rava_parser_parse_expression(parser); } else { field->data.field_decl.initializer = NULL; } _rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after field declaration"); rava_ast_node_add_child(class_decl, field); member_modifiers = NULL; } } } _rava_parser_expect(parser, RAVA_TOKEN_RBRACE, "Expected '}' after class body"); return class_decl; } static RavaASTNode_t* _rava_parser_parse_interface_declaration(RavaParser_t *parser) { RavaModifier_e *modifiers = NULL; size_t modifiers_count = 0; _rava_parser_parse_modifiers(parser, &modifiers, &modifiers_count); _rava_parser_expect(parser, RAVA_TOKEN_KEYWORD_INTERFACE, "Expected 'interface' keyword"); RavaASTNode_t *interface_decl = rava_ast_node_create(RAVA_AST_INTERFACE_DECL, parser->current_token->line, parser->current_token->column); interface_decl->data.interface_decl.modifiers = modifiers; interface_decl->data.interface_decl.modifiers_count = modifiers_count; if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) { interface_decl->data.interface_decl.name = strdup(parser->current_token->lexeme); _rava_parser_advance(parser); } _rava_parser_expect(parser, RAVA_TOKEN_LBRACE, "Expected '{' after interface name"); while (!_rava_parser_check(parser, RAVA_TOKEN_RBRACE) && !_rava_parser_check(parser, RAVA_TOKEN_EOF)) { RavaModifier_e *member_modifiers = NULL; size_t member_modifiers_count = 0; _rava_parser_parse_modifiers(parser, &member_modifiers, &member_modifiers_count); RavaASTNode_t *member_type = _rava_parser_parse_type(parser); if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) { char *name = strdup(parser->current_token->lexeme); _rava_parser_advance(parser); if (_rava_parser_check(parser, RAVA_TOKEN_LPAREN)) { RavaASTNode_t *method = _rava_parser_parse_method_declaration(parser, member_modifiers, member_modifiers_count, member_type); method->data.method_decl.name = name; rava_ast_node_add_child(interface_decl, method); } else { free(name); free(member_modifiers); } } else { free(member_modifiers); } } _rava_parser_expect(parser, RAVA_TOKEN_RBRACE, "Expected '}' after interface body"); return interface_decl; } RavaASTNode_t* rava_parser_parse(RavaParser_t *parser) { RavaASTNode_t *root = rava_ast_node_create(RAVA_AST_COMPILATION_UNIT, 1, 1); while (!_rava_parser_check(parser, RAVA_TOKEN_EOF)) { if (parser->had_error) { break; } RavaModifier_e *modifiers = NULL; size_t modifiers_count = 0; _rava_parser_parse_modifiers(parser, &modifiers, &modifiers_count); RavaASTNode_t *decl = NULL; if (_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_INTERFACE)) { RavaToken_t *saved = parser->current_token; parser->current_token = saved; free(modifiers); decl = _rava_parser_parse_interface_declaration(parser); } else if (_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_CLASS)) { RavaToken_t *saved = parser->current_token; parser->current_token = saved; free(modifiers); decl = _rava_parser_parse_class_declaration(parser); } else { free(modifiers); break; } if (decl) { rava_ast_node_add_child(root, decl); } } return root; }