2025-12-02 06:54:32 +01:00
|
|
|
#define _POSIX_C_SOURCE 200809L
|
|
|
|
|
#include "parser.h"
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
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_expression(RavaParser_t *parser);
|
2025-12-02 21:12:50 +01:00
|
|
|
extern RavaASTNode_t* _rava_parser_parse_array_initializer(RavaParser_t *parser);
|
2025-12-02 06:54:32 +01:00
|
|
|
extern RavaASTNode_t* _rava_parser_parse_type(RavaParser_t *parser);
|
|
|
|
|
|
|
|
|
|
RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser);
|
|
|
|
|
RavaASTNode_t* _rava_parser_parse_block(RavaParser_t *parser);
|
|
|
|
|
|
|
|
|
|
RavaASTNode_t* _rava_parser_parse_block(RavaParser_t *parser) {
|
|
|
|
|
RavaASTNode_t *block = rava_ast_node_create(RAVA_AST_BLOCK_STMT,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_LBRACE, "Expected '{' at start of block");
|
|
|
|
|
|
|
|
|
|
while (!_rava_parser_check(parser, RAVA_TOKEN_RBRACE) &&
|
|
|
|
|
!_rava_parser_check(parser, RAVA_TOKEN_EOF)) {
|
|
|
|
|
RavaASTNode_t *stmt = _rava_parser_parse_statement(parser);
|
|
|
|
|
if (stmt) {
|
|
|
|
|
rava_ast_node_add_child(block, stmt);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_RBRACE, "Expected '}' at end of block");
|
|
|
|
|
|
|
|
|
|
return block;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser) {
|
|
|
|
|
if (_rava_parser_check(parser, RAVA_TOKEN_LBRACE)) {
|
|
|
|
|
return _rava_parser_parse_block(parser);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_IF)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_IF_STMT,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after 'if'");
|
|
|
|
|
node->data.if_stmt.condition = _rava_parser_parse_expression(parser);
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after if condition");
|
|
|
|
|
|
|
|
|
|
node->data.if_stmt.then_stmt = _rava_parser_parse_statement(parser);
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_ELSE)) {
|
|
|
|
|
node->data.if_stmt.else_stmt = _rava_parser_parse_statement(parser);
|
|
|
|
|
} else {
|
|
|
|
|
node->data.if_stmt.else_stmt = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_WHILE)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_WHILE_STMT,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after 'while'");
|
|
|
|
|
node->data.while_stmt.condition = _rava_parser_parse_expression(parser);
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after while condition");
|
|
|
|
|
|
|
|
|
|
node->data.while_stmt.body = _rava_parser_parse_statement(parser);
|
|
|
|
|
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-02 21:12:50 +01:00
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_DO)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_DO_WHILE_STMT,
|
2025-12-02 06:54:32 +01:00
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
|
2025-12-02 21:12:50 +01:00
|
|
|
node->data.while_stmt.body = _rava_parser_parse_statement(parser);
|
|
|
|
|
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_KEYWORD_WHILE, "Expected 'while' after do body");
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after 'while'");
|
|
|
|
|
node->data.while_stmt.condition = _rava_parser_parse_expression(parser);
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after do-while condition");
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after do-while");
|
|
|
|
|
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_FOR)) {
|
|
|
|
|
int line = parser->current_token->line;
|
|
|
|
|
int column = parser->current_token->column;
|
|
|
|
|
|
2025-12-02 06:54:32 +01:00
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after 'for'");
|
|
|
|
|
|
|
|
|
|
if (!_rava_parser_check(parser, RAVA_TOKEN_SEMICOLON)) {
|
|
|
|
|
bool is_type_decl = false;
|
|
|
|
|
if (_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_INT) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_LONG) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_DOUBLE) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_BOOLEAN) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_CHAR)) {
|
|
|
|
|
is_type_decl = true;
|
|
|
|
|
} else if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
|
|
|
|
if (parser->peek_token && parser->peek_token->type == RAVA_TOKEN_IDENTIFIER) {
|
|
|
|
|
is_type_decl = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (is_type_decl) {
|
|
|
|
|
RavaASTNode_t *type = _rava_parser_parse_type(parser);
|
2025-12-02 21:12:50 +01:00
|
|
|
char *var_name = NULL;
|
|
|
|
|
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
|
|
|
|
var_name = strdup(parser->current_token->lexeme);
|
|
|
|
|
_rava_parser_advance(parser);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_COLON)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_ENHANCED_FOR_STMT, line, column);
|
|
|
|
|
node->data.enhanced_for.var_type = type;
|
|
|
|
|
node->data.enhanced_for.var_name = var_name;
|
|
|
|
|
node->data.enhanced_for.iterable = _rava_parser_parse_expression(parser);
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after enhanced for");
|
|
|
|
|
node->data.enhanced_for.body = _rava_parser_parse_statement(parser);
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_FOR_STMT, line, column);
|
2025-12-02 06:54:32 +01:00
|
|
|
RavaASTNode_t *var_decl = rava_ast_node_create(RAVA_AST_VAR_DECL,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
var_decl->data.var_decl.type = type;
|
2025-12-02 21:12:50 +01:00
|
|
|
var_decl->data.var_decl.name = var_name;
|
2025-12-02 06:54:32 +01:00
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_ASSIGN)) {
|
|
|
|
|
var_decl->data.var_decl.initializer = _rava_parser_parse_expression(parser);
|
|
|
|
|
}
|
|
|
|
|
node->data.for_stmt.init = var_decl;
|
2025-12-02 21:12:50 +01:00
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after for init");
|
|
|
|
|
|
|
|
|
|
if (!_rava_parser_check(parser, RAVA_TOKEN_SEMICOLON)) {
|
|
|
|
|
node->data.for_stmt.condition = _rava_parser_parse_expression(parser);
|
|
|
|
|
} else {
|
|
|
|
|
node->data.for_stmt.condition = NULL;
|
|
|
|
|
}
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after for condition");
|
|
|
|
|
|
|
|
|
|
if (!_rava_parser_check(parser, RAVA_TOKEN_RPAREN)) {
|
|
|
|
|
node->data.for_stmt.update = _rava_parser_parse_expression(parser);
|
|
|
|
|
} else {
|
|
|
|
|
node->data.for_stmt.update = NULL;
|
|
|
|
|
}
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after for update");
|
|
|
|
|
|
|
|
|
|
node->data.for_stmt.body = _rava_parser_parse_statement(parser);
|
|
|
|
|
return node;
|
2025-12-02 06:54:32 +01:00
|
|
|
} else {
|
2025-12-02 21:12:50 +01:00
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_FOR_STMT, line, column);
|
2025-12-02 06:54:32 +01:00
|
|
|
node->data.for_stmt.init = _rava_parser_parse_expression(parser);
|
2025-12-02 21:12:50 +01:00
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after for init");
|
|
|
|
|
|
|
|
|
|
if (!_rava_parser_check(parser, RAVA_TOKEN_SEMICOLON)) {
|
|
|
|
|
node->data.for_stmt.condition = _rava_parser_parse_expression(parser);
|
|
|
|
|
} else {
|
|
|
|
|
node->data.for_stmt.condition = NULL;
|
|
|
|
|
}
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after for condition");
|
|
|
|
|
|
|
|
|
|
if (!_rava_parser_check(parser, RAVA_TOKEN_RPAREN)) {
|
|
|
|
|
node->data.for_stmt.update = _rava_parser_parse_expression(parser);
|
|
|
|
|
} else {
|
|
|
|
|
node->data.for_stmt.update = NULL;
|
|
|
|
|
}
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after for update");
|
|
|
|
|
|
|
|
|
|
node->data.for_stmt.body = _rava_parser_parse_statement(parser);
|
|
|
|
|
return node;
|
2025-12-02 06:54:32 +01:00
|
|
|
}
|
|
|
|
|
} else {
|
2025-12-02 21:12:50 +01:00
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_FOR_STMT, line, column);
|
2025-12-02 06:54:32 +01:00
|
|
|
node->data.for_stmt.init = NULL;
|
2025-12-02 21:12:50 +01:00
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after for init");
|
2025-12-02 06:54:32 +01:00
|
|
|
|
2025-12-02 21:12:50 +01:00
|
|
|
if (!_rava_parser_check(parser, RAVA_TOKEN_SEMICOLON)) {
|
|
|
|
|
node->data.for_stmt.condition = _rava_parser_parse_expression(parser);
|
|
|
|
|
} else {
|
|
|
|
|
node->data.for_stmt.condition = NULL;
|
|
|
|
|
}
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after for condition");
|
|
|
|
|
|
|
|
|
|
if (!_rava_parser_check(parser, RAVA_TOKEN_RPAREN)) {
|
|
|
|
|
node->data.for_stmt.update = _rava_parser_parse_expression(parser);
|
|
|
|
|
} else {
|
|
|
|
|
node->data.for_stmt.update = NULL;
|
|
|
|
|
}
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after for update");
|
|
|
|
|
|
|
|
|
|
node->data.for_stmt.body = _rava_parser_parse_statement(parser);
|
|
|
|
|
return node;
|
2025-12-02 06:54:32 +01:00
|
|
|
}
|
2025-12-02 21:12:50 +01:00
|
|
|
}
|
2025-12-02 06:54:32 +01:00
|
|
|
|
2025-12-02 21:12:50 +01:00
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_SWITCH)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_SWITCH_STMT,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after 'switch'");
|
|
|
|
|
node->data.switch_stmt.expression = _rava_parser_parse_expression(parser);
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after switch expression");
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_LBRACE, "Expected '{' after switch");
|
|
|
|
|
|
|
|
|
|
while (!_rava_parser_check(parser, RAVA_TOKEN_RBRACE) &&
|
|
|
|
|
!_rava_parser_check(parser, RAVA_TOKEN_EOF)) {
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_CASE)) {
|
|
|
|
|
RavaASTNode_t *case_node = rava_ast_node_create(RAVA_AST_CASE_STMT,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
case_node->data.case_stmt.is_default = false;
|
|
|
|
|
case_node->data.case_stmt.value = _rava_parser_parse_expression(parser);
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_COLON, "Expected ':' after case value");
|
|
|
|
|
|
|
|
|
|
while (!_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_CASE) &&
|
|
|
|
|
!_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_DEFAULT) &&
|
|
|
|
|
!_rava_parser_check(parser, RAVA_TOKEN_RBRACE) &&
|
|
|
|
|
!_rava_parser_check(parser, RAVA_TOKEN_EOF)) {
|
|
|
|
|
RavaASTNode_t *stmt = _rava_parser_parse_statement(parser);
|
|
|
|
|
if (stmt) {
|
|
|
|
|
rava_ast_node_add_child(case_node, stmt);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rava_ast_node_add_child(node, case_node);
|
|
|
|
|
|
|
|
|
|
} else if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_DEFAULT)) {
|
|
|
|
|
RavaASTNode_t *default_node = rava_ast_node_create(RAVA_AST_CASE_STMT,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
default_node->data.case_stmt.is_default = true;
|
|
|
|
|
default_node->data.case_stmt.value = NULL;
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_COLON, "Expected ':' after default");
|
|
|
|
|
|
|
|
|
|
while (!_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_CASE) &&
|
|
|
|
|
!_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_DEFAULT) &&
|
|
|
|
|
!_rava_parser_check(parser, RAVA_TOKEN_RBRACE) &&
|
|
|
|
|
!_rava_parser_check(parser, RAVA_TOKEN_EOF)) {
|
|
|
|
|
RavaASTNode_t *stmt = _rava_parser_parse_statement(parser);
|
|
|
|
|
if (stmt) {
|
|
|
|
|
rava_ast_node_add_child(default_node, stmt);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rava_ast_node_add_child(node, default_node);
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2025-12-02 06:54:32 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-02 21:12:50 +01:00
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_RBRACE, "Expected '}' at end of switch");
|
2025-12-02 06:54:32 +01:00
|
|
|
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_RETURN)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_RETURN_STMT,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
|
|
|
|
|
if (!_rava_parser_check(parser, RAVA_TOKEN_SEMICOLON)) {
|
|
|
|
|
node->data.return_stmt.value = _rava_parser_parse_expression(parser);
|
|
|
|
|
} else {
|
|
|
|
|
node->data.return_stmt.value = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after return statement");
|
|
|
|
|
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_BREAK)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_BREAK_STMT,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after break");
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_CONTINUE)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_CONTINUE_STMT,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after continue");
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-02 21:12:50 +01:00
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_THROW)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_THROW_STMT,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
node->data.throw_stmt.expression = _rava_parser_parse_expression(parser);
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after throw");
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_TRY)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_TRY_STMT,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
|
|
|
|
|
node->data.try_stmt.try_block = _rava_parser_parse_block(parser);
|
|
|
|
|
node->data.try_stmt.catch_clauses = NULL;
|
|
|
|
|
node->data.try_stmt.catch_count = 0;
|
|
|
|
|
node->data.try_stmt.finally_block = NULL;
|
|
|
|
|
|
|
|
|
|
size_t capacity = 4;
|
|
|
|
|
node->data.try_stmt.catch_clauses = malloc(capacity * sizeof(RavaASTNode_t*));
|
|
|
|
|
|
|
|
|
|
while (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_CATCH)) {
|
|
|
|
|
RavaASTNode_t *catch_node = rava_ast_node_create(RAVA_AST_CATCH_CLAUSE,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after catch");
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
|
|
|
|
catch_node->data.catch_clause.exception_type = strdup(parser->current_token->lexeme);
|
|
|
|
|
_rava_parser_advance(parser);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
|
|
|
|
catch_node->data.catch_clause.exception_name = strdup(parser->current_token->lexeme);
|
|
|
|
|
_rava_parser_advance(parser);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after catch parameter");
|
|
|
|
|
|
|
|
|
|
catch_node->data.catch_clause.body = _rava_parser_parse_block(parser);
|
|
|
|
|
|
|
|
|
|
if (node->data.try_stmt.catch_count >= capacity) {
|
|
|
|
|
capacity *= 2;
|
|
|
|
|
node->data.try_stmt.catch_clauses = realloc(
|
|
|
|
|
node->data.try_stmt.catch_clauses,
|
|
|
|
|
capacity * sizeof(RavaASTNode_t*));
|
|
|
|
|
}
|
|
|
|
|
node->data.try_stmt.catch_clauses[node->data.try_stmt.catch_count++] = catch_node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_FINALLY)) {
|
|
|
|
|
node->data.try_stmt.finally_block = _rava_parser_parse_block(parser);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-02 06:54:32 +01:00
|
|
|
bool is_type_decl = false;
|
|
|
|
|
if (_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)) {
|
|
|
|
|
is_type_decl = true;
|
|
|
|
|
} else if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
|
|
|
|
if (parser->peek_token && parser->peek_token->type == RAVA_TOKEN_IDENTIFIER) {
|
|
|
|
|
is_type_decl = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_type_decl) {
|
|
|
|
|
RavaASTNode_t *type = _rava_parser_parse_type(parser);
|
|
|
|
|
RavaASTNode_t *var_decl = rava_ast_node_create(RAVA_AST_VAR_DECL,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
var_decl->data.var_decl.type = type;
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
|
|
|
|
var_decl->data.var_decl.name = strdup(parser->current_token->lexeme);
|
|
|
|
|
_rava_parser_advance(parser);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_ASSIGN)) {
|
2025-12-02 21:12:50 +01:00
|
|
|
if (_rava_parser_check(parser, RAVA_TOKEN_LBRACE)) {
|
|
|
|
|
var_decl->data.var_decl.initializer = _rava_parser_parse_array_initializer(parser);
|
|
|
|
|
} else {
|
|
|
|
|
var_decl->data.var_decl.initializer = _rava_parser_parse_expression(parser);
|
|
|
|
|
}
|
2025-12-02 06:54:32 +01:00
|
|
|
} else {
|
|
|
|
|
var_decl->data.var_decl.initializer = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after variable declaration");
|
|
|
|
|
|
|
|
|
|
return var_decl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RavaASTNode_t *expr = _rava_parser_parse_expression(parser);
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after expression");
|
|
|
|
|
|
|
|
|
|
RavaASTNode_t *stmt = rava_ast_node_create(RAVA_AST_EXPR_STMT,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
rava_ast_node_add_child(stmt, expr);
|
|
|
|
|
|
|
|
|
|
return stmt;
|
|
|
|
|
}
|