diff --git a/ast.c b/ast.c new file mode 100644 index 0000000..3fd061a --- /dev/null +++ b/ast.c @@ -0,0 +1,127 @@ + +function Decl * +decl_new(Parser *p, Decl_Kind kind, Token *pos, Intern_String name){ + Decl *result = arena_push_struct(&p->main_arena, Decl); + result->kind = kind; + result->pos = pos; + result->name = name; + return result; +} + +function Decl * +decl_struct(Parser *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(Parser *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(Parser *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(Parser *p, Token *pos, Intern_String name, Typespec *typespec, Expr *expr){ + Decl *result = decl_new(p, DECL_Variable, pos, name); + result->variable_decl.type = typespec; + result->variable_decl.expr = expr; + return result; +} + +function void +decl_enum_push(Parser *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->main_arena, 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.first, parent->list.last, child); +} + +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); + result->pos = pos; + result->name = name; + result->expr = expr; + SLLQueuePush(parent->first, parent->last, result); + return result; +} + +function void +decl_pass_notes(Decl *a, Note *b){ + a->first_note = b->first; + a->last_note = b->last; +} + +function Typespec * +typespec_new(Parser *p, Typespec_Kind kind, Token *pos){ + Typespec *result = arena_push_struct(&p->main_arena, Typespec); + result->kind = kind; + result->pos = 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); + result->name = name; + return result; +} + +function Typespec * +typespec_pointer(Parser *p, Token *pos, Typespec *base){ + Typespec *result = typespec_new(p, TS_Pointer, pos); + result->base = base; + return result; +} + +function Typespec * +typespec_array(Parser *p, Token *pos, Typespec *base, Expr *size){ + Typespec *result = typespec_new(p, TS_Array, pos); + result->array_spec.base = base; + result->array_spec.size = size; + return result; +} + +function Typespec * +typespec_function(Parser *p, Token *pos, Typespec *ret){ + Typespec *result = typespec_new(p, TS_Function, pos); + result->function_spec.ret = ret; + return result; +} + +function void +typespec_function_push(Typespec *func, Typespec *arg){ + SLLQueuePush(func->function_spec.first, func->function_spec.last, arg); +} \ No newline at end of file diff --git a/ast.h b/ast.h new file mode 100644 index 0000000..61193c2 --- /dev/null +++ b/ast.h @@ -0,0 +1,106 @@ +typedef struct Decl_Enum_Child Decl_Enum_Child; +typedef struct Typespec Typespec; +typedef struct Decl Decl; +typedef struct Note Note; + +//----------------------------------------------------------------------------- +// Type specifier +//----------------------------------------------------------------------------- +typedef enum Typespec_Kind{ + TS_None, + TS_Name, + TS_Pointer, + TS_Array, + TS_Function, + TS_Struct, +}Typespec_Kind; + +struct Typespec{ + Typespec_Kind kind; + Typespec *next; + Token *pos; + union{ + Intern_String name; + Decl *struct_spec; + struct{ + Typespec *first; + Typespec *last; + Typespec *ret; + }function_spec; + struct{ + Typespec *base; + Expr *size; + }array_spec; + Typespec *base; + }; +}; + +//----------------------------------------------------------------------------- +// Notes +//----------------------------------------------------------------------------- +struct Note{ + Token *pos; + Intern_String name; + Expr *expr; + + Note *next; + Note *first; + Note *last; +}; + +//----------------------------------------------------------------------------- +// Declarations +//----------------------------------------------------------------------------- +typedef enum Decl_Kind{ + DECL_None, + DECL_Struct, + DECL_Union, + DECL_Enum, + DECL_Variable, + DECL_Typedef, + DECL_List, +}Decl_Kind; + +struct Decl_Enum_Child{ + Decl_Enum_Child *next; + Intern_String name; + Token *pos; + Expr *expr; + + Note *first_note; + Note *last_note; +}; + +struct Decl{ + Decl_Kind kind; + Intern_String name; + Token *pos; + Decl *next; + + 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; + }variable_decl; + struct{ + Typespec *type; + }typedef_decl; + struct{ + Decl *first; + Decl *last; + }list; + }; +}; + diff --git a/expr.c b/expr.c index e66330f..6bfb600 100644 --- a/expr.c +++ b/expr.c @@ -53,15 +53,29 @@ expr_index(Parser *p, Token *token, Expr *atom, Expr *index){ return expr; } -/* function Expr * -expr_cast(Parser *p, Token *token, AST_Node *type, Expr *exp){ +expr_cast(Parser *p, Token *token, Typespec *type, Expr *exp){ Expr *expr = expr_new(p, EK_Cast, token); expr->cast.type = type; expr->cast.expr = exp; return expr; } - */ + +function Expr * +expr_sizeof_type(Parser *p, Token *token, Typespec *type){ + Expr *expr = expr_new(p, EK_Sizeof, token); + expr->size_of.kind = SIZEOF_Type; + expr->size_of.type = type; + return expr; +} + +function Expr * +expr_sizeof_expr(Parser *p, Token *token, Expr *in_expr){ + Expr *expr = expr_new(p, EK_Sizeof, token); + expr->size_of.kind = SIZEOF_Expr; + expr->size_of.expr = in_expr; + return expr; +} function Expr * expr_list(Parser *p, Token *token){ diff --git a/expr.h b/expr.h index fd19b4a..ab6c334 100644 --- a/expr.h +++ b/expr.h @@ -1,5 +1,11 @@ #pragma once typedef struct Expr Expr; +typedef struct Typespec Typespec; + +typedef enum Expr_Sizeof_Kind{ + SIZEOF_Expr, + SIZEOF_Type, +}Expr_Sizeof_Kind; typedef enum Expr_Kind{ EK_None, @@ -11,6 +17,7 @@ typedef enum Expr_Kind{ EK_List, EK_Call, EK_Index, + EK_Sizeof, } Expr_Kind; struct Expr { @@ -19,7 +26,7 @@ struct Expr { Expr *next; union { struct { - //Typespec *type; + Typespec *type; Expr* expr; } cast; struct { @@ -46,5 +53,12 @@ struct Expr { Expr* on_true; Expr* on_false; } ternary; + struct{ + Expr_Sizeof_Kind kind; + union{ + Typespec *type; + Expr *expr; + }; + } size_of; }; }; diff --git a/ideas.cpp b/ideas.cpp index ac46da9..3e4076a 100644 --- a/ideas.cpp +++ b/ideas.cpp @@ -1,5 +1,41 @@ +Thing :: struct{ + data: (U32) U32; // Function pointer + data: (U32) U32 @ [32]; // Array of function pointers + data: (U32) U32* @ [32]; // Array of function pointers, they return a pointer + + actual_function :: (first: Thing*, last: Thing*, node: Thing*)/*no type == void*/{ + if first == 0 { + first = last = node; + } + else{ + last = last->next = node; + } + } + + StructInside :: struct { // This is not part of struct + // just in scope + some_val: U16; + some_val2: U16; + } + + insider: StructInside; + + named_union_part_of_struct: union{ + some_val: U16; + some_val2: U32; + } + + _: union { + // Unamed union + val: U32; + } + +} -Thingy::enum{ + + + +Thingy::enum:U32{ @str=10 Value = 1, } diff --git a/main.c b/main.c index ed73962..79e6843 100644 --- a/main.c +++ b/main.c @@ -9,6 +9,7 @@ #include "lex.h" #include "parser.h" #include "expr.h" +#include "ast.h" global FILE *global_output_file; #define lex_print(...) fprintf(global_output_file, __VA_ARGS__) @@ -21,8 +22,10 @@ global FILE *global_output_file; #include "lex.c" #include "expr.c" +#include "ast.c" #include "parse_expr.c" #include "parse_decl.c" +#include "print.c" function void lex_test(){ @@ -77,25 +80,40 @@ parser_test(){ assert(token_match(&p, TK_End)); String exprs[] = { + lit("(534>43?435:42,234,cast(S64)32/*todo cast*/,Thing[10][2],Thing(1,2))"), lit("(4+2*53)"), lit("((4+2)*53)"), lit("++5"), lit("5--"), // @Todo(Krzosa): lit("-5"), lit("(+5)"), - lit("cast(S64)5"), + lit("sizeof(32) + sizeof(:S32*)"), + lit("cast(S64**)5"), lit("cast(S64)5+3"), lit("534>43?435:42"), - lit("(534>43?435:42,234,cast(S64)42,Thing[10][2],Thing(1,2))"), }; for(S64 i = 0; i < buff_cap(exprs); i++){ parser_lex_stream(&p, exprs[i], lit("File")); Expr *expr = parse_expr(&p); assert(expr); - expr_print(expr); + 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); } function S32 diff --git a/output.cc b/output.cc index e69de29..103b9ed 100644 --- a/output.cc +++ b/output.cc @@ -0,0 +1,246 @@ +(((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) +struct OS_Memory{ +data: void*; +commit: SizeU; +reserve: SizeU; +}; + +struct Arena{ +@using memory: OS_Memory; +len: U64; +alignment: U64; +}; + +struct String{ +str: U8*; +len: S64; +}; + +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, +}; + +struct Token{ +kind: Token_Kind; +@using string: String; +val: union { +integer: S64; +error: String; +intern: Intern_String; +}; + +file: String; +line: S64; +line_begin: U8*; +}; + +struct Tokens{ +@array tokens: Token*; +iter: S64; +}; + +struct Lex_Stream{ +stream: U8*; +line_begin: U8*; +filename: String; +line: S64; +}; + +@prefix = EK_ enum Expr_Kind : S64{ +None, +Atom, +Unary, +Binary, +Ternary, +Cast, +List, +Call, +Index, +}; + +struct Expr{ +kind: Expr_Kind; +token: Token*; +next: Expr*; +_: 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_ enum AST_Kind : S64{ +None, +BaseType, +Typedef, +Enum, +Struct, +Union, +Note, +List, +Pointer, +Array, +Function, +Variable, +EnumChild, +}; + +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*; +}; + +}; + +struct Parser_Error{ +next: Parser_Error*; +message: String; +token: Token*; +}; + +struct Scope{ +next: Scope*; +first: AST_Node*; +last: AST_Node*; +}; + +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; +}; + diff --git a/parse_decl.c b/parse_decl.c index 36f71b7..466b4a1 100644 --- a/parse_decl.c +++ b/parse_decl.c @@ -1,20 +1,88 @@ -#if 0 +function Decl *parse_decl(Parser *p); +function Decl *parse_struct(Parser *p, Token *name, Decl_Kind kind); +function Typespec *parse_type(Parser *p); -function Token * -parse__get_name(Parser *p){ - Token *name = token_next(p); - token_next(p); - token_next(p); - return name; +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); + if(!token_is(p, TK_CloseParen)) + for(;;) { + if(token_is(p, TK_Identifier)){ + Typespec *arg = parse_type(p); + typespec_function_push(result, arg); + } + else if(!token_match(p, TK_Comma)){ + break; + } + } + token_expect(p, TK_CloseParen); + if(token_is(p, TK_Identifier)){ + result->function_spec.ret = parse_type(p); + } + else{ + result->function_spec.ret = typespec_name(p, token_get(p), intern_void); + } + return result; +} + +function Typespec * +parse_type(Parser *p){ + 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); + } + else{ + parser_push_error(p, token, "Failed to parse type, unexpected token"); + return 0; + } + + for(;;){ + if((token = token_match(p, TK_Mul))){ + result = typespec_pointer(p, token, result); + } + else if((token = token_match(p, TK_OpenBracket))){ + Expr *expr = parse_expr(p); + result = typespec_array(p, token, result, expr); + token_expect(p, TK_CloseBracket); + } + else if(token_match(p, TK_At)){ + break; + } + else break; + } + return result; +} + +function Expr * +parse_expr_assignment(Parser *p){ + Expr *result = 0; + if(token_match(p, TK_Assign)){ + result = parse_expr(p); + } + return result; } function void -parse_note_list(Parser *ctx, AST_Node *parent) { +parse_note_list(Parser *ctx, Note *parent) { if(token_match(ctx, TK_OpenParen)) { do { Token *name = token_expect(ctx, TK_Identifier); - AST_Node *current = ast_note(ctx, name, name->intern_val, 0); - ast_node_push_note(parent, current); + Note *current = note_push_new(ctx, parent, name, name->intern_val, 0); parse_note_list(ctx, current); if(token_match(ctx, TK_Assign)) { current->expr = parse_expr(ctx); @@ -25,11 +93,10 @@ parse_note_list(Parser *ctx, AST_Node *parent) { } function void -parse__notes(Parser *ctx, AST_Node *result) { +parse__notes(Parser *ctx, Note *result) { while(token_match(ctx, TK_At)) { Token *name = token_expect(ctx, TK_Identifier); - AST_Node *current = ast_note(ctx, name, name->intern_val, 0); - ast_node_push_note(result, current); + Note *current = note_push_new(ctx, result, name, name->intern_val, 0); parse_note_list(ctx, current); if(token_match(ctx, TK_Assign)) { current->expr = parse_expr(ctx); @@ -37,185 +104,316 @@ parse__notes(Parser *ctx, AST_Node *result) { } } -function AST_Node +function Note parse_notes(Parser *p){ - AST_Node result = {}; + Note result = {}; parse__notes(p, &result); return result; } -function AST_Node * +function Decl * parse_enum(Parser *p, Token *name){ - AST_Node *result = 0; - if(token_expect(p, TK_OpenBrace)){ - result = ast_enum(p, name, name->intern_val); - do{ - AST_Node notes = parse_notes(p); - Token *token = token_match(p, TK_Identifier); - if(token){ - Expr *expr = 0; - if(token_match(p, TK_Assign)){ - expr = parse_expr(p); - } - - AST_Node *child = ast_enum_child(p, token, token->intern_val, expr); - ast_node_pass_note_list(child,¬es); - ast_node_push_child(result, child); - } - else{ - break; - } - } while(token_match(p, TK_Comma)); - token_expect(p, TK_CloseBrace); - } - return result; -} - -function AST_Node * -parse_variable(Parser *p, Token *name){ - AST_Node *result = 0; - Token *type_token = token_expect(p, TK_Identifier); - if(type_token){ - AST_Node *type = symbol_require_type(p, type_token); - Token *star; - while((star = token_match(p, TK_Mul))){ - type = ast_type_pointer(p, star, type); - } - while((star = token_match(p, TK_OpenBracket))){ - Expr *expr = parse_expr(p); - type = ast_type_array(p, star, type, expr); - token_expect(p, TK_CloseBracket); - } - Expr *expr = 0; - if(token_match(p, TK_Assign)){ - expr = parse_expr(p); - } - result = ast_variable(p, name, name->intern_val, type, expr); - } - return result; -} - -function AST_Node * -parse_struct(Parser *p, Token *name, AST_Kind kind, B32 is_global){ - AST_Node *result = 0; - if(token_expect(p, TK_OpenBrace)){ - result = ast_struct(p, name, name?name->intern_val:(Intern_String){}, kind); - if(is_global) symbol_register(p, result); - - for(;;){ - AST_Node notes = parse_notes(p); - AST_Node *mem = 0; - Token *mem_name = token_match(p, TK_Identifier); - if(mem_name){ - if(token_expect(p, TK_Colon)){ - - if(token_match_keyword(p, keyword_struct)){ - mem = parse_struct(p, mem_name, AK_Struct, false); - } - else if(token_match_keyword(p, keyword_union)){ - mem = parse_struct(p, mem_name, AK_Union, false); - } - //else if(token_match_keyword(p, keyword_enum)){ - //mem = parse_enum(p, mem_name); - //} - else if(token_is(p, TK_Identifier)){ - mem = parse_variable(p, mem_name); - token_expect(p, TK_Semicolon); - } - else parser_push_error(p, mem_name, "Unrecognized token while parsing struct"); - - if(mem){ - ast_node_pass_note_list(mem, ¬es); - ast_node_push_child(result, mem); - } - - } - else{ - break; - } - } - else if(token_match_keyword(p, keyword_union) && - token_match(p, TK_Colon)){ - mem = parse_struct(p, 0, AK_Union, false); - ast_node_pass_note_list(mem, ¬es); - ast_node_push_child(result, mem); - } - else if(token_match_keyword(p, keyword_struct) && - token_match(p, TK_Colon)){ - mem = parse_struct(p, 0, AK_Struct, false); - ast_node_pass_note_list(mem, ¬es); - ast_node_push_child(result, mem); - } - else if(token_expect(p, TK_CloseBrace)){ - break; - } - else{ - break; - } - } - } - return result; -} - -function AST_Node * -parse_typedef(Parser *p, Token *name){ - Token *type_token = token_expect(p, TK_Identifier); - AST_Node *type = symbol_require_type(p, type_token); - AST_Node *result = ast_typedef(p, name, name->intern_val, type); - token_expect(p, TK_Semicolon); - return result; -} - -function AST_Node_List * -parse(Parser *p){ - AST_Node_List *result = ast_node_new(p, AK_List, token_get(p), intern_empty); + Typespec *type = 0; + if(token_match(p, TK_Colon)) type = parse_type(p); + else type = typespec_name(p, token_get(p), intern_s64); - for(;;){ - AST_Node *node = 0; - AST_Node notes = parse_notes(p); - - if(token_is(p, TK_End)){ + Decl *result = decl_enum(p, name, name->intern_val, type); + token_expect(p, TK_OpenBrace); + do{ + Note notes = parse_notes(p); + Token *token = token_match(p, TK_Identifier); + if(token){ + Expr *expr = parse_expr_assignment(p); + decl_enum_push(p, result, token, token->intern_val, expr, ¬es); + } else break; + } while(token_match(p, TK_Comma)); + token_expect(p, TK_CloseBrace); + return result; +} + +function Decl * +parse_struct(Parser *p, Token *name, Decl_Kind kind){ + Decl *result = decl_struct(p, kind, name, name->intern_val); + 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 { + parser_push_error(p, token_get(p), "Unexpected token while parsing struct"); break; } - else if(token_is(p, TK_Error)){ - break; - } - else if(token_is(p, TK_Identifier) && // Peeking to be more error averse - token_peek_is(p, 1, TK_Colon)){ + } + token_expect(p, TK_CloseBrace); + return result; +} + +function Decl * +parse_variable(Parser *p, Token *name){ + Typespec *type = parse_type(p); + Expr *expr = parse_expr_assignment(p); + token_expect(p, TK_Semicolon); + return decl_variable(p, name, name->intern_val, type, expr); +} + +function Decl * +parse_typedef(Parser *p, Token *name){ + Typespec *type = parse_type(p); + 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); + return result; +} + +function Decl * +parse_decl(Parser *p){ + Decl *result = 0; + Note notes = parse_notes(p); + + if(token_is(p, TK_Identifier)){ + if(token_peek_is(p, 1, TK_DoubleColon)){ if(token_peek_is_keyword(p, 2, keyword_struct)){ - node = parse_struct(p, parse__get_name(p), AK_Struct, true); - symbol_register(p, node); + result = parse_struct(p, parse_get_token_name(p,2), DECL_Struct); } else if(token_peek_is_keyword(p, 2, keyword_union)){ - node = parse_struct(p, parse__get_name(p), AK_Union, true); - symbol_register(p, node); + result = parse_struct(p, parse_get_token_name(p,2), DECL_Union); } else if(token_peek_is_keyword(p, 2, keyword_enum)){ - node = parse_enum(p, parse__get_name(p)); - symbol_register(p, node); + result = parse_enum(p, parse_get_token_name(p,2)); } else if(token_peek_is_keyword(p, 2, keyword_typedef)){ - node = parse_typedef(p, parse__get_name(p)); - symbol_register(p, node); + result = parse_typedef(p, parse_get_token_name(p,2)); + } + } + 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)); + } + } + } + + if(result){ + result->first_note = notes.first; + result->last_note = notes.last; + } + else if(notes.first != 0){ + parser_push_error(p, token_get(p), "Detected notes that are not attached to anything"); + } + + return result; +} + +function Decl * +parse(Parser *p){ + Decl *result = decl_new(p, DECL_List, token_get(p), (Intern_String){}); + for(;;){ + Decl *decl = 0; + if(token_is(p, TK_End)) { + break; + } + else if((decl = parse_decl(p))){ + // Noop + } + else token_next(p); + + if(decl){ + decl_list_push(result, decl); + } + } + return result; +} + + +/* +function Token * +parse__get_name(Parser *p){ +Token *name = token_next(p); +token_next(p); +token_next(p); +return name; +} + +function Note * +parse_enum(Parser *p, Token *name){ +Note *result = 0; +if(token_expect(p, TK_OpenBrace)){ + result = ast_enum(p, name, name->intern_val); + do{ + Note notes = parse_notes(p); + Token *token = token_match(p, TK_Identifier); + if(token){ + Expr *expr = 0; + if(token_match(p, TK_Assign)){ + expr = parse_expr(p); + } + + Note *child = ast_enum_child(p, token, token->intern_val, expr); + ast_node_pass_note_list(child,¬es); + ast_node_push_child(result, child); + } + else{ + break; + } + } while(token_match(p, TK_Comma)); + token_expect(p, TK_CloseBrace); +} +return result; +} + +function Note * +parse_variable(Parser *p, Token *name){ +Note *result = 0; +Token *type_token = token_expect(p, TK_Identifier); +if(type_token){ + Note *type = symbol_require_type(p, type_token); + Token *star; + while((star = token_match(p, TK_Mul))){ + type = ast_type_pointer(p, star, type); + } + while((star = token_match(p, TK_OpenBracket))){ + Expr *expr = parse_expr(p); + type = ast_type_array(p, star, type, expr); + token_expect(p, TK_CloseBracket); + } + Expr *expr = 0; + if(token_match(p, TK_Assign)){ + expr = parse_expr(p); + } + result = ast_variable(p, name, name->intern_val, type, expr); +} +return result; +} + +function Note * +parse_struct(Parser *p, Token *name, AST_Kind kind, B32 is_global){ +Note *result = 0; +if(token_expect(p, TK_OpenBrace)){ + result = ast_struct(p, name, name?name->intern_val:(Intern_String){}, kind); + if(is_global) symbol_register(p, result); + + for(;;){ + Note notes = parse_notes(p); + Note *mem = 0; + Token *mem_name = token_match(p, TK_Identifier); + if(mem_name){ + if(token_expect(p, TK_Colon)){ + + if(token_match_keyword(p, keyword_struct)){ + mem = parse_struct(p, mem_name, AK_Struct, false); + } + else if(token_match_keyword(p, keyword_union)){ + mem = parse_struct(p, mem_name, AK_Union, false); + } + //else if(token_match_keyword(p, keyword_enum)){ + //mem = parse_enum(p, mem_name); + //} + else if(token_is(p, TK_Identifier)){ + mem = parse_variable(p, mem_name); + token_expect(p, TK_Semicolon); + } + else parser_push_error(p, mem_name, "Unrecognized token while parsing struct"); + + if(mem){ + ast_node_pass_note_list(mem, ¬es); + ast_node_push_child(result, mem); + } + } else{ - token_next(p); + break; } } + else if(token_match_keyword(p, keyword_union) && + token_match(p, TK_Colon)){ + mem = parse_struct(p, 0, AK_Union, false); + ast_node_pass_note_list(mem, ¬es); + ast_node_push_child(result, mem); + } + else if(token_match_keyword(p, keyword_struct) && + token_match(p, TK_Colon)){ + mem = parse_struct(p, 0, AK_Struct, false); + ast_node_pass_note_list(mem, ¬es); + ast_node_push_child(result, mem); + } + else if(token_expect(p, TK_CloseBrace)){ + break; + } + else{ + break; + } + } +} +return result; +} + +function Note * +parse_typedef(Parser *p, Token *name){ +Token *type_token = token_expect(p, TK_Identifier); +Note *type = symbol_require_type(p, type_token); +Note *result = ast_typedef(p, name, name->intern_val, type); +token_expect(p, TK_Semicolon); +return result; +} + +function Note_List * +parse(Parser *p){ +Note_List *result = ast_node_new(p, AK_List, token_get(p), intern_empty); + +for(;;){ + Note *node = 0; + Note notes = parse_notes(p); + + if(token_is(p, TK_End)){ + break; + } + else if(token_is(p, TK_Error)){ + break; + } + else if(token_is(p, TK_Identifier) && // Peeking to be more error averse + token_peek_is(p, 1, TK_Colon)){ + if(token_peek_is_keyword(p, 2, keyword_struct)){ + node = parse_struct(p, parse__get_name(p), AK_Struct, true); + symbol_register(p, node); + } + else if(token_peek_is_keyword(p, 2, keyword_union)){ + node = parse_struct(p, parse__get_name(p), AK_Union, true); + symbol_register(p, node); + } + else if(token_peek_is_keyword(p, 2, keyword_enum)){ + node = parse_enum(p, parse__get_name(p)); + symbol_register(p, node); + } + else if(token_peek_is_keyword(p, 2, keyword_typedef)){ + node = parse_typedef(p, parse__get_name(p)); + symbol_register(p, node); + } else{ token_next(p); } - - - if(node){ - ast_node_pass_note_list(node, ¬es); - ast_node_push_child(result, node); - } - else if(notes.first_note != 0){ - parser_push_error(p, token_get(p), "Warning: notes got lost"); - } + } + else{ + token_next(p); } - return result; + + if(node){ + ast_node_pass_note_list(node, ¬es); + ast_node_push_child(result, node); + } + else if(notes.first_note != 0){ + parser_push_error(p, token_get(p), "Warning: notes got lost"); + } } -#endif \ No newline at end of file + +return result; +} +*/ \ No newline at end of file diff --git a/parse_expr.c b/parse_expr.c index e00a1ba..c54cf69 100644 --- a/parse_expr.c +++ b/parse_expr.c @@ -1,5 +1,6 @@ function Expr* parse_expr(Parser* p); function Expr* parse_list_expr(Parser* p); +function Typespec *parse_type(Parser *p); function Expr* parse_atom_expr(Parser* p){ @@ -10,6 +11,21 @@ parse_atom_expr(Parser* p){ token_is(p, TK_Int)){ result = expr_atom(p, token_next(p)); } + + else if (token_is_keyword(p, keyword_sizeof)) { + Token *token = token_next(p); + token_expect(p, TK_OpenParen); + Typespec *type = 0; + Expr *expr = 0; + if(token_match(p, TK_Colon)) { + result = expr_sizeof_type(p, token, parse_type(p)); + } + else { + result = expr_sizeof_expr(p, token, parse_expr(p)); + } + token_expect(p, TK_CloseParen); + } + else if (token_match(p, TK_OpenParen)){ result = parse_list_expr(p); token_expect(p, TK_CloseParen); @@ -24,17 +40,13 @@ function Expr* parse_postfix_expr(Parser* p){ Expr* result = parse_atom_expr(p); while (token_is(p, TK_Dot) - || token_is(p, TK_Arrow) - || token_is(p, TK_DoubleColon) || token_is(p, TK_OpenParen) || token_is(p, TK_OpenBracket) || token_is(p, TK_Decrement) || token_is(p, TK_Increment)){ Token *op = token_get(p); - if (token_match(p, TK_Arrow) - || token_match(p, TK_DoubleColon) - || token_match(p, TK_Dot)){ + if (token_match(p, TK_Dot)){ Expr* r = parse_atom_expr(p); result = expr_binary(p, op, result, r); } @@ -85,35 +97,16 @@ Expr* parse_unary_expr(Parser* p) { result = parse_unary_expr(p); result = expr_unary(p, op, result); } - else if (token_is_keyword(p, keyword_sizeof)) { + + else if (token_is_keyword(p, keyword_cast)) { Token *token = token_next(p); + token_expect(p, TK_OpenParen); + Typespec *type = parse_type(p); + token_expect(p, TK_CloseParen); result = parse_unary_expr(p); - result = expr_unary(p, token, result); + result = expr_cast(p, token, type, result); } - /* - else if (token_is(p, TK_OpenParen)) { // cast requires lookahead - Token *token = token_peek(p, 1); - if (token->kind == TK_Identifier) { - - AST_Node *type = symbol_lookup_type(p, token->intern_val); - if(type){ - token_next(p); - token_next(p); - // @Todo(Krzosa): Parse pointer types - token_expect(p, TK_CloseParen); - result = parse_unary_expr(p); - result = expr_cast(p, token, type, result); - } - else { - result = parse_postfix_expr(p); - } - - } - else { - result = parse_postfix_expr(p); - } - } - */ + else { result = parse_postfix_expr(p); } diff --git a/parser.c b/parser.c index d721454..95bca9d 100644 --- a/parser.c +++ b/parser.c @@ -14,6 +14,7 @@ global Intern_String intern_void; global Intern_String intern_sizeu; global Intern_String keyword_sizeof; +global Intern_String keyword_cast; global Intern_String keyword_enum; global Intern_String keyword_typedef; global Intern_String keyword_struct; @@ -27,6 +28,7 @@ parser_init(Parser *p){ p->interns = arena_push_array(&p->intern_table_arena, Intern_String, p->interns_count); keyword_sizeof = intern_string(p, lit("sizeof")); + keyword_cast = intern_string(p, lit("cast")); keyword_struct = intern_string(p, lit("struct")); keyword_enum = intern_string(p, lit("enum")); keyword_typedef = intern_string(p, lit("typedef")); @@ -36,7 +38,6 @@ parser_init(Parser *p){ p->first_keyword = keyword_sizeof.s.str; p->last_keyword = keyword_global.s.str; - intern_s64 = intern_string(p, lit("S64")); intern_s32 = intern_string(p, lit("S32")); intern_s16 = intern_string(p, lit("S16")); @@ -60,7 +61,6 @@ intern_is_keyword(Parser *p, Intern_String intern){ function void parser_push_error(Parser *p, Token *token, char *str, ...){ - String string; { va_list args1, args2; @@ -80,6 +80,9 @@ parser_push_error(Parser *p, Token *token, char *str, ...){ error->next = 0; error->token = token; SLLQueuePush(p->first_error, p->last_error, error); + + __debugbreak(); + exit(-1); } function void diff --git a/print.c b/print.c new file mode 100644 index 0000000..92a6c82 --- /dev/null +++ b/print.c @@ -0,0 +1,219 @@ +function void print_decl(Parser *p, Decl *node); +function B32 print_typespec(Parser *p, Typespec *spec); + +function void +tokens_print(Tokens tokens){ + lex_print("\n== Token count = %d\n", (S32)tokens.len); + for(Token *t = tokens.tokens; t != tokens.tokens + tokens.len; t++){ + lex_print("%s \"%.*s\"\n", token_kind_string[t->kind].str, (S32)t->len, t->str); + } +} + +function void +token_print(Token *token){ + lex_print("%.*s", (S32)token->len, token->str); +} + +function void +expr_print(Parser *p, Expr *expr){ + switch(expr->kind) { + case EK_Atom: { + token_print(expr->token); + } break; + + case EK_Sizeof:{ + lex_print("sizeof("); + if(expr->size_of.kind == SIZEOF_Expr){ + expr_print(p, expr->size_of.expr); + } + else{ + assert(expr->size_of.kind == SIZEOF_Type); + print_typespec(p, expr->size_of.type); + } + lex_print(")"); + }break; + + case EK_Binary:{ + lex_print("("); + expr_print(p, expr->binary.left); + token_print(expr->token); + expr_print(p, expr->binary.right); + lex_print(")"); + } break; + case EK_Unary:{ + lex_print("("); + token_print(expr->token); + expr_print(p, expr->unary.expr); + lex_print(")"); + } break; + + case EK_Ternary:{ + lex_print("("); + expr_print(p, expr->ternary.cond); + lex_print("?"); + expr_print(p, expr->ternary.on_true); + lex_print(":"); + expr_print(p, expr->ternary.on_false); + lex_print(")"); + } break; + case EK_List:{ + lex_print("("); + for(Expr *n = expr->list.first; n; n=n->next){ + expr_print(p, n); + if(n!=expr->list.last) lex_print(","); + } + lex_print(")"); + }break; + + case EK_Cast:{ + lex_print("("); + lex_print("("); + print_typespec(p, expr->cast.type); + lex_print(")"); + expr_print(p, expr->cast.expr); + lex_print(")"); + } break; + + case EK_Index:{ + expr_print(p, expr->index.atom); + lex_print("["); + expr_print(p, expr->index.index); + lex_print("]"); + }break; + + case EK_Call:{ + expr_print(p, expr->call.atom); + lex_print("("); + expr_print(p, expr->call.list); + lex_print(")"); + }break; + default: {invalid_codepath;} break; + } +} + +global S64 indent; + + +function B32 +print_typespec(Parser *p, Typespec *spec){ + switch(spec->kind) { + case TS_Name: { + 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); + lex_print("*"); + } break; + + case TS_Array: { + print_typespec(p, spec->array_spec.base); + lex_print("["); + expr_print(p, spec->array_spec.size); + lex_print("]"); + } break; + + case TS_Function: { + lex_print("("); + for(Typespec *n = spec->function_spec.first; n; n=n->next){ + print_typespec(p,n); + if(n!=spec->function_spec.last) + lex_print(", "); + } + + lex_print(")"); + print_typespec(p,spec->function_spec.ret); + } break; + default: {invalid_codepath;} break; + } + return true; +} + +function void +print_assign_expr(Parser *p, Expr *expr){ + if(expr){ + lex_print(" = "); + expr_print(p, expr); + } +} + +function void +print_note_list(Parser *p, Note *note){ + if(note){ + lex_print("("); + for(Note *n = note; n; n=n->next){ + lex_print("%s", n->name.s.str); + print_note_list(p,n->first); + print_assign_expr(p, n->expr); + } + lex_print(")"); + } +} + +function void +print_notes(Parser *p, Note *note){ + for(Note *n = note; n; n=n->next){ + lex_print("@%s", n->name.s.str); + print_note_list(p,n->first); + print_assign_expr(p,n->expr); + lex_print(" "); + } +} + +function void +print_decl(Parser *p, Decl *node){ + print_notes(p, node->first_note); + + switch(node->kind) { + case DECL_List: { + for(Decl *n = node->list.first; n; n=n->next){ + print_decl(p,n); + lex_new_line(); + } + } break; + + case DECL_Variable:{ + lex_print("%s: ", node->name.s.str); + B32 r = print_typespec(p, node->variable_decl.type); + print_assign_expr(p,node->variable_decl.expr); + if(r) lex_print(";"); + } break; + + case DECL_Typedef:{ + lex_print("typedef %s ", node->name.s.str); + print_typespec(p, node->typedef_decl.type); + lex_print(";"); + } break; + + case DECL_Struct: + case DECL_Union :{ + const char *struct_name = node->kind==DECL_Struct ? "struct" : "union"; + lex_print("%s %s{\n", struct_name, node->name.s.str?(char*)node->name.s.str:""); + for(Decl *n = node->struct_decl.first; n; n=n->next){ + print_decl(p, n); + lex_print("\n"); + } + lex_print("};\n"); + } break; + case DECL_Enum:{ + lex_print("enum %s : ", node->name.s.str); + print_typespec(p, node->enum_decl.typespec); + lex_print("{\n"); + for(Decl_Enum_Child *n = node->enum_decl.first; n; n=n->next){ + print_notes(p, n->first_note); + lex_print("%s", n->name.s.str); + print_assign_expr(p, n->expr); + lex_print(",\n"); + } + lex_print("};\n"); + } break; + default: {invalid_codepath;} break; + } +} + + diff --git a/test.cc b/test.cc index 94f52b4..5fbcd01 100644 --- a/test.cc +++ b/test.cc @@ -1,26 +1,26 @@ #if 0 -OS_Memory:struct{ +OS_Memory::struct{ data: void*; commit: SizeU; reserve: SizeU; } -Arena:struct{ +Arena::struct{ @using memory: OS_Memory; len: U64; alignment: U64; } -String:struct{ +String::struct{ str: U8*; len: S64; } -Intern_String:typedef String; +Intern_String::typedef String; @stringify @prefix="TK_" -Token_Kind:enum{ +Token_Kind::enum{ @str="End of stream" End, @str="*" Mul, @str="/" Div, @@ -86,25 +86,25 @@ Token_Kind:enum{ Keyword, } -Token:struct{ +Token::struct{ kind:Token_Kind; @using string:String; - union:{ - int_val:S64; - error_val:String; - intern_val:Intern_String; - } + val: union{ + integer:S64; + error:String; + intern:Intern_String; + }; file:String; line:S64; line_begin:U8*; } -Tokens:struct{ +Tokens::struct{ @array tokens: Token*; iter : S64; } -Lex_Stream:struct{ +Lex_Stream::struct{ stream: U8*; line_begin: U8*; filename: String; @@ -112,7 +112,7 @@ Lex_Stream:struct{ } @prefix="EK_" -Expr_Kind: enum{ +Expr_Kind::enum{ None, Atom, Unary, @@ -124,46 +124,44 @@ Expr_Kind: enum{ Index, } -/* -Expr: struct{ +Expr:: struct{ kind: Expr_Kind; token: Token*; next : Expr*; - union:{ - cast: struct{ + _: 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_" -AST_Kind:enum{ +AST_Kind::enum{ None, BaseType, Typedef, @@ -179,7 +177,7 @@ AST_Kind:enum{ EnumChild, } -AST_Node:struct{ +AST_Node::struct{ kind: AST_Kind; pos : Token*; name: Intern_String; @@ -192,28 +190,28 @@ 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{ +Parser_Error :: struct{ next: Parser_Error*; message: String; token : Token *; } -Scope: struct{ +Scope :: struct{ next : Scope*; first: AST_Node*; last : AST_Node*; } -Parser: struct{ +Parser :: struct{ main_arena: Arena; intern_table_arena: Arena; symbol_table_arena: Arena;