diff --git a/ast.c b/ast.c index dc54dd4..4ee6bc0 100644 --- a/ast.c +++ b/ast.c @@ -15,12 +15,47 @@ ast_node_new(Parser *p, AST_Kind kind, Token *token, Intern_String name){ return node; } +function AST_Node * +ast_note(Parser *p, Token *token, Intern_String name, Expr *expr){ + AST_Node *node = ast_node_new(p, AK_Note, token, name); + node->expr = expr; + return node; +} + function AST_Node * ast_enum(Parser *p, Token *token, Intern_String name){ AST_Node *node = ast_node_new(p, AK_Enum, token, name); return node; } +function AST_Node * +ast_struct(Parser *p, Token *token, Intern_String name, AST_Kind kind){ + AST_Node *node = ast_node_new(p, kind, token, name); + return node; +} + +function AST_Node * +ast_variable(Parser *p, Token *token, Intern_String name, AST_Node *type, Expr *expr){ + AST_Node *node = ast_node_new(p, AK_Variable, token, name); + node->variable_type = type; + node->expr = expr; + return node; +} + +function AST_Node * +ast_typedef(Parser *p, Token *token, Intern_String name, AST_Node *type){ + AST_Node *node = ast_node_new(p, AK_Typedef, token, name); + node->typedef_type = type; + return node; +} + +function AST_Node * +ast_function(Parser *p, Token *token, Intern_String name, AST_Node *return_type){ + AST_Node *node = ast_node_new(p, AK_Function, token, name); + node->func_return_type = return_type; + return node; +} + function AST_Node * ast_enum_child(Parser *p, Token *token, Intern_String name, Expr *expr){ AST_Node *node = ast_node_new(p, AK_EnumChild, token, name); @@ -28,6 +63,39 @@ ast_enum_child(Parser *p, Token *token, Intern_String name, Expr *expr){ return node; } +function void +ast_copy_symbol(AST_Node *dst, AST_Node *src){ + AST_Node *scope_next = dst->next_scope; + *dst = *src; + dst->next_scope = scope_next; +} + +function AST_Node * +ast_type_pointer(Parser *p, Token *token, AST_Node *pointer_to){ + AST_Node *node = ast_node_new(p, AK_Pointer, token, intern_empty); + node->pointer = pointer_to; + return node; +} + +function AST_Node * +ast_type_array(Parser *p, Token *token, AST_Node *pointer_to, Expr *expr){ + AST_Node *node = ast_node_new(p, AK_Array, token, intern_empty); + node->pointer = pointer_to; + node->expr = expr; + return node; +} + +function void +ast_node_pass_note_list(AST_Node *node, AST_Node *notes){ + node->first_note = notes->first_note; + node->last_note = notes->last_note; +} + +function void +ast_node_push_note(AST_Node *node, AST_Node *child){ + SLLQueuePush(node->first_note, node->last_note, child); +} + function void ast_node_push_child(AST_Node *node, AST_Node *child){ SLLQueuePush(node->first_child, node->last_child, child); diff --git a/ast.h b/ast.h index 0d61fb0..175a582 100644 --- a/ast.h +++ b/ast.h @@ -1,9 +1,142 @@ +#if 0 + + +String:struct{ + str: U8*; + len: S64; +} +Intern_String:typedef String; + +Token_Kind:enum{ + @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, +} + + +Token:struct{ + kind:Token_Kind; + union:{ + string:String; + struct:{str:U8*; len:U64;} + } + union:{ + int_val:S64; + error_val:String; + intern_val:Intern_String; + } + file:String; + line:S64; + line_begin:U8*; +} + + +AST_Kind:enum{ + BaseType, + Typedef, + Enum, + Struct, + Union, + + Note, + List, + + Pointer, + Array, + Function, + Variable, + EnumChild, +} + +AST_Node:struct{ + kind: AST_Kind; + node: AST_Node[16]; + + 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*; + } +} + +#endif + + typedef struct AST_Node AST_Node; typedef struct Expr Expr; typedef enum AST_Kind{ AK_None, - AK_Undefined, AK_BaseType, AK_Typedef, @@ -19,7 +152,6 @@ typedef enum AST_Kind{ AK_Function, AK_Variable, AK_EnumChild, - }AST_Kind; struct AST_Node{ @@ -29,7 +161,7 @@ struct AST_Node{ Intern_String name; AST_Node *next; - AST_Node *scope_next; + AST_Node *next_scope; AST_Node *first_note; AST_Node *last_note; @@ -37,9 +169,10 @@ struct AST_Node{ AST_Node *first_child; AST_Node *last_child; union{ - AST_Node *pointer; SizeU base_type_size; + AST_Node *pointer; AST_Node *typedef_type; + AST_Node *variable_type; AST_Node *func_return_type; }; }; diff --git a/ideas.cpp b/ideas.cpp index d61293c..25bc94b 100644 --- a/ideas.cpp +++ b/ideas.cpp @@ -1,3 +1,56 @@ + +call:(param:U32)U32{ + +} + +@stringify +Enumeration:enum{ + None, + Thing = 1 << 10, + Thing2, + Thing3, +} + +@sllqueue() +@sllqueue(prefix=thing_scope, next=next_scope) +Thing:struct{ + next: Thing*; + first: Thing*; + last: Thing*; + next_scope: Thing*; + + val: U32[16]; + str: String; + embed: struct{ + thing: S32; + } +} + +@register(sllqueue, first, last, next) +sllqueue_push:(base:T1, child:T2) void { + if(base.first == 0){ + base.first = base.last = child; + } + else{ + base.last = base.last.next = child; + } +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +/* +function void +thing_sllqueue_push(){ + +} + +function void +thing_scope_sllqueue_push(){ + +} +*/ + Builtin types: B8,B16,B32,B64 S8,S16,S32,S64 @@ -42,3 +95,5 @@ return 0; if(a){}elseif(b){}else{} + + diff --git a/lang.h b/lang.h index 34f6f4a..b0c66df 100644 --- a/lang.h +++ b/lang.h @@ -41,7 +41,7 @@ typedef struct String{ S64 len; }String; -#define SLLQueuePush(f,l,n) do{\ +#define SLLQueuePushMod(f,l,n,next) do{\ if((f)==0){\ (f)=(l)=(n);\ }\ @@ -50,6 +50,8 @@ else{\ } \ }while(0) +#define SLLQueuePush(f,l,n) SLLQueuePushMod(f,l,n,next) + #define SLLStackPush(l,n) do{\ (n)->next = (l);\ diff --git a/lex.c b/lex.c index 183c73a..1439061 100644 --- a/lex.c +++ b/lex.c @@ -57,7 +57,7 @@ lex_is_alphanumeric(U8 c){ function void lex_set_len(Lex_Stream *s, Token *token){ - assert(s->stream > token->str); + assert(s->stream >= token->str); token->len = s->stream - token->str; } @@ -150,6 +150,13 @@ break Token *t = token_alloc(tokens); + if(0){ + top: + while(lex_is_whitespace(*s->stream)) + lex_advance(s); + if(lexc(s) == 0) + break; + } lex_token_seed(s, t); lex_advance(s); switch(*t->str) { @@ -164,6 +171,7 @@ break #undef CASE2 #undef CASE3 + case 0: break; case '@': t->kind = TK_At; break; case '(': t->kind = TK_OpenParen; break; case ')': t->kind = TK_CloseParen; break; @@ -279,20 +287,21 @@ break lex_advance(s); if(lexc(s) == '/'){ lex_advance(s); - t->kind = TK_DocComment; + //t->kind = TK_DocComment; } else { - t->kind = TK_Comment; + //t->kind = TK_Comment; } for(;;){ if(lexc(s) == '\n' || lexc(s) == 0) break; lex_advance(s); } - lex_set_len(s,t); + goto top; + //lex_set_len(s,t); } else if(lexc(s) == '*'){ lex_advance(s); - t->kind = TK_Comment; + //t->kind = TK_Comment; for(;;){ if(s->stream[0] == '*' && s->stream[1] == '/'){ lex_advance(s); @@ -305,7 +314,8 @@ break } lex_advance(s); } - lex_set_len(s,t); + goto top; + //lex_set_len(s,t); } else t->kind = TK_Div; } break; @@ -352,7 +362,7 @@ break lex_advance(s); lex_set_len(s,t); } break; - default: { + default:{ token_error(t, lit("Unknown token")); } break; } @@ -424,9 +434,7 @@ token_is_keyword(Parser *p, Intern_String keyword){ function void token_advance(Parser *p){ - do{ - p->tokens.iter = clamp_top_s64(p->tokens.iter + 1, p->tokens.len); - }while(token_is_comment(token_get(p))); + p->tokens.iter = clamp_top_s64(p->tokens.iter + 1, p->tokens.len); } function Token * @@ -495,4 +503,15 @@ token_peek_is(Parser *p, S64 count, Token_Kind kind){ if(token->kind == kind) return token; return 0; -} \ No newline at end of file +} + +function Token * +token_peek_is_keyword(Parser *p, S64 count, Intern_String keyword){ + Token *token = token_peek(p, count); + if(token->kind == TK_Keyword){ + if(intern_compare(keyword, token->intern_val)){ + return token; + } + } + return 0; +} diff --git a/main.c b/main.c index af9e539..3e57b66 100644 --- a/main.c +++ b/main.c @@ -67,10 +67,10 @@ parser_test(){ } parser_lex_stream(&p, lit("S64 thing; S64 second_var = 10;"), lit("File")); - assert(token_match(&p, TK_Keyword)); + assert(token_match(&p, TK_Identifier)); assert(token_match(&p, TK_Identifier)); assert(token_match(&p, TK_Semicolon)); - assert(token_match(&p, TK_Keyword)); + assert(token_match(&p, TK_Identifier)); assert(token_match(&p, TK_Identifier)); assert(token_match(&p, TK_Assign)); assert(token_match(&p, TK_Int)); @@ -99,20 +99,26 @@ parser_test(){ lex_print("\n"); } - String decls[] = { - lit("enum Thing{ Thing_1 = 10, Thing_2 = 20<<1 };"), - }; - for(S64 i = 0; i < buff_cap(decls); i++){ - parser_lex_stream(&p, decls[i], lit("File")); - AST_Node *node = parse(&p); - assert(node); - - } + /* + String decls = + lit("@Test(a=\"thing\") @str=\"based\" Thing:enum{ Thing_1 = 1<<10, Thing_2 = 10 }" + "TTT:struct{ thing:U64; nested:struct{ thing:S64; }}" + "" + ); + */ + + String decls = os_read_file(lit("ast.h")); + parser_lex_stream(&p, decls, lit("File")); + AST_Node *node = parse(&p); + assert(node->first_child); + assert(node->last_child); + ast_print(node); + } function S32 os_main(){ - global_output_file = fopen("output.txt", "w"); + global_output_file = fopen("output.cc", "w"); assert_msg(global_output_file, "Failed to open output.txt"); lex_test(); parser_test(); diff --git a/memory.c b/memory.c index f6d4a05..ea521c3 100644 --- a/memory.c +++ b/memory.c @@ -24,8 +24,8 @@ arena_init(Arena *a){ function void * arena_push_size(Arena *a, SizeU size){ - SizeU generous_size = size + a->alignment; - if(generous_size>a->memory.commit){ + SizeU generous_size = size; + if(a->memory.commit+generous_size>a->memory.commit){ if(a->memory.reserve == 0){ arena_init(a); } diff --git a/os_win32.c b/os_win32.c index 516bc7c..76165bc 100644 --- a/os_win32.c +++ b/os_win32.c @@ -22,6 +22,22 @@ WinMain(HINSTANCE hInstance, HINSTANCE a, LPSTR b, int nShowCmd){ return os_main(); } +function String +os_read_file(String name){ + String result = {}; + FILE *f = fopen((char *)name.str, "rb"); + fseek(f, 0, SEEK_END); + result.len = ftell(f); + fseek(f, 0, SEEK_SET); /* same as rewind(f); */ + + result.str = malloc(result.len + 1); + fread(result.str, result.len, 1, f); + fclose(f); + + result.str[result.len] = 0; + return result; +} + function OS_Memory os_reserve(SizeU size){ OS_Memory result = {0}; diff --git a/output.cc b/output.cc new file mode 100644 index 0000000..3e2f7d6 --- /dev/null +++ b/output.cc @@ -0,0 +1,142 @@ +(4+(2*53)) +Error: Expected token of kind: ), got instead token of kind: End of stream +((4+2)*53) +(++5) +(--5) +(-5) +(+5) +(()5) +((()5)+3) +((534>43)?435:42) +(((534>43)?435:42),234,(()42),Thing[10][2],Thing(1,2)) +typedef struct String String; +struct String{ +U8 *str; +S64 len; +}; + +typedef Intern_String; +enum Token_Kind{ + End, + Mul, + Div, + Add, + Sub, + Mod, + BitAnd, + BitOr, + BitXor, + Neg, + Not, + OpenParen, + CloseParen, + OpenBrace, + CloseBrace, + OpenBracket, + CloseBracket, + Comma, + Pound, + Question, + ThreeDots, + Semicolon, + Dot, + LesserThen, + GreaterThen, + Colon, + Assign, + DivAssign, + MulAssign, + ModAssign, + SubAssign, + AddAssign, + AndAssign, + OrAssign, + XorAssign, + LeftShiftAssign, + RightShiftAssign, + DoubleColon, + At, + Decrement, + Increment, + PostDecrement, + PostIncrement, + LesserThenOrEqual, + GreaterThenOrEqual, + Equals, + And, + Or, + NotEquals, + LeftShift, + RightShift, + Arrow, + ExprSizeof, + DocComment, + Comment, + Identifier, + StringLit, + U8Lit, + Character, + Error, + Float, + Int, + Keyword, +} + +typedef struct Token Token; +struct Token{ +Token_Kind kind; +union { +String string; +struct { +U8 *str; +U64 len; +}; + +}; + +union { +S64 int_val; +String error_val; +String intern_val; +}; + +String file; +S64 line; +U8 *line_begin; +}; + +enum AST_Kind{ + BaseType, + Typedef, + Enum, + Struct, + Union, + Note, + List, + Pointer, + Array, + Function, + Variable, + EnumChild, +} + +typedef struct AST_Node AST_Node; +struct AST_Node{ +AST_Kind kind; +AST_Node node[16]; +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; +}; + +}; + diff --git a/parse_decl.c b/parse_decl.c index db70ff8..b30f32c 100644 --- a/parse_decl.c +++ b/parse_decl.c @@ -1,50 +1,168 @@ -global Intern_String intern_empty; + + +function Token * +parse__get_name(Parser *p){ + Token *name = token_next(p); + token_next(p); + token_next(p); + return name; +} + +function void +parse_note_list(Parser *ctx, AST_Node *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); + parse_note_list(ctx, current); + if(token_match(ctx, TK_Assign)) { + current->expr = parse_expr(ctx); + } + } while(token_match(ctx, TK_Comma)); + token_expect(ctx, TK_CloseParen); + } +} + +function void +parse__notes(Parser *ctx, AST_Node *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); + parse_note_list(ctx, current); + if(token_match(ctx, TK_Assign)) { + current->expr = parse_expr(ctx); + } + } +} + +function AST_Node +parse_notes(Parser *p){ + AST_Node result = {}; + parse__notes(p, &result); + return result; +} function AST_Node * -parse_enum(Parser *p){ +parse_enum(Parser *p, Token *name){ AST_Node *result = 0; - Token *name = token_match(p, TK_Identifier); - if(token_match(p, TK_OpenBrace)){ - Token *op_close_brace = token_match(p, TK_CloseBrace); - - if(!op_close_brace){ - - result = ast_enum(p, name, name->intern_val); - do{ // Parse enum members - Token *identifier = token_match(p, TK_Identifier); - if(identifier){ - Expr *expr = 0; - if(token_match(p, TK_Assign)){ - expr = parse_expr(p); - } - AST_Node *child = ast_enum_child(p, identifier, identifier->intern_val, expr); - ast_node_push_child(result, child); - { - // Insert into scope - } + 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); } - else { - parser_push_error(p, token_get(p), "invalid syntax of enum member"); + + 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; } - } while(token_match(p, TK_Comma)); - token_expect(p, TK_CloseBrace); - - } - else{ - parser_push_error(p, op_close_brace, "enum without body"); + } + 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; + } } } - else{ - if(name == 0){ - parser_push_error(p, token_get(p), "enum without name or body is illegal"); - } - } - - if(ast_is_named(result)){ - // Insert into scope - } - + 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; } @@ -54,6 +172,7 @@ parse(Parser *p){ for(;;){ AST_Node *node = 0; + AST_Node notes = parse_notes(p); if(token_is(p, TK_End)){ break; @@ -61,29 +180,40 @@ parse(Parser *p){ else if(token_is(p, TK_Error)){ break; } - else if(token_match_keyword(p, keyword_struct)){ - + 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); + } } - else if(token_match_keyword(p, keyword_union)){ - - } - else if(token_match_keyword(p, keyword_enum)){ - node = parse_enum(p); - token_expect(p, TK_Semicolon); - } - else if(token_match_keyword(p, keyword_function)){ - - } - else if(token_match_keyword(p, keyword_typedef)){ - - } - else { + 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"); + } } return result; diff --git a/parse_expr.c b/parse_expr.c index 874c264..7fad771 100644 --- a/parse_expr.c +++ b/parse_expr.c @@ -92,7 +92,7 @@ Expr* parse_unary_expr(Parser* p) { } else if (token_is(p, TK_OpenParen)) { // cast requires lookahead Token *token = token_peek(p, 1); - if (token->kind == TK_Keyword || token->kind == TK_Identifier) { + if (token->kind == TK_Identifier) { AST_Node *type = symbol_lookup_type(p, token->intern_val); if(type){ diff --git a/parser.c b/parser.c index 1a12f7a..2128311 100644 --- a/parser.c +++ b/parser.c @@ -1,9 +1,19 @@ -global Intern_String keyword_s64; -global Intern_String keyword_u64; -global Intern_String keyword_void; -global Intern_String keyword_sizeu; -global Intern_String keyword_sizeof; +global Intern_String intern_empty; +global Intern_String intern_s64; +global Intern_String intern_s32; +global Intern_String intern_s16; +global Intern_String intern_s8; + +global Intern_String intern_u64; +global Intern_String intern_u32; +global Intern_String intern_u16; +global Intern_String intern_u8; + +global Intern_String intern_void; +global Intern_String intern_sizeu; + +global Intern_String keyword_sizeof; global Intern_String keyword_enum; global Intern_String keyword_typedef; global Intern_String keyword_struct; @@ -12,7 +22,15 @@ global Intern_String keyword_function; global Intern_String keyword_global; global AST_Node *type_s64; +global AST_Node *type_s32; +global AST_Node *type_s16; +global AST_Node *type_s8; + global AST_Node *type_u64; +global AST_Node *type_u32; +global AST_Node *type_u16; +global AST_Node *type_u8; + global AST_Node *type_void; global AST_Node *type_sizeu; @@ -24,10 +42,6 @@ parser_init(Parser *p){ p->symbols_count = 4096; p->symbols = arena_push_array(&p->symbol_table_arena, AST_Node, p->symbols_count); - keyword_s64 = intern_string(p, lit("S64")); - keyword_u64 = intern_string(p, lit("U64")); - keyword_void = intern_string(p, lit("void")); - keyword_sizeu = intern_string(p, lit("SizeU")); keyword_sizeof = intern_string(p, lit("sizeof")); keyword_struct = intern_string(p, lit("struct")); keyword_enum = intern_string(p, lit("enum")); @@ -35,14 +49,37 @@ parser_init(Parser *p){ keyword_union = intern_string(p, lit("union")); keyword_function = intern_string(p, lit("function")); keyword_global = intern_string(p, lit("global")); - p->first_keyword = keyword_s64.s.str; + 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")); + intern_s8 = intern_string(p, lit("S8")); + + intern_u64 = intern_string(p, lit("U64")); + intern_u32 = intern_string(p, lit("U32")); + intern_u16 = intern_string(p, lit("U16")); + intern_u8 = intern_string(p, lit("U8")); + + intern_void = intern_string(p, lit("void")); + intern_sizeu = intern_string(p, lit("SizeU")); + parser_push_scope(p); // Global scope - type_s64 = symbol_register_basic_type(p, keyword_s64, sizeof(S64)); - type_u64 = symbol_register_basic_type(p, keyword_u64, sizeof(U64)); - type_sizeu = symbol_register_basic_type(p, keyword_sizeu, sizeof(SizeU)); - type_void = symbol_register_basic_type(p, keyword_void, sizeof(void)); + + type_s64 = symbol_register_basic_type(p, intern_s64, sizeof(S64)); + type_s32 = symbol_register_basic_type(p, intern_s32, sizeof(S32)); + type_s16 = symbol_register_basic_type(p, intern_s16, sizeof(S16)); + type_s8 = symbol_register_basic_type(p, intern_s8, sizeof(S8)); + + type_u64 = symbol_register_basic_type(p, intern_u64, sizeof(U64)); + type_u32 = symbol_register_basic_type(p, intern_u32, sizeof(U32)); + type_u16 = symbol_register_basic_type(p, intern_u16, sizeof(U16)); + type_u8 = symbol_register_basic_type(p, intern_u8, sizeof(U8)); + + type_void = symbol_register_basic_type(p, intern_void, sizeof(void)); + type_sizeu = symbol_register_basic_type(p, intern_sizeu, sizeof(SizeU)); } @@ -53,19 +90,6 @@ intern_is_keyword(Parser *p, Intern_String intern){ return false; } -function void -intern_tokens(Parser *p){ - for(S64 i = 0; i < p->tokens.len; i++){ - Token *t = p->tokens.tokens + i; - if(t->kind == TK_Identifier){ - t->intern_val = intern_string(p, t->string); - if(intern_is_keyword(p, t->intern_val)){ - t->kind = TK_Keyword; - } - } - } -} - function void parser_push_error(Parser *p, Token *token, char *str, ...){ @@ -90,6 +114,22 @@ parser_push_error(Parser *p, Token *token, char *str, ...){ SLLQueuePush(p->first_error, p->last_error, error); } +function void +intern_tokens(Parser *p){ + for(S64 i = 0; i < p->tokens.len; i++){ + Token *t = p->tokens.tokens + i; + if(t->kind == TK_Identifier){ + t->intern_val = intern_string(p, t->string); + if(intern_is_keyword(p, t->intern_val)){ + t->kind = TK_Keyword; + } + } + else if(t->kind == TK_Error){ + parser_push_error(p, t, (char *)t->error_val.str); + } + } +} + //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- @@ -162,10 +202,10 @@ symbol_alloc_slot(Parser *p, Intern_String string, B32 is_global){ if(symbol->name.s.str == 0){ /* @Note(Krzosa): Push on scope */ { if(is_global){ - SLLQueuePush(p->scope_stack->first, p->scope_stack->last, symbol); + SLLQueuePushMod(p->scope_stack->first, p->scope_stack->last, symbol, next_scope); } else{ - SLLQueuePush(p->global_scope->first, p->global_scope->last, symbol); + SLLQueuePushMod(p->global_scope->first, p->global_scope->last, symbol, next_scope); } } symbol->name = string; @@ -181,6 +221,7 @@ symbol_alloc_slot(Parser *p, Intern_String string, B32 is_global){ break; } + assert_msg(0, "Ran out of slots in symbol table"); return 0; } @@ -205,11 +246,39 @@ symbol_lookup(Parser *p, Intern_String string){ function AST_Node * symbol_register_basic_type(Parser *p, Intern_String string, SizeU size){ AST_Node *node = symbol_alloc_slot(p, string, true); + assert(node->kind == AK_None); node->kind = AK_BaseType; node->base_type_size = size; return node; } +function void +symbol_register(Parser *p, AST_Node *node){ + AST_Node *look = symbol_alloc_slot(p, node->name, false); + if(look->kind == AK_None){ + ast_copy_symbol(look, node); + } + else if(look->kind == node->kind){ + if(look->kind == AK_Enum || + look->kind == AK_Function || + look->kind == AK_Union || + look->kind == AK_Struct){ + if(look->first_child == 0){ + ast_copy_symbol(look, node); + } + else { + parser_push_error(p, token_get(p), "Symbol already has a body"); + } + } + else { + parser_push_error(p, token_get(p), "Trying to register a symbol again"); + } + } + else{ + parser_push_error(p, token_get(p), "Trying to register a symbol of different kind with the same name"); + } +} + function AST_Node * symbol_lookup_type(Parser *p, Intern_String string){ AST_Node *node = symbol_lookup(p, string); @@ -221,6 +290,15 @@ symbol_lookup_type(Parser *p, Intern_String string){ return 0; } +function AST_Node * +symbol_require_type(Parser *p, Token *token){ + AST_Node *result = symbol_lookup_type(p, token->intern_val); + if(!result){ + parser_push_error(p, token, "Undefined type"); + } + return result; +} + function void parser_push_scope(Parser *p){ Scope *scope = 0; @@ -240,7 +318,7 @@ parser_pop_scope(Parser *p){ SLLStackPop(p->scope_stack, scope); assert(scope); - for(AST_Node *s = scope->first; s; s=s->scope_next){ + for(AST_Node *s = scope->first; s; s=s->next_scope){ memory_zero(s, sizeof(AST_Node)); p->symbols_inserted--; } diff --git a/parser.h b/parser.h index 50fbb8f..f488b44 100644 --- a/parser.h +++ b/parser.h @@ -48,3 +48,4 @@ function Token *token_get(Parser *p); function B32 intern_compare(Intern_String a, Intern_String b); function void parser_push_scope(Parser *p); function AST_Node *symbol_register_basic_type(Parser *p, Intern_String string, SizeU size); +function void ast_copy_symbol(AST_Node *dst, AST_Node *src); \ No newline at end of file diff --git a/print.c b/print.c index 33efe50..65a25d0 100644 --- a/print.c +++ b/print.c @@ -74,3 +74,140 @@ expr_print(Expr *expr){ default: {invalid_codepath;} break; } } + +function void +print_indent(S64 indent){ + for(S64 i = 0; i < indent; i++){ + lex_print(" "); + } +} + +function AST_Node * +ast_get_basis_type(AST_Node *node){ + switch(node->kind) { + case AK_Struct: case AK_Union: case AK_Enum: case AK_BaseType:{return node;} break; + case AK_Function:{return node;} break; + case AK_Typedef:{return node->typedef_type;} break; + case AK_Array: case AK_Pointer:{return ast_get_basis_type(node->pointer);} break; + default: invalid_codepath; + } + return 0; +} + +function void +ast_print_pointers(AST_Node *node){ + if(node->kind == AK_Pointer){ + lex_print("*"); + ast_print_pointers(node->pointer); + } + else if(node->kind == AK_Array){ + ast_print_pointers(node->pointer); + } +} + +function void +ast_print_arrays(AST_Node *node){ + if(node->kind == AK_Pointer){ + ast_print_arrays(node->pointer); + } + else if(node->kind == AK_Array){ + lex_print("["); + expr_print(node->expr); + lex_print("]"); + ast_print_arrays(node->pointer); + } +} + +function void +ast_print_var(AST_Node *node); +function void +ast_print_func_params(AST_Node *node){ + for(AST_Node *n = node->first_child; n; n=n->next){ + ast_print_var(n); + if(n != node->last_child) lex_print(", "); + } +} + +function void +ast_print_var(AST_Node *node){ + AST_Node *basis_type = ast_get_basis_type(node->variable_type); + if(basis_type->kind == AK_Function){ + lex_print("%s (*%s)(", basis_type->func_return_type->name.s.str, node->name.s.str); + ast_print_func_params(basis_type); + lex_print(")"); + } + else{ + lex_print("%s ", basis_type->name.s.str); + ast_print_pointers(node->variable_type); + lex_print("%s", node->name.s.str); + ast_print_arrays(node->variable_type); + } + + if(node->expr){ + lex_print(" = "); + expr_print(node->expr); + } +} + +function void +ast__print(AST_Node *node, S64 indent){ + switch(node->kind){ + + case AK_List:{ + for(AST_Node *n = node->first_child; n; n=n->next){ + ast__print(n, indent); + lex_print("\n"); + } + } break; + + case AK_Union: + case AK_Struct:{ + const char *type = node->kind == AK_Struct ? "struct":"union"; + if(indent == 0) lex_print("typedef %s %s %s;\n", type, node->name.s.str, node->name.s.str); + lex_print("%s %s{\n", type, indent == 0 ? node->name.s.str:(U8 *)""); + for(AST_Node *n = node->first_child; n; n=n->next){ + ast__print(n, indent+2); + lex_print("\n"); + } + + lex_print("}"); + lex_print("%s;\n", indent == 0 ? (U8 *)"":node->name.s.str?node->name.s.str:(U8*)""); + } break; + + case AK_Variable:{ + if(indent == 0) lex_print("global "); + ast_print_var(node); + lex_print(";"); + } break; + + case AK_Typedef:{ + lex_print("typedef "); + lex_print("%s;", node->name.s.str); + } break; + + case AK_Enum:{ + print_indent(indent); + lex_print("enum %s{\n", node->name.s.str); + + for(AST_Node *n = node->first_child; n; n=n->next){ + print_indent(indent+2); + lex_print("%s", n->name.s.str); + if(n->expr){ + lex_print(" = "); + expr_print(n->expr); + } + lex_print(",\n"); + } + + print_indent(indent); + lex_print("}\n"); + } break; + + default: invalid_codepath; + } +} + +function void +ast_print(AST_Node *node){ + ast__print(node, 0); +}