From 557dde1936c20f74c473b4a675cd974ab267369d Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Tue, 3 May 2022 20:08:13 +0200 Subject: [PATCH] C codegen --- ast.c | 74 ++++++++-- ast.h | 64 +++++++- codegen_c.c | 126 ++++++++++++++++ common.c | 1 + main.c | 17 +-- output.cc | 409 +++++++++++++++++++++++++-------------------------- parse_decl.c | 81 +++++++--- parser.c | 3 + print.c | 7 - sym.h | 34 +++++ test.cc | 38 +++-- 11 files changed, 573 insertions(+), 281 deletions(-) create mode 100644 codegen_c.c create mode 100644 sym.h diff --git a/ast.c b/ast.c index 3fd061a..6c7f63c 100644 --- a/ast.c +++ b/ast.c @@ -1,4 +1,6 @@ - +//----------------------------------------------------------------------------- +// Decls +//----------------------------------------------------------------------------- function Decl * decl_new(Parser *p, Decl_Kind kind, Token *pos, Intern_String name){ 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 * -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); Decl *result = decl_new(p, kind, pos, name); + result->struct_decl.kind = struct_kind; return result; } @@ -37,6 +40,23 @@ decl_variable(Parser *p, Token *pos, Intern_String name, Typespec *typespec, Exp 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 decl_enum_push(Parser *p, Decl *parent, Token *pos, Intern_String name, Expr *expr, Note *notes){ assert(parent->kind == DECL_Enum); @@ -61,6 +81,15 @@ decl_list_push(Decl *parent, Decl *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 * note_push_new(Parser *p, Note *parent, Token *pos, Intern_String name, Expr *expr){ 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; } -function void -decl_pass_notes(Decl *a, Note *b){ - a->first_note = b->first; - a->last_note = b->last; +function Note * +find_note(Note *first, String string){ + for(Note *n = first; n; n=n->next){ + 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 * typespec_new(Parser *p, Typespec_Kind kind, Token *pos){ Typespec *result = arena_push_struct(&p->main_arena, Typespec); @@ -85,13 +140,6 @@ typespec_new(Parser *p, Typespec_Kind kind, Token *pos){ 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 * typespec_name(Parser *p, Token *pos, Intern_String name){ Typespec *result = typespec_new(p, TS_Name, pos); diff --git a/ast.h b/ast.h index 61193c2..dd6f13a 100644 --- a/ast.h +++ b/ast.h @@ -1,7 +1,9 @@ typedef struct Decl_Enum_Child Decl_Enum_Child; +typedef struct Decl_Function_Arg Decl_Function_Arg; typedef struct Typespec Typespec; typedef struct Decl Decl; typedef struct Note Note; +typedef struct Stmt Stmt; //----------------------------------------------------------------------------- // Type specifier @@ -12,7 +14,6 @@ typedef enum Typespec_Kind{ TS_Pointer, TS_Array, TS_Function, - TS_Struct, }Typespec_Kind; struct Typespec{ @@ -21,7 +22,6 @@ struct Typespec{ Token *pos; union{ Intern_String name; - Decl *struct_spec; struct{ Typespec *first; Typespec *last; @@ -58,9 +58,22 @@ typedef enum Decl_Kind{ DECL_Enum, DECL_Variable, DECL_Typedef, + DECL_Function, DECL_List, }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{ Decl_Enum_Child *next; Intern_String name; @@ -73,9 +86,10 @@ struct Decl_Enum_Child{ struct Decl{ Decl_Kind kind; + Decl *next; + Intern_String name; Token *pos; - Decl *next; Note *first_note; Note *last_note; @@ -87,6 +101,7 @@ struct Decl{ Typespec *typespec; }enum_decl; struct{ + Decl_Struct_Kind kind; Decl *first; Decl *last; } struct_decl; @@ -97,6 +112,11 @@ struct Decl{ struct{ Typespec *type; }typedef_decl; + struct{ + Decl_Function_Arg *first; + Decl_Function_Arg *last ; + Typespec *ret; + }function_decl; struct{ Decl *first; 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; + }; +}; diff --git a/codegen_c.c b/codegen_c.c new file mode 100644 index 0000000..928754d --- /dev/null +++ b/codegen_c.c @@ -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; + } +} + + diff --git a/common.c b/common.c index cebe3d2..16dbb97 100644 --- a/common.c +++ b/common.c @@ -1,3 +1,4 @@ +global String string_empty; function S64 clamp_top_s64(S64 val, S64 max){ diff --git a/main.c b/main.c index 79e6843..2b5f5eb 100644 --- a/main.c +++ b/main.c @@ -26,6 +26,7 @@ global FILE *global_output_file; #include "parse_expr.c" #include "parse_decl.c" #include "print.c" +#include "codegen_c.c" function void lex_test(){ @@ -96,24 +97,16 @@ parser_test(){ parser_lex_stream(&p, exprs[i], lit("File")); Expr *expr = parse_expr(&p); assert(expr); - expr_print(&p, expr); - lex_print("\n"); + //expr_print(&p, expr); + //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")); parser_lex_stream(&p, string, lit("Parse")); Decl *decls = parse(&p); assert(decls->list.first); - print_decl(&p, decls); + gen_decl(&p, decls); + } function S32 diff --git a/output.cc b/output.cc index 103b9ed..464ff81 100644 --- a/output.cc +++ b/output.cc @@ -1,246 +1,243 @@ -(((534>43)?435:42),234,((S64)32),Thing[10][2],Thing((1,2))) -(4+(2*53)) -((4+2)*53) -(++5) -(--5) -(-5) -(+5) -(sizeof(32)+sizeof(S32*)) -((S64**)5) -(((S64)5)+3) -((534>43)?435:42) +typedef struct OpenGL OpenGL; +struct OpenGL{ +void(*glVertexAttribPointer)(GLuint, GLint, GLenum, GLboolean, GLsizei, GLvoid*); +void(*glBindTexture)(GLenum, GLuint); +void(*glDrawArrays)(GLenum, GLint, GLsizei); +}; + +typedef struct OS_Memory OS_Memory; struct OS_Memory{ -data: void*; -commit: SizeU; -reserve: SizeU; +void* data; +SizeU commit; +SizeU reserve; }; +typedef struct Arena Arena; struct Arena{ -@using memory: OS_Memory; -len: U64; -alignment: U64; +OS_Memory memory; +U64 len; +U64 alignment; }; +typedef struct String String; struct String{ -str: U8*; -len: S64; +U8* str; +S64 len; }; typedef Intern_String String; -@stringify @prefix = TK_ enum Token_Kind : S64{ -@str = End of stream End, -@str = * Mul, -@str = / Div, -@str = + Add, -@str = - Sub, -@str = % Mod, -@str = & BitAnd, -@str = | BitOr, -@str = ^ BitXor, -@str = ~ Neg, -@str = ! Not, -@str = ( OpenParen, -@str = CloseParen, -@str = { OpenBrace, -@str = } CloseBrace, -@str = [ OpenBracket, -@str = ] CloseBracket, -@str = , Comma, -@str = # Pound, -@str = ? Question, -@str = ... ThreeDots, -@str = ; Semicolon, -@str = . Dot, -@str = < LesserThen, -@str = > GreaterThen, -@str = : Colon, -@str = = Assign, -@str = /= DivAssign, -@str = *= MulAssign, -@str = %= ModAssign, -@str = -= SubAssign, -@str = += AddAssign, -@str = &= AndAssign, -@str = |= OrAssign, -@str = ^= XorAssign, -@str = <<= LeftShiftAssign, -@str = >>= RightShiftAssign, -@str = :: DoubleColon, -@str = @ At, -@str = -- Decrement, -@str = ++ Increment, -@str = -- PostDecrement, -@str = ++ PostIncrement, -@str = <= LesserThenOrEqual, -@str = >= GreaterThenOrEqual, -@str = == Equals, -@str = && And, -@str = || Or, -@str = != NotEquals, -@str = << LeftShift, -@str = >> RightShift, -@str = -> Arrow, -@str = sizeof ExprSizeof, -DocComment, -Comment, -Identifier, -StringLit, -U8Lit, -Character, -Error, -Float, -Int, -Keyword, +enum Token_Kind{ +TK_End, +TK_Mul, +TK_Div, +TK_Add, +TK_Sub, +TK_Mod, +TK_BitAnd, +TK_BitOr, +TK_BitXor, +TK_Neg, +TK_Not, +TK_OpenParen, +TK_CloseParen, +TK_OpenBrace, +TK_CloseBrace, +TK_OpenBracket, +TK_CloseBracket, +TK_Comma, +TK_Pound, +TK_Question, +TK_ThreeDots, +TK_Semicolon, +TK_Dot, +TK_LesserThen, +TK_GreaterThen, +TK_Colon, +TK_Assign, +TK_DivAssign, +TK_MulAssign, +TK_ModAssign, +TK_SubAssign, +TK_AddAssign, +TK_AndAssign, +TK_OrAssign, +TK_XorAssign, +TK_LeftShiftAssign, +TK_RightShiftAssign, +TK_DoubleColon, +TK_At, +TK_Decrement, +TK_Increment, +TK_PostDecrement, +TK_PostIncrement, +TK_LesserThenOrEqual, +TK_GreaterThenOrEqual, +TK_Equals, +TK_And, +TK_Or, +TK_NotEquals, +TK_LeftShift, +TK_RightShift, +TK_Arrow, +TK_ExprSizeof, +TK_DocComment, +TK_Comment, +TK_Identifier, +TK_StringLit, +TK_U8Lit, +TK_Character, +TK_Error, +TK_Float, +TK_Int, +TK_Keyword, }; +typedef struct Token Token; struct Token{ -kind: Token_Kind; -@using string: String; -val: union { -integer: S64; -error: String; -intern: Intern_String; -}; - -file: String; -line: S64; -line_begin: U8*; +Token_Kind kind; +String string; +union { +S64 integer_val; +String error_val; +Intern_String intern_val; +}; +String file; +S64 line; +U8* line_begin; }; +typedef struct Tokens Tokens; struct Tokens{ -@array tokens: Token*; -iter: S64; +Token* tokens; +S64 iter; }; +typedef struct Lex_Stream Lex_Stream; struct Lex_Stream{ -stream: U8*; -line_begin: U8*; -filename: String; -line: S64; +U8* stream; +U8* line_begin; +String filename; +S64 line; }; -@prefix = EK_ enum Expr_Kind : S64{ -None, -Atom, -Unary, -Binary, -Ternary, -Cast, -List, -Call, -Index, +enum Expr_Kind{ +EK_None, +EK_Atom, +EK_Unary, +EK_Binary, +EK_Ternary, +EK_Cast, +EK_List, +EK_Call, +EK_Index, }; +typedef struct Expr Expr; struct Expr{ -kind: Expr_Kind; -token: Token*; -next: Expr*; -_: union { -cast_val: struct { -type: AST_Node*; -expr: Expr*; +Expr_Kind kind; +Token* token; +Expr* next; +union { +struct cast_val{ +AST_Node* type; +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 { -first: Expr*; -last: Expr*; -}; - -call: struct { -atom: Expr*; -list: Expr*; -}; - -index: struct { -atom: Expr*; -index: Expr*; -}; - -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, +enum AST_Kind{ +AK_None, +AK_BaseType, +AK_Typedef, +AK_Enum, +AK_Struct, +AK_Union, +AK_Note, +AK_List, +AK_Pointer, +AK_Array, +AK_Function, +AK_Variable, +AK_EnumChild, }; +typedef struct AST_Node AST_Node; struct AST_Node{ -kind: AST_Kind; -pos: Token*; -name: Intern_String; -next: AST_Node*; -next_scope: AST_Node*; -first_note: AST_Node*; -last_note: 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*; -}; - +AST_Kind kind; +Token* pos; +Intern_String name; +AST_Node* next; +AST_Node* next_scope; +AST_Node* first_note; +AST_Node* last_note; +AST_Node* first_child; +AST_Node* last_child; +union { +SizeU base_type_size; +AST_Node* pointer; +AST_Node* typedef_type; +AST_Node* variable_type; +AST_Node* func_return_type; +}; }; +typedef struct Parser_Error Parser_Error; struct Parser_Error{ -next: Parser_Error*; -message: String; -token: Token*; +Parser_Error* next; +String message; +Token* token; }; +typedef struct Scope Scope; struct Scope{ -next: Scope*; -first: AST_Node*; -last: AST_Node*; +Scope* next; +AST_Node* first; +AST_Node* last; }; +typedef struct Parser Parser; struct Parser{ -main_arena: Arena; -intern_table_arena: Arena; -symbol_table_arena: Arena; -scope_free_list: Scope*; -scope_stack: Scope*; -global_scope: Scope*; -symbols_inserted: S64; -symbols_count: S64; -symbols: AST_Node*; -interns: Intern_String*; -interns_in_bytes: S64; -interns_inserted: S64; -interns_count: S64; -first_keyword: U8*; -last_keyword: U8*; -@sllqueue default: Parser_Error; -@sllqueue error: Parser_Error; -@using token_array: Tokens; +Arena main_arena; +Arena intern_table_arena; +Arena symbol_table_arena; +Scope* scope_free_list; +Scope* scope_stack; +Scope* global_scope; +S64 symbols_inserted; +S64 symbols_count; +AST_Node* symbols; +Intern_String* interns; +S64 interns_in_bytes; +S64 interns_inserted; +S64 interns_count; +U8* first_keyword; +U8* last_keyword; +Parser_Error default; +Parser_Error error; +Tokens token_array; }; diff --git a/parse_decl.c b/parse_decl.c index 466b4a1..fc53442 100644 --- a/parse_decl.c +++ b/parse_decl.c @@ -1,15 +1,7 @@ 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_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 * parse_type_function(Parser *p, Token *token){ Typespec *result = typespec_function(p, token, 0); @@ -35,14 +27,13 @@ parse_type_function(Parser *p, Token *token){ function Typespec * parse_type(Parser *p){ + + // Parse as function type or normal Token *token = 0; Typespec *result = 0; if((token = token_match(p, TK_Identifier))){ 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))){ result = parse_type_function(p, token); } @@ -51,6 +42,7 @@ parse_type(Parser *p){ return 0; } + // Parse Pointer/Array for(;;){ if((token = token_match(p, TK_Mul))){ result = typespec_pointer(p, token, result); @@ -65,6 +57,8 @@ parse_type(Parser *p){ } else break; } + + return result; } @@ -111,6 +105,14 @@ parse_notes(Parser *p){ 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 * parse_enum(Parser *p, Token *name){ Typespec *type = 0; @@ -132,18 +134,35 @@ parse_enum(Parser *p, Token *name){ } function Decl * -parse_struct(Parser *p, Token *name, Decl_Kind kind){ - Decl *result = decl_struct(p, kind, name, name->intern_val); +parse_struct(Parser *p, Token *name, Decl_Kind kind, Decl_Struct_Kind struct_kind){ + Decl *result = decl_struct(p, kind, name, name->intern_val, struct_kind); token_expect(p, TK_OpenBrace); while(!token_is(p, TK_CloseBrace)){ Decl *decl = 0; 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 { parser_push_error(p, token_get(p), "Unexpected token while parsing struct"); break; } + + if(decl) decl_struct_push(result, decl); } token_expect(p, TK_CloseBrace); return result; @@ -163,13 +182,29 @@ parse_typedef(Parser *p, Token *name){ return decl_typedef(p, name, name->intern_val, type); } -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); +/* +function Decl * +parse_function(Parser *p, Token *name){ + Decl *result = decl_function(p, name, name->intern_val, 0); + 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; } + */ function Decl * parse_decl(Parser *p){ @@ -179,10 +214,10 @@ parse_decl(Parser *p){ if(token_is(p, TK_Identifier)){ if(token_peek_is(p, 1, TK_DoubleColon)){ 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)){ - 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)){ 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)){ 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)){ result = parse_variable(p, parse_get_token_name(p,1)); } diff --git a/parser.c b/parser.c index 95bca9d..6894f51 100644 --- a/parser.c +++ b/parser.c @@ -95,6 +95,9 @@ intern_tokens(Parser *p){ t->kind = TK_Keyword; } } + else if(t->kind == TK_U8Lit){ + t->intern_val = intern_string(p, t->string); + } else if(t->kind == TK_Error){ parser_push_error(p, t, (char *)t->error_val.str); } diff --git a/print.c b/print.c index 92a6c82..972d323 100644 --- a/print.c +++ b/print.c @@ -91,9 +91,6 @@ expr_print(Parser *p, Expr *expr){ } } -global S64 indent; - - function B32 print_typespec(Parser *p, Typespec *spec){ switch(spec->kind) { @@ -101,10 +98,6 @@ print_typespec(Parser *p, Typespec *spec){ lex_print("%s", spec->name.s.str); } break; - case TS_Struct:{ - print_decl(p, spec->struct_spec); - return false; - } break; case TS_Pointer: { print_typespec(p, spec->base); diff --git a/sym.h b/sym.h new file mode 100644 index 0000000..e431dc5 --- /dev/null +++ b/sym.h @@ -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 +// +// +// +// diff --git a/test.cc b/test.cc index 5fbcd01..446a843 100644 --- a/test.cc +++ b/test.cc @@ -1,5 +1,11 @@ #if 0 +OpenGL :: struct{ + glVertexAttribPointer: (GLuint, GLint, GLenum, GLboolean, GLsizei, GLvoid*); + glBindTexture: (GLenum, GLuint); + glDrawArrays: (GLenum, GLint, GLsizei); +} + OS_Memory::struct{ data: void*; commit: SizeU; @@ -89,11 +95,11 @@ Token_Kind::enum{ Token::struct{ kind:Token_Kind; @using string:String; - val: union{ - integer:S64; - error:String; - intern:Intern_String; - }; + union{ + integer_val:S64; + error_val:String; + intern_val:Intern_String; + } file:String; line:S64; line_begin:U8*; @@ -128,36 +134,36 @@ Expr:: struct{ kind: Expr_Kind; token: Token*; next : Expr*; - _: union{ + union{ cast_val: struct{ type: AST_Node*; expr: Expr*; - }; + } list: struct{ first: Expr *; last: Expr *; - }; + } call: struct{ atom: Expr *; list: Expr *; - }; + } index: struct{ atom: Expr *; index: Expr *; - }; + } unary: struct{ expr: Expr* ; - }; + } binary: struct{ left: Expr* ; right: Expr* ; - }; + } ternary: struct{ cond: Expr* ; on_true: Expr*; on_false: Expr*; - }; - }; + } + } } @prefix="AK_" @@ -190,13 +196,13 @@ AST_Node::struct{ first_child: AST_Node*; last_child: AST_Node*; - _:union{ + union{ base_type_size: SizeU; pointer: AST_Node*; typedef_type: AST_Node*; variable_type: AST_Node*; func_return_type: AST_Node*; - }; + } } Parser_Error :: struct{