diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index eb4b81e..1e207e7 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -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); } diff --git a/src/lexer/token.c b/src/lexer/token.c index ef77300..e1ae531 100644 --- a/src/lexer/token.c +++ b/src/lexer/token.c @@ -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] = "错误", }; diff --git a/src/lexer/token.h b/src/lexer/token.h index 0682065..9c13a9a 100644 --- a/src/lexer/token.h +++ b/src/lexer/token.h @@ -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; diff --git a/src/parser/parser.c b/src/parser/parser.c index f2fc057..4a6c76a 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -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 后应为接口名");