#define _POSIX_C_SOURCE 200809L
#include "parser.h"
#include <stdlib.h>
#include <string.h>
extern void _rava_parser_advance(RavaParser_t *parser);
extern bool _rava_parser_check(RavaParser_t *parser, RavaTokenType_e type);
extern bool _rava_parser_match(RavaParser_t *parser, RavaTokenType_e type);
extern bool _rava_parser_expect(RavaParser_t *parser, RavaTokenType_e type, const char *message);
extern RavaASTNode_t* _rava_parser_parse_expression(RavaParser_t *parser);
extern RavaASTNode_t* _rava_parser_parse_type(RavaParser_t *parser);
RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser);
RavaASTNode_t* _rava_parser_parse_block(RavaParser_t *parser);
RavaASTNode_t* _rava_parser_parse_block(RavaParser_t *parser) {
RavaASTNode_t *block = rava_ast_node_create(RAVA_AST_BLOCK_STMT,
parser->current_token->line,
parser->current_token->column);
_rava_parser_expect(parser, RAVA_TOKEN_LBRACE, "Expected '{' at start of block");
while (!_rava_parser_check(parser, RAVA_TOKEN_RBRACE) &&
!_rava_parser_check(parser, RAVA_TOKEN_EOF)) {
RavaASTNode_t *stmt = _rava_parser_parse_statement(parser);
if (stmt) {
rava_ast_node_add_child(block, stmt);
}
}
_rava_parser_expect(parser, RAVA_TOKEN_RBRACE, "Expected '}' at end of block");
return block;
}
RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser) {
if (_rava_parser_check(parser, RAVA_TOKEN_LBRACE)) {
return _rava_parser_parse_block(parser);
}
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_IF)) {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_IF_STMT,
parser->current_token->line,
parser->current_token->column);
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after 'if'");
node->data.if_stmt.condition = _rava_parser_parse_expression(parser);
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after if condition");
node->data.if_stmt.then_stmt = _rava_parser_parse_statement(parser);
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_ELSE)) {
node->data.if_stmt.else_stmt = _rava_parser_parse_statement(parser);
} else {
node->data.if_stmt.else_stmt = NULL;
}
return node;
}
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_WHILE)) {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_WHILE_STMT,
parser->current_token->line,
parser->current_token->column);
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after 'while'");
node->data.while_stmt.condition = _rava_parser_parse_expression(parser);
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after while condition");
node->data.while_stmt.body = _rava_parser_parse_statement(parser);
return node;
}
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_FOR)) {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_FOR_STMT,
parser->current_token->line,
parser->current_token->column);
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after 'for'");
if (!_rava_parser_check(parser, RAVA_TOKEN_SEMICOLON)) {
bool is_type_decl = false;
if (_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_INT) ||
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_LONG) ||
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_DOUBLE) ||
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_BOOLEAN) ||
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_CHAR)) {
is_type_decl = true;
} else if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
if (parser->peek_token && parser->peek_token->type == RAVA_TOKEN_IDENTIFIER) {
is_type_decl = true;
}
}
if (is_type_decl) {
RavaASTNode_t *type = _rava_parser_parse_type(parser);
RavaASTNode_t *var_decl = rava_ast_node_create(RAVA_AST_VAR_DECL,
parser->current_token->line,
parser->current_token->column);
var_decl->data.var_decl.type = type;
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
var_decl->data.var_decl.name = strdup(parser->current_token->lexeme);
_rava_parser_advance(parser);
}
if (_rava_parser_match(parser, RAVA_TOKEN_ASSIGN)) {
var_decl->data.var_decl.initializer = _rava_parser_parse_expression(parser);
}
node->data.for_stmt.init = var_decl;
} else {
node->data.for_stmt.init = _rava_parser_parse_expression(parser);
}
} else {
node->data.for_stmt.init = NULL;
}
_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;
}
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_RETURN)) {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_RETURN_STMT,
parser->current_token->line,
parser->current_token->column);
if (!_rava_parser_check(parser, RAVA_TOKEN_SEMICOLON)) {
node->data.return_stmt.value = _rava_parser_parse_expression(parser);
} else {
node->data.return_stmt.value = NULL;
}
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after return statement");
return node;
}
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_BREAK)) {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_BREAK_STMT,
parser->current_token->line,
parser->current_token->column);
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after break");
return node;
}
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_CONTINUE)) {
RavaASTNode_t *node = rava_ast_node_create(RAVA_AST_CONTINUE_STMT,
parser->current_token->line,
parser->current_token->column);
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after continue");
return node;
}
bool is_type_decl = false;
if (_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_INT) ||
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_BOOLEAN) ||
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_CHAR) ||
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_BYTE) ||
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_SHORT) ||
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_LONG) ||
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_FLOAT) ||
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_DOUBLE)) {
is_type_decl = true;
} else if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
if (parser->peek_token && parser->peek_token->type == RAVA_TOKEN_IDENTIFIER) {
is_type_decl = true;
}
}
if (is_type_decl) {
RavaASTNode_t *type = _rava_parser_parse_type(parser);
RavaASTNode_t *var_decl = rava_ast_node_create(RAVA_AST_VAR_DECL,
parser->current_token->line,
parser->current_token->column);
var_decl->data.var_decl.type = type;
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
var_decl->data.var_decl.name = strdup(parser->current_token->lexeme);
_rava_parser_advance(parser);
}
if (_rava_parser_match(parser, RAVA_TOKEN_ASSIGN)) {
var_decl->data.var_decl.initializer = _rava_parser_parse_expression(parser);
} else {
var_decl->data.var_decl.initializer = NULL;
}
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after variable declaration");
return var_decl;
}
RavaASTNode_t *expr = _rava_parser_parse_expression(parser);
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after expression");
RavaASTNode_t *stmt = rava_ast_node_create(RAVA_AST_EXPR_STMT,
parser->current_token->line,
parser->current_token->column);
rava_ast_node_add_child(stmt, expr);
return stmt;
}