C codegen

This commit is contained in:
Krzosa Karol
2022-05-03 20:08:13 +02:00
parent 8c04044ea2
commit 557dde1936
11 changed files with 573 additions and 281 deletions

74
ast.c
View File

@@ -1,4 +1,6 @@
//-----------------------------------------------------------------------------
// Decls
//-----------------------------------------------------------------------------
function Decl * function Decl *
decl_new(Parser *p, Decl_Kind kind, Token *pos, Intern_String name){ decl_new(Parser *p, Decl_Kind kind, Token *pos, Intern_String name){
Decl *result = arena_push_struct(&p->main_arena, Decl); Decl *result = arena_push_struct(&p->main_arena, Decl);
@@ -9,9 +11,10 @@ decl_new(Parser *p, Decl_Kind kind, Token *pos, Intern_String name){
} }
function Decl * function Decl *
decl_struct(Parser *p, Decl_Kind kind, Token *pos, Intern_String name){ decl_struct(Parser *p, Decl_Kind kind, Token *pos, Intern_String name, Decl_Struct_Kind struct_kind){
assert(kind == DECL_Struct || kind == DECL_Union); assert(kind == DECL_Struct || kind == DECL_Union);
Decl *result = decl_new(p, kind, pos, name); Decl *result = decl_new(p, kind, pos, name);
result->struct_decl.kind = struct_kind;
return result; return result;
} }
@@ -37,6 +40,23 @@ decl_variable(Parser *p, Token *pos, Intern_String name, Typespec *typespec, Exp
return result; return result;
} }
function Decl *
decl_function(Parser *p, Token *pos, Intern_String name, Typespec *ret){
Decl *result = decl_new(p, DECL_Function, pos, name);
result->function_decl.ret = ret;
return result;
}
function void
decl_function_push(Parser *p, Decl *parent, Token *pos, Intern_String name, Typespec *type){
assert(parent->kind == DECL_Function);
Decl_Function_Arg *result = arena_push_struct(&p->main_arena, Decl_Function_Arg);
result->name = name;
result->typespec = type;
result->pos = pos;
SLLQueuePush(parent->function_decl.first, parent->function_decl.last, result);
}
function void function void
decl_enum_push(Parser *p, Decl *parent, Token *pos, Intern_String name, Expr *expr, Note *notes){ decl_enum_push(Parser *p, Decl *parent, Token *pos, Intern_String name, Expr *expr, Note *notes){
assert(parent->kind == DECL_Enum); assert(parent->kind == DECL_Enum);
@@ -61,6 +81,15 @@ decl_list_push(Decl *parent, Decl *child){
SLLQueuePush(parent->list.first, parent->list.last, child); SLLQueuePush(parent->list.first, parent->list.last, child);
} }
//-----------------------------------------------------------------------------
// Notes
//-----------------------------------------------------------------------------
function void
decl_pass_notes(Decl *a, Note *b){
a->first_note = b->first;
a->last_note = b->last;
}
function Note * function Note *
note_push_new(Parser *p, Note *parent, Token *pos, Intern_String name, Expr *expr){ note_push_new(Parser *p, Note *parent, Token *pos, Intern_String name, Expr *expr){
Note *result = arena_push_struct(&p->main_arena, Note); Note *result = arena_push_struct(&p->main_arena, Note);
@@ -71,12 +100,38 @@ note_push_new(Parser *p, Note *parent, Token *pos, Intern_String name, Expr *exp
return result; return result;
} }
function void function Note *
decl_pass_notes(Decl *a, Note *b){ find_note(Note *first, String string){
a->first_note = b->first; for(Note *n = first; n; n=n->next){
a->last_note = b->last; if(string_compare(string, n->name.s)){
return n;
}
}
return 0;
} }
function String
find_string_note(Note *first, String string, String default_string){
Note *note = find_note(first, string);
if(note){
return note->expr->token->intern_val.s;
}
return default_string;
}
function Note *
decl_find_note(Decl *decl, String string){
return find_note(decl->first_note, string);
}
function String
decl_find_string_note(Decl *decl, String string, String default_string){
return find_string_note(decl->first_note, string, default_string);
}
//-----------------------------------------------------------------------------
// Typespec
//-----------------------------------------------------------------------------
function Typespec * function Typespec *
typespec_new(Parser *p, Typespec_Kind kind, Token *pos){ typespec_new(Parser *p, Typespec_Kind kind, Token *pos){
Typespec *result = arena_push_struct(&p->main_arena, Typespec); Typespec *result = arena_push_struct(&p->main_arena, Typespec);
@@ -85,13 +140,6 @@ typespec_new(Parser *p, Typespec_Kind kind, Token *pos){
return result; return result;
} }
function Typespec *
typespec_struct(Parser *p, Token *pos, Decl *aggregate){
Typespec *result = typespec_new(p, TS_Struct, pos);
result->struct_spec = aggregate;
return result;
}
function Typespec * function Typespec *
typespec_name(Parser *p, Token *pos, Intern_String name){ typespec_name(Parser *p, Token *pos, Intern_String name){
Typespec *result = typespec_new(p, TS_Name, pos); Typespec *result = typespec_new(p, TS_Name, pos);

64
ast.h
View File

@@ -1,7 +1,9 @@
typedef struct Decl_Enum_Child Decl_Enum_Child; typedef struct Decl_Enum_Child Decl_Enum_Child;
typedef struct Decl_Function_Arg Decl_Function_Arg;
typedef struct Typespec Typespec; typedef struct Typespec Typespec;
typedef struct Decl Decl; typedef struct Decl Decl;
typedef struct Note Note; typedef struct Note Note;
typedef struct Stmt Stmt;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Type specifier // Type specifier
@@ -12,7 +14,6 @@ typedef enum Typespec_Kind{
TS_Pointer, TS_Pointer,
TS_Array, TS_Array,
TS_Function, TS_Function,
TS_Struct,
}Typespec_Kind; }Typespec_Kind;
struct Typespec{ struct Typespec{
@@ -21,7 +22,6 @@ struct Typespec{
Token *pos; Token *pos;
union{ union{
Intern_String name; Intern_String name;
Decl *struct_spec;
struct{ struct{
Typespec *first; Typespec *first;
Typespec *last; Typespec *last;
@@ -58,9 +58,22 @@ typedef enum Decl_Kind{
DECL_Enum, DECL_Enum,
DECL_Variable, DECL_Variable,
DECL_Typedef, DECL_Typedef,
DECL_Function,
DECL_List, DECL_List,
}Decl_Kind; }Decl_Kind;
typedef enum Decl_Struct_Kind{
STRUCT_Base ,
STRUCT_Nested,
}Decl_Struct_Kind;
struct Decl_Function_Arg{
Decl_Function_Arg *next;
Intern_String name;
Typespec *typespec;
Token *pos;
};
struct Decl_Enum_Child{ struct Decl_Enum_Child{
Decl_Enum_Child *next; Decl_Enum_Child *next;
Intern_String name; Intern_String name;
@@ -73,9 +86,10 @@ struct Decl_Enum_Child{
struct Decl{ struct Decl{
Decl_Kind kind; Decl_Kind kind;
Decl *next;
Intern_String name; Intern_String name;
Token *pos; Token *pos;
Decl *next;
Note *first_note; Note *first_note;
Note *last_note; Note *last_note;
@@ -87,6 +101,7 @@ struct Decl{
Typespec *typespec; Typespec *typespec;
}enum_decl; }enum_decl;
struct{ struct{
Decl_Struct_Kind kind;
Decl *first; Decl *first;
Decl *last; Decl *last;
} struct_decl; } struct_decl;
@@ -97,6 +112,11 @@ struct Decl{
struct{ struct{
Typespec *type; Typespec *type;
}typedef_decl; }typedef_decl;
struct{
Decl_Function_Arg *first;
Decl_Function_Arg *last ;
Typespec *ret;
}function_decl;
struct{ struct{
Decl *first; Decl *first;
Decl *last; Decl *last;
@@ -104,3 +124,41 @@ struct Decl{
}; };
}; };
//-----------------------------------------------------------------------------
// Statements
//-----------------------------------------------------------------------------
typedef enum Stmt_Kind{
STMT_None,
STMT_Decl,
STMT_Expr,
STMT_Return,
STMT_If,
STMT_For,
}Stmt_Kind;
typedef struct Stmt_List Stmt_List;
struct Stmt_List{
Stmt *first;
Stmt *last;
};
typedef struct Stmt_If Stmt_If;
struct Stmt_If{
Stmt_If *next;
Expr *expr;
union{
struct{Stmt *first; Stmt *last;};
Stmt_List *list;
};
};
struct Stmt{
Stmt_Kind kind;
Stmt *next;
union{
Decl *decl;
Expr *expr;
Stmt_If *if_stmt;
Stmt_List *list;
};
};

126
codegen_c.c Normal file
View File

@@ -0,0 +1,126 @@
function void gen_decl(Parser *p, Decl *node);
function void
gen_typespec(Parser *p, Typespec *spec, B32 is_left){
switch(spec->kind) {
case TS_Name: {
if(is_left) lex_print("%s", spec->name.s.str);
} break;
case TS_Pointer: {
gen_typespec(p, spec->base,is_left);
if(is_left) lex_print("*");
} break;
case TS_Array: {
gen_typespec(p, spec->array_spec.base,is_left);
if(!is_left){
lex_print("[");
expr_print(p, spec->array_spec.size);
lex_print("]");
}
} break;
case TS_Function: {
invalid_codepath;
} break;
default: {invalid_codepath;} break;
}
}
function Typespec *
typespec_get_func(Typespec *type){
switch(type->kind){
case TS_Name:{return 0;} break;
case TS_Pointer:{return typespec_get_func(type->base);} break;
case TS_Array:{return typespec_get_func(type->array_spec.base);} break;
case TS_Function:{return type;} break;
default: {invalid_codepath;} break;
}
return 0;
}
function void
gen_decl(Parser *p, Decl *node){
switch(node->kind) {
case DECL_List: {
for(Decl *n = node->list.first; n; n=n->next){
gen_decl(p,n);
lex_new_line();
}
} break;
case DECL_Variable:{
Typespec *func = typespec_get_func(node->variable_decl.type);
if(!func){
gen_typespec(p, node->variable_decl.type, true);
lex_print(" %s", node->name.s.str);
gen_typespec(p, node->variable_decl.type, false);
}
else{
gen_typespec(p, func->function_spec.ret, true);
lex_print("(*");
lex_print("%s", node->name.s.str);
lex_print(")");
lex_print("(");
for(Typespec *t = func->function_spec.first; t; t=t->next){
gen_typespec(p, t, true);
gen_typespec(p, t, false);
if(t != func->function_spec.last) lex_print(", ");
}
lex_print(")");
}
print_assign_expr(p,node->variable_decl.expr);
lex_print(";");
} break;
case DECL_Typedef:{
lex_print("typedef %s ", node->name.s.str);
gen_typespec(p, node->typedef_decl.type, true);
gen_typespec(p, node->typedef_decl.type, false);
lex_print(";");
} break;
case DECL_Struct:
case DECL_Union :{
U8 *struct_name = node->kind==DECL_Struct ? (U8*)"struct" : (U8*)"union";
U8 *name = node->name.s.str;
if(node->struct_decl.kind == STRUCT_Base)
lex_print("typedef %s %s %s;\n", struct_name, name, name);
lex_print("%s %s{\n", struct_name, name?name:(U8*)"");
for(Decl *n = node->struct_decl.first; n; n=n->next){
gen_decl(p, n);
lex_print("\n");
}
lex_print("};");
if(node->struct_decl.kind == STRUCT_Base)
lex_print("\n");
} break;
case DECL_Enum:{
lex_print("enum %s", node->name.s.str);
if(!intern_compare(node->enum_decl.typespec->name, intern_s64)){
lex_print(" : ");
lex_print("%s", node->enum_decl.typespec->name.s.str);
}
lex_print("{\n");
String prefix = decl_find_string_note(node, lit("prefix"), string_empty);
for(Decl_Enum_Child *n = node->enum_decl.first; n; n=n->next){
lex_print("%.*s%s", (int)prefix.len, prefix.str, n->name.s.str);
print_assign_expr(p, n->expr);
lex_print(",\n");
}
lex_print("};\n");
} break;
default: {invalid_codepath;} break;
}
}

View File

@@ -1,3 +1,4 @@
global String string_empty;
function S64 function S64
clamp_top_s64(S64 val, S64 max){ clamp_top_s64(S64 val, S64 max){

17
main.c
View File

@@ -26,6 +26,7 @@ global FILE *global_output_file;
#include "parse_expr.c" #include "parse_expr.c"
#include "parse_decl.c" #include "parse_decl.c"
#include "print.c" #include "print.c"
#include "codegen_c.c"
function void function void
lex_test(){ lex_test(){
@@ -96,24 +97,16 @@ parser_test(){
parser_lex_stream(&p, exprs[i], lit("File")); parser_lex_stream(&p, exprs[i], lit("File"));
Expr *expr = parse_expr(&p); Expr *expr = parse_expr(&p);
assert(expr); assert(expr);
expr_print(&p, expr); //expr_print(&p, expr);
lex_print("\n"); //lex_print("\n");
} }
/*
String string
= lit(
"@test Thing2 :: struct { thing: union{a:U32;}; _: union{ thing: U32*; }; }"
"Thing :: enum: U32 { @str=\"as\" Thing = 32, Thing2 = 15<<2, }"
"Thing :: struct{ identi: U64*[32]; InnerStruct :: struct { t: U32; } var: InnerStruct; pp :: enum { Thing_1 } }"
"thing:(S64*,U64) U32*@[10]; }"
);
*/
String string = os_read_file(lit("test.cc")); String string = os_read_file(lit("test.cc"));
parser_lex_stream(&p, string, lit("Parse")); parser_lex_stream(&p, string, lit("Parse"));
Decl *decls = parse(&p); Decl *decls = parse(&p);
assert(decls->list.first); assert(decls->list.first);
print_decl(&p, decls); gen_decl(&p, decls);
} }
function S32 function S32

409
output.cc
View File

@@ -1,246 +1,243 @@
(((534>43)?435:42),234,((S64)32),Thing[10][2],Thing((1,2))) typedef struct OpenGL OpenGL;
(4+(2*53)) struct OpenGL{
((4+2)*53) void(*glVertexAttribPointer)(GLuint, GLint, GLenum, GLboolean, GLsizei, GLvoid*);
(++5) void(*glBindTexture)(GLenum, GLuint);
(--5) void(*glDrawArrays)(GLenum, GLint, GLsizei);
(-5) };
(+5)
(sizeof(32)+sizeof(S32*)) typedef struct OS_Memory OS_Memory;
((S64**)5)
(((S64)5)+3)
((534>43)?435:42)
struct OS_Memory{ struct OS_Memory{
data: void*; void* data;
commit: SizeU; SizeU commit;
reserve: SizeU; SizeU reserve;
}; };
typedef struct Arena Arena;
struct Arena{ struct Arena{
@using memory: OS_Memory; OS_Memory memory;
len: U64; U64 len;
alignment: U64; U64 alignment;
}; };
typedef struct String String;
struct String{ struct String{
str: U8*; U8* str;
len: S64; S64 len;
}; };
typedef Intern_String String; typedef Intern_String String;
@stringify @prefix = TK_ enum Token_Kind : S64{ enum Token_Kind{
@str = End of stream End, TK_End,
@str = * Mul, TK_Mul,
@str = / Div, TK_Div,
@str = + Add, TK_Add,
@str = - Sub, TK_Sub,
@str = % Mod, TK_Mod,
@str = & BitAnd, TK_BitAnd,
@str = | BitOr, TK_BitOr,
@str = ^ BitXor, TK_BitXor,
@str = ~ Neg, TK_Neg,
@str = ! Not, TK_Not,
@str = ( OpenParen, TK_OpenParen,
@str = CloseParen, TK_CloseParen,
@str = { OpenBrace, TK_OpenBrace,
@str = } CloseBrace, TK_CloseBrace,
@str = [ OpenBracket, TK_OpenBracket,
@str = ] CloseBracket, TK_CloseBracket,
@str = , Comma, TK_Comma,
@str = # Pound, TK_Pound,
@str = ? Question, TK_Question,
@str = ... ThreeDots, TK_ThreeDots,
@str = ; Semicolon, TK_Semicolon,
@str = . Dot, TK_Dot,
@str = < LesserThen, TK_LesserThen,
@str = > GreaterThen, TK_GreaterThen,
@str = : Colon, TK_Colon,
@str = = Assign, TK_Assign,
@str = /= DivAssign, TK_DivAssign,
@str = *= MulAssign, TK_MulAssign,
@str = %= ModAssign, TK_ModAssign,
@str = -= SubAssign, TK_SubAssign,
@str = += AddAssign, TK_AddAssign,
@str = &= AndAssign, TK_AndAssign,
@str = |= OrAssign, TK_OrAssign,
@str = ^= XorAssign, TK_XorAssign,
@str = <<= LeftShiftAssign, TK_LeftShiftAssign,
@str = >>= RightShiftAssign, TK_RightShiftAssign,
@str = :: DoubleColon, TK_DoubleColon,
@str = @ At, TK_At,
@str = -- Decrement, TK_Decrement,
@str = ++ Increment, TK_Increment,
@str = -- PostDecrement, TK_PostDecrement,
@str = ++ PostIncrement, TK_PostIncrement,
@str = <= LesserThenOrEqual, TK_LesserThenOrEqual,
@str = >= GreaterThenOrEqual, TK_GreaterThenOrEqual,
@str = == Equals, TK_Equals,
@str = && And, TK_And,
@str = || Or, TK_Or,
@str = != NotEquals, TK_NotEquals,
@str = << LeftShift, TK_LeftShift,
@str = >> RightShift, TK_RightShift,
@str = -> Arrow, TK_Arrow,
@str = sizeof ExprSizeof, TK_ExprSizeof,
DocComment, TK_DocComment,
Comment, TK_Comment,
Identifier, TK_Identifier,
StringLit, TK_StringLit,
U8Lit, TK_U8Lit,
Character, TK_Character,
Error, TK_Error,
Float, TK_Float,
Int, TK_Int,
Keyword, TK_Keyword,
}; };
typedef struct Token Token;
struct Token{ struct Token{
kind: Token_Kind; Token_Kind kind;
@using string: String; String string;
val: union { union {
integer: S64; S64 integer_val;
error: String; String error_val;
intern: Intern_String; Intern_String intern_val;
}; };
String file;
file: String; S64 line;
line: S64; U8* line_begin;
line_begin: U8*;
}; };
typedef struct Tokens Tokens;
struct Tokens{ struct Tokens{
@array tokens: Token*; Token* tokens;
iter: S64; S64 iter;
}; };
typedef struct Lex_Stream Lex_Stream;
struct Lex_Stream{ struct Lex_Stream{
stream: U8*; U8* stream;
line_begin: U8*; U8* line_begin;
filename: String; String filename;
line: S64; S64 line;
}; };
@prefix = EK_ enum Expr_Kind : S64{ enum Expr_Kind{
None, EK_None,
Atom, EK_Atom,
Unary, EK_Unary,
Binary, EK_Binary,
Ternary, EK_Ternary,
Cast, EK_Cast,
List, EK_List,
Call, EK_Call,
Index, EK_Index,
}; };
typedef struct Expr Expr;
struct Expr{ struct Expr{
kind: Expr_Kind; Expr_Kind kind;
token: Token*; Token* token;
next: Expr*; Expr* next;
_: union { union {
cast_val: struct { struct cast_val{
type: AST_Node*; AST_Node* type;
expr: Expr*; Expr* expr;
};
struct list{
Expr* first;
Expr* last;
};
struct call{
Expr* atom;
Expr* list;
};
struct index{
Expr* atom;
Expr* index;
};
struct unary{
Expr* expr;
};
struct binary{
Expr* left;
Expr* right;
};
struct ternary{
Expr* cond;
Expr* on_true;
Expr* on_false;
};
};
}; };
list: struct { enum AST_Kind{
first: Expr*; AK_None,
last: Expr*; AK_BaseType,
}; AK_Typedef,
AK_Enum,
call: struct { AK_Struct,
atom: Expr*; AK_Union,
list: Expr*; AK_Note,
}; AK_List,
AK_Pointer,
index: struct { AK_Array,
atom: Expr*; AK_Function,
index: Expr*; AK_Variable,
}; AK_EnumChild,
unary: struct {
expr: Expr*;
};
binary: struct {
left: Expr*;
right: Expr*;
};
ternary: struct {
cond: Expr*;
on_true: Expr*;
on_false: Expr*;
};
};
};
@prefix = AK_ enum AST_Kind : S64{
None,
BaseType,
Typedef,
Enum,
Struct,
Union,
Note,
List,
Pointer,
Array,
Function,
Variable,
EnumChild,
}; };
typedef struct AST_Node AST_Node;
struct AST_Node{ struct AST_Node{
kind: AST_Kind; AST_Kind kind;
pos: Token*; Token* pos;
name: Intern_String; Intern_String name;
next: AST_Node*; AST_Node* next;
next_scope: AST_Node*; AST_Node* next_scope;
first_note: AST_Node*; AST_Node* first_note;
last_note: AST_Node*; AST_Node* last_note;
first_child: AST_Node*; AST_Node* first_child;
last_child: AST_Node*; AST_Node* last_child;
_: union { union {
base_type_size: SizeU; SizeU base_type_size;
pointer: AST_Node*; AST_Node* pointer;
typedef_type: AST_Node*; AST_Node* typedef_type;
variable_type: AST_Node*; AST_Node* variable_type;
func_return_type: AST_Node*; AST_Node* func_return_type;
}; };
}; };
typedef struct Parser_Error Parser_Error;
struct Parser_Error{ struct Parser_Error{
next: Parser_Error*; Parser_Error* next;
message: String; String message;
token: Token*; Token* token;
}; };
typedef struct Scope Scope;
struct Scope{ struct Scope{
next: Scope*; Scope* next;
first: AST_Node*; AST_Node* first;
last: AST_Node*; AST_Node* last;
}; };
typedef struct Parser Parser;
struct Parser{ struct Parser{
main_arena: Arena; Arena main_arena;
intern_table_arena: Arena; Arena intern_table_arena;
symbol_table_arena: Arena; Arena symbol_table_arena;
scope_free_list: Scope*; Scope* scope_free_list;
scope_stack: Scope*; Scope* scope_stack;
global_scope: Scope*; Scope* global_scope;
symbols_inserted: S64; S64 symbols_inserted;
symbols_count: S64; S64 symbols_count;
symbols: AST_Node*; AST_Node* symbols;
interns: Intern_String*; Intern_String* interns;
interns_in_bytes: S64; S64 interns_in_bytes;
interns_inserted: S64; S64 interns_inserted;
interns_count: S64; S64 interns_count;
first_keyword: U8*; U8* first_keyword;
last_keyword: U8*; U8* last_keyword;
@sllqueue default: Parser_Error; Parser_Error default;
@sllqueue error: Parser_Error; Parser_Error error;
@using token_array: Tokens; Tokens token_array;
}; };

View File

@@ -1,15 +1,7 @@
function Decl *parse_decl(Parser *p); function Decl *parse_decl(Parser *p);
function Decl *parse_struct(Parser *p, Token *name, Decl_Kind kind); function Decl *parse_struct(Parser *p, Token *name, Decl_Kind kind, Decl_Struct_Kind);
function Typespec *parse_type(Parser *p); function Typespec *parse_type(Parser *p);
function Typespec *
parse_type_struct(Parser *p, Token *token){
Decl_Kind kind = intern_compare(token->intern_val, keyword_struct) ? DECL_Struct : DECL_Union;
Decl *decl = parse_struct(p, token, kind);
decl->name = (Intern_String){};
return typespec_struct(p, token, decl);
}
function Typespec * function Typespec *
parse_type_function(Parser *p, Token *token){ parse_type_function(Parser *p, Token *token){
Typespec *result = typespec_function(p, token, 0); Typespec *result = typespec_function(p, token, 0);
@@ -35,14 +27,13 @@ parse_type_function(Parser *p, Token *token){
function Typespec * function Typespec *
parse_type(Parser *p){ parse_type(Parser *p){
// Parse as function type or normal
Token *token = 0; Token *token = 0;
Typespec *result = 0; Typespec *result = 0;
if((token = token_match(p, TK_Identifier))){ if((token = token_match(p, TK_Identifier))){
result = typespec_name(p, token, token->intern_val); result = typespec_name(p, token, token->intern_val);
} }
else if((token = token_match_keyword(p, keyword_struct)) || (token = token_match_keyword(p, keyword_union))){
result = parse_type_struct(p, token);
}
else if((token = token_match(p, TK_OpenParen))){ else if((token = token_match(p, TK_OpenParen))){
result = parse_type_function(p, token); result = parse_type_function(p, token);
} }
@@ -51,6 +42,7 @@ parse_type(Parser *p){
return 0; return 0;
} }
// Parse Pointer/Array
for(;;){ for(;;){
if((token = token_match(p, TK_Mul))){ if((token = token_match(p, TK_Mul))){
result = typespec_pointer(p, token, result); result = typespec_pointer(p, token, result);
@@ -65,6 +57,8 @@ parse_type(Parser *p){
} }
else break; else break;
} }
return result; return result;
} }
@@ -111,6 +105,14 @@ parse_notes(Parser *p){
return result; return result;
} }
function Token *
parse_get_token_name(Parser *p, S32 count){
Token *result = token_next(p);
for(S32 i = 0; i < count; i++)
token_next(p);
return result;
}
function Decl * function Decl *
parse_enum(Parser *p, Token *name){ parse_enum(Parser *p, Token *name){
Typespec *type = 0; Typespec *type = 0;
@@ -132,18 +134,35 @@ parse_enum(Parser *p, Token *name){
} }
function Decl * function Decl *
parse_struct(Parser *p, Token *name, Decl_Kind kind){ parse_struct(Parser *p, Token *name, Decl_Kind kind, Decl_Struct_Kind struct_kind){
Decl *result = decl_struct(p, kind, name, name->intern_val); Decl *result = decl_struct(p, kind, name, name->intern_val, struct_kind);
token_expect(p, TK_OpenBrace); token_expect(p, TK_OpenBrace);
while(!token_is(p, TK_CloseBrace)){ while(!token_is(p, TK_CloseBrace)){
Decl *decl = 0; Decl *decl = 0;
if((decl = parse_decl(p))){ if((decl = parse_decl(p))){
decl_struct_push(result, decl); }
else if(token_match_keyword(p, keyword_union)){
decl = parse_struct(p, token_get(p), DECL_Union, STRUCT_Nested);
}
else if(token_match_keyword(p, keyword_struct)){
decl = parse_struct(p, token_get(p), DECL_Struct, STRUCT_Nested);
}
else if(token_is(p, TK_Identifier) &&
token_peek_is(p, 1, TK_Colon) &&
token_peek_is_keyword(p, 2, keyword_union)){
decl = parse_struct(p, parse_get_token_name(p, 2), DECL_Union, STRUCT_Nested);
}
else if(token_is(p, TK_Identifier) &&
token_peek_is(p, 1, TK_Colon) &&
token_peek_is_keyword(p, 2, keyword_struct)){
decl = parse_struct(p, parse_get_token_name(p, 2), DECL_Struct, STRUCT_Nested);
} }
else { else {
parser_push_error(p, token_get(p), "Unexpected token while parsing struct"); parser_push_error(p, token_get(p), "Unexpected token while parsing struct");
break; break;
} }
if(decl) decl_struct_push(result, decl);
} }
token_expect(p, TK_CloseBrace); token_expect(p, TK_CloseBrace);
return result; return result;
@@ -163,13 +182,29 @@ parse_typedef(Parser *p, Token *name){
return decl_typedef(p, name, name->intern_val, type); return decl_typedef(p, name, name->intern_val, type);
} }
function Token * /*
parse_get_token_name(Parser *p, S32 count){ function Decl *
Token *result = token_next(p); parse_function(Parser *p, Token *name){
for(S32 i = 0; i < count; i++) Decl *result = decl_function(p, name, name->intern_val, 0);
token_next(p); if(!token_is(p, TK_CloseParen)){
for(;;) {
if((name = token_match(p, TK_Identifier)))
decl_function_push(p, result, name, name->intern_val, parse_type(p));
else if(!token_match(p, TK_Comma))
break;
}
}
token_expect(p, TK_CloseParen);
if(token_is(p, TK_Identifier))
result->function_decl.ret = parse_type(p);
token_expect(p, TK_OpenBrace);
parse_stmt_list(p, result);
token_expect(p, TK_CloseBrace);
return result; return result;
} }
*/
function Decl * function Decl *
parse_decl(Parser *p){ parse_decl(Parser *p){
@@ -179,10 +214,10 @@ parse_decl(Parser *p){
if(token_is(p, TK_Identifier)){ if(token_is(p, TK_Identifier)){
if(token_peek_is(p, 1, TK_DoubleColon)){ if(token_peek_is(p, 1, TK_DoubleColon)){
if(token_peek_is_keyword(p, 2, keyword_struct)){ if(token_peek_is_keyword(p, 2, keyword_struct)){
result = parse_struct(p, parse_get_token_name(p,2), DECL_Struct); result = parse_struct(p, parse_get_token_name(p,2), DECL_Struct, STRUCT_Base);
} }
else if(token_peek_is_keyword(p, 2, keyword_union)){ else if(token_peek_is_keyword(p, 2, keyword_union)){
result = parse_struct(p, parse_get_token_name(p,2), DECL_Union); result = parse_struct(p, parse_get_token_name(p,2), DECL_Union, STRUCT_Base);
} }
else if(token_peek_is_keyword(p, 2, keyword_enum)){ else if(token_peek_is_keyword(p, 2, keyword_enum)){
result = parse_enum(p, parse_get_token_name(p,2)); result = parse_enum(p, parse_get_token_name(p,2));
@@ -193,8 +228,6 @@ parse_decl(Parser *p){
} }
else if(token_peek_is(p, 1, TK_Colon)){ else if(token_peek_is(p, 1, TK_Colon)){
if(token_peek_is(p, 2, TK_Identifier) || if(token_peek_is(p, 2, TK_Identifier) ||
token_peek_is_keyword(p, 2, keyword_union) ||
token_peek_is_keyword(p, 2, keyword_struct) ||
token_peek_is(p, 2, TK_OpenParen)){ token_peek_is(p, 2, TK_OpenParen)){
result = parse_variable(p, parse_get_token_name(p,1)); result = parse_variable(p, parse_get_token_name(p,1));
} }

View File

@@ -95,6 +95,9 @@ intern_tokens(Parser *p){
t->kind = TK_Keyword; t->kind = TK_Keyword;
} }
} }
else if(t->kind == TK_U8Lit){
t->intern_val = intern_string(p, t->string);
}
else if(t->kind == TK_Error){ else if(t->kind == TK_Error){
parser_push_error(p, t, (char *)t->error_val.str); parser_push_error(p, t, (char *)t->error_val.str);
} }

View File

@@ -91,9 +91,6 @@ expr_print(Parser *p, Expr *expr){
} }
} }
global S64 indent;
function B32 function B32
print_typespec(Parser *p, Typespec *spec){ print_typespec(Parser *p, Typespec *spec){
switch(spec->kind) { switch(spec->kind) {
@@ -101,10 +98,6 @@ print_typespec(Parser *p, Typespec *spec){
lex_print("%s", spec->name.s.str); lex_print("%s", spec->name.s.str);
} break; } break;
case TS_Struct:{
print_decl(p, spec->struct_spec);
return false;
} break;
case TS_Pointer: { case TS_Pointer: {
print_typespec(p, spec->base); print_typespec(p, spec->base);

34
sym.h Normal file
View File

@@ -0,0 +1,34 @@
typedef enum Symbol_Kind{
SYM_None,
SYM_Decl,
SYM_Type,
}Symbol_Kind;
typedef enum Symbol_State{
SYM_STATE_Used,
SYM_STATE_Declared,
}Symbol_State;
typedef struct Symbol{
Symbol_Kind kind;
Symbol_State state;
Symbol *next;
union{
Decl *decl;
struct{
Typespec *spec;
} type;
};
} Symbol;
// First stage would add all symbols as underspecified to the table
// Every encountered typespec would be added to the table as either specified or
// just as encountered name
//
// Then second stage would loop over all of them and report errors on all symbols that were
// found in the wild but not declared
//
//
//
//

38
test.cc
View File

@@ -1,5 +1,11 @@
#if 0 #if 0
OpenGL :: struct{
glVertexAttribPointer: (GLuint, GLint, GLenum, GLboolean, GLsizei, GLvoid*);
glBindTexture: (GLenum, GLuint);
glDrawArrays: (GLenum, GLint, GLsizei);
}
OS_Memory::struct{ OS_Memory::struct{
data: void*; data: void*;
commit: SizeU; commit: SizeU;
@@ -89,11 +95,11 @@ Token_Kind::enum{
Token::struct{ Token::struct{
kind:Token_Kind; kind:Token_Kind;
@using string:String; @using string:String;
val: union{ union{
integer:S64; integer_val:S64;
error:String; error_val:String;
intern:Intern_String; intern_val:Intern_String;
}; }
file:String; file:String;
line:S64; line:S64;
line_begin:U8*; line_begin:U8*;
@@ -128,36 +134,36 @@ Expr:: struct{
kind: Expr_Kind; kind: Expr_Kind;
token: Token*; token: Token*;
next : Expr*; next : Expr*;
_: union{ union{
cast_val: struct{ cast_val: struct{
type: AST_Node*; type: AST_Node*;
expr: Expr*; expr: Expr*;
}; }
list: struct{ list: struct{
first: Expr *; first: Expr *;
last: Expr *; last: Expr *;
}; }
call: struct{ call: struct{
atom: Expr *; atom: Expr *;
list: Expr *; list: Expr *;
}; }
index: struct{ index: struct{
atom: Expr *; atom: Expr *;
index: Expr *; index: Expr *;
}; }
unary: struct{ unary: struct{
expr: Expr* ; expr: Expr* ;
}; }
binary: struct{ binary: struct{
left: Expr* ; left: Expr* ;
right: Expr* ; right: Expr* ;
}; }
ternary: struct{ ternary: struct{
cond: Expr* ; cond: Expr* ;
on_true: Expr*; on_true: Expr*;
on_false: Expr*; on_false: Expr*;
}; }
}; }
} }
@prefix="AK_" @prefix="AK_"
@@ -190,13 +196,13 @@ AST_Node::struct{
first_child: AST_Node*; first_child: AST_Node*;
last_child: AST_Node*; last_child: AST_Node*;
_:union{ union{
base_type_size: SizeU; base_type_size: SizeU;
pointer: AST_Node*; pointer: AST_Node*;
typedef_type: AST_Node*; typedef_type: AST_Node*;
variable_type: AST_Node*; variable_type: AST_Node*;
func_return_type: AST_Node*; func_return_type: AST_Node*;
}; }
} }
Parser_Error :: struct{ Parser_Error :: struct{