9char* read_file(
const char* filename) {
14 FILE* file = fopen(filename,
"r");
16 fprintf(stderr,
"Error: Could not open file '%s'\n", filename);
21 fseek(file, 0, SEEK_END);
22 long size = ftell(file);
23 fseek(file, 0, SEEK_SET);
26 fprintf(stderr,
"Error: Could not determine size of file '%s'\n", filename);
32 char* content = malloc(size + 1);
34 fprintf(stderr,
"Error: Memory allocation failed for file '%s'\n", filename);
40 size_t bytes_read = fread(content, 1, size, file);
41 content[bytes_read] =
'\0';
45 if (bytes_read != (
size_t)size) {
46 fprintf(stderr,
"Warning: Expected to read %ld bytes from '%s', but read %zu\n",
47 size, filename, bytes_read);
54void* safe_malloc(
size_t size) {
55 void* ptr = malloc(size);
57 fprintf(stderr,
"Memory allocation failed: %zu bytes\n", size);
64bool safe_strcpy(
char* dest,
size_t dest_size,
const char* src) {
65 if (!dest || !src || dest_size == 0) {
69 size_t src_len = strlen(src);
70 if (src_len >= dest_size) {
79char* safe_strdup(
const char* src) {
84 size_t len = strlen(src) + 1;
85 char* copy = safe_malloc(len);
107const char* data_type_to_string(
DataType type) {
124const char* ast_node_type_to_string(
ASTNodeType type) {
126 case AST_FUNCTION_DECLARATION:
127 return "function_declaration";
128 case AST_VARIABLE_DECLARATION:
129 return "variable_declaration";
132 case AST_COMPOUND_STATEMENT:
133 return "compound_statement";
134 case AST_EXPRESSION_STATEMENT:
135 return "expression_statement";
136 case AST_IF_STATEMENT:
137 return "if_statement";
138 case AST_WHILE_STATEMENT:
139 return "while_statement";
140 case AST_FOR_STATEMENT:
141 return "for_statement";
142 case AST_RETURN_STATEMENT:
143 return "return_statement";
144 case AST_BREAK_STATEMENT:
145 return "break_statement";
146 case AST_CONTINUE_STATEMENT:
147 return "continue_statement";
154 case AST_FUNCTION_CALL:
155 return "function_call";
158 case AST_NUMBER_LITERAL:
159 return "number_literal";
160 case AST_STRING_LITERAL:
161 return "string_literal";
162 case AST_CHAR_LITERAL:
163 return "char_literal";
174void ast_print(
ASTNode *node,
int indent) {
180 for (
int i = 0; i < indent; i++) {
184 printf(
"%s", ast_node_type_to_string(node->type));
187 switch (node->type) {
189 if (node->data.identifier.name) {
190 printf(
" (%s)", node->data.identifier.name);
193 case AST_NUMBER_LITERAL:
194 printf(
" (%d)", node->data.number.value);
196 case AST_STRING_LITERAL:
197 if (node->data.string.value) {
198 printf(
" (\"%s\")", node->data.string.value);
201 case AST_FUNCTION_DECLARATION:
202 if (node->data.function_decl.name) {
203 printf(
" (%s)", node->data.function_decl.name);
206 case AST_VARIABLE_DECLARATION:
207 if (node->data.var_decl.name) {
208 printf(
" (%s)", node->data.var_decl.name);
212 printf(
" (%s)", token_type_to_string(node->data.binary_expr.operator));
215 printf(
" (%s)", token_type_to_string(node->data.unary_expr.operator));
224 switch (node->type) {
226 for (
int i = 0; i < node->data.program.declaration_count; i++) {
227 ast_print(node->data.program.declarations[i], indent + 1);
230 case AST_FUNCTION_DECLARATION:
231 for (
int i = 0; i < node->data.function_decl.parameter_count; i++) {
232 ast_print(node->data.function_decl.parameters[i], indent + 1);
234 if (node->data.function_decl.body) {
235 ast_print(node->data.function_decl.body, indent + 1);
238 case AST_COMPOUND_STATEMENT:
239 for (
int i = 0; i < node->data.compound_stmt.statement_count; i++) {
240 ast_print(node->data.compound_stmt.statements[i], indent + 1);
243 case AST_IF_STATEMENT:
244 if (node->data.if_stmt.condition) {
245 ast_print(node->data.if_stmt.condition, indent + 1);
247 if (node->data.if_stmt.then_stmt) {
248 ast_print(node->data.if_stmt.then_stmt, indent + 1);
250 if (node->data.if_stmt.else_stmt) {
251 ast_print(node->data.if_stmt.else_stmt, indent + 1);
254 case AST_WHILE_STATEMENT:
255 if (node->data.while_stmt.condition) {
256 ast_print(node->data.while_stmt.condition, indent + 1);
258 if (node->data.while_stmt.body) {
259 ast_print(node->data.while_stmt.body, indent + 1);
262 case AST_FOR_STATEMENT:
263 if (node->data.for_stmt.init) {
264 ast_print(node->data.for_stmt.init, indent + 1);
266 if (node->data.for_stmt.condition) {
267 ast_print(node->data.for_stmt.condition, indent + 1);
269 if (node->data.for_stmt.update) {
270 ast_print(node->data.for_stmt.update, indent + 1);
272 if (node->data.for_stmt.body) {
273 ast_print(node->data.for_stmt.body, indent + 1);
277 if (node->data.binary_expr.left) {
278 ast_print(node->data.binary_expr.left, indent + 1);
280 if (node->data.binary_expr.right) {
281 ast_print(node->data.binary_expr.right, indent + 1);
285 if (node->data.unary_expr.operand) {
286 ast_print(node->data.unary_expr.operand, indent + 1);
290 if (node->data.assignment.value) {
291 ast_print(node->data.assignment.value, indent + 1);
294 case AST_FUNCTION_CALL:
295 for (
int i = 0; i < node->data.call_expr.argument_count; i++) {
296 ast_print(node->data.call_expr.arguments[i], indent + 1);
299 case AST_VARIABLE_DECLARATION:
300 if (node->data.var_decl.initializer) {
301 ast_print(node->data.var_decl.initializer, indent + 1);
304 case AST_EXPRESSION_STATEMENT:
305 if (node->data.expression_stmt.expression) {
306 ast_print(node->data.expression_stmt.expression, indent + 1);
309 case AST_RETURN_STATEMENT:
310 if (node->data.return_stmt.expression) {
311 ast_print(node->data.return_stmt.expression, indent + 1);
ASTNodeType
AST Node types.
TokenType
Token types for lexical analysis.
DataType
Data types supported by the compiler.