diff --git a/build.bat b/build.bat index 2a2f90a..00412ef 100644 --- a/build.bat +++ b/build.bat @@ -2,5 +2,5 @@ rem clang generate.c -fdiagnostics-absolute-paths -std=c99 -g -o generate.exe -Wl,user32.lib rem generate.exe -clang main.c -Wall -Wno-unused-function -fdiagnostics-absolute-paths -std=c99 -g -o main.exe -Wl,user32.lib +clang main.c -Wall -Wno-unused-function -fdiagnostics-absolute-paths -std=c17 -g -o main.exe -Wl,user32.lib rem cl main.c -std:c17 diff --git a/main.c b/main.c index 7d4b77b..5219a60 100644 --- a/main.c +++ b/main.c @@ -13,6 +13,7 @@ #include "new_lex.c" #include "new_ast.c" +#include "new_print.c" #include "new_parse.c" int main(){ diff --git a/new_ast.c b/new_ast.c index 23e956f..36f52f9 100644 --- a/new_ast.c +++ b/new_ast.c @@ -164,6 +164,8 @@ typedef enum Decl_Kind{ DECL_None, DECL_Struct, DECL_Union, + DECL_SubStruct, + DECL_SubUnion, DECL_Enum, DECL_Variable, DECL_Typedef, @@ -497,6 +499,54 @@ function void typespec_function_push(Typespec *func, Typespec *arg){ SLLQueuePush(func->func.first, func->func.last, arg); } +//----------------------------------------------------------------------------- +// Notes +//----------------------------------------------------------------------------- +function void +decl_pass_notes(Decl *a, Note *b){ + a->first_note = b->first; + a->last_note = b->last; +} + +function Note * +note_push_new(Arena *p, Note *parent, Token *pos, Intern_String name, Expr *expr){ + Note *result = arena_push_struct(p, Note); + result->pos = pos; + result->name = name; + result->expr = expr; + SLLQueuePush(parent->first, parent->last, result); + return result; +} + +function Note * +find_note(Note *first, String string){ + for(Note *n = first; n; n=n->next){ + if(string_compare(string, n->name.s)){ + return n; + } + } + return 0; +} + +function String +find_string_note(Note *first, String string, String default_string){ + Note *note = find_note(first, string); + if(note){ + return note->expr->token->intern_val.s; + } + return default_string; +} + +function Note * +decl_find_note(Decl *decl, String string){ + return find_note(decl->first_note, string); +} + +function String +decl_find_string_note(Decl *decl, String string, String default_string){ + return find_string_note(decl->first_note, string, default_string); +} + //----------------------------------------------------------------------------- // Declarations @@ -512,7 +562,7 @@ decl_new(Arena *p, Decl_Kind kind, Token *pos, Intern_String name){ function Decl * decl_struct(Arena *p, Decl_Kind kind, Token *pos, Intern_String name){ - assert(kind == DECL_Struct || kind == DECL_Union); + assert(kind == DECL_Struct || kind == DECL_Union || kind == DECL_SubUnion || kind == DECL_SubStruct); Decl *result = decl_new(p, kind, pos, name); return result; } @@ -570,7 +620,7 @@ decl_enum_push(Arena *p, Decl *parent, Token *pos, Intern_String name, Expr *exp function void decl_struct_push(Decl *parent, Decl *child){ - assert(parent->kind == DECL_Struct || parent->kind == DECL_Union); + assert(parent->kind == DECL_Struct || parent->kind == DECL_Union || parent->kind == DECL_SubUnion || parent->kind == DECL_SubStruct); SLLQueuePush(parent->struct_decl.first, parent->struct_decl.last, child); } diff --git a/new_parse.c b/new_parse.c index d9eae4e..5eb716f 100644 --- a/new_parse.c +++ b/new_parse.c @@ -78,6 +78,15 @@ token_peek_is(Parser *p, Token_Kind kind, S64 i){ return 0; } +function Token * +token_peek_is_keyword(Parser *p, Intern_String keyword, S64 i){ + assert(lex_is_keyword(keyword)); + Token *result = token_peek(p, i); + if(result->kind == TK_Keyword && intern_compare(result->intern_val, keyword)) + return result; + return 0; +} + function Token * token_is(Parser *p, Token_Kind kind){ Token *result = token_get(p); @@ -536,35 +545,155 @@ name::enum{} name::typedef = name2; name::const = 4254; +// Thing::struct{ +// var1, var2: U32; +// union { +// thing: *S64; + // } +// named: union { +// data: [24]U32; +// } +// } + */ -function Decl * -parse_enum(Parser *p, Token *name){ - Typespec *typespec = 0; +function void +parse_note_list(Parser *p, Note *parent) { + if(token_match(p, TK_OpenParen)) { + if(token_match(p, TK_CloseParen)){ + return; + } + do { + Token *name = token_expect(p, TK_Identifier); + Note *current = note_push_new(p->arena, parent, name, name->intern_val, 0); + parse_note_list(p, current); + if(token_match(p, TK_Assign)) { + current->expr = parse_expr(p); + } + } while(token_match(p, TK_Comma)); + token_expect(p, TK_CloseParen); + } +} + +function void +parse__notes(Parser *p, Note *result) { + while(token_match(p, TK_At)) { + Token *name = token_expect(p, TK_Identifier); + Note *current = note_push_new(p->arena, result, name, name->intern_val, 0); + parse_note_list(p, current); + if(token_match(p, TK_Assign)) { + current->expr = parse_expr(p); + } + token_match(p, TK_Semicolon); + } +} + +function Note +parse_notes(Parser *p){ + Note result = {0}; + parse__notes(p, &result); + return result; +} + +function Expr * +parse_assign_expr(Parser *p){ + if(token_match(p, TK_Assign)) + return parse_expr(p); + return 0; +} + +function Typespec * +parse_optional_type(Parser *p){ + Typespec *result = 0; if(token_match(p, TK_Colon)){ - typespec = parse_typespec(p); + result = parse_typespec(p); } else{ - typespec = typespec_name(p->arena, token_get(p), intern_int); + result = typespec_name(p->arena, token_get(p), intern_int); } - + return result; +} + +function Decl * +parse_enum(Parser *p, Token *name){ + Typespec *typespec = parse_optional_type(p); Decl *result = decl_enum(p->arena, name, name->intern_val, typespec); token_expect(p, TK_OpenBrace); do{ + Note notes = parse_notes(p); 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)); + Expr *expr = parse_assign_expr(p); + decl_enum_push(p->arena, result, val, val->intern_val, expr, ¬es); + } while(token_match(p, TK_Comma)); token_expect(p, TK_CloseBrace); return result; } +function void +parse_var_decl(Parser *p, Decl *parent, Token *name){ + Token *name_stack[64]; + S64 name_stack_len = 0; + name_stack[name_stack_len++] = name; + while(token_match(p, TK_Comma)) + name_stack[name_stack_len++] = token_expect(p, TK_Identifier); + token_expect(p, TK_Colon); + Typespec *typespec = parse_typespec(p); + token_expect(p, TK_Semicolon); + for(S64 i = 0; i < name_stack_len; i++){ + Decl *decl = decl_variable(p->arena, name_stack[i], name_stack[i]->intern_val, typespec, 0); + decl_struct_push(parent, decl); + } +} + +function Decl * +parse_struct(Parser *p, Token *name, Decl_Kind struct_kind){ + Intern_String intern_name = name ? name->intern_val : (Intern_String){0}; + Token *token = name ? name : token_get(p); + Decl *result = decl_struct(p->arena, struct_kind, token, intern_name); + token_expect(p, TK_OpenBrace); + do { + Token *token = token_get(p); + if(token_match_keyword(p, keyword_union)){ + Decl *decl = parse_struct(p, 0, DECL_SubUnion); + decl_struct_push(result, decl); + } + else if(token_match_keyword(p, keyword_struct)){ + Decl *decl = parse_struct(p, 0, DECL_SubStruct); + decl_struct_push(result, decl); + } + else if(token_match(p, TK_Identifier)){ + if(token_is(p, TK_Colon)){ + if(token_peek_is_keyword(p, keyword_union, 1)){ + token_next(p); + token_next(p); + Decl *decl = parse_struct(p, token, DECL_SubUnion); + decl_struct_push(result, decl); + } + else if(token_peek_is_keyword(p, keyword_struct, 1)){ + token_next(p); + token_next(p); + Decl *decl = parse_struct(p, token, DECL_SubStruct); + decl_struct_push(result, decl); + } + else{ + parse_var_decl(p, result, token); + } + } + else{ + parse_var_decl(p, result, token); + } + } + else{ + parser_push_error(p, token, "Failed to parse struct, unexpected token of kind '%s'", token_kind_string[token->kind]); + } + } while(!token_match(p, TK_CloseBrace)); + return result; +} + function Decl * parse_decl(Parser *p){ Decl *result = 0; Token *name = 0; + Note note = parse_notes(p); if((name = token_match(p, TK_Identifier))){ if(token_match(p, TK_DoubleColon)){ Token *token = 0; @@ -572,10 +701,10 @@ parse_decl(Parser *p){ result = parse_enum(p, name); } else if((token = token_match_keyword(p, keyword_union))){ - // Union + result = parse_struct(p, name, DECL_Union); } else if((token = token_match_keyword(p, keyword_struct))){ - // Struct + result = parse_struct(p, name, DECL_Struct); } else if((token = token_match_keyword(p, keyword_const))){ // Const value @@ -591,183 +720,16 @@ parse_decl(Parser *p){ parser_push_error(p, token_get(p), "Expected token of kind '::'"); } } + if(result){ + decl_pass_notes(result, ¬e); + } + 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); -} - -function void -expr_compound_print(Expr_Compound_Field *field){ - switch(field->kind){ - case COMPOUND_Default: { - expr_print(field->init); - }break; - case COMPOUND_Named: { - printf("[%s] = ", field->name.s.str); - expr_print(field->init); - }break; - case COMPOUND_Index: { - printf("["); - expr_print(field->index); - printf("] = "); - expr_print(field->init); - }break; - default: invalid_codepath; - } -} - -function void -expr_print(Expr *expr){ - switch(expr->kind) { - case EK_Int:case EK_String:case EK_Identifier: { - token_print(expr->token); - } break; - - case EK_SizeExpr:{ - printf("size_expr("); - expr_print(expr->size_expr.expr); - printf(")"); - }break; - - case EK_Compound:{ - 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); - if(n!=expr->compound.last) printf(","); - } - printf("}"); - } break; - - case EK_SizeType:{ - printf("size_type("); - printf(")"); - }break; - - case EK_Paren:{ - printf("("); - expr_print(expr->paren.expr); - printf(")"); - } break; - - case EK_Field:{ - expr_print(expr->field.expr); - printf(".%s", expr->field.name.s.str); - } break; - - case EK_Binary:{ - printf("("); - expr_print(expr->binary.left); - token_print(expr->token); - expr_print(expr->binary.right); - printf(")"); - } break; - - case EK_PostfixUnary:{ - printf("("); - expr_print(expr->unary.expr); - token_print(expr->token); - printf(")"); - } break; - - case EK_Unary:{ - printf("("); - token_print(expr->token); - expr_print(expr->unary.expr); - printf(")"); - } break; - - case EK_Ternary:{ - printf("("); - expr_print(expr->ternary.cond); - printf("?"); - expr_print(expr->ternary.on_true); - printf(":"); - expr_print(expr->ternary.on_false); - printf(")"); - } break; - - case EK_Cast:{ - printf("("); - printf("("); - typespec_print(expr->cast.typespec); - printf(")"); - expr_print(expr->cast.expr); - printf(")"); - } break; - - case EK_Index:{ - expr_print(expr->index.atom); - printf("["); - expr_print(expr->index.index); - printf("]"); - }break; - - case EK_Call:{ - expr_print(expr->call.atom); - printf("("); - for(Expr_Compound_Field *n = expr->call.first; n; n=n->next){ - expr_compound_print(n); - if(n!=expr->call.last) printf(","); - } - printf(")"); - }break; - default: {invalid_codepath;} break; - } -} - -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){ @@ -904,6 +866,19 @@ parse_test_expr(){ function void parse_test_decls(){ + Arena *scratch = arena_begin_scratch(); + Parser p = parser_make(scratch); + + String decls[] = { + lit("Thing::enum: U64{ Thing_1 = 1<<1, Thing_2 = 2 }"), + lit("Struct::struct{ thing, thing2: *S64; struct { thing:U32; thing2: [64]Vec2; } inner: struct {i:U32;} }"), + }; + for(SizeU i = 0; i < buff_cap(decls); i++){ + parser_restream(&p, decls[i], lit("Decl_Test")); + Decl *decl = parse_decl(&p); + assert(decl); + decl_print(decl); + } } diff --git a/new_print.c b/new_print.c new file mode 100644 index 0000000..eb71961 --- /dev/null +++ b/new_print.c @@ -0,0 +1,261 @@ +function void expr_print(Expr *expr); +function B32 typespec_print(Typespec *spec); + +global S64 indent; + +#define println(...) do{ printf("\n"); print_indent(); printf(__VA_ARGS__); }while(0) + +function void +print_indent(){ + for(S64 i = 0; i < indent*2; i++) + printf(" "); +} + +function void +token_print(Token *token){ + printf("%.*s", (S32)token->len, token->str); +} + +function void +expr_compound_print(Expr_Compound_Field *field){ + switch(field->kind){ + case COMPOUND_Default: { + expr_print(field->init); + }break; + case COMPOUND_Named: { + printf("[%s] = ", field->name.s.str); + expr_print(field->init); + }break; + case COMPOUND_Index: { + printf("["); + expr_print(field->index); + printf("] = "); + expr_print(field->init); + }break; + default: invalid_codepath; + } +} + +function void +expr_print(Expr *expr){ + switch(expr->kind) { + case EK_Int:case EK_String:case EK_Identifier: { + token_print(expr->token); + } break; + + case EK_SizeExpr:{ + printf("size_expr("); + expr_print(expr->size_expr.expr); + printf(")"); + }break; + + case EK_Compound:{ + 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); + if(n!=expr->compound.last) printf(","); + } + printf("}"); + } break; + + case EK_SizeType:{ + printf("size_type("); + printf(")"); + }break; + + case EK_Paren:{ + printf("("); + expr_print(expr->paren.expr); + printf(")"); + } break; + + case EK_Field:{ + expr_print(expr->field.expr); + printf(".%s", expr->field.name.s.str); + } break; + + case EK_Binary:{ + printf("("); + expr_print(expr->binary.left); + token_print(expr->token); + expr_print(expr->binary.right); + printf(")"); + } break; + + case EK_PostfixUnary:{ + printf("("); + expr_print(expr->unary.expr); + token_print(expr->token); + printf(")"); + } break; + + case EK_Unary:{ + printf("("); + token_print(expr->token); + expr_print(expr->unary.expr); + printf(")"); + } break; + + case EK_Ternary:{ + printf("("); + expr_print(expr->ternary.cond); + printf("?"); + expr_print(expr->ternary.on_true); + printf(":"); + expr_print(expr->ternary.on_false); + printf(")"); + } break; + + case EK_Cast:{ + printf("("); + printf("("); + typespec_print(expr->cast.typespec); + printf(")"); + expr_print(expr->cast.expr); + printf(")"); + } break; + + case EK_Index:{ + expr_print(expr->index.atom); + printf("["); + expr_print(expr->index.index); + printf("]"); + }break; + + case EK_Call:{ + expr_print(expr->call.atom); + printf("("); + for(Expr_Compound_Field *n = expr->call.first; n; n=n->next){ + expr_compound_print(n); + if(n!=expr->call.last) printf(","); + } + printf(")"); + }break; + default: {invalid_codepath;} break; + } +} + + +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 void +print_assign_expr(Expr *expr){ + if(expr){ + printf(" = "); + expr_print(expr); + } +} + +function void +decl_print(Decl *node){ + //print_notes(p, node->first_note); + + switch(node->kind) { + + case DECL_List: { + for(Decl *n = node->list_decl.first; n; n=n->next){ + decl_print(n); + printf("\n"); + } + } break; + + case DECL_Variable:{ + println("%s: ", node->name.s.str); + B32 r = typespec_print(node->var_decl.type); + print_assign_expr(node->var_decl.expr); + if(r) printf(";"); + } break; + + case DECL_Typedef:{ + println("typedef %s ", node->name.s.str); + typespec_print(node->typedef_decl.type); + printf(";"); + } break; + + + case DECL_Struct: + case DECL_Union :{ + const char *struct_name = node->kind==DECL_Struct ? "struct" : "union"; + println("%s %s{", struct_name, node->name.s.str?(char*)node->name.s.str:""); + indent++; + for(Decl *n = node->struct_decl.first; n; n=n->next){ + decl_print(n); + } + indent--; + println("};"); + } break; + + case DECL_SubStruct: + case DECL_SubUnion :{ + const char *struct_name = node->kind==DECL_SubStruct ? "struct" : "union"; + println("%s %s{", struct_name, node->name.s.str?(char*)node->name.s.str:""); + indent++; + for(Decl *n = node->struct_decl.first; n; n=n->next){ + decl_print(n); + } + indent--; + println("};"); + } break; + + + case DECL_Enum:{ + println("enum %s : ", node->name.s.str); + typespec_print(node->enum_decl.typespec); + printf("{"); + indent++; + for(Decl_Enum_Child *n = node->enum_decl.first; n; n=n->next){ + //print_notes(p, n->first_note); + println("%s", n->name.s.str); + print_assign_expr(n->expr); + printf(","); + } + indent--; + println("};"); + } break; + default: {invalid_codepath;} break; + } +} +