diff --git a/README.md b/README.md index da0fa03..a7ee7be 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ graph TB - `if` / `else` / `else if` - `while` 循环 -- `for i in 0..10` (去糖为 while) +- `for i in 0 to 10` (去糖为 while) - `match expr { pat => { ... } _ => { ... } }` (去糖为 if-else) - `return` diff --git a/docs/language-reference.md b/docs/language-reference.md index 4e2dd99..5a27475 100644 --- a/docs/language-reference.md +++ b/docs/language-reference.md @@ -188,13 +188,13 @@ while i < 5 { ### for 循环 ```rust -for i in 0..5 { +for i in 0 to 5 { print_i64(i); } // 输出: 0 1 2 3 4 ``` -`for i in start..end` 等价于 `let mut i = start; while i < end { ...; i += 1; }` +`for i in start to end` 等价于 `let mut i = start; while i < end { ...; i += 1; }` ### match @@ -566,7 +566,7 @@ l_lang.exe source.l --emit-ir 类型: i64 f64 bool str void struct enum [T;N] 声明: let x = val let mut x = val let x: Type = val type Alias = Type -控制流: if/else while for i in 0..N match +控制流: if/else while for i in 0 to N match 函数: fn name(p: T) -> Ret { return expr; } 结构体: struct Name { f: Type } Name { f: val } 枚举: enum Name { A, B, C } Name::B diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index df00503..9882c34 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -58,6 +58,7 @@ static TokenKind check_keyword(const Token* tok) { KW("mut", TOK_MUT); KW("if", TOK_IF); KW("else", TOK_ELSE); KW("while", TOK_WHILE); KW("for", TOK_FOR); KW("in", TOK_IN); + KW("to", TOK_TO); KW("return", TOK_RETURN); KW("i64", TOK_I64); KW("f64", TOK_F64); KW("bool", TOK_BOOL); KW("str", TOK_STR); @@ -137,7 +138,6 @@ Token* lex(Arena* a, const char* source, const char* filename, else if (c == '>') { tokens[idx++] = make_token(&l, TOK_GT, l.pos, 1); advance(&l); } else if (c == '&' && peek_next(&l) == '&') { tokens[idx++] = make_token(&l, TOK_AND_AND, l.pos, 2); advance(&l); advance(&l); } else if (c == '|' && peek_next(&l) == '|') { tokens[idx++] = make_token(&l, TOK_PIPE_PIPE, l.pos, 2); advance(&l); advance(&l); } - else if (c == '.' && peek_next(&l) == '.') { tokens[idx++] = make_token(&l, TOK_DOT_DOT, l.pos, 2); advance(&l); advance(&l); } 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); } diff --git a/src/lexer/token.c b/src/lexer/token.c index 89f035c..482a923 100644 --- a/src/lexer/token.c +++ b/src/lexer/token.c @@ -18,7 +18,7 @@ static const char* NAMES[] = { [TOK_EQ_EQ] = "==", [TOK_BANG_EQ] = "!=", [TOK_LT] = "<", [TOK_GT] = ">", [TOK_LT_EQ] = "<=", [TOK_GT_EQ] = ">=", [TOK_AND_AND] = "&&", [TOK_PIPE_PIPE] = "||", [TOK_BANG] = "!", - [TOK_ARROW] = "->", [TOK_DOT_DOT] = "..", [TOK_MATCH_ARROW] = "=>", + [TOK_ARROW] = "->", [TOK_TO] = "to", [TOK_MATCH_ARROW] = "=>", [TOK_PLUS_EQ] = "+=", [TOK_MINUS_EQ] = "-=", [TOK_STAR_EQ] = "*=", [TOK_SLASH_EQ] = "/=", [TOK_LPAREN] = "(", [TOK_RPAREN] = ")", [TOK_LBRACE] = "{", [TOK_RBRACE] = "}", diff --git a/src/lexer/token.h b/src/lexer/token.h index afafad7..fc69f00 100644 --- a/src/lexer/token.h +++ b/src/lexer/token.h @@ -18,7 +18,7 @@ typedef enum { TOK_PLUS, TOK_MINUS, TOK_STAR, TOK_SLASH, TOK_PERCENT, TOK_EQ_EQ, TOK_BANG_EQ, TOK_LT, TOK_GT, TOK_LT_EQ, TOK_GT_EQ, TOK_AND_AND, TOK_PIPE_PIPE, TOK_BANG, - TOK_ARROW, TOK_DOT_DOT, TOK_MATCH_ARROW, + TOK_ARROW, TOK_TO, TOK_MATCH_ARROW, TOK_PLUS_EQ, TOK_MINUS_EQ, TOK_STAR_EQ, TOK_SLASH_EQ, // 分隔符 TOK_LPAREN, TOK_RPAREN, TOK_LBRACE, TOK_RBRACE, diff --git a/src/parser/parser.c b/src/parser/parser.c index c951322..1dcc413 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -546,8 +546,8 @@ static AstNode* parse_statement(Parser* p, ErrorInfo* error) { AstNode* start_expr = parse_expr(p, error); if (!start_expr) return NULL; - // 解析 '..' - if (!expect(p, TOK_DOT_DOT, error, "缺少 '..'")) return NULL; + // 解析 'to' + if (!expect(p, TOK_TO, error, "缺少 'to'")) return NULL; // 解析结束表达式 AstNode* end_expr = parse_expr(p, error); @@ -557,7 +557,7 @@ static AstNode* parse_statement(Parser* p, ErrorInfo* error) { AstNode* body = parse_block(p, error); if (!body) return NULL; - // 脱糖: for i in start..end { body; } + // 脱糖: for i in start to end { body; } // → { let mut i = start; while i < end { body; i = i + 1; } } const char* vname = arena_strdup_impl(p->arena, var_name->start, var_name->length); diff --git a/test/programs/10_for_range.l b/test/programs/10_for_range.l index 47960cb..f556f29 100644 --- a/test/programs/10_for_range.l +++ b/test/programs/10_for_range.l @@ -1,5 +1,5 @@ fn main() -> i64 { - for i in 0..5 { + for i in 0 to 5 { print_i64(i); } return 0; diff --git a/test/programs/11_for_step2.l b/test/programs/11_for_step2.l index 7f3c07a..2ca9103 100644 --- a/test/programs/11_for_step2.l +++ b/test/programs/11_for_step2.l @@ -1,7 +1,7 @@ fn main() -> i64 { let start: i64 = 10; let end: i64 = 15; - for n in start..end { + for n in start to end { print_i64(n); } return 0;