// Lexer::interns::map::allocator - array allocator, resizing // Lexer::tokens - array allocator, resizing // // Parser::ast_arena - arena for asts // Lexer::interns::string_allocator - arena for interns // Intern_String keyword_struct; Intern_String keyword_union; Intern_String keyword_cast; Intern_String keyword_enum; Intern_String intern_void; Intern_String intern_int; Intern_String intern_str; Intern_String intern_unsigned; const U64 Parse_Ctx_ID = 115151; struct Parse_Ctx:Lexer{ Allocator *perm; // Stores: AST, tokens, interns Allocator *heap; U64 unique_ids; Map global_syms; Map type_map; Token empty_token; S64 indent; void init(Allocator *perm_allocator, Allocator *heap_allocator){ perm = perm_allocator; heap = heap_allocator; global_syms = {heap}; type_map = {heap}; lex_init(perm, heap, this); keyword_struct= intern_string(&interns, "struct"_s); keyword_union = intern_string(&interns, "union"_s); keyword_cast = intern_string(&interns, "cast"_s); keyword_enum = intern_string(&interns, "enum"_s); interns.first_keyword = keyword_struct.str; interns.last_keyword = keyword_enum.str; intern_void = intern_string(&interns, "void"_s); intern_int = intern_string(&interns, "int"_s); intern_str = intern_string(&interns, "String"_s); intern_unsigned = intern_string(&interns, "unsigned"_s); } }; thread_local Parse_Ctx *pctx; //----------------------------------------------------------------------------- // AST //----------------------------------------------------------------------------- enum Ast_Kind{ AST_NONE, AST_PACKAGE, AST_STR, AST_INT, AST_CAST, AST_IDENT, AST_INDEX, AST_UNARY, AST_BINARY, AST_COMPOUND_ITEM, AST_COMPOUND, AST_LAMBDA, AST_LAMBDA_PARAM, AST_CONST, AST_VAR, AST_TYPESPEC_IDENT, AST_TYPESPEC_POINTER, AST_TYPESPEC_ARRAY, AST_TYPESPEC_LAMBDA }; struct Ast{ U64 id; Ast_Kind kind; Token *pos; }; struct Ast_Typespec; struct Ast_Expr:Ast{ union{ Intern_String intern_val; U64 int_val; struct{ Token_Kind op; Ast_Expr *expr; }unary; struct{ Token_Kind op; Ast_Expr *left; Ast_Expr *right; } binary; struct{ Ast_Typespec *typespec; Array exprs; }compound; struct{ Ast_Expr *name; // index | name Ast_Expr *index; Ast_Expr *item; }compound_item; struct{ Ast_Expr *expr; Ast_Typespec *typespec; }cast; struct{ Ast_Expr *expr; Ast_Expr *index; }index; struct{ Intern_String name; Ast_Typespec *typespec; }lambda_param; }; }; struct Ast_Lambda : Ast_Expr { Array params; Ast_Typespec *ret; }; struct Ast_Typespec:Ast{ union{ Ast_Typespec *base; Intern_String name; struct{ Ast_Typespec *base; Ast_Expr *expr; }arr; Ast_Lambda *lambda; }; }; struct Ast_Decl:Ast{ Intern_String name; union{ struct{ Ast_Typespec *typespec; Ast_Expr *expr; }var; struct{ Array args; Ast_Typespec *ret; }func; }; }; struct Ast_Package:Ast{ Intern_String name; Array decls; }; //----------------------------------------------------------------------------- // AST Constructors beginning with expressions //----------------------------------------------------------------------------- #define AST_NEW(T,ikind,ipos) \ Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T); \ result->kind = ikind; \ result->pos = ipos; \ result->id = ++pctx->unique_ids function Ast_Expr * ast_expr_string(Token *pos, Intern_String string){ AST_NEW(Expr, AST_STR, pos); result->intern_val = string; return result; } function Ast_Expr * ast_expr_identifier(Token *pos, Intern_String string){ AST_NEW(Expr, AST_IDENT, pos); result->intern_val = string; return result; } function Ast_Expr * ast_expr_integer(Token *pos, S64 integer){ AST_NEW(Expr, AST_INT, pos); result->int_val = integer; return result; } function Ast_Expr * ast_expr_binary(Ast_Expr *left, Ast_Expr *right, Token *op){ AST_NEW(Expr, AST_BINARY, op); result->binary.op = op->kind; result->binary.left = left; result->binary.right = right; return result; } function Ast_Expr * ast_expr_compound(Token *pos, Ast_Typespec *typespec, Array exprs){ AST_NEW(Expr, AST_COMPOUND, pos); result->compound.typespec = typespec; result->compound.exprs = exprs.tight_copy(pctx->perm); return result; } function Ast_Expr * ast_expr_compound_item(Token *pos, Ast_Expr *index, Ast_Expr *name, Ast_Expr *item){ AST_NEW(Expr, AST_COMPOUND_ITEM, pos); result->compound_item.name = name; result->compound_item.index = index; result->compound_item.item = item; return result; } function Ast_Expr * ast_expr_cast(Token *pos, Ast_Expr *expr, Ast_Typespec *typespec){ AST_NEW(Expr, AST_CAST, pos); result->cast.expr = expr; result->cast.typespec = typespec; return result; } function Ast_Expr * ast_expr_unary(Token *pos, Token_Kind op, Ast_Expr *expr){ AST_NEW(Expr, AST_UNARY, pos); result->unary.expr = expr; result->unary.op = op; return result; } function Ast_Expr * ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index){ AST_NEW(Expr, AST_INDEX, pos); result->index.expr = expr; result->index.index = index; return result; } function Ast_Lambda * ast_lambda(Token *pos, Array params, Ast_Typespec *ret){ AST_NEW(Lambda, AST_LAMBDA, pos); result->params = params.tight_copy(pctx->perm); result->ret = ret; return result; } function Ast_Expr * ast_expr_lambda_empty(Token *pos){ AST_NEW(Expr, AST_LAMBDA, pos); return result; } function Ast_Expr * ast_expr_lambda_param(Token *pos, Intern_String name, Ast_Typespec *typespec){ AST_NEW(Expr, AST_LAMBDA_PARAM, pos); result->lambda_param.name = name; result->lambda_param.typespec = typespec; return result; } //----------------------------------------------------------------------------- // Typespecs //----------------------------------------------------------------------------- function Ast_Typespec * ast_typespec_name(Token *pos, Intern_String name){ AST_NEW(Typespec, AST_TYPESPEC_IDENT, pos); result->name = name; return result; } function Ast_Typespec * ast_typespec_pointer(Token *pos, Ast_Typespec *base){ AST_NEW(Typespec, AST_TYPESPEC_POINTER, pos); result->base = base; return result; } function Ast_Typespec * ast_typespec_array(Token *pos, Ast_Typespec *base, Ast_Expr *expr){ AST_NEW(Typespec, AST_TYPESPEC_ARRAY, pos); result->arr.base = base; result->arr.expr = expr; return result; } function Ast_Typespec * ast_typespec_lambda(Token *pos, Ast_Lambda *lambda){ AST_NEW(Typespec, AST_TYPESPEC_LAMBDA, pos); result->lambda = lambda; return result; } //----------------------------------------------------------------------------- // Declarations //----------------------------------------------------------------------------- function Ast_Decl * ast_decl_func(Token *pos, Intern_String name){ AST_NEW(Decl, AST_LAMBDA, pos); result->name = name; return result; } function Ast_Decl * ast_decl_var(Token *pos, Ast_Typespec *typespec, Intern_String name, Ast_Expr *expr){ AST_NEW(Decl, AST_VAR, pos); result->var.expr = expr; result->var.typespec = typespec; result->name = name; return result; } function Ast_Decl * ast_decl_const(Token *pos, Intern_String name, Ast_Expr *expr){ Ast_Decl *result = ast_decl_var(pos, 0, name, expr); result->kind = AST_CONST; return result; } function Ast_Package * ast_package(Token *pos, String name, Array decls){ AST_NEW(Package, AST_PACKAGE, pos); result->decls = decls.tight_copy(pctx->perm); result->name = intern_string(&pctx->interns, name); return result; }