Initial commit of dem beast./plot.py

This commit is contained in:
2025-12-02 06:54:32 +01:00
commit c9cf356cbd
58 changed files with 9092 additions and 0 deletions
+236
View File
@@ -0,0 +1,236 @@
#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);
+251
View File
@@ -0,0 +1,251 @@
#ifndef RAVA_PARSER_H
#define RAVA_PARSER_H
#include "../lexer/lexer.h"
#include <stddef.h>
#include <stdbool.h>
typedef enum {
RAVA_AST_COMPILATION_UNIT,
RAVA_AST_PACKAGE_DECL,
RAVA_AST_IMPORT_DECL,
RAVA_AST_CLASS_DECL,
RAVA_AST_INTERFACE_DECL,
RAVA_AST_ENUM_DECL,
RAVA_AST_FIELD_DECL,
RAVA_AST_METHOD_DECL,
RAVA_AST_CONSTRUCTOR_DECL,
RAVA_AST_INITIALIZER_BLOCK,
RAVA_AST_PARAM_DECL,
RAVA_AST_VAR_DECL,
RAVA_AST_BLOCK_STMT,
RAVA_AST_IF_STMT,
RAVA_AST_WHILE_STMT,
RAVA_AST_DO_WHILE_STMT,
RAVA_AST_FOR_STMT,
RAVA_AST_ENHANCED_FOR_STMT,
RAVA_AST_SWITCH_STMT,
RAVA_AST_CASE_STMT,
RAVA_AST_TRY_STMT,
RAVA_AST_CATCH_CLAUSE,
RAVA_AST_THROW_STMT,
RAVA_AST_RETURN_STMT,
RAVA_AST_BREAK_STMT,
RAVA_AST_CONTINUE_STMT,
RAVA_AST_EXPR_STMT,
RAVA_AST_EMPTY_STMT,
RAVA_AST_SYNCHRONIZED_STMT,
RAVA_AST_ASSERT_STMT,
RAVA_AST_LITERAL_EXPR,
RAVA_AST_IDENTIFIER_EXPR,
RAVA_AST_BINARY_EXPR,
RAVA_AST_UNARY_EXPR,
RAVA_AST_TERNARY_EXPR,
RAVA_AST_ASSIGN_EXPR,
RAVA_AST_CALL_EXPR,
RAVA_AST_MEMBER_ACCESS_EXPR,
RAVA_AST_ARRAY_ACCESS_EXPR,
RAVA_AST_NEW_EXPR,
RAVA_AST_CAST_EXPR,
RAVA_AST_INSTANCEOF_EXPR,
RAVA_AST_THIS_EXPR,
RAVA_AST_SUPER_EXPR,
RAVA_AST_CLASS_LITERAL_EXPR,
RAVA_AST_ARRAY_INIT_EXPR,
RAVA_AST_TYPE,
RAVA_AST_TYPE_PARAM,
RAVA_AST_MODIFIER
} RavaASTNodeType_e;
typedef enum {
RAVA_MODIFIER_PUBLIC,
RAVA_MODIFIER_PRIVATE,
RAVA_MODIFIER_PROTECTED,
RAVA_MODIFIER_STATIC,
RAVA_MODIFIER_FINAL,
RAVA_MODIFIER_ABSTRACT,
RAVA_MODIFIER_NATIVE,
RAVA_MODIFIER_SYNCHRONIZED,
RAVA_MODIFIER_TRANSIENT,
RAVA_MODIFIER_VOLATILE,
RAVA_MODIFIER_STRICTFP
} RavaModifier_e;
typedef enum {
RAVA_BINOP_ADD,
RAVA_BINOP_SUB,
RAVA_BINOP_MUL,
RAVA_BINOP_DIV,
RAVA_BINOP_MOD,
RAVA_BINOP_EQ,
RAVA_BINOP_NE,
RAVA_BINOP_LT,
RAVA_BINOP_LE,
RAVA_BINOP_GT,
RAVA_BINOP_GE,
RAVA_BINOP_AND,
RAVA_BINOP_OR,
RAVA_BINOP_BITAND,
RAVA_BINOP_BITOR,
RAVA_BINOP_BITXOR,
RAVA_BINOP_LSHIFT,
RAVA_BINOP_RSHIFT,
RAVA_BINOP_URSHIFT
} RavaBinaryOp_e;
typedef enum {
RAVA_UNOP_PLUS,
RAVA_UNOP_MINUS,
RAVA_UNOP_NOT,
RAVA_UNOP_BITNOT,
RAVA_UNOP_PREINC,
RAVA_UNOP_PREDEC,
RAVA_UNOP_POSTINC,
RAVA_UNOP_POSTDEC
} RavaUnaryOp_e;
typedef struct RavaASTNode_t RavaASTNode_t;
struct RavaASTNode_t {
RavaASTNodeType_e type;
int line;
int column;
RavaASTNode_t *parent;
RavaASTNode_t **children;
size_t children_count;
size_t children_capacity;
union {
struct {
char *name;
} identifier;
struct {
RavaTokenType_e literal_type;
RavaLiteralValue_u value;
} literal;
struct {
RavaBinaryOp_e op;
RavaASTNode_t *left;
RavaASTNode_t *right;
} binary;
struct {
RavaUnaryOp_e op;
RavaASTNode_t *operand;
} unary;
struct {
RavaASTNode_t *condition;
RavaASTNode_t *true_expr;
RavaASTNode_t *false_expr;
} ternary;
struct {
RavaASTNode_t *target;
RavaASTNode_t *value;
} assign;
struct {
char *name;
char *superclass;
RavaASTNode_t *type;
RavaModifier_e *modifiers;
size_t modifiers_count;
} class_decl;
struct {
char *name;
RavaASTNode_t *return_type;
RavaModifier_e *modifiers;
size_t modifiers_count;
} method_decl;
struct {
char *name;
RavaASTNode_t *type;
RavaASTNode_t *initializer;
} var_decl;
struct {
RavaASTNode_t *condition;
RavaASTNode_t *then_stmt;
RavaASTNode_t *else_stmt;
} if_stmt;
struct {
RavaASTNode_t *condition;
RavaASTNode_t *body;
} while_stmt;
struct {
RavaASTNode_t *init;
RavaASTNode_t *condition;
RavaASTNode_t *update;
RavaASTNode_t *body;
} for_stmt;
struct {
RavaASTNode_t *value;
} return_stmt;
struct {
char *type_name;
bool is_array;
int array_dimensions;
} type;
struct {
RavaASTNode_t *callee;
RavaASTNode_t **arguments;
size_t arguments_count;
} call;
struct {
RavaASTNode_t *object;
char *member;
} member_access;
struct {
RavaASTNode_t *array;
RavaASTNode_t *index;
} array_access;
struct {
RavaASTNode_t *type;
RavaASTNode_t **arguments;
size_t arguments_count;
} new_expr;
struct {
RavaASTNode_t *type;
RavaASTNode_t *expression;
} cast;
} data;
};
typedef struct {
RavaLexer_t *lexer;
RavaToken_t *current_token;
RavaToken_t *peek_token;
char *error_message;
bool had_error;
} RavaParser_t;
RavaParser_t* rava_parser_create(RavaLexer_t *lexer);
void rava_parser_destroy(RavaParser_t *parser);
RavaASTNode_t* rava_parser_parse(RavaParser_t *parser);
RavaASTNode_t* rava_ast_node_create(RavaASTNodeType_e type, int line, int column);
void rava_ast_node_destroy(RavaASTNode_t *node);
void rava_ast_node_add_child(RavaASTNode_t *parent, RavaASTNode_t *child);
#endif
+196
View File
@@ -0,0 +1,196 @@
#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);
extern RavaASTNode_t* _rava_parser_parse_expression(RavaParser_t *parser);
extern RavaASTNode_t* _rava_parser_parse_block(RavaParser_t *parser);
extern void _rava_parser_parse_modifiers(RavaParser_t *parser, RavaModifier_e **modifiers, size_t *count);
static RavaASTNode_t* _rava_parser_parse_method_declaration(RavaParser_t *parser,
RavaModifier_e *modifiers,
size_t modifiers_count,
RavaASTNode_t *return_type) {
RavaASTNode_t *method = rava_ast_node_create(RAVA_AST_METHOD_DECL,
parser->current_token->line,
parser->current_token->column);
method->data.method_decl.modifiers = modifiers;
method->data.method_decl.modifiers_count = modifiers_count;
method->data.method_decl.return_type = return_type;
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
method->data.method_decl.name = strdup(parser->current_token->lexeme);
_rava_parser_advance(parser);
}
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after method name");
while (!_rava_parser_check(parser, RAVA_TOKEN_RPAREN) &&
!_rava_parser_check(parser, RAVA_TOKEN_EOF)) {
RavaASTNode_t *param_type = _rava_parser_parse_type(parser);
RavaASTNode_t *param = rava_ast_node_create(RAVA_AST_PARAM_DECL,
parser->current_token->line,
parser->current_token->column);
param->data.var_decl.type = param_type;
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
param->data.var_decl.name = strdup(parser->current_token->lexeme);
_rava_parser_advance(parser);
}
rava_ast_node_add_child(method, param);
if (!_rava_parser_match(parser, RAVA_TOKEN_COMMA)) {
break;
}
}
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after parameters");
if (_rava_parser_check(parser, RAVA_TOKEN_LBRACE)) {
RavaASTNode_t *body = _rava_parser_parse_block(parser);
rava_ast_node_add_child(method, body);
} else {
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' or '{' after method declaration");
}
return method;
}
RavaASTNode_t* _rava_parser_parse_class_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_CLASS, "Expected 'class' keyword");
RavaASTNode_t *class_decl = rava_ast_node_create(RAVA_AST_CLASS_DECL,
parser->current_token->line,
parser->current_token->column);
class_decl->data.class_decl.modifiers = modifiers;
class_decl->data.class_decl.modifiers_count = modifiers_count;
class_decl->data.class_decl.superclass = NULL;
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
class_decl->data.class_decl.name = strdup(parser->current_token->lexeme);
_rava_parser_advance(parser);
}
if (_rava_parser_match(parser, RAVA_TOKEN_KEYWORD_EXTENDS)) {
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
class_decl->data.class_decl.superclass = strdup(parser->current_token->lexeme);
_rava_parser_advance(parser);
}
}
_rava_parser_expect(parser, RAVA_TOKEN_LBRACE, "Expected '{' after class 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);
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER) &&
strcmp(parser->current_token->lexeme, class_decl->data.class_decl.name) == 0) {
RavaASTNode_t *constructor = rava_ast_node_create(RAVA_AST_CONSTRUCTOR_DECL,
parser->current_token->line,
parser->current_token->column);
_rava_parser_advance(parser);
_rava_parser_expect(parser, RAVA_TOKEN_LPAREN, "Expected '(' after constructor name");
while (!_rava_parser_check(parser, RAVA_TOKEN_RPAREN) &&
!_rava_parser_check(parser, RAVA_TOKEN_EOF)) {
RavaASTNode_t *param_type = _rava_parser_parse_type(parser);
RavaASTNode_t *param = rava_ast_node_create(RAVA_AST_PARAM_DECL,
parser->current_token->line,
parser->current_token->column);
param->data.var_decl.type = param_type;
if (_rava_parser_check(parser, RAVA_TOKEN_IDENTIFIER)) {
param->data.var_decl.name = strdup(parser->current_token->lexeme);
_rava_parser_advance(parser);
}
rava_ast_node_add_child(constructor, param);
if (!_rava_parser_match(parser, RAVA_TOKEN_COMMA)) {
break;
}
}
_rava_parser_expect(parser, RAVA_TOKEN_RPAREN, "Expected ')' after constructor parameters");
if (_rava_parser_check(parser, RAVA_TOKEN_LBRACE)) {
RavaASTNode_t *body = _rava_parser_parse_block(parser);
rava_ast_node_add_child(constructor, body);
}
rava_ast_node_add_child(class_decl, constructor);
free(member_modifiers);
continue;
}
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(class_decl, method);
} else {
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;
if (_rava_parser_match(parser, RAVA_TOKEN_ASSIGN)) {
field->data.var_decl.initializer = _rava_parser_parse_expression(parser);
} else {
field->data.var_decl.initializer = NULL;
}
_rava_parser_expect(parser, RAVA_TOKEN_SEMICOLON, "Expected ';' after field declaration");
rava_ast_node_add_child(class_decl, field);
}
}
}
_rava_parser_expect(parser, RAVA_TOKEN_RBRACE, "Expected '}' after class body");
return class_decl;
}
RavaASTNode_t* rava_parser_parse(RavaParser_t *parser) {
RavaASTNode_t *root = rava_ast_node_create(RAVA_AST_COMPILATION_UNIT, 1, 1);
while (!_rava_parser_check(parser, RAVA_TOKEN_EOF)) {
if (parser->had_error) {
break;
}
RavaASTNode_t *decl = _rava_parser_parse_class_declaration(parser);
if (decl) {
rava_ast_node_add_child(root, decl);
}
}
return root;
}
+433
View File
@@ -0,0 +1,433 @@
#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);
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)) {
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;
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_relational(RavaParser_t *parser) {
RavaASTNode_t *left = _rava_parser_parse_additive(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)) {
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_logical_and(RavaParser_t *parser) {
RavaASTNode_t *left = _rava_parser_parse_equality(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);
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_assignment(RavaParser_t *parser) {
RavaASTNode_t *left = _rava_parser_parse_logical_or(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;
}
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_expression(RavaParser_t *parser) {
return _rava_parser_parse_assignment(parser);
}
+216
View File
@@ -0,0 +1,216 @@
#include "parser.h"
#include <stdio.h>
#include <string.h>
static void _rava_print_indent(int depth) {
for (int i = 0; i < depth; i++) {
printf(" ");
}
}
static const char* _rava_ast_node_type_name(RavaASTNodeType_e type) {
switch (type) {
case RAVA_AST_COMPILATION_UNIT: return "CompilationUnit";
case RAVA_AST_CLASS_DECL: return "ClassDecl";
case RAVA_AST_METHOD_DECL: return "MethodDecl";
case RAVA_AST_FIELD_DECL: return "FieldDecl";
case RAVA_AST_CONSTRUCTOR_DECL: return "ConstructorDecl";
case RAVA_AST_VAR_DECL: return "VarDecl";
case RAVA_AST_PARAM_DECL: return "ParamDecl";
case RAVA_AST_BLOCK_STMT: return "BlockStmt";
case RAVA_AST_IF_STMT: return "IfStmt";
case RAVA_AST_WHILE_STMT: return "WhileStmt";
case RAVA_AST_FOR_STMT: return "ForStmt";
case RAVA_AST_RETURN_STMT: return "ReturnStmt";
case RAVA_AST_BREAK_STMT: return "BreakStmt";
case RAVA_AST_CONTINUE_STMT: return "ContinueStmt";
case RAVA_AST_EXPR_STMT: return "ExprStmt";
case RAVA_AST_LITERAL_EXPR: return "LiteralExpr";
case RAVA_AST_IDENTIFIER_EXPR: return "IdentifierExpr";
case RAVA_AST_BINARY_EXPR: return "BinaryExpr";
case RAVA_AST_UNARY_EXPR: return "UnaryExpr";
case RAVA_AST_ASSIGN_EXPR: return "AssignExpr";
case RAVA_AST_CALL_EXPR: return "CallExpr";
case RAVA_AST_MEMBER_ACCESS_EXPR: return "MemberAccessExpr";
case RAVA_AST_ARRAY_ACCESS_EXPR: return "ArrayAccessExpr";
case RAVA_AST_NEW_EXPR: return "NewExpr";
case RAVA_AST_TYPE: return "Type";
default: return "Unknown";
}
}
void rava_ast_print(RavaASTNode_t *node, int depth) {
if (!node) {
_rava_print_indent(depth);
printf("<null>\n");
return;
}
_rava_print_indent(depth);
printf("%s", _rava_ast_node_type_name(node->type));
switch (node->type) {
case RAVA_AST_CLASS_DECL:
printf(": %s\n", node->data.class_decl.name);
break;
case RAVA_AST_METHOD_DECL:
printf(": %s\n", node->data.method_decl.name);
break;
case RAVA_AST_FIELD_DECL:
case RAVA_AST_VAR_DECL:
case RAVA_AST_PARAM_DECL:
printf(": %s\n", node->data.var_decl.name ? node->data.var_decl.name : "<unnamed>");
break;
case RAVA_AST_IDENTIFIER_EXPR:
printf(": %s\n", node->data.identifier.name);
break;
case RAVA_AST_LITERAL_EXPR:
printf(": ");
if (node->data.literal.literal_type == RAVA_TOKEN_LITERAL_INTEGER ||
node->data.literal.literal_type == RAVA_TOKEN_LITERAL_LONG) {
printf("%lld\n", (long long)node->data.literal.value.int_value);
} else if (node->data.literal.literal_type == RAVA_TOKEN_LITERAL_FLOAT ||
node->data.literal.literal_type == RAVA_TOKEN_LITERAL_DOUBLE) {
printf("%f\n", node->data.literal.value.float_value);
} else if (node->data.literal.literal_type == RAVA_TOKEN_LITERAL_STRING) {
printf("\"%s\"\n", node->data.literal.value.string_value);
} else if (node->data.literal.literal_type == RAVA_TOKEN_LITERAL_TRUE) {
printf("true\n");
} else if (node->data.literal.literal_type == RAVA_TOKEN_LITERAL_FALSE) {
printf("false\n");
} else if (node->data.literal.literal_type == RAVA_TOKEN_LITERAL_NULL) {
printf("null\n");
} else {
printf("?\n");
}
break;
case RAVA_AST_TYPE:
printf(": %s%s\n", node->data.type.type_name,
node->data.type.is_array ? "[]" : "");
break;
case RAVA_AST_MEMBER_ACCESS_EXPR:
printf(": .%s\n", node->data.member_access.member);
break;
default:
printf("\n");
break;
}
if (node->type == RAVA_AST_BINARY_EXPR) {
_rava_print_indent(depth + 1);
printf("Left:\n");
rava_ast_print(node->data.binary.left, depth + 2);
_rava_print_indent(depth + 1);
printf("Right:\n");
rava_ast_print(node->data.binary.right, depth + 2);
} else if (node->type == RAVA_AST_UNARY_EXPR) {
_rava_print_indent(depth + 1);
printf("Operand:\n");
rava_ast_print(node->data.unary.operand, depth + 2);
} else if (node->type == RAVA_AST_ASSIGN_EXPR) {
_rava_print_indent(depth + 1);
printf("Target:\n");
rava_ast_print(node->data.assign.target, depth + 2);
_rava_print_indent(depth + 1);
printf("Value:\n");
rava_ast_print(node->data.assign.value, depth + 2);
} else if (node->type == RAVA_AST_IF_STMT) {
_rava_print_indent(depth + 1);
printf("Condition:\n");
rava_ast_print(node->data.if_stmt.condition, depth + 2);
_rava_print_indent(depth + 1);
printf("Then:\n");
rava_ast_print(node->data.if_stmt.then_stmt, depth + 2);
if (node->data.if_stmt.else_stmt) {
_rava_print_indent(depth + 1);
printf("Else:\n");
rava_ast_print(node->data.if_stmt.else_stmt, depth + 2);
}
} else if (node->type == RAVA_AST_WHILE_STMT) {
_rava_print_indent(depth + 1);
printf("Condition:\n");
rava_ast_print(node->data.while_stmt.condition, depth + 2);
_rava_print_indent(depth + 1);
printf("Body:\n");
rava_ast_print(node->data.while_stmt.body, depth + 2);
} else if (node->type == RAVA_AST_FOR_STMT) {
if (node->data.for_stmt.init) {
_rava_print_indent(depth + 1);
printf("Init:\n");
rava_ast_print(node->data.for_stmt.init, depth + 2);
}
if (node->data.for_stmt.condition) {
_rava_print_indent(depth + 1);
printf("Condition:\n");
rava_ast_print(node->data.for_stmt.condition, depth + 2);
}
if (node->data.for_stmt.update) {
_rava_print_indent(depth + 1);
printf("Update:\n");
rava_ast_print(node->data.for_stmt.update, depth + 2);
}
_rava_print_indent(depth + 1);
printf("Body:\n");
rava_ast_print(node->data.for_stmt.body, depth + 2);
} else if (node->type == RAVA_AST_RETURN_STMT) {
if (node->data.return_stmt.value) {
_rava_print_indent(depth + 1);
printf("Value:\n");
rava_ast_print(node->data.return_stmt.value, depth + 2);
}
} else if (node->type == RAVA_AST_VAR_DECL || node->type == RAVA_AST_FIELD_DECL || node->type == RAVA_AST_PARAM_DECL) {
if (node->data.var_decl.type) {
_rava_print_indent(depth + 1);
printf("Type:\n");
rava_ast_print(node->data.var_decl.type, depth + 2);
}
if (node->data.var_decl.initializer) {
_rava_print_indent(depth + 1);
printf("Initializer:\n");
rava_ast_print(node->data.var_decl.initializer, depth + 2);
}
} else if (node->type == RAVA_AST_METHOD_DECL) {
if (node->data.method_decl.return_type) {
_rava_print_indent(depth + 1);
printf("Return Type:\n");
rava_ast_print(node->data.method_decl.return_type, depth + 2);
}
} else if (node->type == RAVA_AST_CALL_EXPR) {
_rava_print_indent(depth + 1);
printf("Callee:\n");
rava_ast_print(node->data.call.callee, depth + 2);
if (node->data.call.arguments_count > 0) {
_rava_print_indent(depth + 1);
printf("Arguments:\n");
for (size_t i = 0; i < node->data.call.arguments_count; i++) {
rava_ast_print(node->data.call.arguments[i], depth + 2);
}
}
} else if (node->type == RAVA_AST_MEMBER_ACCESS_EXPR) {
_rava_print_indent(depth + 1);
printf("Object:\n");
rava_ast_print(node->data.member_access.object, depth + 2);
} else if (node->type == RAVA_AST_ARRAY_ACCESS_EXPR) {
_rava_print_indent(depth + 1);
printf("Array:\n");
rava_ast_print(node->data.array_access.array, depth + 2);
_rava_print_indent(depth + 1);
printf("Index:\n");
rava_ast_print(node->data.array_access.index, depth + 2);
} else if (node->type == RAVA_AST_NEW_EXPR) {
_rava_print_indent(depth + 1);
printf("Type:\n");
rava_ast_print(node->data.new_expr.type, depth + 2);
if (node->data.new_expr.arguments_count > 0) {
_rava_print_indent(depth + 1);
printf("Arguments:\n");
for (size_t i = 0; i < node->data.new_expr.arguments_count; i++) {
rava_ast_print(node->data.new_expr.arguments[i], depth + 2);
}
}
}
for (size_t i = 0; i < node->children_count; i++) {
rava_ast_print(node->children[i], depth + 1);
}
}
+216
View File
@@ -0,0 +1,216 @@
#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;
}