compiler
This commit is contained in:
parent
facacc90f8
commit
f710aa4199
140
src/compiler/Compiler.c
Normal file
140
src/compiler/Compiler.c
Normal 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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user