function Decl *parse_decl_variable(Parser *p); function B32 intern_empty(Intern_String a){ B32 result = (a.s.str == 0); return result; } function Decl * parse_decl_enum(Parser *p){ Token *token = token_get(p); Intern_String name = {}; if(token_match(p, TK_Identifier)){ name = token->intern_val; } Decl *result = decl_enum(p, token, name); if(token_match(p, TK_OpenBrace)){ for(;;){ Token *token = token_get(p); if(token_match(p, TK_Identifier)){ Expr *expr = 0; if(token_match(p, TK_Assign)){ expr = parse_expr(p); } Decl_Enum_Child *child = decl_enum_child(p, token, expr); const_val_insert(p, token, type_s64, token->intern_val, expr); decl_enum_push(result, child); } else break; if(!token_match(p, TK_Comma)) break; } token_expect(p, TK_CloseBrace); } else { if(name.s.str == 0){ parser_push_error(p, token, "Unnamed enum without body is illegal"); } } if(!intern_empty(name)){ Type *type = type_enum(p, result); type_insert(p, type, name); } return result; } function void parse_decl_variable_right(Parser *p, Type **type, Token **name){ while(token_match(p, TK_Mul)){ *type = type_pointer(p, *type); }; *name = token_expect(p, TK_Identifier); while(token_match(p, TK_OpenBracket)){ Expr *expr = parse_expr(p); *type = type_array(p, *type, expr); token_expect(p, TK_CloseBracket); } } function void parse_argument_list(Parser *p, Decl *func){ if(!token_is(p, TK_CloseParen)){ do{ Decl *var = parse_decl_variable(p); decl_function_push(func, var); }while(token_match(p, TK_Comma)); } } function Decl * parse_decl_variable(Parser *p){ Decl *result = 0; Token *name = 0; Type *type = 0; Token *token = token_get(p); if(token_match(p, TK_Identifier) || token_match(p, TK_Keyword)){ type = type_get(p, token->intern_val); if(token_match(p, TK_OpenParen)){ token_expect(p, TK_Mul); if((name = token_expect(p, TK_Identifier))){ token_expect(p, TK_CloseParen); token_expect(p, TK_OpenParen); Decl *function_p = decl_function(p, name, type); parse_argument_list(p, function_p); token_expect(p, TK_CloseParen); type = type_function_pointer(p, function_p); } } else { parse_decl_variable_right(p, &type, &name); } } else{ parser_push_error(p, token, "Expected type when parsing global variable"); } Expr *expr = 0; if(token_match(p, TK_Assign)){ expr = parse_expr(p); } if(name){ result = decl_variable(p, name, type, expr); } return result; } function Decl * parse_decl_and_register_variable(Parser *p){ Decl *result = parse_decl_variable(p); if(result){ variable_insert(p, result); } return result; } function Decl * parse_struct(Parser *p, Decl_Kind kind){ Token *token = token_get(p); Token *name = token_match(p, TK_Identifier); Decl *result = decl_struct(p, token, name->intern_val); result->kind = kind; if(token_expect(p, TK_OpenBrace)){ do{ if(token_match_keyword(p, keyword_struct)){ Decl *val = parse_struct(p, DK_Struct); decl_aggregate_push(result, val); } else if(token_match_keyword(p, keyword_union)){ Decl *val = parse_struct(p, DK_Union); decl_aggregate_push(result, val); } else if(token_is(p, TK_Keyword) || token_is(p, TK_Identifier)){ Decl *val = parse_decl_variable(p); decl_aggregate_push(result, val); } else if(token_is(p, TK_CloseBrace)){ break; } else { parser_push_error(p, token_get(p), "Failed to parse struct, unexpected token"); break; } }while(token_match(p, TK_Semicolon)); token_expect(p, TK_CloseBrace); } if(name){ Type *type = type_struct(p, result); type_insert(p, type, name->intern_val); } return result; } function Decl * parse_decl_typedef(Parser *p){ Decl *result = decl_type(p, token_get(p), 0, (Intern_String){}); if(token_match_keyword(p, keyword_enum)){ Decl *e = parse_decl_enum(p); result->typedef_val.type = type_enum(p, e); } else if(token_match_keyword(p, keyword_union)){ Decl *e = parse_struct(p, DK_Union); result->typedef_val.type = type_struct(p, e); } else if(token_match_keyword(p, keyword_struct)){ Decl *e = parse_struct(p, DK_Struct); result->typedef_val.type = type_struct(p, e); } else if(token_is(p, TK_Keyword) || token_is(p, TK_Identifier)){ Token *token = token_next(p); result->typedef_val.type = type_get(p, token->intern_val); } else { parser_push_error(p, token_get(p), "Failed to parse typedef, unexpected token"); } Token *name = token_expect(p, TK_Identifier); if(name){ result->name = name->intern_val; type_insert(p, type_typedef(p, result), result->name); } return result; } function Decl * parse_decl_global(Parser *p){ Decl *result = 0; if(token_match_keyword(p, keyword_typedef)){ result = parse_decl_typedef(p); } else if(token_match_keyword(p, keyword_enum)){ result = parse_decl_enum(p); } else if(token_match_keyword(p, keyword_union)){ result = parse_struct(p, DK_Union); } else if(token_match_keyword(p, keyword_struct)){ result = parse_struct(p, DK_Struct); } else if(token_match_keyword(p, keyword_global)){ result = parse_decl_variable(p); } else if(token_match_keyword(p, keyword_function)){ } return result; }