237 lines
8.8 KiB
C
237 lines
8.8 KiB
C
|
|
#define _POSIX_C_SOURCE 200809L
|
||
|
|
#include "parser.h"
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
|
||
|
|
RavaASTNode_t* rava_ast_node_create(RavaASTNodeType_e type, int line, int column) {
|
||
|
|
RavaASTNode_t *node = calloc(1, sizeof(RavaASTNode_t));
|
||
|
|
node->type = type;
|
||
|
|
node->line = line;
|
||
|
|
node->column = column;
|
||
|
|
node->parent = NULL;
|
||
|
|
node->children = NULL;
|
||
|
|
node->children_count = 0;
|
||
|
|
node->children_capacity = 0;
|
||
|
|
return node;
|
||
|
|
}
|
||
|
|
|
||
|
|
void rava_ast_node_destroy(RavaASTNode_t *node) {
|
||
|
|
if (!node) return;
|
||
|
|
|
||
|
|
for (size_t i = 0; i < node->children_count; i++) {
|
||
|
|
rava_ast_node_destroy(node->children[i]);
|
||
|
|
}
|
||
|
|
free(node->children);
|
||
|
|
|
||
|
|
switch (node->type) {
|
||
|
|
case RAVA_AST_IDENTIFIER_EXPR:
|
||
|
|
free(node->data.identifier.name);
|
||
|
|
break;
|
||
|
|
case RAVA_AST_CLASS_DECL:
|
||
|
|
free(node->data.class_decl.name);
|
||
|
|
free(node->data.class_decl.modifiers);
|
||
|
|
rava_ast_node_destroy(node->data.class_decl.type);
|
||
|
|
break;
|
||
|
|
case RAVA_AST_METHOD_DECL:
|
||
|
|
free(node->data.method_decl.name);
|
||
|
|
free(node->data.method_decl.modifiers);
|
||
|
|
rava_ast_node_destroy(node->data.method_decl.return_type);
|
||
|
|
break;
|
||
|
|
case RAVA_AST_VAR_DECL:
|
||
|
|
free(node->data.var_decl.name);
|
||
|
|
rava_ast_node_destroy(node->data.var_decl.type);
|
||
|
|
rava_ast_node_destroy(node->data.var_decl.initializer);
|
||
|
|
break;
|
||
|
|
case RAVA_AST_TYPE:
|
||
|
|
free(node->data.type.type_name);
|
||
|
|
break;
|
||
|
|
case RAVA_AST_MEMBER_ACCESS_EXPR:
|
||
|
|
free(node->data.member_access.member);
|
||
|
|
rava_ast_node_destroy(node->data.member_access.object);
|
||
|
|
break;
|
||
|
|
case RAVA_AST_CALL_EXPR:
|
||
|
|
rava_ast_node_destroy(node->data.call.callee);
|
||
|
|
for (size_t i = 0; i < node->data.call.arguments_count; i++) {
|
||
|
|
rava_ast_node_destroy(node->data.call.arguments[i]);
|
||
|
|
}
|
||
|
|
free(node->data.call.arguments);
|
||
|
|
break;
|
||
|
|
case RAVA_AST_NEW_EXPR:
|
||
|
|
rava_ast_node_destroy(node->data.new_expr.type);
|
||
|
|
for (size_t i = 0; i < node->data.new_expr.arguments_count; i++) {
|
||
|
|
rava_ast_node_destroy(node->data.new_expr.arguments[i]);
|
||
|
|
}
|
||
|
|
free(node->data.new_expr.arguments);
|
||
|
|
break;
|
||
|
|
case RAVA_AST_LITERAL_EXPR:
|
||
|
|
if (node->data.literal.literal_type == RAVA_TOKEN_LITERAL_STRING) {
|
||
|
|
free(node->data.literal.value.string_value);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
free(node);
|
||
|
|
}
|
||
|
|
|
||
|
|
void rava_ast_node_add_child(RavaASTNode_t *parent, RavaASTNode_t *child) {
|
||
|
|
if (!parent || !child) return;
|
||
|
|
|
||
|
|
if (parent->children_count >= parent->children_capacity) {
|
||
|
|
size_t new_capacity = parent->children_capacity == 0 ? 4 : parent->children_capacity * 2;
|
||
|
|
parent->children = realloc(parent->children, sizeof(RavaASTNode_t*) * new_capacity);
|
||
|
|
parent->children_capacity = new_capacity;
|
||
|
|
}
|
||
|
|
|
||
|
|
parent->children[parent->children_count++] = child;
|
||
|
|
child->parent = parent;
|
||
|
|
}
|
||
|
|
|
||
|
|
RavaParser_t* rava_parser_create(RavaLexer_t *lexer) {
|
||
|
|
RavaParser_t *parser = malloc(sizeof(RavaParser_t));
|
||
|
|
parser->lexer = lexer;
|
||
|
|
parser->current_token = rava_lexer_next_token(lexer);
|
||
|
|
parser->peek_token = rava_lexer_next_token(lexer);
|
||
|
|
parser->error_message = NULL;
|
||
|
|
parser->had_error = false;
|
||
|
|
return parser;
|
||
|
|
}
|
||
|
|
|
||
|
|
void rava_parser_destroy(RavaParser_t *parser) {
|
||
|
|
if (!parser) return;
|
||
|
|
|
||
|
|
rava_token_destroy(parser->current_token);
|
||
|
|
rava_token_destroy(parser->peek_token);
|
||
|
|
free(parser->error_message);
|
||
|
|
free(parser);
|
||
|
|
}
|
||
|
|
|
||
|
|
void _rava_parser_advance(RavaParser_t *parser) {
|
||
|
|
rava_token_destroy(parser->current_token);
|
||
|
|
parser->current_token = parser->peek_token;
|
||
|
|
parser->peek_token = rava_lexer_next_token(parser->lexer);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool _rava_parser_check(RavaParser_t *parser, RavaTokenType_e type) {
|
||
|
|
return parser->current_token->type == type;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool _rava_parser_match(RavaParser_t *parser, RavaTokenType_e type) {
|
||
|
|
if (_rava_parser_check(parser, type)) {
|
||
|
|
_rava_parser_advance(parser);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool _rava_parser_expect(RavaParser_t *parser, RavaTokenType_e type, const char *message) {
|
||
|
|
if (_rava_parser_check(parser, type)) {
|
||
|
|
_rava_parser_advance(parser);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
parser->had_error = true;
|
||
|
|
if (parser->error_message) free(parser->error_message);
|
||
|
|
parser->error_message = malloc(256);
|
||
|
|
snprintf(parser->error_message, 256, "%s at line %d, column %d",
|
||
|
|
message, parser->current_token->line, parser->current_token->column);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
extern RavaASTNode_t* _rava_parser_parse_type(RavaParser_t *parser);
|
||
|
|
extern RavaASTNode_t* _rava_parser_parse_expression(RavaParser_t *parser);
|
||
|
|
extern RavaASTNode_t* _rava_parser_parse_statement(RavaParser_t *parser);
|
||
|
|
extern RavaASTNode_t* _rava_parser_parse_block(RavaParser_t *parser);
|
||
|
|
|
||
|
|
static RavaModifier_e _rava_token_to_modifier(RavaTokenType_e type) {
|
||
|
|
switch (type) {
|
||
|
|
case RAVA_TOKEN_KEYWORD_PUBLIC: return RAVA_MODIFIER_PUBLIC;
|
||
|
|
case RAVA_TOKEN_KEYWORD_PRIVATE: return RAVA_MODIFIER_PRIVATE;
|
||
|
|
case RAVA_TOKEN_KEYWORD_PROTECTED: return RAVA_MODIFIER_PROTECTED;
|
||
|
|
case RAVA_TOKEN_KEYWORD_STATIC: return RAVA_MODIFIER_STATIC;
|
||
|
|
case RAVA_TOKEN_KEYWORD_FINAL: return RAVA_MODIFIER_FINAL;
|
||
|
|
case RAVA_TOKEN_KEYWORD_ABSTRACT: return RAVA_MODIFIER_ABSTRACT;
|
||
|
|
case RAVA_TOKEN_KEYWORD_NATIVE: return RAVA_MODIFIER_NATIVE;
|
||
|
|
case RAVA_TOKEN_KEYWORD_SYNCHRONIZED: return RAVA_MODIFIER_SYNCHRONIZED;
|
||
|
|
case RAVA_TOKEN_KEYWORD_TRANSIENT: return RAVA_MODIFIER_TRANSIENT;
|
||
|
|
case RAVA_TOKEN_KEYWORD_VOLATILE: return RAVA_MODIFIER_VOLATILE;
|
||
|
|
case RAVA_TOKEN_KEYWORD_STRICTFP: return RAVA_MODIFIER_STRICTFP;
|
||
|
|
default: return RAVA_MODIFIER_PUBLIC;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static bool _rava_is_modifier(RavaTokenType_e type) {
|
||
|
|
return type == RAVA_TOKEN_KEYWORD_PUBLIC ||
|
||
|
|
type == RAVA_TOKEN_KEYWORD_PRIVATE ||
|
||
|
|
type == RAVA_TOKEN_KEYWORD_PROTECTED ||
|
||
|
|
type == RAVA_TOKEN_KEYWORD_STATIC ||
|
||
|
|
type == RAVA_TOKEN_KEYWORD_FINAL ||
|
||
|
|
type == RAVA_TOKEN_KEYWORD_ABSTRACT ||
|
||
|
|
type == RAVA_TOKEN_KEYWORD_NATIVE ||
|
||
|
|
type == RAVA_TOKEN_KEYWORD_SYNCHRONIZED ||
|
||
|
|
type == RAVA_TOKEN_KEYWORD_TRANSIENT ||
|
||
|
|
type == RAVA_TOKEN_KEYWORD_VOLATILE ||
|
||
|
|
type == RAVA_TOKEN_KEYWORD_STRICTFP;
|
||
|
|
}
|
||
|
|
|
||
|
|
void _rava_parser_parse_modifiers(RavaParser_t *parser, RavaModifier_e **modifiers, size_t *count) {
|
||
|
|
size_t capacity = 4;
|
||
|
|
*modifiers = malloc(sizeof(RavaModifier_e) * capacity);
|
||
|
|
*count = 0;
|
||
|
|
|
||
|
|
while (_rava_is_modifier(parser->current_token->type)) {
|
||
|
|
if (*count >= capacity) {
|
||
|
|
capacity *= 2;
|
||
|
|
*modifiers = realloc(*modifiers, sizeof(RavaModifier_e) * capacity);
|
||
|
|
}
|
||
|
|
(*modifiers)[(*count)++] = _rava_token_to_modifier(parser->current_token->type);
|
||
|
|
_rava_parser_advance(parser);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
RavaASTNode_t* _rava_parser_parse_type(RavaParser_t *parser) {
|
||
|
|
RavaASTNode_t *type_node = rava_ast_node_create(RAVA_AST_TYPE,
|
||
|
|
parser->current_token->line,
|
||
|
|
parser->current_token->column);
|
||
|
|
|
||
|
|
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER) ||
|
||
|
|
_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) ||
|
||
|
|
_rava_parser_check(parser, RAVA_TOKEN_KEYWORD_VOID)) {
|
||
|
|
|
||
|
|
type_node->data.type.type_name = strdup(parser->current_token->lexeme);
|
||
|
|
type_node->data.type.is_array = false;
|
||
|
|
type_node->data.type.array_dimensions = 0;
|
||
|
|
_rava_parser_advance(parser);
|
||
|
|
|
||
|
|
while (_rava_parser_check(parser, RAVA_TOKEN_LBRACKET)) {
|
||
|
|
if (parser->peek_token && parser->peek_token->type == RAVA_TOKEN_RBRACKET) {
|
||
|
|
_rava_parser_advance(parser);
|
||
|
|
_rava_parser_advance(parser);
|
||
|
|
type_node->data.type.is_array = true;
|
||
|
|
type_node->data.type.array_dimensions++;
|
||
|
|
} else {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
parser->had_error = true;
|
||
|
|
if (parser->error_message) free(parser->error_message);
|
||
|
|
parser->error_message = strdup("Expected type name");
|
||
|
|
rava_ast_node_destroy(type_node);
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
return type_node;
|
||
|
|
}
|
||
|
|
|
||
|
|
RavaASTNode_t* rava_parser_parse(RavaParser_t *parser);
|