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 cmp;
|
||||||
Compiler_init(&cmp);
|
Compiler_init(&cmp);
|
||||||
bool success = Compiler_compile(&cmp, source_file, out_file, true);
|
bool success = Compiler_compile(&cmp, source_file, out_file, true);
|
||||||
Compiler_free(&cmp);
|
|
||||||
if(!success){
|
if(!success){
|
||||||
if(cmp.error_message){
|
if(cmp.error_message){
|
||||||
printfe("COMPILER ERROR: %s\n", cmp.error_message);
|
printfe("COMPILER ERROR: %s\n", cmp.error_message);
|
||||||
free(cmp.error_message);
|
free(cmp.error_message);
|
||||||
}
|
}
|
||||||
else printfe("COMPILER ERROR: unknown (error_message is null)\n");
|
else printfe("COMPILER ERROR: unknown (error_message is null)\n");
|
||||||
|
Compiler_free(&cmp);
|
||||||
return 111;
|
return 111;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Compiler_free(&cmp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user