From 905e8a39bfa635e858d1c691161b5869d5bcc35f Mon Sep 17 00:00:00 2001 From: Haoyu Qiu Date: Wed, 11 Sep 2024 21:57:14 +0800 Subject: [PATCH] Fix parsing of `4.` in Expression --- core/math/expression.cpp | 4 +- main/tests/test_expression.cpp | 136 +++++++++++++++++++++++++++++++++ main/tests/test_expression.h | 41 ++++++++++ main/tests/test_main.cpp | 6 ++ 4 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 main/tests/test_expression.cpp create mode 100644 main/tests/test_expression.h diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 6cafb792fc3..135f2b29496 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -1103,7 +1103,9 @@ Error Expression::_get_token(Token &r_token) { is_first_char = false; } - str_ofs--; + if (c != 0) { + str_ofs--; + } r_token.type = TK_CONSTANT; diff --git a/main/tests/test_expression.cpp b/main/tests/test_expression.cpp new file mode 100644 index 00000000000..4d0b7354185 --- /dev/null +++ b/main/tests/test_expression.cpp @@ -0,0 +1,136 @@ +/**************************************************************************/ +/* test_expression.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "test_expression.h" + +#include "core/math/expression.h" +#include "core/os/os.h" + +#define CHECK_MESSAGE(X, msg) \ + if (!(X)) { \ + OS::get_singleton()->print("\tFAIL at %s: %s\n", #X, msg); \ + return false; \ + } else { \ + OS::get_singleton()->print("\tPASS\n"); \ + } + +namespace TestExpression { + +bool floating_point_notation() { + OS::get_singleton()->print("\n\nTest 1: Floating-point notation\n"); + + Expression expression; + + CHECK_MESSAGE( + expression.parse("2.") == OK, + "The expression should parse successfully."); + CHECK_MESSAGE( + Math::is_equal_approx(expression.execute(Array()), 2.0), + "The expression should return the expected result."); + + CHECK_MESSAGE( + expression.parse("(2.)") == OK, + "The expression should parse successfully."); + CHECK_MESSAGE( + Math::is_equal_approx(expression.execute(Array()), 2.0), + "The expression should return the expected result."); + + CHECK_MESSAGE( + expression.parse(".3") == OK, + "The expression should parse successfully."); + CHECK_MESSAGE( + Math::is_equal_approx(expression.execute(Array()), 0.3), + "The expression should return the expected result."); + + CHECK_MESSAGE( + expression.parse("2.+5.") == OK, + "The expression should parse successfully."); + CHECK_MESSAGE( + Math::is_equal_approx(expression.execute(Array()), 7.0), + "The expression should return the expected result."); + + CHECK_MESSAGE( + expression.parse(".3-.8") == OK, + "The expression should parse successfully."); + CHECK_MESSAGE( + Math::is_equal_approx(expression.execute(Array()), -0.5), + "The expression should return the expected result."); + + CHECK_MESSAGE( + expression.parse("2.+.2") == OK, + "The expression should parse successfully."); + CHECK_MESSAGE( + Math::is_equal_approx(expression.execute(Array()), 2.2), + "The expression should return the expected result."); + + CHECK_MESSAGE( + expression.parse(".0*0.") == OK, + "The expression should parse successfully."); + CHECK_MESSAGE( + Math::is_equal_approx(expression.execute(Array()), 0.0), + "The expression should return the expected result."); + + return true; +} + +typedef bool (*TestFunc)(); + +TestFunc test_funcs[] = { + floating_point_notation, + nullptr +}; + +MainLoop *test() { + int count = 0; + int passed = 0; + + while (true) { + if (!test_funcs[count]) { + break; + } + bool pass = test_funcs[count](); + if (pass) { + passed++; + } + OS::get_singleton()->print("\t%s\n", pass ? "PASS" : "FAILED"); + + count++; + } + + OS::get_singleton()->print("\n\n\n"); + OS::get_singleton()->print("*************\n"); + OS::get_singleton()->print("***TOTALS!***\n"); + OS::get_singleton()->print("*************\n"); + + OS::get_singleton()->print("Passed %i of %i tests\n", passed, count); + + return nullptr; +} +} // namespace TestExpression diff --git a/main/tests/test_expression.h b/main/tests/test_expression.h new file mode 100644 index 00000000000..a240dfe673f --- /dev/null +++ b/main/tests/test_expression.h @@ -0,0 +1,41 @@ +/**************************************************************************/ +/* test_expression.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef TEST_EXPRESSION_H +#define TEST_EXPRESSION_H + +#include "core/os/main_loop.h" + +namespace TestExpression { + +MainLoop *test(); +} + +#endif // TEST_EXPRESSION_H diff --git a/main/tests/test_main.cpp b/main/tests/test_main.cpp index 069b3cde12d..2710ebbaa13 100644 --- a/main/tests/test_main.cpp +++ b/main/tests/test_main.cpp @@ -37,6 +37,7 @@ #include "test_astar.h" #include "test_basis.h" #include "test_crypto.h" +#include "test_expression.h" #include "test_gdscript.h" #include "test_gui.h" #include "test_math.h" @@ -71,6 +72,7 @@ const char **tests_get_names() { "astar", "xml_parser", "theme", + "expression", nullptr }; @@ -156,6 +158,10 @@ MainLoop *test_main(String p_test, const List &p_args) { return TestTheme::test(); } + if (p_test == "expression") { + return TestExpression::test(); + } + print_line("Unknown test: " + p_test); return nullptr; }