AST idea
This commit is contained in:
53
ast.c
53
ast.c
@@ -21,7 +21,7 @@ decl_struct(Parser *p, Decl_Kind kind, Token *pos, Intern_String name, Decl_Stru
|
||||
function Decl *
|
||||
decl_typedef(Parser *p, Token *pos, Intern_String name, Typespec *type){
|
||||
Decl *result = decl_new(p, DECL_Typedef, pos, name);
|
||||
result->typedef_decl.type = type;
|
||||
result->typedef_decl.typespec = type;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -227,57 +227,6 @@ typespec_require_name_string(Typespec *type){
|
||||
return string_empty;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Statements
|
||||
//-----------------------------------------------------------------------------
|
||||
function Stmt *
|
||||
stmt_new(Parser *p, Stmt_Kind kind, Token *pos){
|
||||
Stmt *result = arena_push_struct(&p->main_arena, Stmt);
|
||||
result->kind = kind;
|
||||
result->pos = pos;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Stmt *
|
||||
stmt_decl(Parser *p, Token *pos, Decl *decl){
|
||||
Stmt *result = stmt_new(p, STMT_Decl, pos);
|
||||
result->decl = decl;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Stmt *
|
||||
stmt_expr(Parser *p, Token *pos, Expr *expr){
|
||||
Stmt *result = stmt_new(p, STMT_Expr, pos);
|
||||
result->expr = expr;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Stmt *
|
||||
stmt_list(Parser *p, Token *pos){
|
||||
Stmt *result = stmt_new(p, STMT_List, pos);
|
||||
return result;
|
||||
}
|
||||
|
||||
function Stmt *
|
||||
stmt_return(Parser *p, Token *pos, Expr *expr){
|
||||
Stmt *result = stmt_new(p, STMT_Return, pos);
|
||||
result->ret.expr = expr;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Stmt *
|
||||
stmt_if(Parser *p, Token *pos, Stmt *body, Expr *cond){
|
||||
Stmt *result = stmt_new(p, STMT_If, pos);
|
||||
result->stmt_if.cond = cond;
|
||||
result->stmt_if.body = body;
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
stmt_push(Stmt *stmt, Stmt *child){
|
||||
SLLQueuePush(stmt->list.first, stmt->list.last, child);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Pointer Array
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
|
||||
rem clang generate.c -fdiagnostics-absolute-paths -std=c99 -g -o generate.exe -Wl,user32.lib
|
||||
rem generate.exe
|
||||
|
||||
clang main.c -Wall -Wno-unused-function -fdiagnostics-absolute-paths -std=c17 -g -o main.exe -Wl,user32.lib
|
||||
rem cl main.c -std:c17
|
||||
|
||||
55
dllqueue.c
Normal file
55
dllqueue.c
Normal file
@@ -0,0 +1,55 @@
|
||||
function void
|
||||
push(Type *l, Type *node){
|
||||
if(l->first == 0){
|
||||
l->first = l->last = node;
|
||||
node->prev = 0;
|
||||
node->next = 0;
|
||||
}
|
||||
else{
|
||||
l->last->next = node;
|
||||
node->prev = l->last;
|
||||
node->next = 0;
|
||||
l->last = node;
|
||||
}
|
||||
node->parent = l;
|
||||
}
|
||||
|
||||
function void
|
||||
push_front(Type *l, Type *node){
|
||||
if(l->first == 0){
|
||||
l->first = l->last = node;
|
||||
node->prev = 0;
|
||||
node->next = 0;
|
||||
}
|
||||
else{
|
||||
node->next = l->first;
|
||||
l->first->prev = node;
|
||||
node->prev = 0;
|
||||
l->first = node;
|
||||
}
|
||||
node->parent = l;
|
||||
}
|
||||
|
||||
function void
|
||||
remove(Type *l, Type *node){
|
||||
if(l->first == l->last){
|
||||
assert(node == l->last);
|
||||
l->first = l->last = 0;
|
||||
}
|
||||
else if(l->last == node){
|
||||
l->last = l->last->prev;
|
||||
l->last->next = 0;
|
||||
}
|
||||
else if(l->first == node){
|
||||
l->first = l->first->next;
|
||||
l->first->prev = 0;
|
||||
}
|
||||
else{
|
||||
node->prev->next = node->next;
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
|
||||
node->parent = 0;
|
||||
node->prev = 0;
|
||||
node->next = 0;
|
||||
}
|
||||
48
generate.c
48
generate.c
@@ -13,24 +13,54 @@
|
||||
|
||||
#include "new_lex.c"
|
||||
|
||||
int main(){
|
||||
|
||||
FILE *f = fopen("generated.c", "w");
|
||||
assert(f);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// String replacing util
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct String_Map String_Map;
|
||||
struct String_Map{
|
||||
String replace;
|
||||
String with;
|
||||
};
|
||||
|
||||
function void
|
||||
output_template(FILE *f, String filename, String_Map *map, SizeU map_cap){
|
||||
Arena *scratch = arena_begin_scratch();
|
||||
String file = os_read_file(scratch, lit("token_array.c"));
|
||||
Token_Array array = lex_stream(scratch, file, lit("token_array.c"));
|
||||
for(Token *t = token_array_iter_begin(&array); t; t = token_array_iter_next(&array)){
|
||||
String file = os_read_file(scratch, filename);
|
||||
Token_Array array = lex_stream(scratch, file, filename);
|
||||
for(Token *t = token_array_iter_begin(&array); t->kind != TK_End; t = token_array_iter_next(&array)){
|
||||
String string = t->string;
|
||||
for(SizeU i = 0; i < map_cap; i++){
|
||||
if(string_compare(string, map[i].replace)){
|
||||
string = map[i].with;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(f, "%.*s", (int)t->len, t->str);
|
||||
|
||||
fprintf(f, "%.*s", (int)string.len, string.str);
|
||||
if(t->kind == TK_OpenBrace) fprintf(f, "\n");
|
||||
if(t->kind == TK_CloseBrace && token_array_iter_peek(&array, 0)->kind != TK_Semicolon) fprintf(f, "\n");
|
||||
if(t->kind == TK_Semicolon) fprintf(f, "\n");
|
||||
if(t->kind == TK_Keyword) fprintf(f, " ");
|
||||
if(t[0].kind == TK_Identifier && token_array_iter_peek(&array, 0)->kind == TK_Identifier) fprintf(f, " ");
|
||||
token_array_iter_peek(&array, 1);
|
||||
}
|
||||
arena_end_scratch();
|
||||
}
|
||||
|
||||
int main(){
|
||||
|
||||
FILE *f = fopen("generated.c", "w");
|
||||
assert(f);
|
||||
String_Map map[] = {
|
||||
{lit("Type"), lit("Decl")},
|
||||
{lit("first"), lit("list_decl.first")},
|
||||
{lit("last"), lit("list_decl.last")},
|
||||
{lit("remove"), lit("decl_list_remove")},
|
||||
{lit("push_front"), lit("decl_dll_list_push_front")},
|
||||
{lit("push"), lit("decl_dll_list_push")},
|
||||
};
|
||||
output_template(f, lit("dllqueue.c"), map, buff_cap(map));
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
49
generated.c
Normal file
49
generated.c
Normal file
@@ -0,0 +1,49 @@
|
||||
function void decl_dll_list_push(Decl*l,Decl*node){
|
||||
if (l->list_decl.first==0){
|
||||
l->list_decl.first=l->list_decl.last=node;
|
||||
node->prev=0;
|
||||
node->next=0;
|
||||
}
|
||||
else {
|
||||
l->list_decl.last->next=node;
|
||||
node->prev=l->list_decl.last;
|
||||
node->next=0;
|
||||
l->list_decl.last=node;
|
||||
}
|
||||
node->parent=l;
|
||||
}
|
||||
function void decl_dll_list_push_front(Decl*l,Decl*node){
|
||||
if (l->list_decl.first==0){
|
||||
l->list_decl.first=l->list_decl.last=node;
|
||||
node->prev=0;
|
||||
node->next=0;
|
||||
}
|
||||
else {
|
||||
node->next=l->list_decl.first;
|
||||
l->list_decl.first->prev=node;
|
||||
node->prev=0;
|
||||
l->list_decl.first=node;
|
||||
}
|
||||
node->parent=l;
|
||||
}
|
||||
function void decl_list_remove(Decl*l,Decl*node){
|
||||
if (l->list_decl.first==l->list_decl.last){
|
||||
assert(node==l->list_decl.last);
|
||||
l->list_decl.first=l->list_decl.last=0;
|
||||
}
|
||||
else if (l->list_decl.last==node){
|
||||
l->list_decl.last=l->list_decl.last->prev;
|
||||
l->list_decl.last->next=0;
|
||||
}
|
||||
else if (l->list_decl.first==node){
|
||||
l->list_decl.first=l->list_decl.first->next;
|
||||
l->list_decl.first->prev=0;
|
||||
}
|
||||
else {
|
||||
node->prev->next=node->next;
|
||||
node->next->prev=node->prev;
|
||||
}
|
||||
node->parent=0;
|
||||
node->prev=0;
|
||||
node->next=0;
|
||||
}
|
||||
356
new_ast.c
356
new_ast.c
@@ -4,11 +4,86 @@ typedef struct Decl Decl;
|
||||
typedef struct Stmt Stmt;
|
||||
typedef struct Stmt_If Stmt_If;
|
||||
typedef struct Typespec Typespec;
|
||||
typedef struct Typespec_Function_Arg Typespec_Function_Arg;
|
||||
typedef struct Decl_Enum_Child Decl_Enum_Child;
|
||||
typedef struct Decl_Function_Arg Decl_Function_Arg;
|
||||
typedef struct Expr_Compound_Field Expr_Compound_Field;
|
||||
|
||||
typedef struct AST AST;
|
||||
typedef struct AST_Parent AST_Parent;
|
||||
|
||||
typedef enum AST_Kind{
|
||||
AST_None,
|
||||
|
||||
AST_Decl_Struct, //
|
||||
AST_Decl_SubStruct,
|
||||
AST_Decl_SubUnion,
|
||||
AST_Decl_Union,
|
||||
AST_Decl_Enum,
|
||||
AST_Decl_Note,
|
||||
AST_Decl_Func,
|
||||
AST_List,
|
||||
AST_Stmt_If,
|
||||
AST_Stmt_Decl,
|
||||
AST_Stmt_Expr,
|
||||
AST_Stmt_Return,
|
||||
AST_Stmt_For,
|
||||
AST_FirstParent = AST_Decl_Struct,
|
||||
AST_LastParent = AST_Stmt_For,
|
||||
|
||||
AST_Decl_Func_Arg,
|
||||
|
||||
AST_Decl_Variable,
|
||||
}AST_Kind;
|
||||
|
||||
#define AST_FIELDS AST *next, *prev; AST *notes; AST_Parent *parent; Token *pos; AST_Kind kind
|
||||
#define AST_PARENT_FIELDS AST *first, *last
|
||||
#define AST_UNION union{ struct{ AST_FIELDS; }; AST ast; }
|
||||
#define AST_PARENT_UNION union{ struct{ AST_PARENT_FIELDS; }; AST_Parent child; }
|
||||
|
||||
struct AST{
|
||||
AST_FIELDS;
|
||||
};
|
||||
|
||||
typedef struct AST_Parent{
|
||||
AST_UNION;
|
||||
AST_PARENT_FIELDS;
|
||||
} AST_Parent;
|
||||
|
||||
typedef struct AST_Note{
|
||||
AST_PARENT_UNION;
|
||||
Intern_String name;
|
||||
Expr *expr;
|
||||
}AST_Note;
|
||||
|
||||
typedef struct Decl_Struct{
|
||||
AST_PARENT_UNION;
|
||||
Intern_String name;
|
||||
}Decl_Struct;
|
||||
|
||||
typedef struct Decl_Func_Arg{
|
||||
AST_UNION;
|
||||
Intern_String name;
|
||||
Typespec *typespec;
|
||||
}Decl_Func_Arg;
|
||||
|
||||
typedef struct AST_Decl_Enum_Child{
|
||||
AST_UNION;
|
||||
Intern_String name;
|
||||
Expr *expr;
|
||||
}AST_Decl_Enum_Child;
|
||||
|
||||
typedef struct Decl_Enum{
|
||||
AST_PARENT_UNION;
|
||||
Typespec *typespec;
|
||||
}Decl_Enum;
|
||||
|
||||
typedef struct Decl_Func{
|
||||
AST_PARENT_UNION;
|
||||
Typespec *ret;
|
||||
AST *body;
|
||||
}Decl_Func;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Expressions
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -168,11 +243,13 @@ typedef enum Decl_Kind{
|
||||
DECL_SubUnion,
|
||||
DECL_Enum,
|
||||
DECL_Variable,
|
||||
DECL_Const,
|
||||
DECL_Typedef,
|
||||
DECL_Function,
|
||||
DECL_List,
|
||||
}Decl_Kind;
|
||||
|
||||
|
||||
struct Decl{
|
||||
Decl_Kind kind;
|
||||
Decl *next;
|
||||
@@ -197,11 +274,11 @@ struct Decl{
|
||||
Decl *last;
|
||||
}struct_decl;
|
||||
struct{
|
||||
Typespec *type;
|
||||
Typespec *typespec;
|
||||
Expr *expr;
|
||||
}var_decl;
|
||||
struct{
|
||||
Typespec *type;
|
||||
Typespec *typespec;
|
||||
}typedef_decl;
|
||||
struct{
|
||||
Decl_Function_Arg *first;
|
||||
@@ -570,7 +647,15 @@ decl_struct(Arena *p, Decl_Kind kind, Token *pos, Intern_String name){
|
||||
function Decl *
|
||||
decl_typedef(Arena *p, Token *pos, Intern_String name, Typespec *type){
|
||||
Decl *result = decl_new(p, DECL_Typedef, pos, name);
|
||||
result->typedef_decl.type = type;
|
||||
result->typedef_decl.typespec = type;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Decl *
|
||||
decl_const(Arena *arena, Token *pos, Intern_String name, Expr *expr, Typespec *typespec){
|
||||
Decl *result = decl_new(arena, DECL_Const, pos, name);
|
||||
result->var_decl.expr = expr;
|
||||
result->var_decl.typespec = typespec;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -584,7 +669,7 @@ decl_enum(Arena *p, Token *pos, Intern_String name, Typespec *typespec){
|
||||
function Decl *
|
||||
decl_variable(Arena *p, Token *pos, Intern_String name, Typespec *typespec, Expr *expr){
|
||||
Decl *result = decl_new(p, DECL_Variable, pos, name);
|
||||
result->var_decl.type = typespec;
|
||||
result->var_decl.typespec = typespec;
|
||||
result->var_decl.expr = expr;
|
||||
return result;
|
||||
}
|
||||
@@ -630,108 +715,203 @@ decl_list_push(Decl *parent, Decl *child){
|
||||
SLLQueuePush(parent->list_decl.first, parent->list_decl.last, child);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Statements
|
||||
//-----------------------------------------------------------------------------
|
||||
function Stmt *
|
||||
stmt_new(Arena *p, Stmt_Kind kind, Token *pos){
|
||||
Stmt *result = arena_push_struct(p, Stmt);
|
||||
result->kind = kind;
|
||||
result->pos = pos;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Stmt *
|
||||
stmt_decl(Arena *p, Token *pos, Decl *decl){
|
||||
Stmt *result = stmt_new(p, STMT_Decl, pos);
|
||||
result->decl = decl;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Stmt *
|
||||
stmt_expr(Arena *p, Token *pos, Expr *expr){
|
||||
Stmt *result = stmt_new(p, STMT_Expr, pos);
|
||||
result->expr = expr;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Stmt *
|
||||
stmt_list(Arena *p, Token *pos){
|
||||
Stmt *result = stmt_new(p, STMT_List, pos);
|
||||
return result;
|
||||
}
|
||||
|
||||
function Stmt *
|
||||
stmt_return(Arena *p, Token *pos, Expr *expr){
|
||||
Stmt *result = stmt_new(p, STMT_Return, pos);
|
||||
result->ret.expr = expr;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Stmt *
|
||||
stmt_if(Arena *p, Token *pos, Stmt *body, Expr *cond){
|
||||
Stmt *result = stmt_new(p, STMT_If, pos);
|
||||
result->stmt_if.cond = cond;
|
||||
result->stmt_if.body = body;
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
stmt_push(Stmt *stmt, Stmt *child){
|
||||
SLLQueuePush(stmt->list.first, stmt->list.last, child);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Double linked list
|
||||
//-----------------------------------------------------------------------------
|
||||
function void
|
||||
decl_dll_list_push(Decl *l, Decl *node){
|
||||
if(l->list_decl.first == 0){
|
||||
l->list_decl.first = l->list_decl.last = node;
|
||||
node->prev = 0;
|
||||
node->next = 0;
|
||||
}
|
||||
else{
|
||||
l->list_decl.last->next = node;
|
||||
node->prev = l->list_decl.last;
|
||||
node->next = 0;
|
||||
l->list_decl.last = node;
|
||||
}
|
||||
node->parent = l;
|
||||
}
|
||||
|
||||
function void
|
||||
decl_dll_list_push_front(Decl *l, Decl *node){
|
||||
if(l->list_decl.first == 0){
|
||||
l->list_decl.first = l->list_decl.last = node;
|
||||
node->prev = 0;
|
||||
node->next = 0;
|
||||
}
|
||||
else{
|
||||
node->next = l->list_decl.first;
|
||||
l->list_decl.first->prev = node;
|
||||
node->prev = 0;
|
||||
l->list_decl.first = node;
|
||||
}
|
||||
node->parent = l;
|
||||
}
|
||||
|
||||
function void
|
||||
decl_list_remove(Decl *l, Decl *node){
|
||||
if(l->list_decl.first == l->list_decl.last){
|
||||
assert(node == l->list_decl.last);
|
||||
l->list_decl.first = l->list_decl.last = 0;
|
||||
}
|
||||
else if(l->list_decl.last == node){
|
||||
l->list_decl.last = l->list_decl.last->prev;
|
||||
l->list_decl.last->next = 0;
|
||||
}
|
||||
else if(l->list_decl.first == node){
|
||||
l->list_decl.first = l->list_decl.first->next;
|
||||
l->list_decl.first->prev = 0;
|
||||
}
|
||||
else{
|
||||
node->prev->next = node->next;
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
|
||||
node->parent = 0;
|
||||
node->prev = 0;
|
||||
node->next = 0;
|
||||
}
|
||||
|
||||
function void
|
||||
list_print(Decl *decls){
|
||||
|
||||
list_print(AST_Parent *decls){
|
||||
printf("\n");
|
||||
printf("next:");
|
||||
for(Decl *n = decls[0].list_decl.first; n; n=n->next){
|
||||
for(AST *n = decls->first; n; n=n->next){
|
||||
printf("%d", n->kind);
|
||||
}
|
||||
printf("prev:");
|
||||
for(Decl *n = decls[0].list_decl.last; n; n=n->prev){
|
||||
for(AST *n = decls->last; n; n=n->prev){
|
||||
printf("%d", n->kind);
|
||||
}
|
||||
printf("parent:");
|
||||
for(Decl *n = decls[0].list_decl.first; n; n=n->next){
|
||||
for(AST *n = decls->first; n; n=n->next){
|
||||
printf("%d", n->parent->kind);
|
||||
}
|
||||
}
|
||||
|
||||
function void
|
||||
ast_remove(AST *node){
|
||||
AST_Parent *l = node->parent;
|
||||
assert(l);
|
||||
if (l->first==l->last){
|
||||
assert(node==l->last);
|
||||
l->first=l->last=0;
|
||||
}
|
||||
else if (l->last==node){
|
||||
l->last=l->last->prev;
|
||||
l->last->next=0;
|
||||
}
|
||||
else if (l->first==node){
|
||||
l->first=l->first->next;
|
||||
l->first->prev=0;
|
||||
}
|
||||
else {
|
||||
node->prev->next=node->next;
|
||||
node->next->prev=node->prev;
|
||||
}
|
||||
node->parent=0;
|
||||
node->prev=0;
|
||||
node->next=0;
|
||||
}
|
||||
|
||||
function void
|
||||
ast_push_first(AST_Parent *l, AST *node){
|
||||
if (l->first==0){
|
||||
l->first=l->last=node;
|
||||
node->prev=0;
|
||||
node->next=0;
|
||||
}
|
||||
else {
|
||||
l->last->next=node;
|
||||
node->prev=l->last;
|
||||
node->next=0;
|
||||
l->last=node;
|
||||
}
|
||||
node->parent=l;
|
||||
}
|
||||
|
||||
function void
|
||||
ast_push_last(AST_Parent *l, AST *node){
|
||||
if(l->first == 0){
|
||||
l->first = l->last = node;
|
||||
node->prev = 0;
|
||||
node->next = 0;
|
||||
}
|
||||
else {
|
||||
node->next = l->first;
|
||||
l->first->prev = node;
|
||||
node->prev = 0;
|
||||
l->first = node;
|
||||
}
|
||||
node->parent = l;
|
||||
}
|
||||
|
||||
function void
|
||||
ast_test(){
|
||||
Decl decls[16] = {0};
|
||||
decls[0].kind = 9;
|
||||
decls[1].kind = 1;
|
||||
decls[2].kind = 2;
|
||||
decls[3].kind = 3;
|
||||
decls[4].kind = 4;
|
||||
decl_dll_list_push(decls, decls+1);
|
||||
decl_dll_list_push(decls, decls+2);
|
||||
decl_dll_list_push(decls, decls+3);
|
||||
decl_dll_list_push_front(decls, decls+4);
|
||||
ast_push_after(AST *in_list, AST *node){
|
||||
AST_Parent *parent = in_list->parent;
|
||||
assert(parent);
|
||||
assert(parent->first && parent->last);
|
||||
|
||||
//list_print(decls);
|
||||
decl_list_remove(decls, decls+1);
|
||||
//list_print(decls);
|
||||
decl_list_remove(decls, decls+2);
|
||||
//list_print(decls);
|
||||
decl_list_remove(decls, decls+3);
|
||||
//list_print(decls);
|
||||
decl_list_remove(decls, decls+4);
|
||||
//list_print(decls);
|
||||
assert(decls[0].list_decl.first == 0);
|
||||
assert(decls[0].list_decl.last == 0);
|
||||
node->prev = in_list;
|
||||
if(in_list == parent->last){
|
||||
in_list->next = node;
|
||||
parent->last = node;
|
||||
}
|
||||
else {
|
||||
node->next = in_list->next;
|
||||
in_list->next = node;
|
||||
node->next->prev = node;
|
||||
}
|
||||
node->parent=parent;
|
||||
}
|
||||
|
||||
function void
|
||||
ast_push_before(AST *in_list, AST *node){
|
||||
AST_Parent *parent = in_list->parent;
|
||||
assert(parent);
|
||||
assert(parent->first && parent->last);
|
||||
|
||||
node->next = in_list;
|
||||
if(parent->first == in_list){
|
||||
in_list->prev = node;
|
||||
parent->first = node;
|
||||
}
|
||||
else{
|
||||
node->prev = in_list->prev;
|
||||
in_list->prev = node;
|
||||
node->prev->next = node;
|
||||
}
|
||||
node->parent = parent;
|
||||
}
|
||||
|
||||
|
||||
function void
|
||||
ast_test(){
|
||||
printf("\nAST_Size = %u", (U32)sizeof(AST));
|
||||
printf("\nAST_Struct_Size = %u", (U32)sizeof(Decl_Struct));
|
||||
|
||||
AST_Parent parent = {0};
|
||||
AST decls[16] = {0};
|
||||
parent.kind = 0;
|
||||
for(int i = 0; i < buff_cap(decls); i++){
|
||||
decls[i].kind = i+1;
|
||||
}
|
||||
|
||||
ast_push_first(&parent, decls);
|
||||
ast_push_first(&parent, decls+1);
|
||||
ast_push_first(&parent, decls+2);
|
||||
ast_push_before(decls, decls+3);
|
||||
ast_push_before(decls, decls+4);
|
||||
ast_push_after(decls, decls+5);
|
||||
ast_push_after(decls+5, decls+6);
|
||||
|
||||
//list_print(&parent);
|
||||
ast_remove(decls);
|
||||
ast_remove(decls+1);
|
||||
ast_remove(decls+2);
|
||||
ast_remove(decls+3);
|
||||
ast_remove(decls+4);
|
||||
ast_remove(decls+5);
|
||||
ast_remove(decls+6);
|
||||
assert(parent.first == 0);
|
||||
assert(parent.last == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ global Intern_String keyword_else;
|
||||
global Intern_String keyword_size_type;
|
||||
global Intern_String keyword_size_expr;
|
||||
global Intern_String keyword_const;
|
||||
global Intern_String keyword_typedef;
|
||||
global Intern_String keyword_return;
|
||||
global Intern_String keyword_typeof;
|
||||
global Intern_String keyword_while;
|
||||
global Intern_String keyword_switch;
|
||||
@@ -31,7 +33,9 @@ init_default_keywords(Intern_Table *t){
|
||||
keyword_typeof = intern_string(t, lit("typeof"));
|
||||
keyword_const = intern_string(t, lit("const"));
|
||||
keyword_while = intern_string(t, lit("while"));
|
||||
keyword_return = intern_string(t, lit("return"));
|
||||
keyword_switch = intern_string(t, lit("switch"));
|
||||
keyword_typedef = intern_string(t, lit("typedef"));
|
||||
keyword_case = intern_string(t, lit("case"));
|
||||
keyword_struct = intern_string(t, lit("struct"));
|
||||
keyword_enum = intern_string(t, lit("enum"));
|
||||
|
||||
169
new_parse.c
169
new_parse.c
@@ -31,7 +31,7 @@ parser_push_error(Parser *p, Token *token, char *str, ...){
|
||||
|
||||
// @Note(Krzosa): Print nice error message
|
||||
{
|
||||
printf("Error: %s %s:%d\n", string.str, token->file.str, (S32)token->line);
|
||||
printf("\nError: %s %s:%d\n", string.str, token->file.str, (S32)token->line);
|
||||
|
||||
// @Note(Krzosa): Print error line
|
||||
{
|
||||
@@ -171,7 +171,6 @@ Compound literals
|
||||
- { }
|
||||
|
||||
*/
|
||||
|
||||
function Expr_Compound_Field *
|
||||
parse_expr_compound_field(Parser *p){
|
||||
Token *token = token_get(p);
|
||||
@@ -554,7 +553,6 @@ name::const = 4254;
|
||||
// data: [24]U32;
|
||||
// }
|
||||
// }
|
||||
|
||||
*/
|
||||
function void
|
||||
parse_note_list(Parser *p, Note *parent) {
|
||||
@@ -602,34 +600,37 @@ parse_assign_expr(Parser *p){
|
||||
}
|
||||
|
||||
function Typespec *
|
||||
parse_optional_type(Parser *p){
|
||||
parse_optional_type(Parser *p, Intern_String type){
|
||||
Typespec *result = 0;
|
||||
if(token_match(p, TK_Colon)){
|
||||
result = parse_typespec(p);
|
||||
}
|
||||
else{
|
||||
result = typespec_name(p->arena, token_get(p), intern_int);
|
||||
result = typespec_name(p->arena, token_get(p), type);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function Decl *
|
||||
parse_enum(Parser *p, Token *name){
|
||||
Typespec *typespec = parse_optional_type(p);
|
||||
Typespec *typespec = parse_optional_type(p, intern_int);
|
||||
Decl *result = decl_enum(p->arena, name, name->intern_val, typespec);
|
||||
token_expect(p, TK_OpenBrace);
|
||||
do{
|
||||
do {
|
||||
Note notes = parse_notes(p);
|
||||
Token *val = token_expect(p, TK_Identifier);
|
||||
Expr *expr = parse_assign_expr(p);
|
||||
decl_enum_push(p->arena, result, val, val->intern_val, expr, ¬es);
|
||||
} while(token_match(p, TK_Comma));
|
||||
if(!token_match(p, TK_Comma)){
|
||||
break;
|
||||
}
|
||||
}while(!token_is(p, TK_CloseBrace));
|
||||
token_expect(p, TK_CloseBrace);
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
parse_var_decl(Parser *p, Decl *parent, Token *name){
|
||||
parse_var_decl(Parser *p, Decl *parent, Token *name, Note *notes){
|
||||
Token *name_stack[64];
|
||||
S64 name_stack_len = 0;
|
||||
name_stack[name_stack_len++] = name;
|
||||
@@ -640,6 +641,7 @@ parse_var_decl(Parser *p, Decl *parent, Token *name){
|
||||
token_expect(p, TK_Semicolon);
|
||||
for(S64 i = 0; i < name_stack_len; i++){
|
||||
Decl *decl = decl_variable(p->arena, name_stack[i], name_stack[i]->intern_val, typespec, 0);
|
||||
decl_pass_notes(decl, notes);
|
||||
decl_struct_push(parent, decl);
|
||||
}
|
||||
}
|
||||
@@ -651,35 +653,38 @@ parse_struct(Parser *p, Token *name, Decl_Kind struct_kind){
|
||||
Decl *result = decl_struct(p->arena, struct_kind, token, intern_name);
|
||||
token_expect(p, TK_OpenBrace);
|
||||
do {
|
||||
Note notes = parse_notes(p);
|
||||
Token *token = token_get(p);
|
||||
if(token_match_keyword(p, keyword_union)){
|
||||
Decl *decl = parse_struct(p, 0, DECL_SubUnion);
|
||||
decl_pass_notes(decl, ¬es);
|
||||
decl_struct_push(result, decl);
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_struct)){
|
||||
Decl *decl = parse_struct(p, 0, DECL_SubStruct);
|
||||
decl_pass_notes(decl, ¬es);
|
||||
decl_struct_push(result, decl);
|
||||
}
|
||||
else if(token_match(p, TK_Identifier)){
|
||||
if(token_is(p, TK_Colon)){
|
||||
if(token_peek_is_keyword(p, keyword_union, 1)){
|
||||
token_next(p);
|
||||
token_next(p);
|
||||
token_next(p); token_next(p);
|
||||
Decl *decl = parse_struct(p, token, DECL_SubUnion);
|
||||
decl_pass_notes(decl, ¬es);
|
||||
decl_struct_push(result, decl);
|
||||
}
|
||||
else if(token_peek_is_keyword(p, keyword_struct, 1)){
|
||||
token_next(p);
|
||||
token_next(p);
|
||||
token_next(p); token_next(p);
|
||||
Decl *decl = parse_struct(p, token, DECL_SubStruct);
|
||||
decl_pass_notes(decl, ¬es);
|
||||
decl_struct_push(result, decl);
|
||||
}
|
||||
else{
|
||||
parse_var_decl(p, result, token);
|
||||
parse_var_decl(p, result, token, ¬es);
|
||||
}
|
||||
}
|
||||
else{
|
||||
parse_var_decl(p, result, token);
|
||||
parse_var_decl(p, result, token, ¬es);
|
||||
}
|
||||
}
|
||||
else{
|
||||
@@ -690,9 +695,47 @@ parse_struct(Parser *p, Token *name, Decl_Kind struct_kind){
|
||||
}
|
||||
|
||||
function Decl *
|
||||
parse_decl(Parser *p){
|
||||
Decl *result = 0;
|
||||
parse_typedef(Parser *p, Token *name){
|
||||
token_expect(p, TK_Assign);
|
||||
Typespec *typespec = parse_typespec(p);
|
||||
token_expect(p, TK_Semicolon);
|
||||
Decl *result = decl_typedef(p->arena, name, name->intern_val, typespec);
|
||||
return result;
|
||||
}
|
||||
|
||||
function Decl *
|
||||
parse_const(Parser *p, Token *name){
|
||||
Typespec *typespec = 0;
|
||||
if(token_match(p, TK_Colon))
|
||||
typespec = parse_typespec(p);
|
||||
token_expect(p, TK_Assign);
|
||||
Expr *expr = parse_expr(p);
|
||||
token_expect(p, TK_Semicolon);
|
||||
Decl *result = decl_const(p->arena, name, name->intern_val, expr, typespec);
|
||||
return result;
|
||||
}
|
||||
|
||||
function Decl *
|
||||
parse_function(Parser *p, Token *name){
|
||||
Decl *result = decl_function(p->arena, name, name->intern_val, 0);
|
||||
if(!token_is(p, TK_CloseParen)){
|
||||
do{
|
||||
name = token_expect(p, TK_Identifier);
|
||||
token_expect(p, TK_Colon);
|
||||
Typespec *typespec = parse_typespec(p);
|
||||
decl_func_push(p->arena, result, name, name->intern_val, typespec);
|
||||
} while(token_match(p, TK_Comma));
|
||||
}
|
||||
token_expect(p, TK_CloseParen);
|
||||
result->func_decl.ret = parse_optional_type(p, intern_void);
|
||||
token_expect(p, TK_Semicolon);
|
||||
return result;
|
||||
}
|
||||
|
||||
function B32
|
||||
parse_decl(Parser *p, Decl *parent){
|
||||
Token *name = 0;
|
||||
Decl *result = 0;
|
||||
Note note = parse_notes(p);
|
||||
if((name = token_match(p, TK_Identifier))){
|
||||
if(token_match(p, TK_DoubleColon)){
|
||||
@@ -706,31 +749,91 @@ parse_decl(Parser *p){
|
||||
else if((token = token_match_keyword(p, keyword_struct))){
|
||||
result = parse_struct(p, name, DECL_Struct);
|
||||
}
|
||||
else if((token = token_match_keyword(p, keyword_typedef))){
|
||||
result = parse_typedef(p, name);
|
||||
}
|
||||
else if((token = token_match_keyword(p, keyword_const))){
|
||||
// Const value
|
||||
result = parse_const(p, name);
|
||||
}
|
||||
else if((token = token_match(p, TK_OpenParen))){
|
||||
// Function
|
||||
result = parse_function(p, name);
|
||||
}
|
||||
else{
|
||||
parser_push_error(p, token_get(p), "Expected token of kind todo:decl_tokens");
|
||||
token = token_get(p);
|
||||
parser_push_error(p, token, "Expected a declaration keyword. Got instead: %s", token_kind_string[token->kind]);
|
||||
}
|
||||
}
|
||||
else{
|
||||
parser_push_error(p, token_get(p), "Expected token of kind '::'");
|
||||
Token *token = token_get(p);
|
||||
parser_push_error(p, token, "Expected a declaration which starts with token '::' got instead"
|
||||
"token '%s'", token_kind_string[token->kind]);
|
||||
}
|
||||
}
|
||||
|
||||
if(result){
|
||||
decl_pass_notes(result, ¬e);
|
||||
decl_list_push(parent, result);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function Decl
|
||||
parse_decls(Parser *p){
|
||||
Decl decl_list = {.kind=DECL_List};
|
||||
while(!token_is(p, TK_End)){
|
||||
B32 success = parse_decl(p, &decl_list);
|
||||
if(!success){
|
||||
parser_push_error(p, token_get(p), "Failed to parse decls, unexpected token!");
|
||||
}
|
||||
}
|
||||
return decl_list;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Statement parsing
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
stmt_list = '{' stmt* '}'
|
||||
stmt =
|
||||
| stmt_list
|
||||
| 'return' expr ';'
|
||||
| 'if' expr stmt_list
|
||||
| 'for' simple_stmt_list ';' expr ';' simple_stmt_list stmt_list
|
||||
| 'for' expr stmt_list
|
||||
| expr assign? ';'
|
||||
//| 'while' expr stmt_or_stmt_list
|
||||
|
||||
*/
|
||||
|
||||
function Stmt *
|
||||
parse_stmt(Parser *p){
|
||||
Note notes = parse_notes(p);
|
||||
Stmt *result = 0;
|
||||
if(token_match_keyword(p, keyword_if)){
|
||||
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_for)){
|
||||
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_while)){
|
||||
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_return)){
|
||||
|
||||
}
|
||||
else if(token_match(p, TK_OpenBrace)){
|
||||
// Scope
|
||||
}
|
||||
else{
|
||||
// Expr
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Test code
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function S64
|
||||
eval_expr(Expr *expr){
|
||||
switch(expr->kind){
|
||||
@@ -875,15 +978,27 @@ parse_test_decls(){
|
||||
};
|
||||
for(SizeU i = 0; i < buff_cap(decls); i++){
|
||||
parser_restream(&p, decls[i], lit("Decl_Test"));
|
||||
Decl *decl = parse_decl(&p);
|
||||
assert(decl);
|
||||
decl_print(decl);
|
||||
Decl decl = parse_decls(&p);
|
||||
assert(decl.list_decl.first);
|
||||
decl_print(decl.list_decl.first);
|
||||
}
|
||||
|
||||
arena_end_scratch();
|
||||
}
|
||||
|
||||
function void
|
||||
parse_test_from_file(){
|
||||
const String FILENAME = lit("test.cc");
|
||||
Arena *scratch = arena_begin_scratch();
|
||||
String file = os_read_file(scratch, FILENAME);
|
||||
Parser p = parser_make_stream(scratch, file, FILENAME);
|
||||
Decl d = parse_decls(&p);
|
||||
decl_print(&d);
|
||||
arena_end_scratch();
|
||||
}
|
||||
|
||||
function void
|
||||
parse_test(){
|
||||
parse_test_expr();
|
||||
parse_test_decls();
|
||||
parse_test_from_file();
|
||||
}
|
||||
19
new_print.c
19
new_print.c
@@ -202,19 +202,32 @@ decl_print(Decl *node){
|
||||
}
|
||||
} break;
|
||||
|
||||
case DECL_Const:
|
||||
case DECL_Variable:{
|
||||
println("%s: ", node->name.s.str);
|
||||
B32 r = typespec_print(node->var_decl.type);
|
||||
if(node->var_decl.typespec) typespec_print(node->var_decl.typespec);
|
||||
print_assign_expr(node->var_decl.expr);
|
||||
if(r) printf(";");
|
||||
} break;
|
||||
|
||||
case DECL_Typedef:{
|
||||
println("typedef %s ", node->name.s.str);
|
||||
typespec_print(node->typedef_decl.type);
|
||||
typespec_print(node->typedef_decl.typespec);
|
||||
printf(";");
|
||||
} break;
|
||||
|
||||
case DECL_Function:{
|
||||
println("");
|
||||
typespec_print(node->func_decl.ret);
|
||||
printf(" %s", node->name.s.str);
|
||||
printf("(");
|
||||
for(Decl_Function_Arg *arg = node->func_decl.first; arg; arg=arg->next){
|
||||
printf("%s: ", arg->name.s.str);
|
||||
typespec_print(arg->typespec);
|
||||
if(arg != node->func_decl.last)
|
||||
printf(", ");
|
||||
}
|
||||
printf(");");
|
||||
} break;
|
||||
|
||||
case DECL_Struct:
|
||||
case DECL_Union :{
|
||||
|
||||
139
test.cc
139
test.cc
@@ -1,57 +1,23 @@
|
||||
#if 0
|
||||
Thing :: const: *U32 = 0;
|
||||
CONST_VAL::const = 185210591;
|
||||
|
||||
|
||||
@register
|
||||
@param_expr(size)
|
||||
@param_type(Type)
|
||||
test::struct{
|
||||
Array_Block::struct{
|
||||
next: Array_Block*;
|
||||
data: Type[size];
|
||||
}
|
||||
|
||||
@inline Array::struct{
|
||||
first: Array_Block;
|
||||
last : Array_Block*;
|
||||
block: S64;
|
||||
len : S64;
|
||||
}
|
||||
|
||||
array_make::(arena: Arena*) Type {
|
||||
thing: Test_Type;
|
||||
result: Type;
|
||||
result.arena = arena;
|
||||
result.last = &result.first;
|
||||
return result;
|
||||
}
|
||||
|
||||
array_push::(array: Array*, item: Type*){
|
||||
if array->len+1 > size{
|
||||
assert(array->len);
|
||||
block: Array_Block* = cast(Thing)arena_push_struct(array->arena, sizeof(:Array_Block));
|
||||
array->last = array->last.next = block;
|
||||
array->len = 0;
|
||||
array->block += 1;
|
||||
}
|
||||
array->last.data[array->len++] = *item;
|
||||
}
|
||||
}
|
||||
new_function::(Thing:[32]U32): U32;
|
||||
|
||||
@test(size = 4096)
|
||||
OpenGL :: struct{
|
||||
glVertexAttribPointer: (GLuint, GLint, GLenum, GLboolean, GLsizei, GLvoid*);
|
||||
glVertexAttribPointer: (GLuint, GLint, GLenum, GLboolean, GLsizei, *GLvoid);
|
||||
glBindTexture: (GLenum, GLuint);
|
||||
glDrawArrays: (GLenum, GLint, GLsizei);
|
||||
|
||||
test_array: int*[10];
|
||||
test_array: [10]*int;
|
||||
|
||||
thing : Things*;
|
||||
thing : *Things;
|
||||
thing_cap: S64;
|
||||
thing_len: S64;
|
||||
}
|
||||
|
||||
OS_Memory::struct{
|
||||
data: void*;
|
||||
data: *void;
|
||||
commit: SizeU;
|
||||
reserve: SizeU;
|
||||
}
|
||||
@@ -63,10 +29,11 @@ Arena::struct{
|
||||
}
|
||||
|
||||
String::struct{
|
||||
str: U8*;
|
||||
str: *U8;
|
||||
len: S64;
|
||||
}
|
||||
Intern_String::typedef String;
|
||||
Intern_String::typedef = String;
|
||||
//CONST_VALUE::const = 121591;
|
||||
|
||||
@stringify
|
||||
@prefix="TK_"
|
||||
@@ -147,12 +114,12 @@ Token::struct{
|
||||
}
|
||||
file:String;
|
||||
line:S64;
|
||||
line_begin:U8*;
|
||||
line_begin:*U8;
|
||||
}
|
||||
|
||||
Lex_Stream::struct{
|
||||
stream: U8*;
|
||||
line_begin: U8*;
|
||||
stream: *U8;
|
||||
line_begin: *U8;
|
||||
filename: String;
|
||||
line: S64;
|
||||
}
|
||||
@@ -172,36 +139,36 @@ Expr_Kind::enum{
|
||||
|
||||
Expr:: struct{
|
||||
kind: Expr_Kind;
|
||||
token: Token*;
|
||||
next : Expr*;
|
||||
token: *Token;
|
||||
next : *Expr;
|
||||
union{
|
||||
cast_val: struct{
|
||||
type: AST_Node*;
|
||||
expr: Expr*;
|
||||
type: *AST_Node;
|
||||
expr: *Expr;
|
||||
}
|
||||
list: struct{
|
||||
first: Expr *;
|
||||
last: Expr *;
|
||||
first: *Expr;
|
||||
last: *Expr;
|
||||
}
|
||||
call: struct{
|
||||
atom: Expr *;
|
||||
list: Expr *;
|
||||
atom: *Expr;
|
||||
list: *Expr;
|
||||
}
|
||||
index: struct{
|
||||
atom: Expr *;
|
||||
index: Expr *;
|
||||
atom: *Expr;
|
||||
index: *Expr;
|
||||
}
|
||||
unary: struct{
|
||||
expr: Expr* ;
|
||||
expr: *Expr ;
|
||||
}
|
||||
binary: struct{
|
||||
left: Expr* ;
|
||||
right: Expr* ;
|
||||
left: *Expr ;
|
||||
right: *Expr ;
|
||||
}
|
||||
ternary: struct{
|
||||
cond: Expr* ;
|
||||
on_true: Expr*;
|
||||
on_false: Expr*;
|
||||
cond: *Expr ;
|
||||
on_true: *Expr;
|
||||
on_false: *Expr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,36 +192,36 @@ AST_Kind::enum{
|
||||
|
||||
AST_Node::struct{
|
||||
kind: AST_Kind;
|
||||
pos : Token*;
|
||||
pos : *Token;
|
||||
name: Intern_String;
|
||||
|
||||
next: AST_Node*;
|
||||
next_scope: AST_Node*;
|
||||
next: *AST_Node;
|
||||
next_scope: *AST_Node;
|
||||
|
||||
first_note: AST_Node*;
|
||||
last_note: AST_Node*;
|
||||
first_note: *AST_Node;
|
||||
last_note: *AST_Node;
|
||||
|
||||
first_child: AST_Node*;
|
||||
last_child: AST_Node*;
|
||||
first_child: *AST_Node;
|
||||
last_child: *AST_Node;
|
||||
union{
|
||||
base_type_size: SizeU;
|
||||
pointer: AST_Node*;
|
||||
typedef_type: AST_Node*;
|
||||
variable_type: AST_Node*;
|
||||
func_return_type: AST_Node*;
|
||||
pointer: *AST_Node;
|
||||
typedef_type: *AST_Node;
|
||||
variable_type: *AST_Node;
|
||||
func_return_type: *AST_Node;
|
||||
}
|
||||
}
|
||||
|
||||
Parser_Error :: struct{
|
||||
next: Parser_Error*;
|
||||
next: *Parser_Error;
|
||||
message: String;
|
||||
token : Token *;
|
||||
token : *Token;
|
||||
}
|
||||
|
||||
Scope :: struct{
|
||||
next : Scope*;
|
||||
first: AST_Node*;
|
||||
last : AST_Node*;
|
||||
next : *Scope;
|
||||
first: *AST_Node;
|
||||
last : *AST_Node;
|
||||
}
|
||||
|
||||
|
||||
@@ -263,21 +230,21 @@ Parser :: struct{
|
||||
intern_table_arena: Arena;
|
||||
symbol_table_arena: Arena;
|
||||
|
||||
scope_free_list: Scope *;
|
||||
scope_stack: Scope *;
|
||||
global_scope: Scope *;
|
||||
scope_free_list: Scope;
|
||||
scope_stack: Scope;
|
||||
global_scope: Scope;
|
||||
|
||||
symbols_inserted: S64;
|
||||
symbols_count: S64;
|
||||
symbols: AST_Node *;
|
||||
symbols: AST_Node;
|
||||
|
||||
interns: Intern_String *;
|
||||
interns: Intern_String;
|
||||
interns_in_bytes: S64;
|
||||
interns_inserted: S64;
|
||||
interns_count: S64;
|
||||
|
||||
first_keyword: U8 *;
|
||||
last_keyword: U8 *;
|
||||
first_keyword: U8;
|
||||
last_keyword: U8;
|
||||
|
||||
//@map(type="sparse") symbols: AST_Node;
|
||||
|
||||
@@ -305,5 +272,3 @@ struct_type_lower_var_name_lower_push(struct_type *parent, var_type *child){
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
@@ -71,6 +71,8 @@ token_array_iter_next(Token_Array *array){
|
||||
|
||||
function Token *
|
||||
token_array_iter_peek(Token_Array *array, S64 i){
|
||||
// @Todo(Krzosa): Simplify, too many calculations here
|
||||
// Why even change state?
|
||||
S64 save_len = array->iter_len;
|
||||
S64 save_block = array->iter_block;
|
||||
Token_Bucket *save_bucket = array->iter_bucket;
|
||||
|
||||
Reference in New Issue
Block a user