This commit is contained in:
2025-12-02 21:12:50 +01:00
parent 3872c52997
commit de48b1e64c
11 changed files with 2435 additions and 71 deletions
+59
View File
@@ -157,11 +157,19 @@ struct RavaASTNode_t {
struct {
char *name;
char *superclass;
char **interfaces;
size_t interfaces_count;
RavaASTNode_t *type;
RavaModifier_e *modifiers;
size_t modifiers_count;
} class_decl;
struct {
char *name;
RavaModifier_e *modifiers;
size_t modifiers_count;
} interface_decl;
struct {
char *name;
RavaASTNode_t *return_type;
@@ -175,6 +183,14 @@ struct RavaASTNode_t {
RavaASTNode_t *initializer;
} var_decl;
struct {
char *name;
RavaASTNode_t *type;
RavaASTNode_t *initializer;
RavaModifier_e *modifiers;
size_t modifiers_count;
} field_decl;
struct {
RavaASTNode_t *condition;
RavaASTNode_t *then_stmt;
@@ -193,6 +209,13 @@ struct RavaASTNode_t {
RavaASTNode_t *body;
} for_stmt;
struct {
RavaASTNode_t *var_type;
char *var_name;
RavaASTNode_t *iterable;
RavaASTNode_t *body;
} enhanced_for;
struct {
RavaASTNode_t *value;
} return_stmt;
@@ -229,6 +252,42 @@ struct RavaASTNode_t {
RavaASTNode_t *type;
RavaASTNode_t *expression;
} cast;
struct {
RavaASTNode_t *expression;
} switch_stmt;
struct {
RavaASTNode_t *value;
bool is_default;
} case_stmt;
struct {
RavaASTNode_t *try_block;
RavaASTNode_t **catch_clauses;
size_t catch_count;
RavaASTNode_t *finally_block;
} try_stmt;
struct {
char *exception_type;
char *exception_name;
RavaASTNode_t *body;
} catch_clause;
struct {
RavaASTNode_t *expression;
} throw_stmt;
struct {
RavaASTNode_t **elements;
size_t elements_count;
} array_init;
struct {
RavaASTNode_t *expression;
char *type_name;
} instanceof_expr;
} data;
};
+105 -5
View File
@@ -78,6 +78,8 @@ RavaASTNode_t* _rava_parser_parse_class_declaration(RavaParser_t *parser) {
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);
@@ -91,6 +93,24 @@ RavaASTNode_t* _rava_parser_parse_class_declaration(RavaParser_t *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) &&
@@ -160,15 +180,18 @@ RavaASTNode_t* _rava_parser_parse_class_declaration(RavaParser_t *parser) {
RavaASTNode_t *field = rava_ast_node_create(RAVA_AST_FIELD_DECL,
parser->current_token->line,
parser->current_token->column);
field->data.var_decl.type = member_type;
field->data.var_decl.name = name;
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.var_decl.initializer = _rava_parser_parse_expression(parser);
field->data.field_decl.initializer = _rava_parser_parse_expression(parser);
} else {
field->data.var_decl.initializer = NULL;
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;
}
}
}
@@ -178,6 +201,63 @@ RavaASTNode_t* _rava_parser_parse_class_declaration(RavaParser_t *parser) {
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);
@@ -186,7 +266,27 @@ RavaASTNode_t* rava_parser_parse(RavaParser_t *parser) {
break;
}
RavaASTNode_t *decl = _rava_parser_parse_class_declaration(parser);
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);
}
+163 -8
View File
@@ -10,6 +10,19 @@ extern bool _rava_parser_expect(RavaParser_t *parser, RavaTokenType_e type, cons
extern RavaASTNode_t* _rava_parser_parse_type(RavaParser_t *parser);
RavaASTNode_t* _rava_parser_parse_expression(RavaParser_t *parser);
RavaASTNode_t* _rava_parser_parse_array_initializer(RavaParser_t *parser);
static RavaASTNode_t* _rava_parser_parse_unary(RavaParser_t *parser);
static bool _is_primitive_type_token(RavaTokenType_e type) {
return type == RAVA_TOKEN_KEYWORD_INT ||
type == RAVA_TOKEN_KEYWORD_LONG ||
type == RAVA_TOKEN_KEYWORD_DOUBLE ||
type == RAVA_TOKEN_KEYWORD_FLOAT ||
type == RAVA_TOKEN_KEYWORD_BOOLEAN ||
type == RAVA_TOKEN_KEYWORD_CHAR ||
type == RAVA_TOKEN_KEYWORD_BYTE ||
type == RAVA_TOKEN_KEYWORD_SHORT;
}
static RavaASTNode_t* _rava_parser_parse_primary(RavaParser_t *parser) {
RavaASTNode_t *node = NULL;
@@ -60,6 +73,16 @@ static RavaASTNode_t* _rava_parser_parse_primary(RavaParser_t *parser) {
}
if (_rava_parser_match(parser, RAVA_TOKEN_LPAREN)) {
if (_is_primitive_type_token(parser->current_token->type) &&
parser->peek_token && parser->peek_token->type == RAVA_TOKEN_RPAREN) {
RavaASTNode_t *cast_node = rava_ast_node_create(RAVA_AST_CAST_EXPR,
parser->current_token->line,
parser->current_token->column);
cast_node->data.cast.type = _rava_parser_parse_type(parser);
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after type in cast");
cast_node->data.cast.expression = _rava_parser_parse_unary(parser);
return cast_node;
}
RavaASTNode_t *expr = _rava_parser_parse_expression(parser);
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after expression");
return expr;
@@ -76,9 +99,10 @@ static RavaASTNode_t* _rava_parser_parse_primary(RavaParser_t *parser) {
node->data.new_expr.arguments = malloc(sizeof(RavaASTNode_t*) * args_capacity);
node->data.new_expr.arguments_count = 0;
node->data.new_expr.arguments[node->data.new_expr.arguments_count++] =
_rava_parser_parse_expression(parser);
if (!_rava_parser_check(parser, RAVA_TOKEN_RBRACKET)) {
node->data.new_expr.arguments[node->data.new_expr.arguments_count++] =
_rava_parser_parse_expression(parser);
}
_rava_parser_expect(parser, RAVA_TOKEN_RBRACKET, "Expected ']' after array size");
while (_rava_parser_match(parser, RAVA_TOKEN_LBRACKET)) {
@@ -304,13 +328,51 @@ static RavaASTNode_t* _rava_parser_parse_additive(RavaParser_t *parser) {
return left;
}
static RavaASTNode_t* _rava_parser_parse_relational(RavaParser_t *parser) {
static RavaASTNode_t* _rava_parser_parse_shift(RavaParser_t *parser) {
RavaASTNode_t *left = _rava_parser_parse_additive(parser);
while (_rava_parser_check(parser, RAVA_TOKEN_LSHIFT) ||
_rava_parser_check(parser, RAVA_TOKEN_RSHIFT) ||
_rava_parser_check(parser, RAVA_TOKEN_URSHIFT)) {
RavaBinaryOp_e op;
if (_rava_parser_match(parser, RAVA_TOKEN_LSHIFT)) op = RAVA_BINOP_LSHIFT;
else if (_rava_parser_match(parser, RAVA_TOKEN_RSHIFT)) op = RAVA_BINOP_RSHIFT;
else { _rava_parser_advance(parser); op = RAVA_BINOP_URSHIFT; }
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_BINARY_EXPR,
parser->current_token->line,
parser->current_token->column);
node->data.binary.op = op;
node->data.binary.left = left;
node->data.binary.right = _rava_parser_parse_additive(parser);
left = node;
}
return left;
}
static RavaASTNode_t* _rava_parser_parse_relational(RavaParser_t *parser) {
RavaASTNode_t *left = _rava_parser_parse_shift(parser);
while (_rava_parser_check(parser, RAVA_TOKEN_LT) ||
_rava_parser_check(parser, RAVA_TOKEN_GT) ||
_rava_parser_check(parser, RAVA_TOKEN_LE) ||
_rava_parser_check(parser, RAVA_TOKEN_GE)) {
_rava_parser_check(parser, RAVA_TOKEN_GE) ||
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_INSTANCEOF)) {
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_INSTANCEOF)) {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_INSTANCEOF_EXPR,
parser->current_token->line,
parser->current_token->column);
node->data.instanceof_expr.expression = left;
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
node->data.instanceof_expr.type_name = strdup(parser->current_token->lexeme);
_rava_parser_advance(parser);
}
left = node;
continue;
}
RavaBinaryOp_e op;
if (_rava_parser_match(parser, RAVA_TOKEN_LT)) op = RAVA_BINOP_LT;
@@ -352,16 +414,64 @@ static RavaASTNode_t* _rava_parser_parse_equality(RavaParser_t *parser) {
return left;
}
static RavaASTNode_t* _rava_parser_parse_logical_and(RavaParser_t *parser) {
static RavaASTNode_t* _rava_parser_parse_bitwise_and(RavaParser_t *parser) {
RavaASTNode_t *left = _rava_parser_parse_equality(parser);
while (_rava_parser_match(parser, RAVA_TOKEN_AMP)) {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_BINARY_EXPR,
parser->current_token->line,
parser->current_token->column);
node->data.binary.op = RAVA_BINOP_BITAND;
node->data.binary.left = left;
node->data.binary.right = _rava_parser_parse_equality(parser);
left = node;
}
return left;
}
static RavaASTNode_t* _rava_parser_parse_bitwise_xor(RavaParser_t *parser) {
RavaASTNode_t *left = _rava_parser_parse_bitwise_and(parser);
while (_rava_parser_match(parser, RAVA_TOKEN_CARET)) {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_BINARY_EXPR,
parser->current_token->line,
parser->current_token->column);
node->data.binary.op = RAVA_BINOP_BITXOR;
node->data.binary.left = left;
node->data.binary.right = _rava_parser_parse_bitwise_and(parser);
left = node;
}
return left;
}
static RavaASTNode_t* _rava_parser_parse_bitwise_or(RavaParser_t *parser) {
RavaASTNode_t *left = _rava_parser_parse_bitwise_xor(parser);
while (_rava_parser_match(parser, RAVA_TOKEN_PIPE)) {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_BINARY_EXPR,
parser->current_token->line,
parser->current_token->column);
node->data.binary.op = RAVA_BINOP_BITOR;
node->data.binary.left = left;
node->data.binary.right = _rava_parser_parse_bitwise_xor(parser);
left = node;
}
return left;
}
static RavaASTNode_t* _rava_parser_parse_logical_and(RavaParser_t *parser) {
RavaASTNode_t *left = _rava_parser_parse_bitwise_or(parser);
while (_rava_parser_match(parser, RAVA_TOKEN_AND)) {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_BINARY_EXPR,
parser->current_token->line,
parser->current_token->column);
node->data.binary.op = RAVA_BINOP_AND;
node->data.binary.left = left;
node->data.binary.right = _rava_parser_parse_equality(parser);
node->data.binary.right = _rava_parser_parse_bitwise_or(parser);
left = node;
}
@@ -384,8 +494,25 @@ static RavaASTNode_t* _rava_parser_parse_logical_or(RavaParser_t *parser) {
return left;
}
static RavaASTNode_t* _rava_parser_parse_ternary(RavaParser_t *parser) {
RavaASTNode_t *condition = _rava_parser_parse_logical_or(parser);
if (_rava_parser_match(parser, RAVA_TOKEN_QUESTION)) {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_TERNARY_EXPR,
parser->current_token->line,
parser->current_token->column);
node->data.ternary.condition = condition;
node->data.ternary.true_expr = _rava_parser_parse_expression(parser);
_rava_parser_expect(parser, RAVA_TOKEN_COLON, "Expected ':' in ternary expression");
node->data.ternary.false_expr = _rava_parser_parse_ternary(parser);
return node;
}
return condition;
}
static RavaASTNode_t* _rava_parser_parse_assignment(RavaParser_t *parser) {
RavaASTNode_t *left = _rava_parser_parse_logical_or(parser);
RavaASTNode_t *left = _rava_parser_parse_ternary(parser);
if (_rava_parser_match(parser, RAVA_TOKEN_ASSIGN)) {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_ASSIGN_EXPR,
@@ -428,6 +555,34 @@ static RavaASTNode_t* _rava_parser_parse_assignment(RavaParser_t *parser) {
return left;
}
RavaASTNode_t* _rava_parser_parse_array_initializer(RavaParser_t *parser) {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_ARRAY_INIT_EXPR,
parser->current_token->line,
parser->current_token->column);
_rava_parser_expect(parser, RAVA_TOKEN_LBRACE, "Expected '{' for array initializer");
size_t capacity = 8;
node->data.array_init.elements = malloc(sizeof(RavaASTNode_t*) * capacity);
node->data.array_init.elements_count = 0;
if (!_rava_parser_check(parser, RAVA_TOKEN_RBRACE)) {
do {
if (node->data.array_init.elements_count >= capacity) {
capacity *= 2;
node->data.array_init.elements = realloc(node->data.array_init.elements,
sizeof(RavaASTNode_t*) * capacity);
}
node->data.array_init.elements[node->data.array_init.elements_count++] =
_rava_parser_parse_expression(parser);
} while (_rava_parser_match(parser, RAVA_TOKEN_COMMA));
}
_rava_parser_expect(parser, RAVA_TOKEN_RBRACE, "Expected '}' after array initializer");
return node;
}
RavaASTNode_t* _rava_parser_parse_expression(RavaParser_t *parser) {
return _rava_parser_parse_assignment(parser);
}
+214 -22
View File
@@ -8,6 +8,7 @@ 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);
extern RavaASTNode_t* _rava_parser_parse_array_initializer(RavaParser_t *parser);
extern RavaASTNode_t* _rava_parser_parse_type(RavaParser_t *parser);
RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser);
@@ -72,11 +73,26 @@ RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser) {
return node;
}
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_FOR)) {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_FOR_STMT,
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_DO)) {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_DO_WHILE_STMT,
parser->current_token->line,
parser->current_token->column);
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;
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after 'for'");
if (!_rava_parser_check(parser, RAVA_TOKEN_SEMICOLON)) {
@@ -94,41 +110,154 @@ RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser) {
}
if (is_type_decl) {
RavaASTNode_t *type = _rava_parser_parse_type(parser);
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);
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);
}
var_decl->data.var_decl.name = var_name;
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;
_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;
} else {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_FOR_STMT, line, column);
node->data.for_stmt.init = _rava_parser_parse_expression(parser);
_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;
}
} else {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_FOR_STMT, line, column);
node->data.for_stmt.init = NULL;
}
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after for init");
_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_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");
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);
node->data.for_stmt.body = _rava_parser_parse_statement(parser);
return node;
}
}
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;
}
}
_rava_parser_expect(parser, RAVA_TOKEN_RBRACE, "Expected '}' at end of switch");
return node;
}
@@ -165,6 +294,65 @@ RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser) {
return node;
}
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;
}
bool is_type_decl = false;
if (_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_INT) ||
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_BOOLEAN) ||
@@ -194,7 +382,11 @@ RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser) {
}
if (_rava_parser_match(parser, RAVA_TOKEN_ASSIGN)) {
var_decl->data.var_decl.initializer = _rava_parser_parse_expression(parser);
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);
}
} else {
var_decl->data.var_decl.initializer = NULL;
}