diff options
Diffstat (limited to 'modules/gdscript')
| -rw-r--r-- | modules/gdscript/editor/gdscript_highlighter.cpp | 21 | ||||
| -rw-r--r-- | modules/gdscript/editor/gdscript_highlighter.h | 2 | ||||
| -rw-r--r-- | modules/gdscript/gdscript.cpp | 24 | ||||
| -rw-r--r-- | modules/gdscript/gdscript.h | 5 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_compiler.cpp | 8 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_editor.cpp | 16 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_functions.cpp | 16 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_functions.h | 1 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_parser.cpp | 78 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_parser.h | 2 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_tokenizer.cpp | 27 |
11 files changed, 167 insertions, 33 deletions
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index 4f59b06ae6..62b65fe96b 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -56,6 +56,10 @@ static bool _is_hex_symbol(CharType c) { return ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); } +static bool _is_bin_symbol(CharType c) { + return (c == '0' || c == '1'); +} + Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) { Map<int, TextEdit::HighlighterInfo> color_map; @@ -76,6 +80,7 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ bool in_member_variable = false; bool in_node_path = false; bool is_hex_notation = false; + bool is_bin_notation = false; bool expect_type = false; Color keyword_color; Color color; @@ -118,14 +123,26 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ is_hex_notation = false; } + // disallow anything not a 0 or 1 + if (is_bin_notation && (_is_bin_symbol(str[j]))) { + is_number = true; + } else if (is_bin_notation) { + is_bin_notation = false; + is_number = false; + } else { + is_bin_notation = false; + } + // check for dot or underscore or 'x' for hex notation in floating point number or 'e' for scientific notation - if ((str[j] == '.' || str[j] == 'x' || str[j] == '_' || str[j] == 'e') && !in_word && prev_is_number && !is_number) { + if ((str[j] == '.' || str[j] == 'x' || str[j] == 'b' || str[j] == '_' || str[j] == 'e') && !in_word && prev_is_number && !is_number) { is_number = true; is_symbol = false; is_char = false; if (str[j] == 'x' && str[j - 1] == '0') { is_hex_notation = true; + } else if (str[j] == 'b' && str[j - 1] == '0') { + is_bin_notation = true; } } @@ -330,7 +347,7 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ return color_map; } -String GDScriptSyntaxHighlighter::get_name() { +String GDScriptSyntaxHighlighter::get_name() const { return "GDScript"; } diff --git a/modules/gdscript/editor/gdscript_highlighter.h b/modules/gdscript/editor/gdscript_highlighter.h index 9dc10a5d1b..9ba2c80552 100644 --- a/modules/gdscript/editor/gdscript_highlighter.h +++ b/modules/gdscript/editor/gdscript_highlighter.h @@ -65,7 +65,7 @@ public: virtual void _update_cache(); virtual Map<int, TextEdit::HighlighterInfo> _get_line_syntax_highlighting(int p_line); - virtual String get_name(); + virtual String get_name() const; virtual List<String> get_supported_languages(); }; diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 33e99cb82f..3fb9268702 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -30,6 +30,7 @@ #include "gdscript.h" +#include "core/core_string_names.h" #include "core/engine.h" #include "core/global_constants.h" #include "core/io/file_access_encrypted.h" @@ -1064,7 +1065,7 @@ Variant::Type GDScriptInstance::get_property_type(const StringName &p_name, bool } void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const { - // exported members, not doen yet! + // exported members, not done yet! const GDScript *sptr = script.ptr(); List<PropertyInfo> props; @@ -1234,6 +1235,27 @@ void GDScriptInstance::notification(int p_notification) { } } +String GDScriptInstance::to_string(bool *r_valid) { + if (has_method(CoreStringNames::get_singleton()->_to_string)) { + Variant::CallError ce; + Variant ret = call(CoreStringNames::get_singleton()->_to_string, NULL, 0, ce); + if (ce.error == Variant::CallError::CALL_OK) { + if (ret.get_type() != Variant::STRING) { + if (r_valid) + *r_valid = false; + ERR_EXPLAIN("Wrong type for " + CoreStringNames::get_singleton()->_to_string + ", must be a String."); + ERR_FAIL_V(String()); + } + if (r_valid) + *r_valid = true; + return ret.operator String(); + } + } + if (r_valid) + *r_valid = false; + return String(); +} + Ref<Script> GDScriptInstance::get_script() const { return script; diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 38009b878d..40b773d99f 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -251,6 +251,7 @@ public: Variant debug_get_member_by_index(int p_idx) const { return members[p_idx]; } virtual void notification(int p_notification); + String to_string(bool *r_valid); virtual Ref<Script> get_script() const; @@ -457,9 +458,9 @@ public: virtual bool can_inherit_from_file() { return true; } virtual int find_function(const String &p_function, const String &p_code) const; virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const; - virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint); + virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint); #ifdef TOOLS_ENABLED - virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_base_path, Object *p_owner, LookupResult &r_result); + virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result); #endif virtual String _get_indentation() const; virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index f7be0ce37c..189317b163 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -1977,12 +1977,12 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar for (int i = 0; i < p_class->subclasses.size(); i++) { StringName name = p_class->subclasses[i]->name; - - GDScript *subclass = p_script->subclasses[name].ptr(); + Ref<GDScript> &subclass = p_script->subclasses[name]; + GDScript *subclass_ptr = subclass.ptr(); // Subclass might still be parsing, just skip it - if (!parsed_classes.has(subclass) && !parsing_classes.has(subclass)) { - Error err = _parse_class_level(subclass, p_class->subclasses[i], p_keep_state); + if (!parsed_classes.has(subclass_ptr) && !parsing_classes.has(subclass_ptr)) { + Error err = _parse_class_level(subclass_ptr, p_class->subclasses[i], p_keep_state); if (err) return err; } diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index d91e32249e..6c77968f44 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -2054,7 +2054,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context if (!p_only_functions) { List<PropertyInfo> members; - tmp.get_property_list(&members); + p_base.value.get_property_list(&members); for (List<PropertyInfo>::Element *E = members.front(); E; E = E->next()) { if (String(E->get().name).find("/") == -1) { @@ -2461,13 +2461,13 @@ static void _find_call_arguments(GDScriptCompletionContext &p_context, const GDS r_forced = r_result.size() > 0; } -Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint) { +Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint) { const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\""; GDScriptParser parser; - parser.parse(p_code, p_base_path, false, "", true); + parser.parse(p_code, p_path.get_base_dir(), false, p_path, true); r_forced = false; Set<String> options; GDScriptCompletionContext context; @@ -2478,7 +2478,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base if (!context._class || context._class->owner == NULL) { context.base = p_owner; - context.base_path = p_base_path; + context.base_path = p_path.get_base_dir(); } bool is_function = false; @@ -2884,7 +2884,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base #else -Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint) { +Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint) { return OK; } @@ -3155,7 +3155,7 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co return ERR_CANT_RESOLVE; } -Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol, const String &p_base_path, Object *p_owner, LookupResult &r_result) { +Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result) { //before parsing, try the usual stuff if (ClassDB::class_exists(p_symbol)) { @@ -3197,7 +3197,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol } GDScriptParser parser; - parser.parse(p_code, p_base_path, false, "", true); + parser.parse(p_code, p_path.get_base_dir(), false, p_path, true); if (parser.get_completion_type() == GDScriptParser::COMPLETION_NONE) { return ERR_CANT_RESOLVE; @@ -3209,7 +3209,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol context.block = parser.get_completion_block(); context.line = parser.get_completion_line(); context.base = p_owner; - context.base_path = p_base_path; + context.base_path = p_path.get_base_dir(); if (context._class && context._class->extends_class.size() > 0) { bool success = false; diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp index 5ebcddfd7c..0736f3d010 100644 --- a/modules/gdscript/gdscript_functions.cpp +++ b/modules/gdscript/gdscript_functions.cpp @@ -78,6 +78,7 @@ const char *GDScriptFunctions::get_func_name(Function p_func) { "inverse_lerp", "range_lerp", "smoothstep", + "move_toward", "dectime", "randomize", "randi", @@ -341,7 +342,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ VALIDATE_ARG_NUM(0); r_ret = Math::step_decimals((double)*p_args[0]); ERR_EXPLAIN("GDScript method 'decimals' is deprecated and has been renamed to 'step_decimals', please update your code accordingly."); - WARN_DEPRECATED + WARN_DEPRECATED; } break; case MATH_STEP_DECIMALS: { VALIDATE_ARG_COUNT(1); @@ -398,6 +399,13 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ VALIDATE_ARG_NUM(2); r_ret = Math::smoothstep((double)*p_args[0], (double)*p_args[1], (double)*p_args[2]); } break; + case MATH_MOVE_TOWARD: { + VALIDATE_ARG_COUNT(3); + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + VALIDATE_ARG_NUM(2); + r_ret = Math::move_toward((double)*p_args[0], (double)*p_args[1], (double)*p_args[2]); + } break; case MATH_DECTIME: { VALIDATE_ARG_COUNT(3); VALIDATE_ARG_NUM(0); @@ -1466,6 +1474,7 @@ bool GDScriptFunctions::is_deterministic(Function p_func) { case MATH_INVERSE_LERP: case MATH_RANGE_LERP: case MATH_SMOOTHSTEP: + case MATH_MOVE_TOWARD: case MATH_DECTIME: case MATH_DEG2RAD: case MATH_RAD2DEG: @@ -1669,6 +1678,11 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { mi.return_val.type = Variant::REAL; return mi; } break; + case MATH_MOVE_TOWARD: { + MethodInfo mi("move_toward", PropertyInfo(Variant::REAL, "from"), PropertyInfo(Variant::REAL, "to"), PropertyInfo(Variant::REAL, "delta")); + mi.return_val.type = Variant::REAL; + return mi; + } break; case MATH_DECTIME: { MethodInfo mi("dectime", PropertyInfo(Variant::REAL, "value"), PropertyInfo(Variant::REAL, "amount"), PropertyInfo(Variant::REAL, "step")); mi.return_val.type = Variant::REAL; diff --git a/modules/gdscript/gdscript_functions.h b/modules/gdscript/gdscript_functions.h index c594480ff8..6ad70f2eb4 100644 --- a/modules/gdscript/gdscript_functions.h +++ b/modules/gdscript/gdscript_functions.h @@ -69,6 +69,7 @@ public: MATH_INVERSE_LERP, MATH_RANGE_LERP, MATH_SMOOTHSTEP, + MATH_MOVE_TOWARD, MATH_DECTIME, MATH_RANDOMIZE, MATH_RAND, diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 903b3892d1..ec3e72eef7 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -1995,7 +1995,6 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to } } - ERR_FAIL_V(op); } break; default: { return p_node; @@ -3369,7 +3368,7 @@ void GDScriptParser::_parse_extends(ClassNode *p_class) { return; } - if (!p_class->constant_expressions.empty() || !p_class->subclasses.empty() || !p_class->functions.empty() || !p_class->variables.empty()) { + if (!p_class->constant_expressions.empty() || !p_class->subclasses.empty() || !p_class->functions.empty() || !p_class->variables.empty() || p_class->classname_used) { _set_error("'extends' must be used before anything else."); return; @@ -3497,7 +3496,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { _set_error("'class_name' is only valid for the main class namespace."); return; } - if (self_path.empty()) { + if (self_path.begins_with("res://") && self_path.find("::") != -1) { _set_error("'class_name' not allowed in built-in scripts."); return; } @@ -3506,6 +3505,12 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { _set_error("'class_name' syntax: 'class_name <UniqueName>'"); return; } + if (p_class->classname_used) { + _set_error("'class_name' already used for this class."); + return; + } + + p_class->classname_used = true; p_class->name = tokenizer->get_token_identifier(1); @@ -4019,7 +4024,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { ERR_EXPLAIN("Exporting bit flags hint requires string constants."); - WARN_DEPRECATED + WARN_DEPRECATED; break; } if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) { @@ -4062,6 +4067,50 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { break; } + if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_2D_RENDER") { + + tokenizer->advance(); + if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { + _set_error("Expected ')' in layers 2D render hint."); + return; + } + current_export.hint = PROPERTY_HINT_LAYERS_2D_RENDER; + break; + } + + if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_2D_PHYSICS") { + + tokenizer->advance(); + if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { + _set_error("Expected ')' in layers 2D physics hint."); + return; + } + current_export.hint = PROPERTY_HINT_LAYERS_2D_PHYSICS; + break; + } + + if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_3D_RENDER") { + + tokenizer->advance(); + if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { + _set_error("Expected ')' in layers 3D render hint."); + return; + } + current_export.hint = PROPERTY_HINT_LAYERS_3D_RENDER; + break; + } + + if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_3D_PHYSICS") { + + tokenizer->advance(); + if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { + _set_error("Expected ')' in layers 3D physics hint."); + return; + } + current_export.hint = PROPERTY_HINT_LAYERS_3D_PHYSICS; + break; + } + if (tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type() == Variant::STRING) { //enumeration current_export.hint = PROPERTY_HINT_ENUM; @@ -5248,6 +5297,7 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class) { if (base_script.is_valid()) { String ident = base; + Ref<GDScript> find_subclass = base_script; for (int i = extend_iter; i < p_class->extends_class.size(); i++) { @@ -5257,7 +5307,7 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class) { if (base_script->get_subclasses().has(subclass)) { - base_script = base_script->get_subclasses()[subclass]; + find_subclass = base_script->get_subclasses()[subclass]; } else if (base_script->get_constants().has(subclass)) { Ref<GDScript> new_base_class = base_script->get_constants()[subclass]; @@ -5265,7 +5315,7 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class) { _set_error("Constant is not a class: " + ident, p_class->line); return; } - base_script = new_base_class; + find_subclass = new_base_class; } else { _set_error("Could not find subclass: " + ident, p_class->line); @@ -5273,7 +5323,7 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class) { } } - script = base_script; + script = find_subclass; } else if (!base_class) { @@ -6014,7 +6064,11 @@ bool GDScriptParser::_is_type_compatible(const DataType &p_container, const Data } GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { +#ifdef DEBUG_ENABLED + if (p_node->get_datatype().has_type && p_node->type != Node::TYPE_ARRAY && p_node->type != Node::TYPE_DICTIONARY) { +#else if (p_node->get_datatype().has_type) { +#endif return p_node->get_datatype(); } @@ -7473,7 +7527,7 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { return; } - // Replace assignment with implict conversion + // Replace assignment with implicit conversion BuiltInFunctionNode *convert = alloc_node<BuiltInFunctionNode>(); convert->line = v.line; convert->function = GDScriptFunctions::TYPE_CONVERT; @@ -7837,14 +7891,14 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { if (_is_type_compatible(assign_type, lv->datatype)) { _mark_line_as_unsafe(lv->line); } else { - // Try implict conversion + // Try implicit conversion if (lv->datatype.kind != DataType::BUILTIN || !_is_type_compatible(lv->datatype, assign_type, true)) { _set_error("Assigned value type (" + assign_type.to_string() + ") doesn't match the variable's type (" + lv->datatype.to_string() + ").", lv->line); return; } - // Replace assignment with implict conversion + // Replace assignment with implicit conversion BuiltInFunctionNode *convert = alloc_node<BuiltInFunctionNode>(); convert->line = lv->line; convert->function = GDScriptFunctions::TYPE_CONVERT; @@ -7968,14 +8022,14 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { if (_is_type_compatible(rh_type, lh_type)) { _mark_line_as_unsafe(op->line); } else { - // Try implict conversion + // Try implicit conversion if (lh_type.kind != DataType::BUILTIN || !_is_type_compatible(lh_type, rh_type, true)) { _set_error("Assigned value type (" + rh_type.to_string() + ") doesn't match the variable's type (" + lh_type.to_string() + ").", op->line); return; } - // Replace assignment with implict conversion + // Replace assignment with implicit conversion BuiltInFunctionNode *convert = alloc_node<BuiltInFunctionNode>(); convert->line = op->line; convert->function = GDScriptFunctions::TYPE_CONVERT; diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 809bff8f20..5e4de11357 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -149,6 +149,7 @@ public: bool tool; StringName name; bool extends_used; + bool classname_used; StringName extends_file; Vector<StringName> extends_class; DataType base_type; @@ -198,6 +199,7 @@ public: tool = false; type = TYPE_CLASS; extends_used = false; + classname_used = false; end_line = -1; owner = NULL; } diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index b8048fb5dd..a93d1ceebb 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -376,6 +376,11 @@ static bool _is_hex(CharType c) { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); } +static bool _is_bin(CharType c) { + + return (c == '0' || c == '1'); +} + void GDScriptTokenizerText::_make_token(Token p_type) { TokenData &tk = tk_rb[tk_rb_pos]; @@ -877,6 +882,7 @@ void GDScriptTokenizerText::_advance() { bool period_found = false; bool exponent_found = false; bool hexa_found = false; + bool bin_found = false; bool sign_found = false; String str; @@ -887,16 +893,28 @@ void GDScriptTokenizerText::_advance() { if (period_found || exponent_found) { _make_error("Invalid numeric constant at '.'"); return; + } else if (bin_found) { + _make_error("Invalid binary constant at '.'"); + return; + } else if (hexa_found) { + _make_error("Invalid hexadecimal constant at '.'"); + return; } period_found = true; } else if (GETCHAR(i) == 'x') { - if (hexa_found || str.length() != 1 || !((i == 1 && str[0] == '0') || (i == 2 && str[1] == '0' && str[0] == '-'))) { + if (hexa_found || bin_found || str.length() != 1 || !((i == 1 && str[0] == '0') || (i == 2 && str[1] == '0' && str[0] == '-'))) { _make_error("Invalid numeric constant at 'x'"); return; } hexa_found = true; + } else if (GETCHAR(i) == 'b') { + if (hexa_found || bin_found || str.length() != 1 || !((i == 1 && str[0] == '0') || (i == 2 && str[1] == '0' && str[0] == '-'))) { + _make_error("Invalid numeric constant at 'b'"); + return; + } + bin_found = true; } else if (!hexa_found && GETCHAR(i) == 'e') { - if (exponent_found) { + if (exponent_found || bin_found) { _make_error("Invalid numeric constant at 'e'"); return; } @@ -905,6 +923,8 @@ void GDScriptTokenizerText::_advance() { //all ok } else if (hexa_found && _is_hex(GETCHAR(i))) { + } else if (bin_found && _is_bin(GETCHAR(i))) { + } else if ((GETCHAR(i) == '-' || GETCHAR(i) == '+') && exponent_found) { if (sign_found) { _make_error("Invalid numeric constant at '-'"); @@ -930,6 +950,9 @@ void GDScriptTokenizerText::_advance() { if (hexa_found) { int64_t val = str.hex_to_int64(); _make_constant(val); + } else if (bin_found) { + int64_t val = str.bin_to_int64(); + _make_constant(val); } else if (period_found || exponent_found) { double val = str.to_double(); _make_constant(val); |