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_type(RavaParser_t *parser);
|
|
|
|
|
|
|
|
|
|
RavaASTNode_t* _rava_parser_parse_expression(RavaParser_t *parser);
|
2025-12-02 21:12:50 +01:00
|
|
|
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;
|
|
|
|
|
}
|
2025-12-02 06:54:32 +01:00
|
|
|
|
|
|
|
|
static RavaASTNode_t* _rava_parser_parse_primary(RavaParser_t *parser) {
|
|
|
|
|
RavaASTNode_t *node = NULL;
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_check(parser, RAVA_TOKEN_LITERAL_INTEGER) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_LITERAL_LONG) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_LITERAL_FLOAT) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_LITERAL_DOUBLE) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_LITERAL_STRING) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_LITERAL_CHARACTER) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_LITERAL_TRUE) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_LITERAL_FALSE) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_LITERAL_NULL)) {
|
|
|
|
|
|
|
|
|
|
node = rava_ast_node_create(RAVA_AST_LITERAL_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
node->data.literal.literal_type = parser->current_token->type;
|
|
|
|
|
node->data.literal.value = parser->current_token->value;
|
|
|
|
|
|
|
|
|
|
if (parser->current_token->type == RAVA_TOKEN_LITERAL_STRING) {
|
|
|
|
|
node->data.literal.value.string_value = strdup(parser->current_token->value.string_value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_rava_parser_advance(parser);
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
|
|
|
|
node = rava_ast_node_create(RAVA_AST_IDENTIFIER_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
node->data.identifier.name = strdup(parser->current_token->lexeme);
|
|
|
|
|
_rava_parser_advance(parser);
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_THIS)) {
|
|
|
|
|
return rava_ast_node_create(RAVA_AST_THIS_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_SUPER)) {
|
|
|
|
|
return rava_ast_node_create(RAVA_AST_SUPER_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_LPAREN)) {
|
2025-12-02 21:12:50 +01:00
|
|
|
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;
|
|
|
|
|
}
|
2025-12-02 06:54:32 +01:00
|
|
|
RavaASTNode_t *expr = _rava_parser_parse_expression(parser);
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after expression");
|
|
|
|
|
return expr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_NEW)) {
|
|
|
|
|
node = rava_ast_node_create(RAVA_AST_NEW_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
node->data.new_expr.type = _rava_parser_parse_type(parser);
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_LBRACKET)) {
|
|
|
|
|
size_t args_capacity = 4;
|
|
|
|
|
node->data.new_expr.arguments = malloc(sizeof(RavaASTNode_t*) * args_capacity);
|
|
|
|
|
node->data.new_expr.arguments_count = 0;
|
|
|
|
|
|
2025-12-02 21:12:50 +01:00
|
|
|
if (!_rava_parser_check(parser, RAVA_TOKEN_RBRACKET)) {
|
|
|
|
|
node->data.new_expr.arguments[node->data.new_expr.arguments_count++] =
|
|
|
|
|
_rava_parser_parse_expression(parser);
|
|
|
|
|
}
|
2025-12-02 06:54:32 +01:00
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_RBRACKET, "Expected ']' after array size");
|
|
|
|
|
|
|
|
|
|
while (_rava_parser_match(parser, RAVA_TOKEN_LBRACKET)) {
|
|
|
|
|
if (node->data.new_expr.arguments_count >= args_capacity) {
|
|
|
|
|
args_capacity *= 2;
|
|
|
|
|
node->data.new_expr.arguments = realloc(node->data.new_expr.arguments,
|
|
|
|
|
sizeof(RavaASTNode_t*) * args_capacity);
|
|
|
|
|
}
|
|
|
|
|
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 ']'");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (node->data.new_expr.type) {
|
|
|
|
|
node->data.new_expr.type->data.type.is_array = true;
|
|
|
|
|
node->data.new_expr.type->data.type.array_dimensions = (int)node->data.new_expr.arguments_count;
|
|
|
|
|
}
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' or '[' after type in new expression");
|
|
|
|
|
|
|
|
|
|
size_t args_capacity = 4;
|
|
|
|
|
node->data.new_expr.arguments = malloc(sizeof(RavaASTNode_t*) * args_capacity);
|
|
|
|
|
node->data.new_expr.arguments_count = 0;
|
|
|
|
|
|
|
|
|
|
if (!_rava_parser_check(parser, RAVA_TOKEN_RPAREN)) {
|
|
|
|
|
do {
|
|
|
|
|
if (node->data.new_expr.arguments_count >= args_capacity) {
|
|
|
|
|
args_capacity *= 2;
|
|
|
|
|
node->data.new_expr.arguments = realloc(node->data.new_expr.arguments,
|
|
|
|
|
sizeof(RavaASTNode_t*) * args_capacity);
|
|
|
|
|
}
|
|
|
|
|
node->data.new_expr.arguments[node->data.new_expr.arguments_count++] =
|
|
|
|
|
_rava_parser_parse_expression(parser);
|
|
|
|
|
} while (_rava_parser_match(parser, RAVA_TOKEN_COMMA));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after arguments");
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parser->had_error = true;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static RavaASTNode_t* _rava_parser_parse_postfix(RavaParser_t *parser) {
|
|
|
|
|
RavaASTNode_t *expr = _rava_parser_parse_primary(parser);
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_DOT)) {
|
|
|
|
|
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
|
|
|
|
|
RavaASTNode_t *member_access = rava_ast_node_create(RAVA_AST_MEMBER_ACCESS_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
member_access->data.member_access.object = expr;
|
|
|
|
|
member_access->data.member_access.member = strdup(parser->current_token->lexeme);
|
|
|
|
|
_rava_parser_advance(parser);
|
|
|
|
|
expr = member_access;
|
|
|
|
|
}
|
|
|
|
|
} else if (_rava_parser_match(parser, RAVA_TOKEN_LPAREN)) {
|
|
|
|
|
RavaASTNode_t *call = rava_ast_node_create(RAVA_AST_CALL_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
call->data.call.callee = expr;
|
|
|
|
|
|
|
|
|
|
size_t args_capacity = 4;
|
|
|
|
|
call->data.call.arguments = malloc(sizeof(RavaASTNode_t*) * args_capacity);
|
|
|
|
|
call->data.call.arguments_count = 0;
|
|
|
|
|
|
|
|
|
|
if (!_rava_parser_check(parser, RAVA_TOKEN_RPAREN)) {
|
|
|
|
|
do {
|
|
|
|
|
if (call->data.call.arguments_count >= args_capacity) {
|
|
|
|
|
args_capacity *= 2;
|
|
|
|
|
call->data.call.arguments = realloc(call->data.call.arguments,
|
|
|
|
|
sizeof(RavaASTNode_t*) * args_capacity);
|
|
|
|
|
}
|
|
|
|
|
call->data.call.arguments[call->data.call.arguments_count++] =
|
|
|
|
|
_rava_parser_parse_expression(parser);
|
|
|
|
|
} while (_rava_parser_match(parser, RAVA_TOKEN_COMMA));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after arguments");
|
|
|
|
|
expr = call;
|
|
|
|
|
} else if (_rava_parser_match(parser, RAVA_TOKEN_LBRACKET)) {
|
|
|
|
|
RavaASTNode_t *array_access = rava_ast_node_create(RAVA_AST_ARRAY_ACCESS_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
array_access->data.array_access.array = expr;
|
|
|
|
|
array_access->data.array_access.index = _rava_parser_parse_expression(parser);
|
|
|
|
|
_rava_parser_expect(parser, RAVA_TOKEN_RBRACKET, "Expected ']' after array index");
|
|
|
|
|
expr = array_access;
|
|
|
|
|
} else if (_rava_parser_match(parser, RAVA_TOKEN_INC)) {
|
|
|
|
|
RavaASTNode_t *unary = rava_ast_node_create(RAVA_AST_UNARY_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
unary->data.unary.op = RAVA_UNOP_POSTINC;
|
|
|
|
|
unary->data.unary.operand = expr;
|
|
|
|
|
expr = unary;
|
|
|
|
|
} else if (_rava_parser_match(parser, RAVA_TOKEN_DEC)) {
|
|
|
|
|
RavaASTNode_t *unary = rava_ast_node_create(RAVA_AST_UNARY_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
unary->data.unary.op = RAVA_UNOP_POSTDEC;
|
|
|
|
|
unary->data.unary.operand = expr;
|
|
|
|
|
expr = unary;
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return expr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static RavaASTNode_t* _rava_parser_parse_unary(RavaParser_t *parser) {
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_PLUS)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_UNARY_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
node->data.unary.op = RAVA_UNOP_PLUS;
|
|
|
|
|
node->data.unary.operand = _rava_parser_parse_unary(parser);
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_MINUS)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_UNARY_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
node->data.unary.op = RAVA_UNOP_MINUS;
|
|
|
|
|
node->data.unary.operand = _rava_parser_parse_unary(parser);
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_BANG)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_UNARY_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
node->data.unary.op = RAVA_UNOP_NOT;
|
|
|
|
|
node->data.unary.operand = _rava_parser_parse_unary(parser);
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_TILDE)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_UNARY_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
node->data.unary.op = RAVA_UNOP_BITNOT;
|
|
|
|
|
node->data.unary.operand = _rava_parser_parse_unary(parser);
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_INC)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_UNARY_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
node->data.unary.op = RAVA_UNOP_PREINC;
|
|
|
|
|
node->data.unary.operand = _rava_parser_parse_unary(parser);
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_DEC)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_UNARY_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
node->data.unary.op = RAVA_UNOP_PREDEC;
|
|
|
|
|
node->data.unary.operand = _rava_parser_parse_unary(parser);
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _rava_parser_parse_postfix(parser);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static RavaASTNode_t* _rava_parser_parse_multiplicative(RavaParser_t *parser) {
|
|
|
|
|
RavaASTNode_t *left = _rava_parser_parse_unary(parser);
|
|
|
|
|
|
|
|
|
|
while (_rava_parser_check(parser, RAVA_TOKEN_STAR) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_SLASH) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_PERCENT)) {
|
|
|
|
|
|
|
|
|
|
RavaBinaryOp_e op;
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_STAR)) {
|
|
|
|
|
op = RAVA_BINOP_MUL;
|
|
|
|
|
} else if (_rava_parser_match(parser, RAVA_TOKEN_SLASH)) {
|
|
|
|
|
op = RAVA_BINOP_DIV;
|
|
|
|
|
} else {
|
|
|
|
|
_rava_parser_advance(parser);
|
|
|
|
|
op = RAVA_BINOP_MOD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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_unary(parser);
|
|
|
|
|
left = node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return left;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static RavaASTNode_t* _rava_parser_parse_additive(RavaParser_t *parser) {
|
|
|
|
|
RavaASTNode_t *left = _rava_parser_parse_multiplicative(parser);
|
|
|
|
|
|
|
|
|
|
while (_rava_parser_check(parser, RAVA_TOKEN_PLUS) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_MINUS)) {
|
|
|
|
|
|
|
|
|
|
RavaBinaryOp_e op = _rava_parser_match(parser, RAVA_TOKEN_PLUS) ?
|
|
|
|
|
RAVA_BINOP_ADD : RAVA_BINOP_SUB;
|
|
|
|
|
if (op == RAVA_BINOP_SUB) _rava_parser_advance(parser);
|
|
|
|
|
|
|
|
|
|
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_multiplicative(parser);
|
|
|
|
|
left = node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return left;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-02 21:12:50 +01:00
|
|
|
static RavaASTNode_t* _rava_parser_parse_shift(RavaParser_t *parser) {
|
2025-12-02 06:54:32 +01:00
|
|
|
RavaASTNode_t *left = _rava_parser_parse_additive(parser);
|
|
|
|
|
|
2025-12-02 21:12:50 +01:00
|
|
|
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);
|
|
|
|
|
|
2025-12-02 06:54:32 +01:00
|
|
|
while (_rava_parser_check(parser, RAVA_TOKEN_LT) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_GT) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_LE) ||
|
2025-12-02 21:12:50 +01:00
|
|
|
_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;
|
|
|
|
|
}
|
2025-12-02 06:54:32 +01:00
|
|
|
|
|
|
|
|
RavaBinaryOp_e op;
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_LT)) op = RAVA_BINOP_LT;
|
|
|
|
|
else if (_rava_parser_match(parser, RAVA_TOKEN_GT)) op = RAVA_BINOP_GT;
|
|
|
|
|
else if (_rava_parser_match(parser, RAVA_TOKEN_LE)) op = RAVA_BINOP_LE;
|
|
|
|
|
else { _rava_parser_advance(parser); op = RAVA_BINOP_GE; }
|
|
|
|
|
|
|
|
|
|
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_equality(RavaParser_t *parser) {
|
|
|
|
|
RavaASTNode_t *left = _rava_parser_parse_relational(parser);
|
|
|
|
|
|
|
|
|
|
while (_rava_parser_check(parser, RAVA_TOKEN_EQUAL) ||
|
|
|
|
|
_rava_parser_check(parser, RAVA_TOKEN_NE)) {
|
|
|
|
|
|
|
|
|
|
RavaBinaryOp_e op = _rava_parser_match(parser, RAVA_TOKEN_EQUAL) ?
|
|
|
|
|
RAVA_BINOP_EQ : RAVA_BINOP_NE;
|
|
|
|
|
if (op == RAVA_BINOP_NE) _rava_parser_advance(parser);
|
|
|
|
|
|
|
|
|
|
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_relational(parser);
|
|
|
|
|
left = node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return left;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-02 21:12:50 +01:00
|
|
|
static RavaASTNode_t* _rava_parser_parse_bitwise_and(RavaParser_t *parser) {
|
2025-12-02 06:54:32 +01:00
|
|
|
RavaASTNode_t *left = _rava_parser_parse_equality(parser);
|
|
|
|
|
|
2025-12-02 21:12:50 +01:00
|
|
|
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);
|
|
|
|
|
|
2025-12-02 06:54:32 +01:00
|
|
|
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;
|
2025-12-02 21:12:50 +01:00
|
|
|
node->data.binary.right = _rava_parser_parse_bitwise_or(parser);
|
2025-12-02 06:54:32 +01:00
|
|
|
left = node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return left;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static RavaASTNode_t* _rava_parser_parse_logical_or(RavaParser_t *parser) {
|
|
|
|
|
RavaASTNode_t *left = _rava_parser_parse_logical_and(parser);
|
|
|
|
|
|
|
|
|
|
while (_rava_parser_match(parser, RAVA_TOKEN_OR)) {
|
|
|
|
|
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_OR;
|
|
|
|
|
node->data.binary.left = left;
|
|
|
|
|
node->data.binary.right = _rava_parser_parse_logical_and(parser);
|
|
|
|
|
left = node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return left;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-02 21:12:50 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-02 06:54:32 +01:00
|
|
|
static RavaASTNode_t* _rava_parser_parse_assignment(RavaParser_t *parser) {
|
2025-12-02 21:12:50 +01:00
|
|
|
RavaASTNode_t *left = _rava_parser_parse_ternary(parser);
|
2025-12-02 06:54:32 +01:00
|
|
|
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_ASSIGN)) {
|
|
|
|
|
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_ASSIGN_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
node->data.assign.target = left;
|
|
|
|
|
node->data.assign.value = _rava_parser_parse_assignment(parser);
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RavaBinaryOp_e compound_op = -1;
|
|
|
|
|
if (_rava_parser_match(parser, RAVA_TOKEN_PLUSASSIGN)) {
|
|
|
|
|
compound_op = RAVA_BINOP_ADD;
|
|
|
|
|
} else if (_rava_parser_match(parser, RAVA_TOKEN_MINUSASSIGN)) {
|
|
|
|
|
compound_op = RAVA_BINOP_SUB;
|
|
|
|
|
} else if (_rava_parser_match(parser, RAVA_TOKEN_STARASSIGN)) {
|
|
|
|
|
compound_op = RAVA_BINOP_MUL;
|
|
|
|
|
} else if (_rava_parser_match(parser, RAVA_TOKEN_SLASHASSIGN)) {
|
|
|
|
|
compound_op = RAVA_BINOP_DIV;
|
|
|
|
|
} else if (_rava_parser_match(parser, RAVA_TOKEN_PERCENTASSIGN)) {
|
|
|
|
|
compound_op = RAVA_BINOP_MOD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (compound_op != (RavaBinaryOp_e)-1) {
|
|
|
|
|
RavaASTNode_t *binary = rava_ast_node_create(RAVA_AST_BINARY_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
binary->data.binary.op = compound_op;
|
|
|
|
|
binary->data.binary.left = left;
|
|
|
|
|
binary->data.binary.right = _rava_parser_parse_assignment(parser);
|
|
|
|
|
|
|
|
|
|
RavaASTNode_t *assign = rava_ast_node_create(RAVA_AST_ASSIGN_EXPR,
|
|
|
|
|
parser->current_token->line,
|
|
|
|
|
parser->current_token->column);
|
|
|
|
|
assign->data.assign.target = left;
|
|
|
|
|
assign->data.assign.value = binary;
|
|
|
|
|
return assign;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return left;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-02 21:12:50 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-02 06:54:32 +01:00
|
|
|
RavaASTNode_t* _rava_parser_parse_expression(RavaParser_t *parser) {
|
|
|
|
|
return _rava_parser_parse_assignment(parser);
|
|
|
|
|
}
|