/* spl_lexer.h — 独立词法分析器 */ #ifndef __SPL_LEXER_H__ #define __SPL_LEXER_H__ #include "../stage0/spl_ir.h" /* clang-format off */ #define KEYWORD_TABLE \ X(as , KW_AS , SPL_V0) \ X(asm , KW_ASM , SPL_V0) \ X(bool , KW_BOOL , SPL_V0) \ X(break , KW_BREAK , SPL_V0) \ X(catch , KW_CATCH , SPL_V0) \ X(comptime , KW_COMPTIME , SPL_V0) \ X(const , KW_CONST , SPL_V0) \ X(continue , KW_CONTINUE , SPL_V0) \ X(defer , KW_DEFER , SPL_V0) \ X(else , KW_ELSE , SPL_V0) \ X(enum , KW_ENUM , SPL_V0) \ X(errdefer , KW_ERRDEFER , SPL_V0) \ X(false , KW_FALSE , SPL_V0) \ X(fn , KW_FN , SPL_V0) \ X(for , KW_FOR , SPL_V0) \ X(if , KW_IF , SPL_V0) \ X(loop , KW_LOOP , SPL_V0) \ X(match , KW_MATCH , SPL_V0) \ X(null , KW_NULL , SPL_V0) \ X(pub , KW_PUB , SPL_V0) \ X(ret , KW_RET , SPL_V0) \ X(struct , KW_STRUCT , SPL_V0) \ X(test , KW_TEST , SPL_V0) \ X(true , KW_TRUE , SPL_V0) \ X(try , KW_TRY , SPL_V0) \ X(type , KW_TYPE , SPL_V0) \ X(union , KW_UNION , SPL_V0) \ X(var , KW_VAR , SPL_V0) \ X(void , KW_VOID , SPL_V0) \ X(while , KW_WHILE , SPL_V0) \ X(_ , KW_ANY , SPL_V0) \ // KEYWORD_TABLE #define TOKEN_TABLE \ X(unknown , TOK_UNKNOWN , SPL_V0 ) \ X(EOF , TOK_EOF , SPL_V0 ) \ X(blank , TOK_BLANK , SPL_V0 ) \ X(endline , TOK_ENDLINE , SPL_V0 ) \ X("#" , TOK_SHARP , SPL_V0 ) \ X("@" , TOK_AT , SPL_V0 ) \ X("==" , TOK_EQ , SPL_V0 ) \ X("=" , TOK_ASSIGN , SPL_V0 ) \ X("+=" , TOK_ASSIGN_ADD , SPL_V0 ) \ X("+" , TOK_ADD , SPL_V0 ) \ X("-=" , TOK_ASSIGN_SUB , SPL_V0 ) \ X("->" , TOK_RIGHT_ARRAY , SPL_V0 ) \ X("<-" , TOK_LEFT_ARRAY , SPL_V0 ) \ X("-" , TOK_SUB , SPL_V0 ) \ X("*=" , TOK_ASSIGN_MUL , SPL_V0 ) \ X("*" , TOK_MUL , SPL_V0 ) \ X("/=" , TOK_ASSIGN_DIV , SPL_V0 ) \ X("/" , TOK_DIV , SPL_V0 ) \ X("//" , TOK_LINE_COMMENT , SPL_V0 ) \ X("/* */" , TOK_BLOCK_COMMENT , SPL_V0 ) \ X("%=" , TOK_ASSIGN_MOD , SPL_V0 ) \ X("%" , TOK_MOD , SPL_V0 ) \ X("&&" , TOK_AND_AND , SPL_V0 ) \ X("&=" , TOK_ASSIGN_AND , SPL_V0 ) \ X("&" , TOK_AND , SPL_V0 ) \ X("||" , TOK_OR_OR , SPL_V0 ) \ X("|=" , TOK_ASSIGN_OR , SPL_V0 ) \ X("|" , TOK_OR , SPL_V0 ) \ X("^=" , TOK_ASSIGN_XOR , SPL_V0 ) \ X("^" , TOK_XOR , SPL_V0 ) \ X("<<=" , TOK_ASSIGN_L_SH , SPL_V0 ) \ X("<<" , TOK_L_SH , SPL_V0 ) \ X("<=" , TOK_LE , SPL_V0 ) \ X("<" , TOK_LT , SPL_V0 ) \ X(">>=" , TOK_ASSIGN_R_SH , SPL_V0 ) \ X(">>" , TOK_R_SH , SPL_V0 ) \ X(">=" , TOK_GE , SPL_V0 ) \ X(">" , TOK_GT , SPL_V0 ) \ X("!" , TOK_NOT , SPL_V0 ) \ X("!=" , TOK_NEQ , SPL_V0 ) \ X("~" , TOK_BIT_NOT , SPL_V0 ) \ X("[" , TOK_L_BRACKET , SPL_V0 ) \ X("]" , TOK_R_BRACKET , SPL_V0 ) \ X("(" , TOK_L_PAREN , SPL_V0 ) \ X(")" , TOK_R_PAREN , SPL_V0 ) \ X("{" , TOK_L_BRACE , SPL_V0 ) \ X("}" , TOK_R_BRACE , SPL_V0 ) \ X(";" , TOK_SEMICOLON , SPL_V0 ) \ X("," , TOK_COMMA , SPL_V0 ) \ X(":" , TOK_COLON , SPL_V0 ) \ X(":=" , TOK_COLON_ASSIGN , SPL_V0 ) \ X("." , TOK_DOT , SPL_V0 ) \ X(".." , TOK_RANGE , SPL_V0 ) \ X("..." , TOK_ELLIPSIS , SPL_V0 ) \ X("?" , TOK_COND , SPL_V0 ) \ X(ident , TOK_IDENT , SPL_V0 ) \ X(int , TOK_INT_LITERAL , SPL_V0 ) \ X(float , TOK_FLOAT_LITERAL , SPL_V0 ) \ X(char , TOK_CHAR_LITERAL , SPL_V0 ) \ X(string , TOK_STRING_LITERAL , SPL_V0 ) \ // TOKEN_TABLE /* clang-format on */ /* spl_tok_type_t — KEYWORD_TABLE + TOKEN_TABLE 展开 */ /* clang-format off */ typedef enum { #define X(name, enum_name, dummy) enum_name, KEYWORD_TABLE #undef X #define X(name, enum_name, dummy) enum_name, TOKEN_TABLE #undef X } spl_tok_type_t; /* clang-format on */ typedef struct { spl_tok_type_t type; const char *lexeme; usize len; /* token length in bytes */ const char *fname; usize offset; usize line; usize col; } spl_tok_t; typedef VEC(spl_tok_t) spl_tok_vec_t; /* Lexer entry point */ spl_tok_vec_t spl_lex(const char *source, const char *fname); /* Utility functions */ const char *spl_tok_type_name(spl_tok_type_t type); void spl_tok_dump(spl_tok_t *tok); void spl_tok_vec_dump(spl_tok_vec_t *toks); void spl_tok_vec_drop(spl_tok_vec_t *toks); usize spl_tok_copy_name(spl_tok_t *tok, char *buf, usize buf_size); /* Decode escape sequence, advance *s past it. Returns 0 on success. */ int spl_decode_escape(const char **s, char *out); #endif /* __SPL_LEXER_H__ */