diff --git a/README.md b/README.md index 42c49dd2..8c1ea449 100644 --- a/README.md +++ b/README.md @@ -398,7 +398,7 @@ $ make $ ./json_unit "*" =============================================================================== -All tests passed (3341947 assertions in 28 test cases) +All tests passed (3343239 assertions in 28 test cases) ``` For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml). diff --git a/src/json.hpp b/src/json.hpp index 253bb311..dbb18576 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6459,21 +6459,21 @@ class basic_json case token_type::value_number: return "number literal"; case token_type::begin_array: - return "["; + return "'['"; case token_type::begin_object: - return "{"; + return "'{'"; case token_type::end_array: - return "]"; + return "']'"; case token_type::end_object: - return "}"; + return "'}'"; case token_type::name_separator: - return ":"; + return "':'"; case token_type::value_separator: - return ","; + return "','"; case token_type::parse_error: return ""; case token_type::end_of_input: - return ""; + return "end of input"; default: { // catch non-enum values @@ -7752,10 +7752,10 @@ basic_json_parser_64: { if (t != last_token) { - std::string error_msg = "parse error - unexpected \'"; - error_msg += m_lexer.get_token(); - error_msg += "\' (" + lexer::token_type_name(last_token); - error_msg += "); expected " + lexer::token_type_name(t); + std::string error_msg = "parse error - unexpected "; + error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") : + lexer::token_type_name(last_token)); + error_msg += "; expected " + lexer::token_type_name(t); throw std::invalid_argument(error_msg); } } @@ -7764,9 +7764,9 @@ basic_json_parser_64: { if (t == last_token) { - std::string error_msg = "parse error - unexpected \'"; - error_msg += m_lexer.get_token(); - error_msg += "\'"; + std::string error_msg = "parse error - unexpected "; + error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") : + lexer::token_type_name(last_token)); throw std::invalid_argument(error_msg); } } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 84ceccc3..9ef7f330 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6441,7 +6441,7 @@ class basic_json return result; } - /// return name of values of type token_type + /// return name of values of type token_type (only used for errors) static std::string token_type_name(token_type t) { switch (t) @@ -6459,21 +6459,21 @@ class basic_json case token_type::value_number: return "number literal"; case token_type::begin_array: - return "["; + return "'['"; case token_type::begin_object: - return "{"; + return "'{'"; case token_type::end_array: - return "]"; + return "']'"; case token_type::end_object: - return "}"; + return "'}'"; case token_type::name_separator: - return ":"; + return "':'"; case token_type::value_separator: - return ","; + return "','"; case token_type::parse_error: return ""; case token_type::end_of_input: - return ""; + return "end of input"; default: { // catch non-enum values @@ -7031,10 +7031,10 @@ class basic_json { if (t != last_token) { - std::string error_msg = "parse error - unexpected \'"; - error_msg += m_lexer.get_token(); - error_msg += "\' (" + lexer::token_type_name(last_token); - error_msg += "); expected " + lexer::token_type_name(t); + std::string error_msg = "parse error - unexpected "; + error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") : + lexer::token_type_name(last_token)); + error_msg += "; expected " + lexer::token_type_name(t); throw std::invalid_argument(error_msg); } } @@ -7043,9 +7043,9 @@ class basic_json { if (t == last_token) { - std::string error_msg = "parse error - unexpected \'"; - error_msg += m_lexer.get_token(); - error_msg += "\'"; + std::string error_msg = "parse error - unexpected "; + error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") : + lexer::token_type_name(last_token)); throw std::invalid_argument(error_msg); } } diff --git a/test/unit.cpp b/test/unit.cpp index 57f6adb4..6386fd69 100644 --- a/test/unit.cpp +++ b/test/unit.cpp @@ -8647,14 +8647,14 @@ TEST_CASE("lexer class") CHECK(json::lexer::token_type_name(json::lexer::token_type::literal_null) == "null literal"); CHECK(json::lexer::token_type_name(json::lexer::token_type::value_string) == "string literal"); CHECK(json::lexer::token_type_name(json::lexer::token_type::value_number) == "number literal"); - CHECK(json::lexer::token_type_name(json::lexer::token_type::begin_array) == "["); - CHECK(json::lexer::token_type_name(json::lexer::token_type::begin_object) == "{"); - CHECK(json::lexer::token_type_name(json::lexer::token_type::end_array) == "]"); - CHECK(json::lexer::token_type_name(json::lexer::token_type::end_object) == "}"); - CHECK(json::lexer::token_type_name(json::lexer::token_type::name_separator) == ":"); - CHECK(json::lexer::token_type_name(json::lexer::token_type::value_separator) == ","); + CHECK(json::lexer::token_type_name(json::lexer::token_type::begin_array) == "'['"); + CHECK(json::lexer::token_type_name(json::lexer::token_type::begin_object) == "'{'"); + CHECK(json::lexer::token_type_name(json::lexer::token_type::end_array) == "']'"); + CHECK(json::lexer::token_type_name(json::lexer::token_type::end_object) == "'}'"); + CHECK(json::lexer::token_type_name(json::lexer::token_type::name_separator) == "':'"); + CHECK(json::lexer::token_type_name(json::lexer::token_type::value_separator) == "','"); CHECK(json::lexer::token_type_name(json::lexer::token_type::parse_error) == ""); - CHECK(json::lexer::token_type_name(json::lexer::token_type::end_of_input) == ""); + CHECK(json::lexer::token_type_name(json::lexer::token_type::end_of_input) == "end of input"); } SECTION("parse errors on first character") @@ -8929,31 +8929,31 @@ TEST_CASE("parser class") CHECK_THROWS_NAME(json::parser("1.").parse(), std::invalid_argument, "parse error - 1 is not a number"); CHECK_THROWS_NAME(json::parser("1E").parse(), std::invalid_argument, - "parse error - unexpected 'E' (); expected "); + "parse error - unexpected 'E'; expected end of input"); CHECK_THROWS_NAME(json::parser("1E-").parse(), std::invalid_argument, - "parse error - unexpected 'E' (); expected "); + "parse error - unexpected 'E'; expected end of input"); CHECK_THROWS_NAME(json::parser("1.E1").parse(), std::invalid_argument, "parse error - 1 is not a number"); CHECK_THROWS_NAME(json::parser("-1E").parse(), std::invalid_argument, - "parse error - unexpected 'E' (); expected "); + "parse error - unexpected 'E'; expected end of input"); CHECK_THROWS_NAME(json::parser("-0E#").parse(), std::invalid_argument, - "parse error - unexpected 'E' (); expected "); + "parse error - unexpected 'E'; expected end of input"); CHECK_THROWS_NAME(json::parser("-0E-#").parse(), std::invalid_argument, - "parse error - unexpected 'E' (); expected "); + "parse error - unexpected 'E'; expected end of input"); CHECK_THROWS_NAME(json::parser("-0#").parse(), std::invalid_argument, - "parse error - unexpected '#' (); expected "); + "parse error - unexpected '#'; expected end of input"); CHECK_THROWS_NAME(json::parser("-0.0:").parse(), std::invalid_argument, - "parse error - unexpected ':' (:); expected "); + "parse error - unexpected ':'; expected end of input"); CHECK_THROWS_NAME(json::parser("-0.0Z").parse(), std::invalid_argument, - "parse error - unexpected 'Z' (); expected "); + "parse error - unexpected 'Z'; expected end of input"); CHECK_THROWS_NAME(json::parser("-0E123:").parse(), std::invalid_argument, - "parse error - unexpected ':' (:); expected "); + "parse error - unexpected ':'; expected end of input"); CHECK_THROWS_NAME(json::parser("-0e0-:").parse(), std::invalid_argument, - "parse error - unexpected '-' (); expected "); + "parse error - unexpected '-'; expected end of input"); CHECK_THROWS_NAME(json::parser("-0e-:").parse(), std::invalid_argument, - "parse error - unexpected 'e' (); expected "); + "parse error - unexpected 'e'; expected end of input"); CHECK_THROWS_NAME(json::parser("-0f").parse(), std::invalid_argument, - "parse error - unexpected 'f' (); expected "); + "parse error - unexpected 'f'; expected end of input"); } } } @@ -8975,6 +8975,33 @@ TEST_CASE("parser class") CHECK_THROWS_AS(json::parser("1E.").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("1E/").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("1E:").parse(), std::invalid_argument); + CHECK_THROWS_NAME(json::parser("0.").parse(), std::invalid_argument, + "parse error - 0 is not a number"); + CHECK_THROWS_NAME(json::parser("-").parse(), std::invalid_argument, "parse error - unexpected '-'"); + CHECK_THROWS_NAME(json::parser("--").parse(), std::invalid_argument, + "parse error - unexpected '-'"); + CHECK_THROWS_NAME(json::parser("-0.").parse(), std::invalid_argument, + "parse error - -0 is not a number"); + CHECK_THROWS_NAME(json::parser("-.").parse(), std::invalid_argument, + "parse error - unexpected '-'"); + CHECK_THROWS_NAME(json::parser("-:").parse(), std::invalid_argument, + "parse error - unexpected '-'"); + CHECK_THROWS_NAME(json::parser("0.:").parse(), std::invalid_argument, + "parse error - 0 is not a number"); + CHECK_THROWS_NAME(json::parser("e.").parse(), std::invalid_argument, + "parse error - unexpected 'e'"); + CHECK_THROWS_NAME(json::parser("1e.").parse(), std::invalid_argument, + "parse error - unexpected 'e'; expected end of input"); + CHECK_THROWS_NAME(json::parser("1e/").parse(), std::invalid_argument, + "parse error - unexpected 'e'; expected end of input"); + CHECK_THROWS_NAME(json::parser("1e:").parse(), std::invalid_argument, + "parse error - unexpected 'e'; expected end of input"); + CHECK_THROWS_NAME(json::parser("1E.").parse(), std::invalid_argument, + "parse error - unexpected 'E'; expected end of input"); + CHECK_THROWS_NAME(json::parser("1E/").parse(), std::invalid_argument, + "parse error - unexpected 'E'; expected end of input"); + CHECK_THROWS_NAME(json::parser("1E:").parse(), std::invalid_argument, + "parse error - unexpected 'E'; expected end of input"); // unexpected end of null CHECK_THROWS_AS(json::parser("n").parse(), std::invalid_argument); @@ -9010,36 +9037,38 @@ TEST_CASE("parser class") "parse error - unexpected 'f'"); // missing/unexpected end of array - // TODO: Better error messages - "parse error - unexpected '" just ends CHECK_THROWS_AS(json::parser("[").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("[1").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("[1,").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("[1,]").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("]").parse(), std::invalid_argument); - CHECK_THROWS_NAME(json::parser("[").parse(), std::invalid_argument, "parse error - unexpected '"); - CHECK_THROWS_NAME(json::parser("[1").parse(), std::invalid_argument, "parse error - unexpected '"); - CHECK_THROWS_NAME(json::parser("[1,").parse(), std::invalid_argument, "parse error - unexpected '"); + CHECK_THROWS_NAME(json::parser("[").parse(), std::invalid_argument, + "parse error - unexpected end of input"); + CHECK_THROWS_NAME(json::parser("[1").parse(), std::invalid_argument, + "parse error - unexpected end of input; expected ']'"); + CHECK_THROWS_NAME(json::parser("[1,").parse(), std::invalid_argument, + "parse error - unexpected end of input"); CHECK_THROWS_NAME(json::parser("[1,]").parse(), std::invalid_argument, "parse error - unexpected ']'"); CHECK_THROWS_NAME(json::parser("]").parse(), std::invalid_argument, "parse error - unexpected ']'"); // missing/unexpected end of object - // TODO: Better error messages - "parse error - unexpected '" just ends CHECK_THROWS_AS(json::parser("{").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("{\"foo\"").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("{\"foo\":").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("{\"foo\":}").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("{\"foo\":1,}").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("}").parse(), std::invalid_argument); - CHECK_THROWS_NAME(json::parser("{").parse(), std::invalid_argument, "parse error - unexpected '"); + CHECK_THROWS_NAME(json::parser("{").parse(), std::invalid_argument, + "parse error - unexpected end of input; expected string literal"); CHECK_THROWS_NAME(json::parser("{\"foo\"").parse(), std::invalid_argument, - "parse error - unexpected '"); + "parse error - unexpected end of input; expected ':'"); CHECK_THROWS_NAME(json::parser("{\"foo\":").parse(), std::invalid_argument, - "parse error - unexpected '"); + "parse error - unexpected end of input"); CHECK_THROWS_NAME(json::parser("{\"foo\":}").parse(), std::invalid_argument, "parse error - unexpected '}'"); CHECK_THROWS_NAME(json::parser("{\"foo\":1,}").parse(), std::invalid_argument, - "parse error - unexpected '}' (}); expected string literal"); + "parse error - unexpected '}'; expected string literal"); CHECK_THROWS_NAME(json::parser("}").parse(), std::invalid_argument, "parse error - unexpected '}'"); // missing/unexpected end of string