瀏覽代碼

GDScript: Fix repeated `_` are allowed after decimal point

Danil Alexeev 2 年之前
父節點
當前提交
fba8cbe6db

+ 35 - 4
modules/gdscript/gdscript_tokenizer.cpp

@@ -659,12 +659,20 @@ GDScriptTokenizer::Token GDScriptTokenizer::number() {
 		}
 	}
 
-	// Allow '_' to be used in a number, for readability.
-	bool previous_was_underscore = false;
+	if (base != 10 && is_underscore(_peek())) { // Disallow `0x_` and `0b_`.
+		Token error = make_error(vformat(R"(Unexpected underscore after "0%c".)", _peek(-1)));
+		error.start_column = column;
+		error.leftmost_column = column;
+		error.end_column = column + 1;
+		error.rightmost_column = column + 1;
+		push_error(error);
+		has_error = true;
+	}
+	bool previous_was_underscore = false; // Allow `_` to be used in a number, for readability.
 	while (digit_check_func(_peek()) || is_underscore(_peek())) {
 		if (is_underscore(_peek())) {
 			if (previous_was_underscore) {
-				Token error = make_error(R"(Only one underscore can be used as a numeric separator.)");
+				Token error = make_error(R"(Multiple underscores cannot be adjacent in a numeric literal.)");
 				error.start_column = column;
 				error.leftmost_column = column;
 				error.end_column = column + 1;
@@ -711,7 +719,30 @@ GDScriptTokenizer::Token GDScriptTokenizer::number() {
 			_advance();
 
 			// Consume decimal digits.
+			if (is_underscore(_peek())) { // Disallow `10._`, but allow `10.`.
+				Token error = make_error(R"(Unexpected underscore after decimal point.)");
+				error.start_column = column;
+				error.leftmost_column = column;
+				error.end_column = column + 1;
+				error.rightmost_column = column + 1;
+				push_error(error);
+				has_error = true;
+			}
+			previous_was_underscore = false;
 			while (is_digit(_peek()) || is_underscore(_peek())) {
+				if (is_underscore(_peek())) {
+					if (previous_was_underscore) {
+						Token error = make_error(R"(Multiple underscores cannot be adjacent in a numeric literal.)");
+						error.start_column = column;
+						error.leftmost_column = column;
+						error.end_column = column + 1;
+						error.rightmost_column = column + 1;
+						push_error(error);
+					}
+					previous_was_underscore = true;
+				} else {
+					previous_was_underscore = false;
+				}
 				_advance();
 			}
 		}
@@ -737,7 +768,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::number() {
 			while (is_digit(_peek()) || is_underscore(_peek())) {
 				if (is_underscore(_peek())) {
 					if (previous_was_underscore) {
-						Token error = make_error(R"(Only one underscore can be used as a numeric separator.)");
+						Token error = make_error(R"(Multiple underscores cannot be adjacent in a numeric literal.)");
 						error.start_column = column;
 						error.leftmost_column = column;
 						error.end_column = column + 1;

+ 1 - 1
modules/gdscript/tests/scripts/parser/errors/multiple_number_separators.gd

@@ -1,3 +1,3 @@
 func test():
 	# Number separators may not be placed right next to each other.
-	var __ = 1__23
+	var _num = 1__23

+ 1 - 1
modules/gdscript/tests/scripts/parser/errors/multiple_number_separators.out

@@ -1,2 +1,2 @@
 GDTEST_PARSER_ERROR
-Only one underscore can be used as a numeric separator.
+Multiple underscores cannot be adjacent in a numeric literal.

+ 3 - 0
modules/gdscript/tests/scripts/parser/errors/multiple_number_separators_after_decimal.gd

@@ -0,0 +1,3 @@
+func test():
+	# Number separators may not be placed right next to each other.
+	var _num = 123.45__67

+ 2 - 0
modules/gdscript/tests/scripts/parser/errors/multiple_number_separators_after_decimal.out

@@ -0,0 +1,2 @@
+GDTEST_PARSER_ERROR
+Multiple underscores cannot be adjacent in a numeric literal.

+ 23 - 9
modules/gdscript/tests/scripts/parser/features/number_separators.gd

@@ -1,12 +1,26 @@
 func test():
 	# `_` can be used as a separator for numbers in GDScript.
 	# It can be placed anywhere in the number, except at the beginning.
-	# Currently, GDScript in the `master` branch only allows using one separator
-	# per number.
-	# Results are assigned to variables to avoid warnings.
-	var __ = 1_23
-	__ = 123_  # Trailing number separators are OK.
-	__ = 12_3
-	__ = 123_456
-	__ = 0x1234_5678
-	__ = 0b1001_0101
+	print(1_23)
+	print(12_3)
+	print(1_2_3)
+	print(123_) # Trailing number separators are OK.
+	print(123_456)
+	print(123_45_6_)
+	print("---")
+	print(0x1234_00ff)
+	print(0x1234_00_f_f_)
+	print(0b1001_0101)
+	print(0b1001_01_0_1_)
+	print("---")
+	print(-1_234.456_7)
+	print(-1_23_4_.4_56_7_)
+	print(-1_234.)
+	print(-1_23_4_.)
+	print(.456_7)
+	print(.4_56_7_)
+	print("---")
+	print(-1_234.5e000_3)
+	print(-1_23_4_.5e0_00_3_)
+	print(-1_234.5e+000_3)
+	print(-1_23_4_.5e+0_00_3_)

+ 23 - 0
modules/gdscript/tests/scripts/parser/features/number_separators.out

@@ -1 +1,24 @@
 GDTEST_OK
+123
+123
+123
+123
+123456
+123456
+---
+305398015
+305398015
+149
+149
+---
+-1234.4567
+-1234.4567
+-1234
+-1234
+0.4567
+0.4567
+---
+-1234500
+-1234500
+-1234500
+-1234500