diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index 08e9cb3..5149f42 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -56,7 +56,7 @@ static TokenKind check_keyword(const Token* tok) { #define KW(s, k) if (tok->length == sizeof(s)-1 && memcmp(tok->start, s, sizeof(s)-1) == 0) return k KW("fn", TOK_FN); KW("let", TOK_LET); KW("var", TOK_VAR); - KW("if", TOK_IF); KW("else", TOK_ELSE); + KW("if", TOK_IF); KW("else", TOK_ELSE); KW("guard", TOK_GUARD); KW("while", TOK_WHILE); KW("for", TOK_FOR); KW("in", TOK_IN); KW("to", TOK_TO); KW("return", TOK_RETURN); diff --git a/src/lexer/token.c b/src/lexer/token.c index 391ad43..eec53c7 100644 --- a/src/lexer/token.c +++ b/src/lexer/token.c @@ -5,7 +5,7 @@ #include static const char* NAMES[] = { - [TOK_FN] = "fn", [TOK_LET] = "let", [TOK_VAR] = "var", [TOK_IF] = "if", + [TOK_FN] = "fn", [TOK_LET] = "let", [TOK_VAR] = "var", [TOK_IF] = "if", [TOK_GUARD] = "guard", [TOK_ELSE] = "else", [TOK_WHILE] = "while", [TOK_FOR] = "for", [TOK_IN] = "in", [TOK_RETURN] = "return", [TOK_STRUCT] = "struct", [TOK_TYPE] = "type", [TOK_ENUM] = "enum", [TOK_EXTEND] = "extend", [TOK_MATCH] = "match", diff --git a/src/lexer/token.h b/src/lexer/token.h index 39cb41a..d544278 100644 --- a/src/lexer/token.h +++ b/src/lexer/token.h @@ -6,7 +6,7 @@ // === Token 类型枚举 === typedef enum { // 关键字 - TOK_FN, TOK_LET, TOK_VAR, TOK_IF, TOK_ELSE, TOK_WHILE, TOK_FOR, TOK_IN, TOK_RETURN, + TOK_FN, TOK_LET, TOK_VAR, TOK_IF, TOK_ELSE, TOK_WHILE, TOK_FOR, TOK_IN, TOK_RETURN, TOK_GUARD, TOK_STRUCT, TOK_TYPE, TOK_ENUM, TOK_EXTEND, TOK_MATCH, // 类型关键字 TOK_I32, TOK_I64, TOK_U64, TOK_F64, TOK_BOOL, TOK_CHAR, TOK_STR, TOK_VOID, diff --git a/src/parser/parser.c b/src/parser/parser.c index 065ee21..8825635 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -621,6 +621,19 @@ static AstNode* parse_statement(Parser* p, ErrorInfo* error) { return parse_match_stmt(p, error); } + if (t->kind == TOK_GUARD) { + // guard expr else { ... } → if !(expr) { ... } + const Token* guard_tok = advance(p); + AstNode* cond = parse_expr(p, error); + if (!cond) return NULL; + if (!expect(p, TOK_ELSE, error, "guard 缺少 'else'")) return NULL; + AstNode* body = parse_block(p, error); + if (!body) return NULL; + // 去糖: if !cond { body } + AstNode* not_cond = ast_make_unary(p->arena, OP_NOT, cond, tok_loc(guard_tok)); + return ast_make_if(p->arena, not_cond, body, NULL, tok_loc(guard_tok)); + } + if (t->kind == TOK_RETURN) { advance(p); if (match(p, TOK_SEMICOLON)) { diff --git a/test/programs/26_guard.l b/test/programs/26_guard.l new file mode 100644 index 0000000..44e5520 --- /dev/null +++ b/test/programs/26_guard.l @@ -0,0 +1,11 @@ +fn abs(x: i64) -> i64 { + guard x >= 0 else { return -x; } + return x; +} + +fn main() -> i64 { + print_i64(abs(10)); // 10 + print_i64(abs(-5)); // 5 + print_i64(abs(0)); // 0 + return 0; +}