Sfoglia il codice sorgente

Allow not_in as keyword over notin, but still allow notin to work

gingerBill 5 anni fa
parent
commit
159150c6d9

+ 5 - 5
core/odin/parser/parser.odin

@@ -1146,7 +1146,7 @@ token_precedence :: proc(p: ^Parser, kind: tokenizer.Token_Kind) -> int {
 	     .Lt, .Gt,
 	     .Lt_Eq, .Gt_Eq:
 		return 5;
-	case .In, .Notin:
+	case .In, .Not_In:
 		if p.expr_level < 0 && !p.allow_in_expr {
 			return 0;
 		}
@@ -1390,7 +1390,7 @@ check_field_flag_prefixes :: proc(p: ^Parser, name_count: int, allowed_flags, se
 	}
 
 	for flag in ast.Field_Flag {
-		if flag notin allowed_flags && flag in flags {
+		if flag not_in allowed_flags && flag in flags {
 			switch flag {
 			case .Using:
 				error(p, p.curr_tok.pos, "'using' is not allowed within this field list");
@@ -1557,7 +1557,7 @@ parse_field_list :: proc(p: ^Parser, follow: tokenizer.Token_Kind, allowed_flags
 
 		if allow_token(p, .Eq) {
 			default_value = parse_expr(p, false);
-			if ast.Field_Flag.Default_Parameters notin allowed_flags {
+			if ast.Field_Flag.Default_Parameters not_in allowed_flags {
 				error(p, p.curr_tok.pos, "default parameters are only allowed for procedures");
 				default_value = nil;
 			}
@@ -1585,7 +1585,7 @@ parse_field_list :: proc(p: ^Parser, follow: tokenizer.Token_Kind, allowed_flags
 		if type != nil && default_value == nil {
 			if p.curr_tok.kind == .String {
 				tag = expect_token(p, .String);
-				if .Tags notin allowed_flags {
+				if .Tags not_in allowed_flags {
 					error(p, tag.pos, "Field tags are only allowed within structures");
 				}
 			}
@@ -1644,7 +1644,7 @@ parse_field_list :: proc(p: ^Parser, follow: tokenizer.Token_Kind, allowed_flags
 			type := eaf.expr;
 			tok: tokenizer.Token;
 			tok.pos = type.pos;
-			if ast.Field_Flag.Results notin allowed_flags {
+			if ast.Field_Flag.Results not_in allowed_flags {
 				tok.text = "_";
 			}
 

+ 3 - 3
core/odin/tokenizer/token.odin

@@ -124,7 +124,7 @@ Token_Kind :: enum u32 {
 		For,
 		Switch,
 		In,
-		Notin,
+		Not_In,
 		Do,
 		Case,
 		Break,
@@ -259,7 +259,7 @@ tokens := [Token_Kind.COUNT]string {
 	"for",
 	"switch",
 	"in",
-	"notin",
+	"not_in",
 	"do",
 	"case",
 	"break",
@@ -316,7 +316,7 @@ is_operator :: proc(kind: Token_Kind) -> bool {
 	#partial switch kind {
 	case .B_Operator_Begin .. .B_Operator_End:
 		return true;
-	case .In, .Notin:
+	case .In, .Not_In:
 		return true;
 	}
 	return false;

+ 3 - 6
core/odin/tokenizer/tokenizer.odin

@@ -501,6 +501,9 @@ scan :: proc(t: ^Tokenizer) -> Token {
 					break check_keyword;
 				}
 			}
+			if kind == .Ident && lit == "notin" {
+				kind = .Not_In;
+			}
 		}
 	case '0' <= ch && ch <= '9':
 		kind, lit = scan_number(t, false);
@@ -575,12 +578,6 @@ scan :: proc(t: ^Tokenizer) -> Token {
 			}
 		case '>': kind = switch4(t, .Gt, .Gt_Eq, '>', .Shr,.Shr_Eq);
 
-		case '≠': kind = .Not_Eq;
-		case '≤': kind = .Lt_Eq;
-		case '≥': kind = .Gt_Eq;
-		case '∈': kind = .In;
-		case '∉': kind = .Notin;
-
 		case '.':
 			if '0' <= t.ch && t.ch <= '9' {
 				kind, lit = scan_number(t, true);

+ 1 - 1
examples/demo/demo.odin

@@ -1363,7 +1363,7 @@ bit_set_type :: proc() {
 		incl(&x, 'F');
 		assert('F' in x);
 		excl(&x, 'F');
-		assert('F' notin x);
+		assert('F' not_in x);
 
 		y |= {1, 4, 2};
 		assert(2 in y);

+ 1 - 1
examples/hms2019/hms2019.odin

@@ -1271,7 +1271,7 @@ bit_set_type :: proc() {
 		incl(&x, 'F');
 		assert('F' in x);
 		excl(&x, 'F');
-		assert('F' notin x);
+		assert('F' not_in x);
 
 		y |= {1, 4, 2};
 		assert(2 in y);

+ 3 - 3
src/check_expr.cpp

@@ -2397,7 +2397,7 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint
 	}
 
 	case Token_in:
-	case Token_notin:
+	case Token_not_in:
 		// IMPORTANT NOTE(bill): This uses right-left evaluation in type checking only no in
 
 		check_expr(c, y, be->right);
@@ -2426,7 +2426,7 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint
 			if (op.kind == Token_in) {
 				check_assignment(c, x, yt->Map.key, str_lit("map 'in'"));
 			} else {
-				check_assignment(c, x, yt->Map.key, str_lit("map 'notin'"));
+				check_assignment(c, x, yt->Map.key, str_lit("map 'not_in'"));
 			}
 
 			add_package_dependency(c, "runtime", "__dynamic_map_get");
@@ -2436,7 +2436,7 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint
 			if (op.kind == Token_in) {
 				check_assignment(c, x, yt->BitSet.elem, str_lit("bit_set 'in'"));
 			} else {
-				check_assignment(c, x, yt->BitSet.elem, str_lit("bit_set 'notin'"));
+				check_assignment(c, x, yt->BitSet.elem, str_lit("bit_set 'not_in'"));
 			}
 			if (x->mode == Addressing_Constant && y->mode == Addressing_Constant) {
 				ExactValue k = exact_value_to_integer(x->value);

+ 3 - 3
src/ir.cpp

@@ -7302,7 +7302,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 
 
 		case Token_in:
-		case Token_notin: {
+		case Token_not_in: {
 			irValue *left = ir_build_expr(proc, be->left);
 			Type *type = default_type(tv.type);
 			irValue *right = ir_build_expr(proc, be->right);
@@ -7313,7 +7313,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 					if (be->op.kind == Token_in) {
 						ir_emit_comment(proc, str_lit("map in"));
 					} else {
-						ir_emit_comment(proc, str_lit("map notin"));
+						ir_emit_comment(proc, str_lit("map not_in"));
 					}
 
 					irValue *addr = ir_address_from_load_or_generate_local(proc, right);
@@ -7337,7 +7337,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 					if (be->op.kind == Token_in) {
 						ir_emit_comment(proc, str_lit("bit_set in"));
 					} else {
-						ir_emit_comment(proc, str_lit("bit_set notin"));
+						ir_emit_comment(proc, str_lit("bit_set not_in"));
 					}
 
 					Type *key_type = rt->BitSet.elem;

+ 2 - 2
src/parser.cpp

@@ -1196,7 +1196,7 @@ bool is_token_range(Token tok) {
 
 Token expect_operator(AstFile *f) {
 	Token prev = f->curr_token;
-	if ((prev.kind == Token_in || prev.kind == Token_notin) && (f->expr_level >= 0 || f->allow_in_expr)) {
+	if ((prev.kind == Token_in || prev.kind == Token_not_in) && (f->expr_level >= 0 || f->allow_in_expr)) {
 		// okay
 	} else if (!gb_is_between(prev.kind, Token__OperatorBegin+1, Token__OperatorEnd-1)) {
 		syntax_error(f->curr_token, "Expected an operator, got '%.*s'",
@@ -2515,7 +2515,7 @@ i32 token_precedence(AstFile *f, TokenKind t) {
 		return 5;
 
 	case Token_in:
-	case Token_notin:
+	case Token_not_in:
 		if (f->expr_level < 0 && !f->allow_in_expr) {
 			return 0;
 		}

+ 10 - 6
src/tokenizer.cpp

@@ -92,7 +92,7 @@ TOKEN_KIND(Token__KeywordBegin, ""), \
 	TOKEN_KIND(Token_for,         "for"),         \
 	TOKEN_KIND(Token_switch,      "switch"),      \
 	TOKEN_KIND(Token_in,          "in"),          \
-	TOKEN_KIND(Token_notin,       "notin"),       \
+	TOKEN_KIND(Token_not_in,      "not_in"),      \
 	TOKEN_KIND(Token_do,          "do"),          \
 	TOKEN_KIND(Token_case,        "case"),        \
 	TOKEN_KIND(Token_break,       "break"),       \
@@ -902,6 +902,10 @@ Token tokenizer_get_token(Tokenizer *t) {
 					break;
 				}
 			}
+
+			if (token.kind == Token_Ident && token.string == "notin") {
+				token.kind = Token_not_in; 
+			}
 		}
 
 	} else if (gb_is_between(curr_rune, '0', '9')) {
@@ -1029,11 +1033,11 @@ Token tokenizer_get_token(Tokenizer *t) {
 		case '}':  token.kind = Token_CloseBrace;   break;
 		case '\\': token.kind = Token_BackSlash;    break;
 
-		case 0x2260: token.kind = Token_NotEq; break; // '≠'
-		case 0x2264: token.kind = Token_LtEq;  break; // '≤'
-		case 0x2265: token.kind = Token_GtEq;  break; // '≥'
-		case 0x2208: token.kind = Token_in;    break; // '∈'
-		case 0x2209: token.kind = Token_notin; break; // '∉'
+		// case 0x2260: token.kind = Token_NotEq;  break; // '≠'
+		// case 0x2264: token.kind = Token_LtEq;   break; // '≤'
+		// case 0x2265: token.kind = Token_GtEq;   break; // '≥'
+		// case 0x2208: token.kind = Token_in;     break; // '∈'
+		// case 0x2209: token.kind = Token_not_in; break; // '∉'
 
 		case '%': token.kind = token_kind_dub_eq(t, '%', Token_Mod, Token_ModEq, Token_ModMod, Token_ModModEq);  break;