#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); 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; 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)) { 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; } 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; 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)) { 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; } 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_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; 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; } 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_bitwise_or(parser); 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; } 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_ternary(parser); 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; } else if (_rava_parser_match(parser, RAVA_TOKEN_ANDASSIGN)) { compound_op = RAVA_BINOP_BITAND; } else if (_rava_parser_match(parser, RAVA_TOKEN_ORASSIGN)) { compound_op = RAVA_BINOP_BITOR; } else if (_rava_parser_match(parser, RAVA_TOKEN_CARETASSIGN)) { compound_op = RAVA_BINOP_BITXOR; } else if (_rava_parser_match(parser, RAVA_TOKEN_LSHIFTASSIGN)) { compound_op = RAVA_BINOP_LSHIFT; } else if (_rava_parser_match(parser, RAVA_TOKEN_RSHIFTASSIGN)) { compound_op = RAVA_BINOP_RSHIFT; } else if (_rava_parser_match(parser, RAVA_TOKEN_URSHIFTASSIGN)) { compound_op = RAVA_BINOP_URSHIFT; } 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; } 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); }