chore: remove trailing whitespace from README.md formatting
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user