Compare commits
No commits in common. "823223ffa7f820ad24b5972a5067a91bcfc91749" and "2831474f79086772120927f1b54528555c4af380" have entirely different histories.
823223ffa7
...
2831474f79
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
#include "../std.h"
|
||||
#include "../string/str.h"
|
||||
|
||||
typedef union Register {
|
||||
u32 u32v;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#include "List.h"
|
||||
|
||||
List_define(cstr);
|
||||
List_define(u32);
|
||||
List_define(u8);
|
||||
|
||||
@ -54,5 +54,6 @@
|
||||
}\
|
||||
|
||||
|
||||
List_declare(cstr);
|
||||
List_declare(u32);
|
||||
List_declare(u8);
|
||||
|
||||
@ -5,30 +5,30 @@ List_define(Operation);
|
||||
List_define(DataDefinition);
|
||||
List_define(Section);
|
||||
|
||||
static str _ArgumentType_str[] = {
|
||||
STR("Unset"),
|
||||
STR("Register"),
|
||||
STR("ConstValue"),
|
||||
STR("DataName"),
|
||||
STR("NamedDataPointer"),
|
||||
STR("NamedDataSize"),
|
||||
static cstr _ArgumentType_str[] = {
|
||||
"Unset",
|
||||
"Register",
|
||||
"ConstValue",
|
||||
"DataName",
|
||||
"NamedDataPointer",
|
||||
"NamedDataSize",
|
||||
};
|
||||
|
||||
str ArgumentType_toString(ArgumentType t){
|
||||
cstr ArgumentType_toString(ArgumentType t){
|
||||
if(t >= ARRAY_SIZE(_ArgumentType_str))
|
||||
return STR("!!INDEX_ERROR!!");
|
||||
return "!!INDEX_ERROR!!";
|
||||
return _ArgumentType_str[t];
|
||||
}
|
||||
|
||||
|
||||
void Section_init(Section* sec, str name){
|
||||
void Section_init(Section* sec, char* name){
|
||||
sec->name = name;
|
||||
sec->data = List_DataDefinition_alloc(256);
|
||||
sec->code = List_Operation_alloc(1024);
|
||||
}
|
||||
|
||||
void Section_free(Section* sec){
|
||||
free(sec->name.data);
|
||||
free(sec->name);
|
||||
free(sec->data.data);
|
||||
free(sec->code.data);
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
#include "../std.h"
|
||||
#include "../string/str.h"
|
||||
#include "../instructions/instructions.h"
|
||||
#include "../collections/List.h"
|
||||
|
||||
@ -13,7 +12,7 @@ typedef enum ArgumentType {
|
||||
ArgumentType_NamedDataSize,
|
||||
} ArgumentType;
|
||||
|
||||
str ArgumentType_toString(ArgumentType t);
|
||||
cstr ArgumentType_toString(ArgumentType t);
|
||||
|
||||
|
||||
typedef struct Argument {
|
||||
@ -33,7 +32,7 @@ List_declare(Operation);
|
||||
|
||||
|
||||
typedef struct DataDefinition {
|
||||
str name;
|
||||
cstr name;
|
||||
List_u8 data;
|
||||
u32 element_size;
|
||||
} DataDefinition;
|
||||
@ -42,14 +41,14 @@ List_declare(DataDefinition);
|
||||
|
||||
|
||||
typedef struct Section {
|
||||
str name;
|
||||
char* name;
|
||||
List_DataDefinition data;
|
||||
List_Operation code;
|
||||
} Section;
|
||||
|
||||
List_declare(Section);
|
||||
|
||||
void Section_init(Section* Section, str name);
|
||||
void Section_init(Section* Section, char* name);
|
||||
void Section_free(Section* Section);
|
||||
|
||||
typedef struct AST {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include "Compiler_internal.h"
|
||||
|
||||
|
||||
void Compiler_init(Compiler* cmp){
|
||||
memset(cmp, 0, sizeof(Compiler));
|
||||
cmp->state = CompilerState_Initial;
|
||||
@ -9,7 +10,7 @@ void Compiler_init(Compiler* cmp){
|
||||
}
|
||||
|
||||
void Compiler_free(Compiler* cmp){
|
||||
free(cmp->code.data);
|
||||
free(cmp->code);
|
||||
free(cmp->tokens.data);
|
||||
free(cmp->line_lengths.data);
|
||||
AST_free(&cmp->ast);
|
||||
@ -17,7 +18,7 @@ void Compiler_free(Compiler* cmp){
|
||||
|
||||
CodePos Compiler_getLineAndColumn(Compiler* cmp, u32 pos){
|
||||
u32 prev_lines_len = 0;
|
||||
if(pos >= cmp->code.len)
|
||||
if(pos >= cmp->code_len)
|
||||
return CodePos_create(0, 0);
|
||||
|
||||
for(u32 i = 0; i < cmp->line_lengths.len; i++){
|
||||
@ -32,8 +33,8 @@ CodePos Compiler_getLineAndColumn(Compiler* cmp, u32 pos){
|
||||
|
||||
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;
|
||||
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);
|
||||
@ -55,8 +56,10 @@ void _Compiler_setError(Compiler* cmp, cstr context, cstr format, ...){
|
||||
Compiler_setError(cmp, FORMAT, ##__VA_ARGS__);\
|
||||
}
|
||||
|
||||
str Compiler_constructTokenStr(Compiler* cmp, Token t){
|
||||
str s = str_construct((char*)(cmp->code.data + t.begin), t.length, false);
|
||||
char* Compiler_extractTokenStr(Compiler* cmp, Token t){
|
||||
char* s = malloc(t.length + 1);
|
||||
memcpy(s, cmp->code, t.length);
|
||||
s[t.length] = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -72,34 +75,37 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name,
|
||||
if(f == NULL)
|
||||
returnError("ERROR: can't open file '%s'", source_file_name);
|
||||
|
||||
StringBuilder sb = StringBuilder_alloc(64 * 1024);
|
||||
List_u8 buf = List_u8_alloc(64 * 1024);
|
||||
int ret;
|
||||
while((ret = fgetc(f)) != EOF) {
|
||||
StringBuilder_append_char(&sb, ret);
|
||||
List_u8_push(&buf, ret);
|
||||
}
|
||||
if(ferror(f)){
|
||||
StringBuilder_free(&sb);
|
||||
free(buf.data);
|
||||
fclose(f);
|
||||
returnError("can't read file '%s'", source_file_name);
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
if(sb.buffer.len == 0){
|
||||
StringBuilder_free(&sb);
|
||||
if(buf.len == 0){
|
||||
free(buf.data);
|
||||
fclose(f);
|
||||
returnError("soucre file is empty");
|
||||
}
|
||||
|
||||
cmp->code = str_copy(StringBuilder_getStr(&sb));
|
||||
StringBuilder_free(&sb);
|
||||
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_log){
|
||||
printf("----------------------------------[%s]---------------------------------\n", source_file_name);
|
||||
fputs(cmp->code.data, stdout);
|
||||
fputs(cmp->code, stdout);
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
|
||||
@ -114,11 +120,11 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name,
|
||||
Token t = cmp->tokens.data[i];
|
||||
CodePos pos = Compiler_getLineAndColumn(cmp, t.begin);
|
||||
char* tokstr = malloc(4096);
|
||||
strncpy(tokstr, cmp->code.data + t.begin, t.length);
|
||||
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).data, tokstr);
|
||||
pos.line, pos.column,
|
||||
TokenType_toString(t.type), tokstr);
|
||||
free(tokstr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
#include "../std.h"
|
||||
#include "../string/str.h"
|
||||
#include "../collections/List.h"
|
||||
#include "Token.h"
|
||||
#include "AST.h"
|
||||
@ -15,7 +14,8 @@ typedef enum CompilerState {
|
||||
} CompilerState;
|
||||
|
||||
typedef struct Compiler {
|
||||
str code;
|
||||
char* code;
|
||||
u32 code_len;
|
||||
u32 column; // > 0 if code parsing started
|
||||
u32 pos;
|
||||
CompilerState state;
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
#include "Compiler.h"
|
||||
#include "../string/StringBuilder.h"
|
||||
|
||||
void _Compiler_setError(Compiler* cmp, cstr context, cstr format, ...) __attribute__((__format__(__printf__, 3, 4)));
|
||||
|
||||
@ -24,7 +23,7 @@ typedef struct CodePos {
|
||||
/// @param pos index in code buffer
|
||||
CodePos Compiler_getLineAndColumn(Compiler* cmp, u32 pos);
|
||||
|
||||
str Compiler_constructTokenStr(Compiler* cmp, Token t);
|
||||
char* Compiler_extractTokenStr(Compiler* cmp, Token t);
|
||||
|
||||
bool Compiler_lex(Compiler* cmp);
|
||||
bool Compiler_parse(Compiler* cmp);
|
||||
|
||||
@ -19,8 +19,8 @@ static void readCommentSingleLine(Compiler* cmp){
|
||||
cmp->column++;
|
||||
cmp->pos++;
|
||||
|
||||
while(cmp->pos < cmp->code.len){
|
||||
c = cmp->code.data[cmp->pos];
|
||||
while(cmp->pos < cmp->code_len){
|
||||
c = cmp->code[cmp->pos];
|
||||
// end of line
|
||||
if(c == '\r' || c == '\n'){
|
||||
tok.length = cmp->pos - tok.begin;
|
||||
@ -44,10 +44,10 @@ static void readCommentMultiLine(Compiler* cmp){
|
||||
cmp->column++;
|
||||
cmp->pos++;
|
||||
|
||||
while(cmp->pos < cmp->code.len){
|
||||
c = cmp->code.data[cmp->pos];
|
||||
while(cmp->pos < cmp->code_len){
|
||||
c = cmp->code[cmp->pos];
|
||||
// closing comment
|
||||
if(cmp->pos > tok.begin + 3 && c == '/' && cmp->code.data[cmp->pos - 1] == '*') {
|
||||
if(cmp->pos > tok.begin + 3 && c == '/' && cmp->code[cmp->pos - 1] == '*') {
|
||||
tok.length = cmp->pos - tok.begin + 1;
|
||||
List_Token_push(&cmp->tokens, tok);
|
||||
return;
|
||||
@ -65,14 +65,14 @@ static void readCommentMultiLine(Compiler* cmp){
|
||||
|
||||
static void readComment(Compiler* cmp){
|
||||
char c; // '/'
|
||||
if(cmp->pos + 1 == cmp->code.len){
|
||||
if(cmp->pos + 1 == cmp->code_len){
|
||||
setError(Error_endOfFile);
|
||||
return;
|
||||
}
|
||||
|
||||
c = cmp->code.data[cmp->pos + 1];
|
||||
c = cmp->code[cmp->pos + 1];
|
||||
if(c == '\r' || c == '\n'){
|
||||
setError(Error_unexpectedCharacter(cmp->code.data[--cmp->pos]));
|
||||
setError(Error_unexpectedCharacter(cmp->code[--cmp->pos]));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -91,14 +91,14 @@ static void readLabel(Compiler* cmp){
|
||||
cmp->column++;
|
||||
Token tok = Token_construct(TokenType_Label, cmp->pos, 0);
|
||||
|
||||
while(cmp->pos < cmp->code.len){
|
||||
c = cmp->code.data[cmp->pos];
|
||||
while(cmp->pos < cmp->code_len){
|
||||
c = cmp->code[cmp->pos];
|
||||
// end of line
|
||||
if(c == ':' || c == '\r' || c == '\n'){
|
||||
tok.length = cmp->pos - tok.begin;
|
||||
if(tok.length > 0)
|
||||
List_Token_push(&cmp->tokens, tok);
|
||||
else setError(Error_unexpectedCharacter(cmp->code.data[--cmp->pos]));
|
||||
else setError(Error_unexpectedCharacter(cmp->code[--cmp->pos]));
|
||||
// cmp->line will be increased in lex()
|
||||
return;
|
||||
}
|
||||
@ -125,12 +125,12 @@ static void readArguments(Compiler* cmp){
|
||||
Token tok = Token_construct(TokenType_Unset, cmp->pos, 0);
|
||||
char quot = '\0'; // quotation character of a string value
|
||||
|
||||
while(cmp->pos < cmp->code.len){
|
||||
c = cmp->code.data[cmp->pos];
|
||||
while(cmp->pos < cmp->code_len){
|
||||
c = cmp->code[cmp->pos];
|
||||
|
||||
// string argument reading
|
||||
if(quot != '\0'){
|
||||
if(c == quot && cmp->code.data[cmp->pos - 1] != '\\'){
|
||||
if(c == quot && cmp->code[cmp->pos - 1] != '\\'){
|
||||
quot = '\0';
|
||||
}
|
||||
else if(c == '\r' || c == '\n'){
|
||||
@ -189,8 +189,8 @@ static void readInstruction(Compiler* cmp){
|
||||
cmp->pos++;
|
||||
cmp->column++;
|
||||
|
||||
while(cmp->pos < cmp->code.len){
|
||||
char c = cmp->code.data[cmp->pos];
|
||||
while(cmp->pos < cmp->code_len){
|
||||
char c = cmp->code[cmp->pos];
|
||||
// end of line
|
||||
if(c == '\r' || c == '\n' || c == ';'){
|
||||
tok.length = cmp->pos - tok.begin;
|
||||
@ -232,8 +232,8 @@ bool Compiler_lex(Compiler* cmp){
|
||||
cmp->state = CompilerState_Lexing;
|
||||
cmp->column = 1;
|
||||
|
||||
while(cmp->pos < cmp->code.len){
|
||||
char c = cmp->code.data[cmp->pos];
|
||||
while(cmp->pos < cmp->code_len){
|
||||
char c = cmp->code[cmp->pos];
|
||||
switch(c){
|
||||
// skip blank characters
|
||||
case ' ': case '\t': case '\r': case '\n':
|
||||
@ -257,7 +257,7 @@ bool Compiler_lex(Compiler* cmp){
|
||||
if(cmp->state == CompilerState_Error)
|
||||
return false;
|
||||
|
||||
c = cmp->code.data[cmp->pos];
|
||||
c = cmp->code[cmp->pos];
|
||||
if(c == '\n')
|
||||
completeLine(cmp);
|
||||
cmp->column++;
|
||||
|
||||
@ -6,15 +6,15 @@
|
||||
}
|
||||
|
||||
#define setError_unexpectedToken(T) {\
|
||||
str tok_str = str_copy(Compiler_constructTokenStr(cmp, T));\
|
||||
char* tok_str = Compiler_extractTokenStr(cmp, T);\
|
||||
cmp->pos = T.begin;\
|
||||
Compiler_setError(cmp, "unexpected token '%s'", tok_str.data);\
|
||||
free(tok_str.data);\
|
||||
Compiler_setError(cmp, "unexpected token '%s'", tok_str);\
|
||||
free(tok_str);\
|
||||
}
|
||||
|
||||
#define setError_unexpectedTokenChar(T, I) {\
|
||||
cmp->pos = T.begin + I;\
|
||||
Compiler_setError(cmp, "unexpected token '%c'", cmp->code.data[cmp->pos]);\
|
||||
Compiler_setError(cmp, "unexpected token '%c'", cmp->code[cmp->pos]);\
|
||||
}
|
||||
|
||||
|
||||
@ -30,63 +30,62 @@ static void List_u8_pushBytes(List_u8* l, void* value, u32 startIndex, u32 count
|
||||
|
||||
static inline bool isVarSizeBits(u32 B) { return (B == 8 && B == 16 && B == 32 && B == 64); }
|
||||
|
||||
static NULLABLE(str) resolveEscapeSequences(Compiler* cmp, str src){
|
||||
StringBuilder sb = StringBuilder_alloc(src.len);
|
||||
static NULLABLE(u8*) resolveEscapeSequences(Compiler* cmp, cstr src){
|
||||
u32 len = strlen(src);
|
||||
List_u8 resolved = List_u8_alloc(len);
|
||||
char c;
|
||||
bool escaped = false;
|
||||
for(u32 i = 0; i < src.len; i++){
|
||||
c = src.data[i];
|
||||
for(u32 i = 0; i < len; i++){
|
||||
c = src[i];
|
||||
if(c == '\\'){
|
||||
escaped = !escaped;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!escaped){
|
||||
StringBuilder_append_char(&sb, c);
|
||||
List_u8_push(&resolved, c);
|
||||
continue;
|
||||
}
|
||||
|
||||
// escape codes
|
||||
switch(c){
|
||||
case '0':
|
||||
StringBuilder_append_char(&sb, '\0');
|
||||
List_u8_push(&resolved, '\0');
|
||||
break;
|
||||
case 'n':
|
||||
StringBuilder_append_char(&sb, '\n');
|
||||
List_u8_push(&resolved, '\n');
|
||||
break;
|
||||
case 'r':
|
||||
StringBuilder_append_char(&sb, '\r');
|
||||
List_u8_push(&resolved, '\r');
|
||||
break;
|
||||
case 't':
|
||||
StringBuilder_append_char(&sb, '\t');
|
||||
List_u8_push(&resolved, '\t');
|
||||
break;
|
||||
case 'e':
|
||||
StringBuilder_append_char(&sb, '\e');
|
||||
List_u8_push(&resolved, '\e');
|
||||
break;
|
||||
default:
|
||||
setError_unexpectedTokenChar(cmp->tokens.data[cmp->tok_i], i);
|
||||
StringBuilder_free(&sb);
|
||||
return str_null;
|
||||
free(resolved.data);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return StringBuilder_getStr(&sb);
|
||||
return resolved.data;
|
||||
}
|
||||
|
||||
static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* ddf){
|
||||
static void parseDataDefinition(Compiler* cmp, char* instr_name, DataDefinition* ddf){
|
||||
i32 _element_size_bits;
|
||||
str _instr_name_zero_terminated = str_copy(instr_name);
|
||||
if(sscanf(_instr_name_zero_terminated.data, "const%i", &_element_size_bits) != 1 || !isVarSizeBits(_element_size_bits)){
|
||||
free(_instr_name_zero_terminated.data);
|
||||
if(sscanf(instr_name, "const%i", &_element_size_bits) != 1 || !isVarSizeBits(_element_size_bits)){
|
||||
setError(Error_BitSize);
|
||||
return;
|
||||
}
|
||||
free(_instr_name_zero_terminated.data);
|
||||
ddf->element_size = _element_size_bits / 8;
|
||||
|
||||
Token tok = cmp->tokens.data[++cmp->tok_i];
|
||||
str tok_str = Compiler_constructTokenStr(cmp, tok);
|
||||
str processed_str = str_null;
|
||||
char* tok_str = Compiler_extractTokenStr(cmp, tok);
|
||||
u8* processed_str = NULL;
|
||||
u32 len = 0;
|
||||
ddf->name = tok_str;
|
||||
|
||||
while(++cmp->tok_i < cmp->tokens.len){
|
||||
@ -99,38 +98,37 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d
|
||||
// skip comments
|
||||
break;
|
||||
case TokenType_Number:
|
||||
tok_str = Compiler_constructTokenStr(cmp, tok);
|
||||
processed_str = str_copy(tok_str);
|
||||
if(str_seekChar(tok_str, '.', 0) != -1){
|
||||
f64 f = atof(tok_str.data);
|
||||
tok_str = Compiler_extractTokenStr(cmp, tok);
|
||||
if(cstr_seekChar(tok_str, '.', 0, -1) != -1){
|
||||
f64 f = atof(tok_str);
|
||||
List_u8_pushBytes(&ddf->data, &f, 8 - ddf->element_size, ddf->element_size);
|
||||
}
|
||||
else {
|
||||
i64 i = atoll(tok_str.data);
|
||||
i64 i = atoll(tok_str);
|
||||
List_u8_pushBytes(&ddf->data, &i, 8 - ddf->element_size, ddf->element_size);
|
||||
}
|
||||
free(processed_str.data);
|
||||
break;
|
||||
case TokenType_Char:
|
||||
tok.begin += 1;
|
||||
tok.length -= 2;
|
||||
tok_str = Compiler_constructTokenStr(cmp, tok);
|
||||
tok_str = Compiler_extractTokenStr(cmp, tok);
|
||||
processed_str = resolveEscapeSequences(cmp, tok_str);
|
||||
|
||||
if(processed_str.len != ddf->element_size){
|
||||
setError("can't fit char of size %i in %u bit variable", processed_str.len, _element_size_bits);
|
||||
free(tok_str);
|
||||
len = strlen((char*)processed_str);
|
||||
if(len != ddf->element_size){
|
||||
setError("can't fit char of size %i in %u bit variable", len, _element_size_bits);
|
||||
return;
|
||||
}
|
||||
List_u8_pushBytes(&ddf->data, processed_str.data, 0, processed_str.len);
|
||||
free(processed_str.data);
|
||||
List_u8_pushBytes(&ddf->data, processed_str, 0, len);
|
||||
break;
|
||||
case TokenType_String:
|
||||
tok.begin += 1;
|
||||
tok.length -= 2;
|
||||
tok_str = Compiler_constructTokenStr(cmp, tok);
|
||||
tok_str = Compiler_extractTokenStr(cmp, tok);
|
||||
processed_str = resolveEscapeSequences(cmp, tok_str);
|
||||
List_u8_pushBytes(&ddf->data, processed_str.data, 0, processed_str.len);
|
||||
free(processed_str.data);
|
||||
free(tok_str);
|
||||
len = strlen((char*)processed_str);
|
||||
List_u8_pushBytes(&ddf->data, processed_str, 0, len);
|
||||
break;
|
||||
case TokenType_OperationEnd:
|
||||
return;
|
||||
@ -142,7 +140,7 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d
|
||||
}
|
||||
|
||||
|
||||
static void parseOperation(Compiler* cmp, str instr_name, Operation* operPtr){
|
||||
static void parseOperation(Compiler* cmp, char* instr_name, Operation* operPtr){
|
||||
|
||||
}
|
||||
|
||||
@ -164,14 +162,14 @@ bool Compiler_parse(Compiler* cmp){
|
||||
case TokenType_Label:
|
||||
// create new section
|
||||
sec = List_Section_expand(&cmp->ast.sections, 1);
|
||||
Section_init(sec, Compiler_constructTokenStr(cmp, tok));
|
||||
Section_init(sec, Compiler_extractTokenStr(cmp, tok));
|
||||
break;
|
||||
case TokenType_Instruction:
|
||||
if(sec == NULL)
|
||||
returnError("no section");
|
||||
str instr_name = Compiler_constructTokenStr(cmp, tok);
|
||||
char* instr_name = Compiler_extractTokenStr(cmp, tok);
|
||||
// data definition starts with const
|
||||
if(str_startsWith(instr_name, STR("const"))){
|
||||
if(cstr_seek(instr_name, "const", 0, 1)){
|
||||
DataDefinition* dataDefPtr = List_DataDefinition_expand(&sec->data, 1);
|
||||
parseDataDefinition(cmp, instr_name, dataDefPtr);
|
||||
}
|
||||
|
||||
@ -2,22 +2,22 @@
|
||||
|
||||
List_define(Token);
|
||||
|
||||
static str _TokenType_str[] = {
|
||||
STR("Unset"),
|
||||
STR("SingleLineComment"),
|
||||
STR("MultiLineComment"),
|
||||
STR("Instruction"),
|
||||
STR("Label"),
|
||||
STR("Number"),
|
||||
STR("Char"),
|
||||
STR("String"),
|
||||
STR("Name"),
|
||||
STR("NamedDataPointer"),
|
||||
STR("NamedDataSize")
|
||||
static cstr _TokenType_str[] = {
|
||||
"Unset",
|
||||
"SingleLineComment",
|
||||
"MultiLineComment",
|
||||
"Instruction",
|
||||
"Label",
|
||||
"Number",
|
||||
"Char",
|
||||
"String",
|
||||
"Name",
|
||||
"NamedDataPointer",
|
||||
"NamedDataSize"
|
||||
};
|
||||
|
||||
str TokenType_toString(TokenType t){
|
||||
cstr TokenType_toString(TokenType t){
|
||||
if(t >= ARRAY_SIZE(_TokenType_str))
|
||||
return STR("!!INDEX_ERROR!!");
|
||||
return "!!INDEX_ERROR!!";
|
||||
return _TokenType_str[t];
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
#include "../std.h"
|
||||
#include "../string/str.h"
|
||||
#include "../collections/List.h"
|
||||
|
||||
typedef enum TokenType {
|
||||
@ -18,7 +17,7 @@ typedef enum TokenType {
|
||||
TokenType_OperationEnd, // EOL or EOF or ;
|
||||
} TokenType;
|
||||
|
||||
str TokenType_toString(TokenType t);
|
||||
cstr TokenType_toString(TokenType t);
|
||||
|
||||
typedef struct Token {
|
||||
u32 begin; // some index in Compiler->code
|
||||
|
||||
68
src/cstr.c
68
src/cstr.c
@ -50,3 +50,71 @@ char* NULLABLE(vsprintf_malloc)(size_t buffer_size, cstr format, va_list argv){
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
i32 cstr_seek(const char* src, const char* fragment, u32 startIndex, u32 seekLength){
|
||||
char sc = *src, fc = *fragment;
|
||||
if(sc == 0 || fc == 0)
|
||||
return -1;
|
||||
u32 fr_start = startIndex;
|
||||
for(u32 si = startIndex; si-startIndex < seekLength && sc != 0; si++){
|
||||
sc = src[si];
|
||||
fc = fragment[si-fr_start];
|
||||
if(fc == 0)
|
||||
return fr_start;
|
||||
if(sc != fc)
|
||||
fr_start++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
i32 cstr_seekReverse(const char* src, const char* fragment, u32 startIndex, u32 seekLength){
|
||||
char sc = *src, fc = *fragment;
|
||||
if(sc == 0 || fc == 0)
|
||||
return -1;
|
||||
i32 len = strlen(src);
|
||||
if(startIndex == (u32)-1)
|
||||
startIndex = len-1;
|
||||
u32 fr_len = strlen(fragment);
|
||||
for(u32 si = startIndex; si < (u32)-1 && si != (len - seekLength - 1); si--){
|
||||
if(si + 1 < fr_len)
|
||||
return -1;
|
||||
sc = src[si];
|
||||
fc = fragment[0];
|
||||
u32 fr_start = si;
|
||||
for(u32 fi = 0; fc == sc ; fi++){
|
||||
if(fi == fr_len)
|
||||
return fr_start;
|
||||
fc = fragment[fi];
|
||||
sc = src[si--];
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
i32 cstr_seekChar(const char* src, char fragment, u32 startIndex, u32 seekLength){
|
||||
char sc=*src;
|
||||
if(sc==0 || fragment==0)
|
||||
return -1;
|
||||
for(u32 si=startIndex; si-startIndex<seekLength && sc!=0; si++){
|
||||
sc=src[si];
|
||||
if(sc==fragment)
|
||||
return si;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
i32 cstr_seekCharReverse(const char* src, char fragment, u32 startIndex, u32 seekLength){
|
||||
char sc=*src;
|
||||
if(sc==0 || fragment==0)
|
||||
return -1;
|
||||
i32 len=strlen(src);
|
||||
if(startIndex==(u32)-1)
|
||||
startIndex=len-1;
|
||||
for(u32 si=startIndex; si<(u32)-1 && si!=len-1-seekLength; si--){
|
||||
sc=src[si];
|
||||
if(sc==fragment)
|
||||
return si;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -19,13 +19,13 @@ typedef enum __attribute__((__packed__)) Opcode {
|
||||
} Opcode;
|
||||
|
||||
typedef struct Instruction {
|
||||
str name;
|
||||
cstr name;
|
||||
InstructionImplFunc_t implementation;
|
||||
Opcode opcode;
|
||||
} Instruction;
|
||||
|
||||
#define Instruction_construct(NAME) {\
|
||||
.name = STR(#NAME), \
|
||||
.name = #NAME, \
|
||||
.implementation = NAME##_impl, \
|
||||
.opcode = Opcode_##NAME\
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ i32 main(const i32 argc, cstr* argv){
|
||||
for(u8 opcode = 0; opcode < 255; opcode++){
|
||||
const Instruction* instr = Instruction_getByOpcode(opcode);
|
||||
if(instr != NULL){
|
||||
printf("%02X %s\n", opcode, instr->name.data);
|
||||
printf("%02X %s\n", opcode, instr->name);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
20
src/std.h
20
src/std.h
@ -58,3 +58,23 @@ char* NULLABLE(vsprintf_malloc)(size_t buffer_size, cstr format, va_list argv);
|
||||
static inline bool isAlphabeticalLower(char c) { return 'a' <= c && c <= 'z'; }
|
||||
static inline bool isAlphabeticalUpper(char c) { return 'A' <= c && c <= 'Z'; }
|
||||
static inline bool isDigit(char c) { return '0' <= c && c <= '9'; }
|
||||
|
||||
/// @param startIndex 0 ... src length
|
||||
/// @param seekLength 0 ... -1
|
||||
/// @return pos of first <fragment> inclusion in <src> or -1 if not found
|
||||
i32 cstr_seek(const char* src, const char* fragment, u32 startIndex, u32 seekLength);
|
||||
|
||||
/// @param startIndex -1 ... src length
|
||||
/// @param seekLength 0 ... -1
|
||||
/// @return pos of first <fragment> inclusion in <src> or -1 if not found
|
||||
i32 cstr_seekReverse(const char* src, const char* fragment, u32 startIndex, u32 seekLength);
|
||||
|
||||
/// @param startIndex 0 ... src length
|
||||
/// @param seekLength 0 ... -1
|
||||
/// @return pos of first <fragment> inclusion in <src> or -1 if not found
|
||||
i32 cstr_seekChar(const char* src, char fragment, u32 startIndex, u32 seekLength);
|
||||
|
||||
/// @param startIndex -1 ... src length
|
||||
/// @param seekLength 0 ... -1
|
||||
/// @return pos of first <fragment> inclusion in <src> or -1 if not found
|
||||
i32 cstr_seekCharReverse(const char* src, char fragment, u32 startIndex, u32 seekLength);
|
||||
|
||||
@ -2,24 +2,14 @@
|
||||
|
||||
void StringBuilder_free(StringBuilder* b){
|
||||
free(b->buffer.data);
|
||||
b->buffer = List_u8_construct(NULL, 0, 0);
|
||||
}
|
||||
|
||||
str StringBuilder_getStr(StringBuilder* b){
|
||||
str StringBuilder_build(StringBuilder* b){
|
||||
List_u8_push(&b->buffer, '\0');
|
||||
str result = str_construct((char*)b->buffer.data, b->buffer.len - 1, true);
|
||||
return result;
|
||||
}
|
||||
|
||||
void StringBuilder_removeFromEnd(StringBuilder* b, u32 count){
|
||||
if(count < b->buffer.len){
|
||||
b->buffer.len -= count;
|
||||
}
|
||||
else{
|
||||
b->buffer.len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void StringBuilder_append_char(StringBuilder* b, char c){
|
||||
List_u8_push(&b->buffer, c);
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../collections/List.h"
|
||||
#include "str.h"
|
||||
|
||||
@ -7,12 +11,11 @@ typedef struct StringBuilder {
|
||||
List_u8 buffer;
|
||||
} StringBuilder;
|
||||
|
||||
static inline StringBuilder StringBuilder_alloc(u32 initial_size) {
|
||||
static inline StringBuilder StringBuilder_construct(u32 initial_size) {
|
||||
return (StringBuilder){ .buffer = List_u8_alloc(initial_size) };
|
||||
}
|
||||
void StringBuilder_free(StringBuilder* b);
|
||||
|
||||
/// @param count set to -1 to clear StringBuilder
|
||||
void StringBuilder_removeFromEnd(StringBuilder* b, u32 count);
|
||||
void StringBuilder_append_char(StringBuilder* b, char c);
|
||||
void StringBuilder_append_cstr(StringBuilder* b, char* s);
|
||||
@ -23,3 +26,7 @@ void StringBuilder_append_f64(StringBuilder* b, f64 a);
|
||||
|
||||
// adds '\0' to the buffer and returns pointer to buffer content
|
||||
str StringBuilder_getStr(StringBuilder* b);
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -3,97 +3,27 @@
|
||||
str str_copy(str src){
|
||||
if(src.data == NULL || src.len == 0)
|
||||
return src;
|
||||
|
||||
str nstr = str_construct((char*)malloc(src.len + 1), src.len, true);
|
||||
memcpy(nstr.data, src.data, src.len);
|
||||
nstr.data[nstr.len] = '\0';
|
||||
return nstr;
|
||||
}
|
||||
|
||||
bool str_equals(str s0, str s1){
|
||||
if(s0.len != s1.len)
|
||||
return false;
|
||||
|
||||
for(u32 i = 0; i < s0.len; i++)
|
||||
if(s0.data[i] != s1.data[i])
|
||||
bool str_compare(str str0, str str1){
|
||||
if(str0.len!= str1.len) return false;
|
||||
if(!str0.data) return str1.data ? false : true;
|
||||
else if(!str1.data) return false;
|
||||
while(str0.len-- > 0)
|
||||
if(*str0.data++ != *str1.data++ )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
str str_reverse(str s){
|
||||
if(s.data == NULL || s.len == 0)
|
||||
return s;
|
||||
|
||||
str r = str_construct(malloc(s.len), s.len, s.isZeroTerminated);
|
||||
for(u32 i = 0; i < s.len; i++ )
|
||||
r.data[i] = s.data[s.len - i - 1];
|
||||
return r;
|
||||
}
|
||||
|
||||
i32 str_seek(str src, str fragment, u32 startIndex){
|
||||
if(src.len == 0 || fragment.len == 0)
|
||||
return -1;
|
||||
|
||||
for(u32 i = startIndex; i < src.len - fragment.len + 1; i++){
|
||||
for(u32 j = 0;; j++){
|
||||
if(j == fragment.len)
|
||||
return i;
|
||||
if(src.data[i + j] != fragment.data[j])
|
||||
break;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
i32 str_seekReverse(str src, str fragment, u32 startIndex){
|
||||
if(src.len == 0 || fragment.len == 0)
|
||||
return -1;
|
||||
|
||||
if(startIndex > src.len - 1)
|
||||
startIndex = src.len - 1;
|
||||
for(u32 i = startIndex; i >= fragment.len - 1; i--){
|
||||
for(u32 j = 0;; j++){
|
||||
if(j == fragment.len)
|
||||
return i - j + 1;
|
||||
if(src.data[i - j] != fragment.data[fragment.len - 1 - j])
|
||||
break;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
i32 str_seekChar(str src, char c, u32 startIndex){
|
||||
for(u32 i = startIndex; i < src.len; i++){
|
||||
if(src.data[i] == c)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
i32 str_seekCharReverse(str src, char c, u32 startIndex){
|
||||
if(startIndex > src.len - 1)
|
||||
startIndex = src.len - 1;
|
||||
for(u32 i = startIndex; i != (u32)-1; i--){
|
||||
if(src.data[i] == c)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool str_startsWith(str src, str fragment){
|
||||
if(src.len < fragment.len)
|
||||
return false;
|
||||
|
||||
src.len = fragment.len;
|
||||
return str_equals(src, fragment);
|
||||
}
|
||||
|
||||
bool str_endsWith(str src, str fragment){
|
||||
if(src.len < fragment.len)
|
||||
return false;
|
||||
|
||||
src.data = (char*)(src.data + src.len - fragment.len);
|
||||
src.len = fragment.len;
|
||||
return str_equals(src, fragment);
|
||||
}
|
||||
|
||||
@ -8,27 +8,23 @@ typedef struct str {
|
||||
bool isZeroTerminated;
|
||||
} str;
|
||||
|
||||
// creates str from a string literal
|
||||
#define STR(LITERAL) str_construct(LITERAL, ARRAY_SIZE(LITERAL) - 1, true)
|
||||
|
||||
#define str_construct(DATA, LEN, ZERO_TERMINATED) ((str){ .data = DATA, .len = LEN, .isZeroTerminated = ZERO_TERMINATED })
|
||||
|
||||
static const str str_null = str_construct(NULL, 0, 0);
|
||||
|
||||
|
||||
/// copies str content to new char pointer value (adding '\0' at the end)
|
||||
char* str_extractcstr(str str);
|
||||
|
||||
/// copies src content to new string and adds \0 at the end
|
||||
str str_copy(str src);
|
||||
|
||||
/// compares two strings, NullPtr-friendly
|
||||
bool str_equals(str str0, str str1);
|
||||
bool str_compare(str str0, str str1);
|
||||
|
||||
/// allocates new string which is reversed variant of <s>
|
||||
str str_reverse(str s);
|
||||
|
||||
i32 str_seek(str src, str fragment, u32 startIndex);
|
||||
i32 str_seekReverse(str src, str fragment, u32 startIndex);
|
||||
|
||||
i32 str_seekChar(str src, char c, u32 startIndex);
|
||||
i32 str_seekCharReverse(str src, char c, u32 startIndex);
|
||||
|
||||
bool str_startsWith(str src, str fragment);
|
||||
bool str_endsWith(str src, str fragment);
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user