This commit is contained in:
Timerix 2025-01-20 22:52:23 +05:00
parent facacc90f8
commit f710aa4199
3 changed files with 143 additions and 2 deletions

140
src/compiler/Compiler.c Normal file
View File

@ -0,0 +1,140 @@
#include "Compiler_internal.h"
void Compiler_init(Compiler* cmp){
memset(cmp, 0, sizeof(Compiler));
cmp->state = CompilerState_Initial;
cmp->tokens = List_Token_alloc(4096);
cmp->line_lengths = List_u32_alloc(1024);
}
void Compiler_free(Compiler* cmp){
free(cmp->code);
free(cmp->tokens.data);
free(cmp->line_lengths.data);
}
CodePos Compiler_getLineAndColumn(Compiler* cmp, u32 pos){
u32 prev_lines_len = 0;
if(pos >= cmp->code_len)
return CodePos_create(0, 0);
for(u32 i = 0; i < cmp->line_lengths.len; i++){
u32 line_len = cmp->line_lengths.data[i];
if(prev_lines_len + line_len > pos)
return CodePos_create(i + 1, pos + 1 - prev_lines_len);
prev_lines_len += line_len;
}
return CodePos_create(0, 0);
}
void _Compiler_setError(Compiler* cmp, cstr context, cstr format, ...){
// happens at the end of file
if(cmp->pos >= cmp->code_len)
cmp->pos = cmp->code_len - 1;
char position_str[32];
CodePos code_pos = Compiler_getLineAndColumn(cmp, cmp->pos);
sprintf(position_str, "[at %u:%u][", code_pos.line, code_pos.column);
char* real_format = strcat_malloc(position_str, context, "] ", format);
va_list argv;
va_start(argv, format);
char* NULLABLE(buf) = vsprintf_malloc(512, real_format, argv);
va_end(argv);
free(real_format);
if(buf == NULL){
buf = malloc(16);
strcpy(buf, "SPRINTF FAILED");
}
cmp->state = CompilerState_Error;
cmp->error_message = buf;
}
#define setError(FORMAT, ...) {\
Compiler_setError(cmp, FORMAT, ##__VA_ARGS__);\
}
static bool compileFile(Compiler* cmp, FILE* f){
returnErrorIf_auto(cmp->state != CompilerState_Parsing);
cmp->state = CompilerState_Compiling;
return true;
}
bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name, bool debug){
FILE* f = fopen(source_file_name, "rb");
if(f == NULL)
returnError("ERROR: can't open file '%s'", source_file_name);
List_u8 buf = List_u8_alloc(64 * 1024);
int ret;
while((ret = fgetc(f)) != EOF) {
List_u8_push(&buf, ret);
}
if(ferror(f)){
free(buf.data);
fclose(f);
returnError("can't read file '%s'", source_file_name);
}
fclose(f);
if(buf.len == 0){
free(buf.data);
fclose(f);
returnError("soucre file is empty");
}
cmp->code = (char*)buf.data;
cmp->code_len = buf.len;
List_u8_push(&buf, 0);
f = fopen(out_file_name, "wb");
if(f == NULL){
free(buf.data);
returnError("ERROR: can't open file '%s'", out_file_name);
}
if(debug){
printf("----------------------------------[%s]---------------------------------\n", source_file_name);
fputs(cmp->code, stdout);
fputc('\n', stdout);
}
bool success = Compiler_lex(cmp);
if(debug){
printf("------------------------------------[lines]-----------------------------------\n");
for(u32 i = 0; i < cmp->line_lengths.len; i++){
printf("[%u] length: %u\n", i+1, cmp->line_lengths.data[i]);
}
printf("------------------------------------[tokens]-----------------------------------\n");
for(u32 i = 0; i < cmp->tokens.len; i++){
Token t = cmp->tokens.data[i];
CodePos pos = Compiler_getLineAndColumn(cmp, t.begin);
char* tokstr = malloc(4096);
strncpy(tokstr, cmp->code + t.begin, t.length);
tokstr[t.length] = 0;
printf("[l:%3u, c:%3u] %s '%s'\n",
pos.line, pos.column,
TokenType_toString(t.type), tokstr);
free(tokstr);
}
}
if(!success){
fclose(f);
return false;
}
success = Compiler_parse(cmp);
if(!success){
fclose(f);
return false;
}
success = compileFile(cmp, f);
fclose(f);
if(success){
cmp->state = CompilerState_Success;
}
return success;
}

View File

@ -135,15 +135,16 @@ i32 compileSources(cstr source_file, cstr out_file){
Compiler cmp;
Compiler_init(&cmp);
bool success = Compiler_compile(&cmp, source_file, out_file, true);
Compiler_free(&cmp);
if(!success){
if(cmp.error_message){
printfe("COMPILER ERROR: %s\n", cmp.error_message);
free(cmp.error_message);
}
else printfe("COMPILER ERROR: unknown (error_message is null)\n");
Compiler_free(&cmp);
return 111;
}
Compiler_free(&cmp);
return 0;
}