feat: 装饰器 #[attr] 语法 — parser 解析并跳过
Token(74): +TOK_HASH, lexer 识别 '#', parser 在 fn/struct/enum 前解析 #[ident] 语法就位, 后续可扩展存储属性到 AST 节点 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -158,6 +158,7 @@ Token* lex(Arena* a, const char* source, const char* filename,
|
||||
else if (c == '.') { tokens[idx++] = make_token(&l, TOK_DOT, l.pos, 1); advance(&l); }
|
||||
else if (c == '[') { tokens[idx++] = make_token(&l, TOK_LBRACKET, l.pos, 1); advance(&l); }
|
||||
else if (c == ']') { tokens[idx++] = make_token(&l, TOK_RBRACKET, l.pos, 1); advance(&l); }
|
||||
else if (c == '#') { tokens[idx++] = make_token(&l, TOK_HASH, l.pos, 1); advance(&l); }
|
||||
else if (c == '(') { tokens[idx++] = make_token(&l, TOK_LPAREN, l.pos, 1); advance(&l); }
|
||||
else if (c == ')') { tokens[idx++] = make_token(&l, TOK_RPAREN, l.pos, 1); advance(&l); }
|
||||
else if (c == '{') { tokens[idx++] = make_token(&l, TOK_LBRACE, l.pos, 1); advance(&l); }
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ static const char* NAMES[] = {
|
||||
[TOK_LBRACKET] = "[", [TOK_RBRACKET] = "]",
|
||||
[TOK_COMMA] = ",", [TOK_COLON] = ":", [TOK_SEMICOLON] = ";",
|
||||
[TOK_ASSIGN] = "=",
|
||||
[TOK_DOT] = ".", [TOK_COLON_COLON] = "::",
|
||||
[TOK_DOT] = ".", [TOK_COLON_COLON] = "::", [TOK_HASH] = "#",
|
||||
[TOK_EOF] = "EOF", [TOK_ERROR] = "错误",
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ typedef enum {
|
||||
TOK_LBRACKET, TOK_RBRACKET,
|
||||
TOK_COMMA, TOK_COLON, TOK_SEMICOLON, TOK_ASSIGN,
|
||||
// 特殊
|
||||
TOK_DOT, TOK_COLON_COLON,
|
||||
TOK_DOT, TOK_COLON_COLON, TOK_HASH,
|
||||
TOK_EOF, TOK_ERROR,
|
||||
} TokenKind;
|
||||
|
||||
|
||||
@@ -413,6 +413,13 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count,
|
||||
if (peek(&p)->kind == TOK_PUB) {
|
||||
is_pub = true; advance(&p);
|
||||
}
|
||||
// 装饰器 #[attr]
|
||||
while (peek(&p)->kind == TOK_HASH) {
|
||||
advance(&p); // 跳过 #
|
||||
if (!expect(&p, TOK_LBRACKET, error, "# 后应为 '['")) return NULL;
|
||||
if (!expect(&p, TOK_IDENT, error, "装饰器名")) return NULL;
|
||||
if (!expect(&p, TOK_RBRACKET, error, "缺少 ']'")) return NULL;
|
||||
}
|
||||
if (peek(&p)->kind == TOK_TRAIT) {
|
||||
const Token* tt = advance(&p);
|
||||
const Token* tname = expect(&p, TOK_IDENT, error, "trait 后应为接口名");
|
||||
|
||||
Reference in New Issue
Block a user