mirror of
https://github.com/odin-lang/Odin.git
synced 2026-06-06 18:54:12 +00:00
Change label syntax for for and match from #label name to name:
This commit is contained in:
@@ -561,10 +561,10 @@ _write_int :: proc(fi: ^FmtInfo, u: u64, base: int, is_signed: bool, bit_size: i
|
||||
}
|
||||
|
||||
buf: [256]byte;
|
||||
flags: strconv.Int_Flag;
|
||||
if fi.hash { flags |= strconv.Int_Flag.PREFIX; }
|
||||
if fi.plus { flags |= strconv.Int_Flag.PLUS; }
|
||||
if fi.space { flags |= strconv.Int_Flag.SPACE; }
|
||||
flags: strconv.IntFlag;
|
||||
if fi.hash { flags |= strconv.IntFlag.PREFIX; }
|
||||
if fi.plus { flags |= strconv.IntFlag.PLUS; }
|
||||
if fi.space { flags |= strconv.IntFlag.SPACE; }
|
||||
s := strconv.append_bits(buf[0..<0], u, base, is_signed, bit_size, digits, flags);
|
||||
|
||||
prev_zero := fi.zero;
|
||||
@@ -1089,7 +1089,7 @@ sbprintf :: proc(b: ^StringBuffer, fmt: string, args: ..any) -> string {
|
||||
// Process a "verb"
|
||||
i++;
|
||||
|
||||
#label prefix_loop
|
||||
prefix_loop:
|
||||
for ; i < end; i++ {
|
||||
match fmt[i] {
|
||||
case '+':
|
||||
|
||||
@@ -41,7 +41,7 @@ RTLD_FIRST :: 0x100;
|
||||
|
||||
args: [dynamic]string;
|
||||
|
||||
FileTime :: struct #ordered {
|
||||
_FileTime :: struct #ordered {
|
||||
seconds: i64,
|
||||
nanoseconds: i64
|
||||
}
|
||||
|
||||
150
src/parser.c
150
src/parser.c
@@ -106,6 +106,13 @@ typedef enum FieldFlag {
|
||||
FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_immutable,
|
||||
} FieldListTag;
|
||||
|
||||
typedef enum StmtAllowFlag {
|
||||
StmtAllowFlag_None = 0,
|
||||
StmtAllowFlag_In = 1<<0,
|
||||
StmtAllowFlag_Label = 1<<1,
|
||||
} StmtAllowFlag;
|
||||
|
||||
|
||||
|
||||
AstNodeArray make_ast_node_array(AstFile *f) {
|
||||
AstNodeArray a;
|
||||
@@ -1594,6 +1601,14 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
|
||||
}
|
||||
|
||||
switch (s->kind) {
|
||||
case AstNode_IfStmt:
|
||||
case AstNode_WhenStmt:
|
||||
case AstNode_ForStmt:
|
||||
case AstNode_RangeStmt:
|
||||
case AstNode_MatchStmt:
|
||||
case AstNode_TypeMatchStmt:
|
||||
return true;
|
||||
|
||||
case AstNode_HelperType:
|
||||
return is_semicolon_optional_for_node(f, s->HelperType.type);
|
||||
|
||||
@@ -1912,9 +1927,10 @@ void parse_proc_tags(AstFile *f, u64 *tags, AstNode **foreign_library_token, Str
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AstNodeArray parse_lhs_expr_list(AstFile *f);
|
||||
AstNodeArray parse_rhs_expr_list(AstFile *f);
|
||||
AstNode * parse_simple_stmt (AstFile *f, bool in_stmt_ok);
|
||||
AstNode * parse_simple_stmt (AstFile *f, StmtAllowFlag flags);
|
||||
AstNode * parse_type (AstFile *f);
|
||||
|
||||
AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) {
|
||||
@@ -1932,73 +1948,6 @@ AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) {
|
||||
|
||||
|
||||
|
||||
// AstNode *parse_block_expr(AstFile *f) {
|
||||
// AstNodeArray stmts = {0};
|
||||
// Token open, close;
|
||||
// open = expect_token(f, Token_OpenBrace);
|
||||
// f->expr_level++;
|
||||
// stmts = parse_stmt_list(f);
|
||||
// f->expr_level--;
|
||||
// close = expect_token(f, Token_CloseBrace);
|
||||
// return ast_block_expr(f, stmts, open, close);
|
||||
// }
|
||||
|
||||
// AstNode *parse_if_expr(AstFile *f) {
|
||||
// if (f->curr_proc == NULL) {
|
||||
// syntax_error(f->curr_token, "You cannot use an if expression in the file scope");
|
||||
// return ast_bad_stmt(f, f->curr_token, f->curr_token);
|
||||
// }
|
||||
|
||||
// Token token = expect_token(f, Token_if);
|
||||
// AstNode *init = NULL;
|
||||
// AstNode *cond = NULL;
|
||||
// AstNode *body = NULL;
|
||||
// AstNode *else_expr = NULL;
|
||||
|
||||
// isize prev_level = f->expr_level;
|
||||
// f->expr_level = -1;
|
||||
|
||||
// if (allow_token(f, Token_Semicolon)) {
|
||||
// cond = parse_expr(f, false);
|
||||
// } else {
|
||||
// init = parse_simple_stmt(f, false);
|
||||
// if (allow_token(f, Token_Semicolon)) {
|
||||
// cond = parse_expr(f, false);
|
||||
// } else {
|
||||
// cond = convert_stmt_to_expr(f, init, str_lit("boolean expression"));
|
||||
// init = NULL;
|
||||
// }
|
||||
// }
|
||||
|
||||
// f->expr_level = prev_level;
|
||||
|
||||
// if (cond == NULL) {
|
||||
// syntax_error(f->curr_token, "Expected condition for if statement");
|
||||
// }
|
||||
|
||||
// body = parse_block_expr(f);
|
||||
|
||||
// if (allow_token(f, Token_else)) {
|
||||
// switch (f->curr_token.kind) {
|
||||
// case Token_if:
|
||||
// else_expr = parse_if_expr(f);
|
||||
// break;
|
||||
// case Token_OpenBrace:
|
||||
// else_expr = parse_block_expr(f);
|
||||
// break;
|
||||
// default:
|
||||
// syntax_error(f->curr_token, "Expected if expression block statement");
|
||||
// else_expr = ast_bad_expr(f, f->curr_token, f->tokens.e[f->curr_token_index+1]);
|
||||
// break;
|
||||
// }
|
||||
// } else {
|
||||
// syntax_error(f->curr_token, "An if expression must have an else clause");
|
||||
// return ast_bad_stmt(f, f->curr_token, f->tokens.e[f->curr_token_index+1]);
|
||||
// }
|
||||
|
||||
// return ast_if_expr(f, token, init, cond, body, else_expr);
|
||||
// }
|
||||
|
||||
AstNode *parse_operand(AstFile *f, bool lhs) {
|
||||
AstNode *operand = NULL; // Operand
|
||||
switch (f->curr_token.kind) {
|
||||
@@ -2556,7 +2505,7 @@ AstNode *parse_value_decl(AstFile *f, AstNodeArray lhs) {
|
||||
|
||||
|
||||
|
||||
AstNode *parse_simple_stmt(AstFile *f, bool in_stmt_ok) {
|
||||
AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) {
|
||||
AstNodeArray lhs = parse_lhs_expr_list(f);
|
||||
Token token = f->curr_token;
|
||||
switch (token.kind) {
|
||||
@@ -2590,7 +2539,7 @@ AstNode *parse_simple_stmt(AstFile *f, bool in_stmt_ok) {
|
||||
} break;
|
||||
|
||||
case Token_in:
|
||||
if (in_stmt_ok) {
|
||||
if (flags&StmtAllowFlag_In) {
|
||||
allow_token(f, Token_in);
|
||||
bool prev_allow_range = f->allow_range;
|
||||
f->allow_range = true;
|
||||
@@ -2606,6 +2555,31 @@ AstNode *parse_simple_stmt(AstFile *f, bool in_stmt_ok) {
|
||||
break;
|
||||
|
||||
case Token_Colon:
|
||||
if ((flags&StmtAllowFlag_Label) && lhs.count == 1) {
|
||||
TokenKind next = look_ahead_token_kind(f, 1);
|
||||
switch (next) {
|
||||
case Token_for:
|
||||
case Token_match: {
|
||||
next_token(f);
|
||||
AstNode *name = lhs.e[0];
|
||||
AstNode *label = ast_label_decl(f, ast_node_token(name), name);
|
||||
AstNode *stmt = parse_stmt(f);
|
||||
#define _SET_LABEL(Kind_, label_) case GB_JOIN2(AstNode_, Kind_): (stmt->Kind_).label = label_; break
|
||||
switch (stmt->kind) {
|
||||
_SET_LABEL(ForStmt, label);
|
||||
_SET_LABEL(RangeStmt, label);
|
||||
_SET_LABEL(MatchStmt, label);
|
||||
_SET_LABEL(TypeMatchStmt, label);
|
||||
default:
|
||||
syntax_error(token, "Labels can only be applied to a loop or match statement");
|
||||
break;
|
||||
}
|
||||
#undef _SET_LABEL
|
||||
return stmt;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
return parse_value_decl(f, lhs);
|
||||
}
|
||||
|
||||
@@ -2614,6 +2588,8 @@ AstNode *parse_simple_stmt(AstFile *f, bool in_stmt_ok) {
|
||||
return ast_bad_stmt(f, token, f->curr_token);
|
||||
}
|
||||
|
||||
|
||||
|
||||
switch (token.kind) {
|
||||
case Token_Inc:
|
||||
case Token_Dec:
|
||||
@@ -3207,7 +3183,7 @@ AstNode *parse_if_stmt(AstFile *f) {
|
||||
if (allow_token(f, Token_Semicolon)) {
|
||||
cond = parse_expr(f, false);
|
||||
} else {
|
||||
init = parse_simple_stmt(f, false);
|
||||
init = parse_simple_stmt(f, StmtAllowFlag_None);
|
||||
if (allow_token(f, Token_Semicolon)) {
|
||||
cond = parse_expr(f, false);
|
||||
} else {
|
||||
@@ -3343,7 +3319,7 @@ AstNode *parse_for_stmt(AstFile *f) {
|
||||
isize prev_level = f->expr_level;
|
||||
f->expr_level = -1;
|
||||
if (f->curr_token.kind != Token_Semicolon) {
|
||||
cond = parse_simple_stmt(f, true);
|
||||
cond = parse_simple_stmt(f, StmtAllowFlag_In);
|
||||
if (cond->kind == AstNode_AssignStmt && cond->AssignStmt.op.kind == Token_in) {
|
||||
is_range = true;
|
||||
}
|
||||
@@ -3354,11 +3330,11 @@ AstNode *parse_for_stmt(AstFile *f) {
|
||||
init = cond;
|
||||
cond = NULL;
|
||||
if (f->curr_token.kind != Token_Semicolon) {
|
||||
cond = parse_simple_stmt(f, false);
|
||||
cond = parse_simple_stmt(f, StmtAllowFlag_None);
|
||||
}
|
||||
expect_semicolon(f, cond);
|
||||
if (f->curr_token.kind != Token_OpenBrace) {
|
||||
post = parse_simple_stmt(f, false);
|
||||
post = parse_simple_stmt(f, StmtAllowFlag_None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3432,7 +3408,7 @@ AstNode *parse_match_stmt(AstFile *f) {
|
||||
isize prev_level = f->expr_level;
|
||||
f->expr_level = -1;
|
||||
|
||||
tag = parse_simple_stmt(f, true);
|
||||
tag = parse_simple_stmt(f, StmtAllowFlag_In);
|
||||
if (tag->kind == AstNode_AssignStmt && tag->AssignStmt.op.kind == Token_in) {
|
||||
is_type_match = true;
|
||||
} else {
|
||||
@@ -3440,7 +3416,7 @@ AstNode *parse_match_stmt(AstFile *f) {
|
||||
init = tag;
|
||||
tag = NULL;
|
||||
if (f->curr_token.kind != Token_OpenBrace) {
|
||||
tag = parse_simple_stmt(f, false);
|
||||
tag = parse_simple_stmt(f, StmtAllowFlag_None);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3536,7 +3512,7 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
case Token_Xor:
|
||||
case Token_Not:
|
||||
case Token_And:
|
||||
s = parse_simple_stmt(f, false);
|
||||
s = parse_simple_stmt(f, StmtAllowFlag_Label);
|
||||
expect_semicolon(f, s);
|
||||
return s;
|
||||
|
||||
@@ -3648,25 +3624,7 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
Token name = expect_token(f, Token_Ident);
|
||||
String tag = name.string;
|
||||
|
||||
if (str_eq(tag, str_lit("label"))) {
|
||||
AstNode *name = parse_ident(f);
|
||||
AstNode *label = ast_label_decl(f, token, name);
|
||||
AstNode *stmt = parse_stmt(f);
|
||||
|
||||
#define _SET_LABEL(Kind_, label_) case GB_JOIN2(AstNode_, Kind_): (stmt->Kind_).label = label_; break
|
||||
switch (stmt->kind) {
|
||||
_SET_LABEL(ForStmt, label);
|
||||
_SET_LABEL(RangeStmt, label);
|
||||
_SET_LABEL(MatchStmt, label);
|
||||
_SET_LABEL(TypeMatchStmt, label);
|
||||
default:
|
||||
syntax_error(token, "#label cannot only be applied to a loop or match statement");
|
||||
break;
|
||||
}
|
||||
#undef _SET_LABEL
|
||||
|
||||
return stmt;
|
||||
} else if (str_eq(tag, str_lit("import"))) {
|
||||
if (str_eq(tag, str_lit("import"))) {
|
||||
AstNode *cond = NULL;
|
||||
Token import_name = {0};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user