summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanil Alexeev <danil@alexeev.xyz>2023-02-15 17:41:46 +0300
committerDanil Alexeev <danil@alexeev.xyz>2023-02-15 17:41:46 +0300
commitd15511725acdfe90f9d5967119294b591becd8fa (patch)
treea583082b6cff2e980ed0743917db870688f89c12
parentd2b1474da79a4dce5c2031b3a3fafe8aaa2a161f (diff)
downloadredot-engine-d15511725acdfe90f9d5967119294b591becd8fa.tar.gz
GDScript: Fix `MIN_INT` not representable as numeric literal
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp31
-rw-r--r--modules/gdscript/gdscript_tokenizer.h2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/number_literals_with_sign.gd17
-rw-r--r--modules/gdscript/tests/scripts/parser/features/number_literals_with_sign.out16
4 files changed, 66 insertions, 0 deletions
diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index d586380c41..034d517f6e 100644
--- a/modules/gdscript/gdscript_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -162,6 +162,24 @@ const char *GDScriptTokenizer::Token::get_name() const {
return token_names[type];
}
+bool GDScriptTokenizer::Token::can_precede_bin_op() const {
+ switch (type) {
+ case IDENTIFIER:
+ case LITERAL:
+ case SELF:
+ case BRACKET_CLOSE:
+ case BRACE_CLOSE:
+ case PARENTHESIS_CLOSE:
+ case CONST_PI:
+ case CONST_TAU:
+ case CONST_INF:
+ case CONST_NAN:
+ return true;
+ default:
+ return false;
+ }
+}
+
bool GDScriptTokenizer::Token::is_identifier() const {
// Note: Most keywords should not be recognized as identifiers.
// These are only exceptions for stuff that already is on the engine's API.
@@ -382,6 +400,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::make_token(Token::Type p_type) {
}
}
+ last_token = token;
return token;
}
@@ -627,6 +646,7 @@ void GDScriptTokenizer::newline(bool p_make_token) {
newline.leftmost_column = newline.start_column;
newline.rightmost_column = newline.end_column;
pending_newline = true;
+ last_token = newline;
last_newline = newline;
}
@@ -643,6 +663,11 @@ GDScriptTokenizer::Token GDScriptTokenizer::number() {
bool has_error = false;
bool (*digit_check_func)(char32_t) = is_digit;
+ // Sign before hexadecimal or binary.
+ if ((_peek(-1) == '+' || _peek(-1) == '-') && _peek() == '0') {
+ _advance();
+ }
+
if (_peek(-1) == '.') {
has_decimal = true;
} else if (_peek(-1) == '0') {
@@ -1431,6 +1456,9 @@ GDScriptTokenizer::Token GDScriptTokenizer::scan() {
if (_peek() == '=') {
_advance();
return make_token(Token::PLUS_EQUAL);
+ } else if (is_digit(_peek()) && !last_token.can_precede_bin_op()) {
+ // Number starting with '+'.
+ return number();
} else {
return make_token(Token::PLUS);
}
@@ -1438,6 +1466,9 @@ GDScriptTokenizer::Token GDScriptTokenizer::scan() {
if (_peek() == '=') {
_advance();
return make_token(Token::MINUS_EQUAL);
+ } else if (is_digit(_peek()) && !last_token.can_precede_bin_op()) {
+ // Number starting with '-'.
+ return number();
} else if (_peek() == '>') {
_advance();
return make_token(Token::FORWARD_ARROW);
diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h
index 608840d3f1..068393cee9 100644
--- a/modules/gdscript/gdscript_tokenizer.h
+++ b/modules/gdscript/gdscript_tokenizer.h
@@ -171,6 +171,7 @@ public:
String source;
const char *get_name() const;
+ bool can_precede_bin_op() const;
bool is_identifier() const;
bool is_node_name() const;
StringName get_identifier() const { return source; }
@@ -216,6 +217,7 @@ private:
bool multiline_mode = false;
List<Token> error_stack;
bool pending_newline = false;
+ Token last_token;
Token last_newline;
int pending_indents = 0;
List<int> indent_stack;
diff --git a/modules/gdscript/tests/scripts/parser/features/number_literals_with_sign.gd b/modules/gdscript/tests/scripts/parser/features/number_literals_with_sign.gd
new file mode 100644
index 0000000000..cf7fb1518c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/number_literals_with_sign.gd
@@ -0,0 +1,17 @@
+func test():
+ print(-9223372036854775808 == (1 << 63))
+ print(-2)
+ print(- 2)
+ print(---2)
+ print(3 - 2)
+ print(3-2)
+ print(3---2)
+ print(-3 - 2)
+ print(-3 - -2)
+ print(-(3 - 2)-2)
+ print([1, 2, 3][0]-1)
+ var t = 1
+ print(t-1)
+ print(-0xFF)
+ print(1--0xFF)
+ print(floor(PI-1))
diff --git a/modules/gdscript/tests/scripts/parser/features/number_literals_with_sign.out b/modules/gdscript/tests/scripts/parser/features/number_literals_with_sign.out
new file mode 100644
index 0000000000..c5958365ec
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/number_literals_with_sign.out
@@ -0,0 +1,16 @@
+GDTEST_OK
+true
+-2
+-2
+-2
+1
+1
+1
+-5
+-1
+-3
+0
+0
+-255
+256
+2