enum Token_Kind{ TK_End, TK_Mul, TK_Div, TK_Mod, TK_LeftShift, TK_RightShift, TK_FirstMul = TK_Mul, TK_LastMul = TK_RightShift, TK_Add, TK_Sub, TK_FirstAdd = TK_Add, TK_LastAdd = TK_Sub, TK_Equals, TK_LesserThenOrEqual, TK_GreaterThenOrEqual, TK_LesserThen, TK_GreaterThen, TK_NotEquals, TK_FirstCompare = TK_Equals, TK_LastCompare = TK_NotEquals, TK_BitAnd, TK_BitOr, TK_BitXor, TK_And, TK_Or, TK_FirstLogical = TK_BitAnd, TK_LastLogical = TK_Or, 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_NewLine, TK_Colon, TK_Assign, TK_ColonAssign, TK_DivAssign, TK_MulAssign, TK_ModAssign, TK_SubAssign, TK_AddAssign, TK_AndAssign, TK_OrAssign, TK_XorAssign, TK_LeftShiftAssign, TK_RightShiftAssign, TK_FirstAssign = TK_Assign, TK_LastAssign = TK_RightShiftAssign, TK_DoubleColon, TK_At, TK_Decrement, TK_Increment, TK_PostDecrement, TK_PostIncrement, TK_Arrow, TK_ExprSizeof, TK_DocComment, TK_Comment, TK_Identifier, TK_UnicodeLit, TK_StringLit, TK_Error, TK_Float, TK_Integer, TK_Keyword, TK_FOREIGN, TK_Pointer = TK_Mul, TK_Dereference = TK_BitAnd, OPEN_SCOPE = 128, CLOSE_SCOPE, SAME_SCOPE, }; struct Token{ Token_Kind kind; union{ String string; struct{U8 *str; S64 len;}; }; union { U32 unicode; BigInt int_val; F64 f64_val; String error_val; Intern_String intern_val; S64 indent; }; String file; S32 line; U8 *line_begin; }; struct Lex_Stream{ String stream; S64 iter; U8 *line_begin; String file; S32 line; S32 inside_brace_paren; Array indent_stack; }; struct Lexer{ Allocator *arena; Lex_Stream stream; Array tokens; Intern_Table interns; S64 token_iter; Intern_String intern(String string){ return intern_string(&interns, string); } }; // 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_return; Intern_String keyword_if; Intern_String keyword_else; Intern_String keyword_true; Intern_String keyword_false; Intern_String keyword_for; Intern_String keyword_pass; Intern_String keyword_cast; Intern_String keyword_enum; Intern_String intern_void; Intern_String intern_foreign; struct Ast_Package; struct Sym; struct Parse_Ctx:Lexer{ Allocator *perm; // Stores: AST, tokens, interns Allocator *heap; U64 unique_ids; Map type_map; Ast_Package *resolving_package; Map resolved; Map syms; S32 scope; Array local_syms; Token empty_token; S64 indent; String_Builder gen; }; //----------------------------------------------------------------------------- // Constructors //----------------------------------------------------------------------------- thread_local Parse_Ctx *pctx; function void lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){ l->arena = token_string_arena; l->tokens = array_make(token_string_arena, 1024*2); l->interns= intern_table_make(token_string_arena, map_allocator, 1024); keyword_struct= l->intern("struct"_s); keyword_union = l->intern("union"_s); keyword_cast = l->intern("cast"_s); keyword_true = l->intern("true"_s); keyword_false = l->intern("false"_s); keyword_return = l->intern("return"_s); keyword_if = l->intern("if"_s); keyword_pass = l->intern("pass"_s); keyword_else = l->intern("else"_s); keyword_for = l->intern("for"_s); keyword_enum = intern_string(&l->interns, "enum"_s); l->interns.first_keyword = keyword_struct.str; l->interns.last_keyword = keyword_enum.str; intern_foreign = intern_string(&l->interns, "#foreign"_s); intern_void = intern_string(&l->interns, "void"_s); } function void parse_init(Parse_Ctx *ctx, Allocator *perm_allocator, Allocator *heap_allocator){ ctx->perm = perm_allocator; ctx->heap = heap_allocator; ctx->gen = {ctx->perm}; ctx->resolved = {ctx->heap}; ctx->syms = {ctx->heap}; ctx->type_map = {ctx->heap}; ctx->local_syms = {ctx->heap}; bigint_allocator = ctx->perm; lex_init(ctx->perm, ctx->heap, ctx); pctx = ctx; }