688 lines
16 KiB
C
688 lines
16 KiB
C
typedef struct Expr Expr;
|
|
typedef struct Note Note;
|
|
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;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Expressions
|
|
//-----------------------------------------------------------------------------
|
|
typedef enum Expr_Sizeof_Kind{
|
|
SIZEOF_Expr,
|
|
SIZEOF_Type,
|
|
}Expr_Sizeof_Kind;
|
|
|
|
typedef enum Expr_Kind{
|
|
EK_None,
|
|
EK_Int,
|
|
EK_String,
|
|
EK_Identifier,
|
|
EK_Compound,
|
|
EK_Paren,
|
|
EK_PostfixUnary,
|
|
EK_Unary,
|
|
EK_Binary,
|
|
EK_Ternary,
|
|
EK_Cast,
|
|
EK_Field,
|
|
EK_Call,
|
|
EK_Index,
|
|
EK_SizeType,
|
|
EK_SizeExpr,
|
|
} Expr_Kind;
|
|
|
|
typedef enum Expr_Compound_Kind{
|
|
COMPOUND_None,
|
|
COMPOUND_Default,
|
|
COMPOUND_Named,
|
|
COMPOUND_Index,
|
|
}Expr_Compound_Kind;
|
|
|
|
struct Expr_Compound_Field{
|
|
Expr_Compound_Field *next;
|
|
Expr_Compound_Kind kind;
|
|
Token *pos;
|
|
Expr *init;
|
|
union{
|
|
Expr *index;
|
|
Intern_String name;
|
|
};
|
|
};
|
|
|
|
struct Expr {
|
|
Expr_Kind kind;
|
|
Token *token;
|
|
Expr *next;
|
|
union {
|
|
U64 int_val;
|
|
Intern_String intern_val;
|
|
double float_val;
|
|
struct {
|
|
Expr *expr;
|
|
} paren;
|
|
struct {
|
|
Typespec *typespec;
|
|
Expr* expr;
|
|
} cast;
|
|
struct{
|
|
Intern_String name;
|
|
Expr *expr;
|
|
}field;
|
|
|
|
struct{
|
|
Typespec *typespec;
|
|
Expr_Compound_Field *first;
|
|
Expr_Compound_Field *last;
|
|
}compound;
|
|
|
|
struct {
|
|
Expr *atom;
|
|
Expr_Compound_Field *first;
|
|
Expr_Compound_Field *last;
|
|
} call;
|
|
struct{
|
|
|
|
}arg;
|
|
struct {
|
|
Expr *atom;
|
|
Expr *index;
|
|
} index;
|
|
|
|
struct {
|
|
Token_Kind op;
|
|
Expr* expr;
|
|
} unary;
|
|
struct {
|
|
Token_Kind op;
|
|
Expr *expr;
|
|
} postfix_unary;
|
|
struct {
|
|
Token_Kind op;
|
|
Expr* left;
|
|
Expr* right;
|
|
} binary;
|
|
struct {
|
|
Expr* cond;
|
|
Expr* on_true;
|
|
Expr* on_false;
|
|
} ternary;
|
|
|
|
struct{
|
|
Typespec *typespec;
|
|
} size_type;
|
|
|
|
struct{
|
|
Expr *expr;
|
|
} size_expr;
|
|
};
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Type specifiers
|
|
//-----------------------------------------------------------------------------
|
|
typedef enum Typespec_Kind{
|
|
TS_None,
|
|
TS_Name,
|
|
TS_Pointer,
|
|
TS_Array,
|
|
TS_Function,
|
|
TS_NamedArgument,
|
|
}Typespec_Kind;
|
|
|
|
struct Typespec{
|
|
Typespec *next;
|
|
Typespec_Kind kind;
|
|
Token *pos;
|
|
union{
|
|
Typespec *base;
|
|
Intern_String name;
|
|
struct{
|
|
Intern_String name;
|
|
Typespec *base;
|
|
}named;
|
|
struct{
|
|
Typespec *first;
|
|
Typespec *last;
|
|
Typespec *ret;
|
|
}func;
|
|
struct{
|
|
Typespec *base;
|
|
Expr *size;
|
|
}arr;
|
|
};
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Declarations
|
|
//-----------------------------------------------------------------------------
|
|
typedef enum Decl_Kind{
|
|
DECL_None,
|
|
DECL_Struct,
|
|
DECL_Union,
|
|
DECL_Enum,
|
|
DECL_Variable,
|
|
DECL_Typedef,
|
|
DECL_Function,
|
|
DECL_List,
|
|
}Decl_Kind;
|
|
|
|
struct Decl{
|
|
Decl_Kind kind;
|
|
Decl *next;
|
|
B32 is_incomplete;
|
|
|
|
Decl *prev; // Doubly linked list?
|
|
Decl *parent; // ?
|
|
|
|
Intern_String name;
|
|
Token *pos;
|
|
|
|
Note *first_note;
|
|
Note *last_note;
|
|
union{
|
|
struct{
|
|
Decl_Enum_Child *first;
|
|
Decl_Enum_Child *last;
|
|
Typespec *typespec;
|
|
}enum_decl;
|
|
struct{
|
|
Decl *first;
|
|
Decl *last;
|
|
}struct_decl;
|
|
struct{
|
|
Typespec *type;
|
|
Expr *expr;
|
|
}var_decl;
|
|
struct{
|
|
Typespec *type;
|
|
}typedef_decl;
|
|
struct{
|
|
Decl_Function_Arg *first;
|
|
Decl_Function_Arg *last;
|
|
Typespec *ret;
|
|
Stmt *body;
|
|
}func_decl;
|
|
struct{
|
|
Decl *first;
|
|
Decl *last;
|
|
}list_decl;
|
|
};
|
|
};
|
|
|
|
struct Note{
|
|
Token *pos;
|
|
Intern_String name;
|
|
Expr *expr;
|
|
Note *next;
|
|
Note *first;
|
|
Note *last;
|
|
};
|
|
|
|
struct Decl_Function_Arg{
|
|
Decl_Function_Arg *next;
|
|
Token *pos;
|
|
Intern_String name;
|
|
Typespec *typespec;
|
|
};
|
|
|
|
struct Decl_Enum_Child{
|
|
Decl_Enum_Child *next;
|
|
Intern_String name;
|
|
Token *pos;
|
|
Expr *expr;
|
|
Note *first_note;
|
|
Note *last_note;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Statements
|
|
//-----------------------------------------------------------------------------
|
|
typedef enum Stmt_Kind{
|
|
STMT_None,
|
|
STMT_Decl,
|
|
STMT_Expr,
|
|
STMT_List,
|
|
STMT_Return,
|
|
STMT_If,
|
|
STMT_For,
|
|
}Stmt_Kind;
|
|
|
|
struct Stmt_If{
|
|
Stmt_If *next;
|
|
Expr *cond;
|
|
Stmt *body;
|
|
};
|
|
|
|
struct Stmt{
|
|
Stmt_Kind kind;
|
|
Stmt *next;
|
|
Token *pos;
|
|
union{
|
|
Stmt_If stmt_if;
|
|
Decl *decl;
|
|
Expr *expr;
|
|
struct{
|
|
Stmt *first;
|
|
Stmt *last;
|
|
}list;
|
|
struct{
|
|
Expr *expr;
|
|
}ret;
|
|
};
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Expression constructors
|
|
//-----------------------------------------------------------------------------
|
|
function Expr *
|
|
expr_new(Arena *p, Expr_Kind kind, Token *token){
|
|
Expr *expr = arena_push_struct(p, Expr);
|
|
expr->kind = kind;
|
|
expr->token = token;
|
|
return expr;
|
|
}
|
|
|
|
function Expr *
|
|
expr_int(Arena *p, Token *token){
|
|
assert(token->kind == TK_Int);
|
|
Expr *expr = expr_new(p, EK_Int, token);
|
|
expr->int_val = token->int_val;
|
|
return expr;
|
|
}
|
|
|
|
function Expr *
|
|
expr_str(Arena *p, Token *token){
|
|
assert(token->kind == TK_StringLit);
|
|
Expr *expr = expr_new(p, EK_String, token);
|
|
expr->intern_val = token->intern_val;
|
|
return expr;
|
|
}
|
|
|
|
function Expr *
|
|
expr_identifier(Arena *p, Token *token){
|
|
assert(token->kind == TK_Identifier);
|
|
Expr *expr = expr_new(p, EK_Identifier, token);
|
|
expr->intern_val = token->intern_val;
|
|
return expr;
|
|
}
|
|
|
|
function Expr *
|
|
expr_field(Arena *p, Token *token, Expr *inexpr){
|
|
assert(token->kind == TK_Identifier);
|
|
Expr *expr = expr_new(p, EK_Field, token);
|
|
expr->field.expr = inexpr;
|
|
expr->field.name = token->intern_val;
|
|
return expr;
|
|
}
|
|
|
|
function Expr *
|
|
expr_paren(Arena *p, Token *token, Expr *inexpr){
|
|
Expr *expr = expr_new(p, EK_Paren, token);
|
|
expr->paren.expr = inexpr;
|
|
return expr;
|
|
}
|
|
|
|
function Expr *
|
|
expr_postfix_unary(Arena *p, Token *op, Expr *exp){
|
|
Expr *expr = expr_new(p, EK_PostfixUnary, op);
|
|
expr->unary.op = op->kind;
|
|
expr->unary.expr = exp;
|
|
return expr;
|
|
}
|
|
|
|
function Expr *
|
|
expr_unary(Arena *p, Token *op, Expr *exp){
|
|
Expr *expr = expr_new(p, EK_Unary, op);
|
|
expr->unary.op = op->kind;
|
|
expr->unary.expr = exp;
|
|
return expr;
|
|
}
|
|
|
|
function Expr *
|
|
expr_binary(Arena *p, Token *op, Expr *left, Expr *right){
|
|
Expr *expr = expr_new(p, EK_Binary, op);
|
|
expr->binary.op = op->kind;
|
|
expr->binary.left = left;
|
|
expr->binary.right = right;
|
|
return expr;
|
|
}
|
|
|
|
function Expr *
|
|
expr_ternary(Arena *p, Token *op, Expr *cond, Expr *on_true, Expr *on_false){
|
|
Expr *expr = expr_new(p, EK_Ternary, op);
|
|
expr->ternary.cond = cond;
|
|
expr->ternary.on_true = on_true;
|
|
expr->ternary.on_false = on_false;
|
|
return expr;
|
|
}
|
|
|
|
function Expr *
|
|
expr_call(Arena *p, Token *token, Expr *atom){
|
|
Expr *expr = expr_new(p, EK_Call, token);
|
|
expr->call.atom = atom;
|
|
return expr;
|
|
}
|
|
|
|
function Expr *
|
|
expr_index(Arena *p, Token *token, Expr *atom, Expr *index){
|
|
Expr *expr = expr_new(p, EK_Index, token);
|
|
expr->index.atom = atom;
|
|
expr->index.index = index;
|
|
return expr;
|
|
}
|
|
|
|
function Expr *
|
|
expr_cast(Arena *p, Token *token, Typespec *type, Expr *exp){
|
|
Expr *expr = expr_new(p, EK_Cast, token);
|
|
expr->cast.typespec = type;
|
|
expr->cast.expr = exp;
|
|
return expr;
|
|
}
|
|
|
|
function Expr *
|
|
expr_size_type(Arena *p, Token *token, Typespec *type){
|
|
Expr *expr = expr_new(p, EK_SizeType, token);
|
|
expr->size_type.typespec = type;
|
|
return expr;
|
|
}
|
|
|
|
function Expr *
|
|
expr_sizeof_expr(Arena *p, Token *token, Expr *in_expr){
|
|
Expr *expr = expr_new(p, EK_SizeExpr, token);
|
|
expr->size_expr.expr = in_expr;
|
|
return expr;
|
|
}
|
|
|
|
function Expr *
|
|
expr_compound(Arena *arena, Token *pos, Typespec *typespec){
|
|
Expr *result = expr_new(arena, EK_Compound, pos);
|
|
result->compound.typespec = typespec;
|
|
return result;
|
|
}
|
|
|
|
function Expr_Compound_Field *
|
|
expr_compound_new(Arena *arena, Expr_Compound_Kind kind, Token *pos, Expr *init){
|
|
Expr_Compound_Field *result = arena_push_struct(arena, Expr_Compound_Field);
|
|
result->kind = kind;
|
|
result->pos = pos;
|
|
result->init = init;
|
|
return result;
|
|
}
|
|
|
|
function Expr_Compound_Field *
|
|
expr_compound_default(Arena *arena, Token *pos, Expr *init){
|
|
Expr_Compound_Field *result = expr_compound_new(arena, COMPOUND_Default, pos, init);
|
|
return result;
|
|
}
|
|
|
|
function Expr_Compound_Field *
|
|
expr_compound_named(Arena *arena, Token *pos, Intern_String name, Expr *init){
|
|
Expr_Compound_Field *result = expr_compound_new(arena, COMPOUND_Named, pos, init);
|
|
result->name = name;
|
|
return result;
|
|
}
|
|
|
|
function Expr_Compound_Field *
|
|
expr_compound_index(Arena *arena, Token *pos, Expr *index, Expr *init){
|
|
Expr_Compound_Field *result = expr_compound_new(arena, COMPOUND_Index, pos, init);
|
|
result->index = index;
|
|
return result;
|
|
}
|
|
|
|
function void
|
|
expr_call_push(Expr *list, Expr_Compound_Field *field){
|
|
SLLQueuePush(list->call.first, list->call.last, field);
|
|
}
|
|
|
|
function void
|
|
expr_compound_push(Expr *list, Expr_Compound_Field *field){
|
|
SLLQueuePush(list->compound.first, list->compound.last, field);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Type specifier constructors
|
|
//-----------------------------------------------------------------------------
|
|
function Typespec *
|
|
typespec_new(Arena *p, Typespec_Kind kind, Token *pos){
|
|
Typespec *result = arena_push_struct(p, Typespec);
|
|
result->kind = kind;
|
|
result->pos = pos;
|
|
return result;
|
|
}
|
|
|
|
function Typespec *
|
|
typespec_name(Arena *p, Token *pos, Intern_String name){
|
|
Typespec *result = typespec_new(p, TS_Name, pos);
|
|
result->name = name;
|
|
return result;
|
|
}
|
|
|
|
function Typespec *
|
|
typespec_pointer(Arena *p, Token *pos, Typespec *base){
|
|
Typespec *result = typespec_new(p, TS_Pointer, pos);
|
|
result->base = base;
|
|
return result;
|
|
}
|
|
|
|
function Typespec *
|
|
typespec_array(Arena *p, Token *pos, Typespec *base, Expr *size){
|
|
Typespec *result = typespec_new(p, TS_Array, pos);
|
|
result->arr.base = base;
|
|
result->arr.size = size;
|
|
return result;
|
|
}
|
|
|
|
function Typespec *
|
|
typespec_function(Arena *p, Token *pos, Typespec *ret){
|
|
Typespec *result = typespec_new(p, TS_Function, pos);
|
|
result->func.ret = ret;
|
|
return result;
|
|
}
|
|
|
|
function Typespec *
|
|
typespec_named_argument(Arena *arena, Token *pos, Typespec *typespec, Intern_String name){
|
|
Typespec *result = typespec_new(arena, TS_NamedArgument, pos);
|
|
result->named.base = typespec;
|
|
result->named.name = name;
|
|
return result;
|
|
}
|
|
|
|
function void
|
|
typespec_function_push(Typespec *func, Typespec *arg){
|
|
SLLQueuePush(func->func.first, func->func.last, arg);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Declarations
|
|
//-----------------------------------------------------------------------------
|
|
function Decl *
|
|
decl_new(Arena *p, Decl_Kind kind, Token *pos, Intern_String name){
|
|
Decl *result = arena_push_struct(p, Decl);
|
|
result->kind = kind;
|
|
result->pos = pos;
|
|
result->name = name;
|
|
return result;
|
|
}
|
|
|
|
function Decl *
|
|
decl_struct(Arena *p, Decl_Kind kind, Token *pos, Intern_String name){
|
|
assert(kind == DECL_Struct || kind == DECL_Union);
|
|
Decl *result = decl_new(p, kind, pos, name);
|
|
return result;
|
|
}
|
|
|
|
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;
|
|
return result;
|
|
}
|
|
|
|
function Decl *
|
|
decl_enum(Arena *p, Token *pos, Intern_String name, Typespec *typespec){
|
|
Decl *result = decl_new(p, DECL_Enum, pos, name);
|
|
result->enum_decl.typespec = typespec;
|
|
return result;
|
|
}
|
|
|
|
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.expr = expr;
|
|
return result;
|
|
}
|
|
|
|
function Decl *
|
|
decl_function(Arena *p, Token *pos, Intern_String name, Typespec *ret){
|
|
Decl *result = decl_new(p, DECL_Function, pos, name);
|
|
result->func_decl.ret = ret;
|
|
return result;
|
|
}
|
|
|
|
function void
|
|
decl_func_push(Arena *p, Decl *parent, Token *pos, Intern_String name, Typespec *type){
|
|
assert(parent->kind == DECL_Function);
|
|
Decl_Function_Arg *result = arena_push_struct(p, Decl_Function_Arg);
|
|
result->name = name;
|
|
result->typespec = type;
|
|
result->pos = pos;
|
|
SLLQueuePush(parent->func_decl.first, parent->func_decl.last, result);
|
|
}
|
|
|
|
function void
|
|
decl_enum_push(Arena *p, Decl *parent, Token *pos, Intern_String name, Expr *expr, Note *notes){
|
|
assert(parent->kind == DECL_Enum);
|
|
Decl_Enum_Child *child = arena_push_struct(p, Decl_Enum_Child);
|
|
child->pos = pos;
|
|
child->name = name;
|
|
child->expr = expr;
|
|
child->first_note = notes->first;
|
|
child->last_note = notes->last;
|
|
SLLQueuePush(parent->enum_decl.first, parent->enum_decl.last, child);
|
|
}
|
|
|
|
function void
|
|
decl_struct_push(Decl *parent, Decl *child){
|
|
assert(parent->kind == DECL_Struct || parent->kind == DECL_Union);
|
|
SLLQueuePush(parent->struct_decl.first, parent->struct_decl.last, child);
|
|
}
|
|
|
|
function void
|
|
decl_list_push(Decl *parent, Decl *child){
|
|
assert(parent->kind == DECL_List);
|
|
SLLQueuePush(parent->list_decl.first, parent->list_decl.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){
|
|
|
|
printf("next:");
|
|
for(Decl *n = decls[0].list_decl.first; n; n=n->next){
|
|
printf("%d", n->kind);
|
|
}
|
|
printf("prev:");
|
|
for(Decl *n = decls[0].list_decl.last; n; n=n->prev){
|
|
printf("%d", n->kind);
|
|
}
|
|
printf("parent:");
|
|
for(Decl *n = decls[0].list_decl.first; n; n=n->next){
|
|
printf("%d", n->parent->kind);
|
|
}
|
|
}
|
|
|
|
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);
|
|
|
|
//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);
|
|
}
|
|
|
|
|