diff --git a/generated.c b/generated.c deleted file mode 100644 index 49de99d..0000000 --- a/generated.c +++ /dev/null @@ -1,69 +0,0 @@ -typedef struct Token_Bucket Token_Bucket; -typedef struct Token_Array Token_Array; -struct Token_Bucket{ -Token_Bucket*next; -Token data[4096]; -}; -struct Token_Array{ -Intern_Table interns; -Token_Bucket first; -Token_Bucket*last; -S64 len; -S64 block; -Arena*arena; -Token_Bucket*iter_bucket; -S64 iter_len; -S64 iter_block; -}; -function Token_Array token_array_make(Arena*arena){ -Token_Array result={ -.last=&result.first,.arena=arena,.interns=intern_table(arena,4096*4)}; -return result; -} -function void token_array_push(Token_Array*array,Token*p){ -if(array->len>=buff_cap(array->first.data)){ -Token_Bucket*bucket=arena_push_struct(array->arena,Token_Bucket); -array->last=array->last->next=bucket; -array->len=0; -array->block+=1; -} -array->last->data[array->len++]=*p; -} -function B32 token_array_iter_is_end(Token_Array*array){ -B32 result=array->iter_len==array->len&&array->iter_block==array->block; -return result; -} -function Token*token_array_iter_next(Token_Array*array){ -if(token_array_iter_is_end(array)){ -return0; -} -if(array->iter_len>=buff_cap(array->first.data)){ -array->iter_len=0; -array->iter_block+=1; -array->iter_bucket=array->iter_bucket->next; -} -Token*result=array->iter_bucket->data+array->iter_len++; -return result; -} -function Token*token_array_iter_peek(Token_Array*array,S64 i){ -S64 save_len=array->iter_len; -Token_Bucket*save_bucket=array->iter_bucket; -assert(ifirst.data)); -S64 over=i; -if(array->iter_len+i>=buff_cap(array->first.data)){ -over=buff_cap(array->first.data)-(array->iter_len+i); -array->iter_len=0; -array->iter_bucket=array->iter_bucket->next; -} -Token*result=array->iter_bucket->data+array->iter_len+over; -array->iter_len=save_len; -array->iter_bucket=save_bucket; -return result; -} -function Token*token_array_iter_begin(Token_Array*array){ -array->iter_len=0; -array->iter_block=0; -array->iter_bucket=&array->first; -Token*result=token_array_iter_next(array); -return result; -} diff --git a/generated_lex.h b/generated_lex.h index 778798f..7f24f2e 100644 --- a/generated_lex.h +++ b/generated_lex.h @@ -8,129 +8,91 @@ typedef struct Lex_Stream Lex_Stream; typedef struct Tokens Tokens; struct Intern_String{ -String s; + String s; }; typedef 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, + 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, }Token_Kind; struct Token{ -Token_Kind kind; -union{ -struct{ -U8 (*str); -S64 len; -}; -String string; -}; -union{ -S64 int_val; -String error_val; -Intern_String intern_val; -}; -String file; -S64 line; -U8 (*line_begin); -}; - -// Generated Array block -typedef struct Token_Array Token_Array; -typedef struct Token_Array_Block Token_Array_Block; -typedef struct Token_Array_Iter Token_Array_Iter; -struct Token_Array_Block{ -Token_Array_Block*next; -Token data[4096]; -}; -struct Token_Array_Iter{ -Token_Array_Block*block; -U32 iter_len; -U32 iter_block; -U32 total_len; -U32 total_block; -}; -struct Token_Array{ -Token_Array_Block first; -Token_Array_Block*last; -Token_Array_Iter it; -Arena*arena; -S64 block; -S64 len; -}; - -struct Lex_Stream{ -U8 (*stream); -U8 (*line_begin); -String filename; -S64 line; -}; - -struct Tokens{ -Token (*tokens); -S64 len; -S64 cap; -S64 iter; + Token_Kind kind; + union{ + struct{ + U8 (*str); + S64 len; + }; + String string; + }; + union{ + S64 int_val; + String error_val; + Intern_String intern_val; + }; + String file; + S64 line; + U8 (*line_begin); }; diff --git a/new_ast.c b/new_ast.c index e2cae2e..23e956f 100644 --- a/new_ast.c +++ b/new_ast.c @@ -4,6 +4,7 @@ typedef struct Decl Decl; typedef struct Stmt Stmt; typedef struct Stmt_If Stmt_If; typedef struct Typespec Typespec; +typedef struct Typespec_Function_Arg Typespec_Function_Arg; typedef struct Decl_Enum_Child Decl_Enum_Child; typedef struct Decl_Function_Arg Decl_Function_Arg; typedef struct Expr_Compound_Field Expr_Compound_Field; @@ -130,15 +131,20 @@ typedef enum Typespec_Kind{ TS_Pointer, TS_Array, TS_Function, + TS_NamedArgument, }Typespec_Kind; struct Typespec{ - Typespec_Kind kind; Typespec *next; + Typespec_Kind kind; Token *pos; union{ - Intern_String name; Typespec *base; + Intern_String name; + struct{ + Intern_String name; + Typespec *base; + }named; struct{ Typespec *first; Typespec *last; @@ -165,15 +171,6 @@ typedef enum Decl_Kind{ DECL_List, }Decl_Kind; -struct Note{ - Token *pos; - Intern_String name; - Expr *expr; - Note *next; - Note *first; - Note *last; -}; - struct Decl{ Decl_Kind kind; Decl *next; @@ -208,7 +205,7 @@ struct Decl{ Decl_Function_Arg *first; Decl_Function_Arg *last; Typespec *ret; - //Stmt *body; + Stmt *body; }func_decl; struct{ Decl *first; @@ -217,6 +214,15 @@ struct Decl{ }; }; +struct Note{ + Token *pos; + Intern_String name; + Expr *expr; + Note *next; + Note *first; + Note *last; +}; + struct Decl_Function_Arg{ Decl_Function_Arg *next; Token *pos; @@ -439,11 +445,148 @@ expr_compound_push(Expr *list, Expr_Compound_Field *field){ SLLQueuePush(list->compound.first, list->compound.last, field); } +//----------------------------------------------------------------------------- +// Type specifier constructors +//----------------------------------------------------------------------------- +function Typespec * +typespec_new(Arena *p, Typespec_Kind kind, Token *pos){ + Typespec *result = arena_push_struct(p, Typespec); + result->kind = kind; + result->pos = pos; + return result; +} + +function Typespec * +typespec_name(Arena *p, Token *pos, Intern_String name){ + Typespec *result = typespec_new(p, TS_Name, pos); + result->name = name; + return result; +} + +function Typespec * +typespec_pointer(Arena *p, Token *pos, Typespec *base){ + Typespec *result = typespec_new(p, TS_Pointer, pos); + result->base = base; + return result; +} + +function Typespec * +typespec_array(Arena *p, Token *pos, Typespec *base, Expr *size){ + Typespec *result = typespec_new(p, TS_Array, pos); + result->arr.base = base; + result->arr.size = size; + return result; +} + +function Typespec * +typespec_function(Arena *p, Token *pos, Typespec *ret){ + Typespec *result = typespec_new(p, TS_Function, pos); + result->func.ret = ret; + return result; +} + +function Typespec * +typespec_named_argument(Arena *arena, Token *pos, Typespec *typespec, Intern_String name){ + Typespec *result = typespec_new(arena, TS_NamedArgument, pos); + result->named.base = typespec; + result->named.name = name; + return result; +} + +function void +typespec_function_push(Typespec *func, Typespec *arg){ + SLLQueuePush(func->func.first, func->func.last, arg); +} + +//----------------------------------------------------------------------------- +// Declarations +//----------------------------------------------------------------------------- +function Decl * +decl_new(Arena *p, Decl_Kind kind, Token *pos, Intern_String name){ + Decl *result = arena_push_struct(p, Decl); + result->kind = kind; + result->pos = pos; + result->name = name; + return result; +} + +function Decl * +decl_struct(Arena *p, Decl_Kind kind, Token *pos, Intern_String name){ + assert(kind == DECL_Struct || kind == DECL_Union); + Decl *result = decl_new(p, kind, pos, name); + return result; +} + +function Decl * +decl_typedef(Arena *p, Token *pos, Intern_String name, Typespec *type){ + Decl *result = decl_new(p, DECL_Typedef, pos, name); + result->typedef_decl.type = type; + return result; +} + +function Decl * +decl_enum(Arena *p, Token *pos, Intern_String name, Typespec *typespec){ + Decl *result = decl_new(p, DECL_Enum, pos, name); + result->enum_decl.typespec = typespec; + return result; +} + +function Decl * +decl_variable(Arena *p, Token *pos, Intern_String name, Typespec *typespec, Expr *expr){ + Decl *result = decl_new(p, DECL_Variable, pos, name); + result->var_decl.type = typespec; + result->var_decl.expr = expr; + return result; +} + +function Decl * +decl_function(Arena *p, Token *pos, Intern_String name, Typespec *ret){ + Decl *result = decl_new(p, DECL_Function, pos, name); + result->func_decl.ret = ret; + return result; +} + +function void +decl_func_push(Arena *p, Decl *parent, Token *pos, Intern_String name, Typespec *type){ + assert(parent->kind == DECL_Function); + Decl_Function_Arg *result = arena_push_struct(p, Decl_Function_Arg); + result->name = name; + result->typespec = type; + result->pos = pos; + SLLQueuePush(parent->func_decl.first, parent->func_decl.last, result); +} + +function void +decl_enum_push(Arena *p, Decl *parent, Token *pos, Intern_String name, Expr *expr, Note *notes){ + assert(parent->kind == DECL_Enum); + Decl_Enum_Child *child = arena_push_struct(p, Decl_Enum_Child); + child->pos = pos; + child->name = name; + child->expr = expr; + child->first_note = notes->first; + child->last_note = notes->last; + SLLQueuePush(parent->enum_decl.first, parent->enum_decl.last, child); +} + +function void +decl_struct_push(Decl *parent, Decl *child){ + assert(parent->kind == DECL_Struct || parent->kind == DECL_Union); + SLLQueuePush(parent->struct_decl.first, parent->struct_decl.last, child); +} + +function void +decl_list_push(Decl *parent, Decl *child){ + assert(parent->kind == DECL_List); + SLLQueuePush(parent->list_decl.first, parent->list_decl.last, child); +} + + + //----------------------------------------------------------------------------- // Double linked list //----------------------------------------------------------------------------- function void -decl_list_push(Decl *l, Decl *node){ +decl_dll_list_push(Decl *l, Decl *node){ if(l->list_decl.first == 0){ l->list_decl.first = l->list_decl.last = node; node->prev = 0; @@ -459,7 +602,7 @@ decl_list_push(Decl *l, Decl *node){ } function void -decl_list_push_front(Decl *l, Decl *node){ +decl_dll_list_push_front(Decl *l, Decl *node){ if(l->list_decl.first == 0){ l->list_decl.first = l->list_decl.last = node; node->prev = 0; @@ -523,10 +666,10 @@ ast_test(){ decls[2].kind = 2; decls[3].kind = 3; decls[4].kind = 4; - decl_list_push(decls, decls+1); - decl_list_push(decls, decls+2); - decl_list_push(decls, decls+3); - decl_list_push_front(decls, decls+4); + decl_dll_list_push(decls, decls+1); + decl_dll_list_push(decls, decls+2); + decl_dll_list_push(decls, decls+3); + decl_dll_list_push_front(decls, decls+4); //list_print(decls); decl_list_remove(decls, decls+1); diff --git a/new_lex.c b/new_lex.c index 84a9e42..e9f990f 100644 --- a/new_lex.c +++ b/new_lex.c @@ -4,6 +4,7 @@ global Intern_String keyword_cast; global Intern_String keyword_else; global Intern_String keyword_size_type; global Intern_String keyword_size_expr; +global Intern_String keyword_const; global Intern_String keyword_typeof; global Intern_String keyword_while; global Intern_String keyword_switch; @@ -14,6 +15,9 @@ global Intern_String keyword_union; global U8 *first_keyword; global U8 *last_keyword; +global Intern_String intern_void; +global Intern_String intern_int; + function void init_default_keywords(Intern_Table *t){ keyword_if = intern_string(t, lit("if")); @@ -25,6 +29,7 @@ init_default_keywords(Intern_Table *t){ keyword_size_type = intern_string(t, lit("size_type")); keyword_size_expr = intern_string(t, lit("size_expr")); keyword_typeof = intern_string(t, lit("typeof")); + keyword_const = intern_string(t, lit("const")); keyword_while = intern_string(t, lit("while")); keyword_switch = intern_string(t, lit("switch")); keyword_case = intern_string(t, lit("case")); @@ -33,6 +38,9 @@ init_default_keywords(Intern_Table *t){ keyword_union = intern_string(t, lit("union")); last_keyword = keyword_union.s.str; + + intern_void = intern_string(t, lit("void")); + intern_int = intern_string(t, lit("int")); } function B32 @@ -489,15 +497,32 @@ lex__stream(Token_Array *array, Lex_Stream *s){ } } -function Token_Array -lex_stream(Arena *arena, String stream, String file){ +function void +lex_add_stream(Token_Array *array, String stream, String file){ Lex_Stream s = {stream, 0, stream.str, file, 0}; + lex__stream(array, &s); +} + +function Token_Array +lex_make_token_array(Arena *arena){ Token_Array array = token_array_make(arena); init_default_keywords(&array.interns); - lex__stream(&array, &s); return array; } +function Token_Array +lex_stream(Arena *arena, String stream, String file){ + Token_Array array = lex_make_token_array(arena); + lex_add_stream(&array, stream, file); + return array; +} + +function void +lex_restream(Token_Array *array, String stream, String file){ + token_array_reset(array); + lex_add_stream(array, stream, file); +} + function void lex_test(){ Arena *scratch = arena_begin_scratch(); diff --git a/new_parse.c b/new_parse.c index a4142e0..d9eae4e 100644 --- a/new_parse.c +++ b/new_parse.c @@ -29,7 +29,23 @@ parser_push_error(Parser *p, Token *token, char *str, ...){ va_end(args1); } - printf("Error: %s %s:%d\n", string.str, token->file.str, (S32)token->line); + // @Note(Krzosa): Print nice error message + { + printf("Error: %s %s:%d\n", string.str, token->file.str, (S32)token->line); + + // @Note(Krzosa): Print error line + { + int i = 0; + while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++; + printf("%.*s\n", i, token->line_begin); + + // @Note(Krzosa): Print error marker + int token_i = token->str - token->line_begin; + for(int i = 0; i < token_i-2; i++) printf(" "); + printf("^^^^^^\n"); + } + } + Parser_Error *error = arena_push_struct(p->arena, Parser_Error); error->message = string; error->next = 0; @@ -48,6 +64,20 @@ token_get(Parser *p){ return result; } +function Token * +token_peek(Parser *p, S64 i){ + Token *result = token_array_iter_peek(&p->tokens, i); + return result; +} + +function Token * +token_peek_is(Parser *p, Token_Kind kind, S64 i){ + Token *result = token_peek(p, i); + if(result->kind == kind) + return result; + return 0; +} + function Token * token_is(Parser *p, Token_Kind kind){ Token *result = token_get(p); @@ -95,6 +125,8 @@ token_expect(Parser *p, Token_Kind kind){ return 0; } +function Typespec *parse_typespec(Parser *p); +function Expr *parse_expr(Parser *p); //----------------------------------------------------------------------------- // Expression parsing //----------------------------------------------------------------------------- @@ -112,6 +144,9 @@ atom_expr = Int | 'cast' '(' typespec ',' expr ')' | 'size_type' '(' typespec ')' | 'size_expr' '(' expr ')' +| '{' compound_expr '}' +| '(' expr ')' +| '(' ':' typespec ')' '{' compound_expr '}' postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')* unary_expr = unary ? unary_expr : atom_expr mul_expr = atom_expr (mul atom_expr)* @@ -120,57 +155,16 @@ logical_expr = add_expr (logical add_expr)* compare_expr = logical_expr (compare logical_expr)* ternary_expr = compare_expr ('?' ternary_expr ':' ternary_expr)? expr = logical_expr + +Compound literals +- (:[23]*Type){} + - Type{} +- { } + */ -function Expr *parse_expr(Parser *p); - -function Expr * -parse_expr_atom(Parser *p){ - Token *token = 0; - if((token = token_match(p, TK_StringLit))){ - Expr *result = expr_str(p->arena, token); - return result; - } - else if((token = token_match(p, TK_Identifier))){ - Expr *result = expr_identifier(p->arena, token); - return result; - } - else if((token = token_match(p, TK_Int))){ - Expr *result = expr_int(p->arena, token); - return result; - } - else if((token = token_match(p, TK_OpenParen))){ - Expr *expr = parse_expr(p); - token_expect(p, TK_CloseParen); - Expr *result = expr_paren(p->arena, token, expr); - return result; - } - else if((token = token_match_keyword(p, keyword_cast))){ - token_expect(p, TK_OpenParen); - token_expect(p, TK_Identifier); - token_expect(p, TK_Comma); - token_expect(p, TK_Identifier); - token_expect(p, TK_CloseParen); - return 0; - } - else{ - parser_push_error(p, token_get(p), "Failed to parse expression"); - return 0; - } -} - -function B32 -token_is_postfix(Parser *p){ - Token *token = token_get(p); - B32 result = token->kind == TK_OpenBracket - || token->kind == TK_OpenParen - || token->kind == TK_Dot - || token->kind == TK_Increment - || token->kind == TK_Decrement; - return result; -} function Expr_Compound_Field * -parse_expr_compound(Parser *p){ +parse_expr_compound_field(Parser *p){ Token *token = token_get(p); Expr_Compound_Field *result = 0; if(token_match(p, TK_OpenBracket)){ @@ -196,6 +190,81 @@ parse_expr_compound(Parser *p){ return result; } +function Expr * +parse_expr_compound(Parser *p, Typespec *typespec){ + Token *token = token_expect(p, TK_OpenBrace); + Expr *expr = expr_compound(p->arena, token, typespec); + while(!token_is(p, TK_CloseBrace)){ + Expr_Compound_Field *field = parse_expr_compound_field(p); + expr_compound_push(expr, field); + if(!token_match(p, TK_Comma)){ + break; + } + } + token_expect(p, TK_CloseBrace); + return expr; +} + +function Expr * +parse_expr_atom(Parser *p){ + Expr *result = 0; + Token *token = token_get(p); + if(token_match(p, TK_StringLit)){ + result = expr_str(p->arena, token); + } + else if(token_match(p, TK_Identifier)){ + if(token_is(p, TK_OpenBrace)){ + Typespec *typespec = typespec_name(p->arena, token, token->intern_val); + result = parse_expr_compound(p, typespec); + } + else{ + result = expr_identifier(p->arena, token); + } + } + else if(token_match(p, TK_Int)){ + result = expr_int(p->arena, token); + } + else if(token_is(p, TK_OpenBrace)){ + result = parse_expr_compound(p, 0); + } + + else if(token_match(p, TK_OpenParen)){ + if(token_match(p, TK_Colon)){ + Typespec *typespec = parse_typespec(p); + token_expect(p, TK_CloseParen); + result = parse_expr_compound(p, typespec); + } + else{ + Expr *expr = parse_expr(p); + token_expect(p, TK_CloseParen); + result = expr_paren(p->arena, token, expr); + } + } + else if(token_match_keyword(p, keyword_cast)){ + token_expect(p, TK_OpenParen); + Typespec *typespec = parse_typespec(p); + token_expect(p, TK_Comma); + Expr *expr = parse_expr(p); + token_expect(p, TK_CloseParen); + result = expr_cast(p->arena, token, typespec, expr); + } + else{ + parser_push_error(p, token, "Failed to parse expression"); + } + return result; +} + +function B32 +token_is_postfix(Parser *p){ + Token *token = token_get(p); + B32 result = token->kind == TK_OpenBracket + || token->kind == TK_OpenParen + || token->kind == TK_Dot + || token->kind == TK_Increment + || token->kind == TK_Decrement; + return result; +} + function Expr_Compound_Field * parse_expr_function_argument(Parser *p){ Token *token = token_get(p); @@ -365,10 +434,171 @@ parse_expr(Parser *p){ return parse_expr_ternary(p); } +//----------------------------------------------------------------------------- +// Type specifier parsing +//----------------------------------------------------------------------------- +/* + base_type = NAME +| '(' type_list? ')' type? + +type = ('*' | '[' expr ']')* base_type + +Examples: +[32]*U32 - Array of 32 pointers to U32 +**CustomDataType - Pointer to pointer of CustomDataType +(*U32, S64) **S64 - Function pointer +(CoolType: optional, S32) - Implicit void return value + +*/ +function Typespec * +parse_typespec_function(Parser *p, Token *token){ + Typespec *result = typespec_function(p->arena, token, 0); + if(!token_is(p, TK_CloseParen)) + for(;;) { + + // Optional name + Token *name = 0; + if((token = token_is(p, TK_Identifier))){ + if(token_peek_is(p, TK_Colon, 1)){ + token_next(p); + token_next(p); + name = token; + } + } + + // Parse type + Typespec *arg = parse_typespec(p); + if(name) + arg = typespec_named_argument(p->arena, name, arg, name->intern_val); + typespec_function_push(result, arg); + + if(!token_match(p, TK_Comma)){ + break; + } + } + token_expect(p, TK_CloseParen); + if(token_is(p, TK_Identifier) + || token_is(p, TK_OpenParen) + || token_is(p, TK_Mul) + || token_is(p, TK_OpenBracket)) + result->func.ret = parse_typespec(p); + else + result->func.ret = typespec_name(p->arena, token_get(p), intern_void); + + return result; +} + +// [10]*int - Array of 10 pointers to ints +function Typespec * +parse_typespec_recurse(Parser *p){ + Token *token = token_get(p); + if(token_match(p, TK_Mul)){ + Typespec *result = parse_typespec_recurse(p); + result = typespec_pointer(p->arena, token, result); + return result; + } + else if(token_match(p, TK_OpenBracket)){ + Expr *expr = parse_expr(p); + token_expect(p, TK_CloseBracket); + Typespec *result = parse_typespec_recurse(p); + result = typespec_array(p->arena, token, result, expr); + return result; + } + else if(token_match(p, TK_OpenParen)){ + Typespec *result = parse_typespec_function(p, token); + return result; + } + else if(token_match(p, TK_Identifier)){ + Typespec *result = typespec_name(p->arena, token, token->intern_val); + return result; + } + else{ + parser_push_error(p, token, "Failed to parse type, unexpected token"); + return 0; + } +} + +function Typespec * +parse_typespec(Parser *p){ + Typespec *result = parse_typespec_recurse(p); + return result; +} + +//----------------------------------------------------------------------------- +// Parsing decls +//----------------------------------------------------------------------------- +/* +name::(param:U32)*U32{} +name::struct{} +name::union{} +name::enum{} + +name::typedef = name2; +name::const = 4254; + +*/ +function Decl * +parse_enum(Parser *p, Token *name){ + Typespec *typespec = 0; + if(token_match(p, TK_Colon)){ + typespec = parse_typespec(p); + } + else{ + typespec = typespec_name(p->arena, token_get(p), intern_int); + } + + Decl *result = decl_enum(p->arena, name, name->intern_val, typespec); + token_expect(p, TK_OpenBrace); + do{ + Token *val = token_expect(p, TK_Identifier); + Expr *expr = 0; + if(token_match(p, TK_Assign)){ + expr = parse_expr(p); + } + decl_enum_push(p->arena, result, val, val->intern_val, expr, 0); + } while(token_is(p, TK_Comma)); + token_expect(p, TK_CloseBrace); + return result; +} + +function Decl * +parse_decl(Parser *p){ + Decl *result = 0; + Token *name = 0; + if((name = token_match(p, TK_Identifier))){ + if(token_match(p, TK_DoubleColon)){ + Token *token = 0; + if((token = token_match_keyword(p, keyword_enum))){ + result = parse_enum(p, name); + } + else if((token = token_match_keyword(p, keyword_union))){ + // Union + } + else if((token = token_match_keyword(p, keyword_struct))){ + // Struct + } + else if((token = token_match_keyword(p, keyword_const))){ + // Const value + } + else if((token = token_match(p, TK_OpenParen))){ + // Function + } + else{ + parser_push_error(p, token_get(p), "Expected token of kind todo:decl_tokens"); + } + } + else{ + parser_push_error(p, token_get(p), "Expected token of kind '::'"); + } + } + return result; +} + //----------------------------------------------------------------------------- // Test code //----------------------------------------------------------------------------- function void expr_print(Expr *expr); +function B32 typespec_print(Typespec *spec); function void token_print(Token *token){ printf("%.*s", (S32)token->len, token->str); @@ -408,7 +638,11 @@ expr_print(Expr *expr){ }break; case EK_Compound:{ - // typespec_print(p); + if(expr->compound.typespec){ + printf("("); + typespec_print(expr->compound.typespec); + printf(")"); + } printf("{"); for(Expr_Compound_Field *n = expr->compound.first; n; n=n->next){ expr_compound_print(n); @@ -468,7 +702,7 @@ expr_print(Expr *expr){ case EK_Cast:{ printf("("); printf("("); - //print_typespec(expr->cast.type); + typespec_print(expr->cast.typespec); printf(")"); expr_print(expr->cast.expr); printf(")"); @@ -494,6 +728,46 @@ expr_print(Expr *expr){ } } +function B32 +typespec_print(Typespec *spec){ + switch(spec->kind) { + case TS_Name: { + printf("%s", spec->name.s.str); + } break; + + case TS_NamedArgument: { + printf("%s: ", spec->named.name.s.str); + typespec_print(spec->named.base); + }break; + + case TS_Pointer: { + typespec_print(spec->base); + printf("*"); + } break; + + case TS_Array: { + typespec_print(spec->arr.base); + printf("["); + expr_print(spec->arr.size); + printf("]"); + } break; + + case TS_Function: { + printf("("); + for(Typespec *n = spec->func.first; n; n=n->next){ + typespec_print(n); + if(n!=spec->func.last) + printf(", "); + } + + printf(")"); + typespec_print(spec->func.ret); + } break; + default: {invalid_codepath;} break; + } + return true; +} + function S64 eval_expr(Expr *expr){ @@ -545,8 +819,34 @@ eval_expr(Expr *expr){ return 0; } +function Parser +parser_make(Arena *arena){ + Parser result = { + .tokens = lex_make_token_array(arena), + .arena = arena, + }; + return result; +} + function void -parse_test(){ +parser_restream(Parser *p, String stream, String file){ + lex_restream(&p->tokens, stream, file); +} + +function Parser +parser_make_stream(Arena *arena, String stream, String file){ + Parser parser = parser_make(arena); + lex_restream(&parser.tokens, stream, file); + return parser; +} + +function void +parser_add_stream(Parser *p, String string, String file){ + lex_add_stream(&p->tokens, string, file); +} + +function void +parse_test_expr(){ Arena *scratch = arena_begin_scratch(); String test_case = lit("32+52-242*2/424%5-23" " 1<<5>>6<<2 " @@ -558,12 +858,9 @@ parse_test(){ " 1>5 ? 1 : 2 " " !!!!!1 " " ~~1 + -!2 " - " 1 + ++Thing[12]++ + ++Thing[12].expr + --Not_Thing[156](Thing) + test_func(asd=func1, af=func2, gg=func3)" + " 1 + ++Thing[12]++ + ++Thing[12].expr +" ); - Parser parser = { - .tokens = lex_stream(scratch, test_case, lit("expr_test")), - .arena = scratch, - }; + Parser parser = parser_make_stream(scratch, test_case, lit("Big_Expr")); Parser *p = &parser; S64 t = 5; @@ -585,10 +882,33 @@ parse_test(){ assert(val == test_val[i]); } - Expr *expr = parse_expr(p); - expr_print(expr); + String exprs[] = { + lit("cast([12](thing: U32, qwe: *U32) [32]Result, (123+234))"), + lit("cast((thing: U32, qwe: *U32), (123+234))"), + lit("(:(U32,U32)){Thing=10}"), + lit("--Not_Thing[156](Thing) + test_func(asd=func1, af=func2, gg=func3)"), + lit("(:[23]*Type){Thing=10}"), + lit("cast(**Data,{Thing=10})"), + lit("(:[64]S64){1,2,3,4,5}"), + lit("Data_Type{1,2,3,4,5}"), + }; + for(SizeU i = 0; i < buff_cap(exprs); i++){ + parser_restream(p, exprs[i], lit("Test_Exprs")); + Expr *expr = parse_expr(p); + expr_print(expr); + printf("\n"); + } arena_end_scratch(); } +function void +parse_test_decls(){ + +} +function void +parse_test(){ + parse_test_expr(); + parse_test_decls(); +} \ No newline at end of file diff --git a/token_array.c b/token_array.c index 7f111de..67943dd 100644 --- a/token_array.c +++ b/token_array.c @@ -96,6 +96,19 @@ token_array_iter_peek(Token_Array *array, S64 i){ return result; } +function void +token_array_reset(Token_Array *array){ + // @Todo(Krzosa): Add free list + assert(&array->first == array->last); + array->len = 0; + array->block = 0; + array->last = &array->first; + array->last->next = 0; + array->iter_bucket = array->last; + array->iter_len = 0; + array->iter_block = 0; +} + function Token * token_array_iter_begin(Token_Array *array){ array->iter_len = 0;