🔨 added error messages to SAX interface
This commit is contained in:
parent
86991d5204
commit
9d27429527
5 changed files with 57 additions and 29 deletions
|
@ -113,9 +113,12 @@ struct json_sax
|
||||||
@brief a parse error occurred
|
@brief a parse error occurred
|
||||||
@param[in] position the position in the input where the error occurs
|
@param[in] position the position in the input where the error occurs
|
||||||
@param[in] last_token the last read token
|
@param[in] last_token the last read token
|
||||||
|
@param[in] error_msg a detailed error message
|
||||||
@return whether parsing should proceed
|
@return whether parsing should proceed
|
||||||
*/
|
*/
|
||||||
virtual bool parse_error(std::size_t position, const std::string& last_token) = 0;
|
virtual bool parse_error(std::size_t position,
|
||||||
|
const std::string& last_token,
|
||||||
|
const std::string& error_msg) = 0;
|
||||||
|
|
||||||
virtual ~json_sax() = default;
|
virtual ~json_sax() = default;
|
||||||
};
|
};
|
||||||
|
|
|
@ -562,7 +562,8 @@ class parser
|
||||||
if (JSON_UNLIKELY(last_token != token_type::value_string))
|
if (JSON_UNLIKELY(last_token != token_type::value_string))
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string());
|
m_lexer.get_token_string(),
|
||||||
|
exception_message(token_type::value_string));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -577,7 +578,8 @@ class parser
|
||||||
if (JSON_UNLIKELY(last_token != token_type::name_separator))
|
if (JSON_UNLIKELY(last_token != token_type::name_separator))
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string());
|
m_lexer.get_token_string(),
|
||||||
|
exception_message(token_type::name_separator));
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse value
|
// parse value
|
||||||
|
@ -603,7 +605,8 @@ class parser
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string());
|
m_lexer.get_token_string(),
|
||||||
|
exception_message(token_type::end_object));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -649,7 +652,8 @@ class parser
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string());
|
m_lexer.get_token_string(),
|
||||||
|
exception_message(token_type::end_array));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -661,7 +665,8 @@ class parser
|
||||||
if (JSON_UNLIKELY(not std::isfinite(res)))
|
if (JSON_UNLIKELY(not std::isfinite(res)))
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string());
|
m_lexer.get_token_string(),
|
||||||
|
"number overflow");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -699,10 +704,19 @@ class parser
|
||||||
return sax->number_unsigned(m_lexer.get_number_unsigned());
|
return sax->number_unsigned(m_lexer.get_number_unsigned());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case token_type::parse_error:
|
||||||
|
{
|
||||||
|
// using "uninitialized" to avoid "expected" message
|
||||||
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
|
m_lexer.get_token_string(),
|
||||||
|
exception_message(token_type::uninitialized));
|
||||||
|
}
|
||||||
|
|
||||||
default: // the last token was unexpected
|
default: // the last token was unexpected
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string());
|
m_lexer.get_token_string(),
|
||||||
|
exception_message(token_type::literal_or_value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -721,10 +735,9 @@ class parser
|
||||||
if (JSON_UNLIKELY(t != last_token))
|
if (JSON_UNLIKELY(t != last_token))
|
||||||
{
|
{
|
||||||
errored = true;
|
errored = true;
|
||||||
expected = t;
|
|
||||||
if (allow_exceptions)
|
if (allow_exceptions)
|
||||||
{
|
{
|
||||||
throw_exception();
|
JSON_THROW(parse_error::create(101, m_lexer.get_position(), exception_message(t)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -735,7 +748,7 @@ class parser
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[noreturn]] void throw_exception() const
|
std::string exception_message(const token_type expected)
|
||||||
{
|
{
|
||||||
std::string error_msg = "syntax error - ";
|
std::string error_msg = "syntax error - ";
|
||||||
if (last_token == token_type::parse_error)
|
if (last_token == token_type::parse_error)
|
||||||
|
@ -753,7 +766,7 @@ class parser
|
||||||
error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
|
error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg));
|
return error_msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -767,8 +780,6 @@ class parser
|
||||||
lexer_t m_lexer;
|
lexer_t m_lexer;
|
||||||
/// whether a syntax error occurred
|
/// whether a syntax error occurred
|
||||||
bool errored = false;
|
bool errored = false;
|
||||||
/// possible reason for the syntax error
|
|
||||||
token_type expected = token_type::uninitialized;
|
|
||||||
/// whether to throw exceptions in case of errors
|
/// whether to throw exceptions in case of errors
|
||||||
const bool allow_exceptions = true;
|
const bool allow_exceptions = true;
|
||||||
/// associated SAX parse event receiver
|
/// associated SAX parse event receiver
|
||||||
|
|
|
@ -3247,9 +3247,12 @@ struct json_sax
|
||||||
@brief a parse error occurred
|
@brief a parse error occurred
|
||||||
@param[in] position the position in the input where the error occurs
|
@param[in] position the position in the input where the error occurs
|
||||||
@param[in] last_token the last read token
|
@param[in] last_token the last read token
|
||||||
|
@param[in] error_msg a detailed error message
|
||||||
@return whether parsing should proceed
|
@return whether parsing should proceed
|
||||||
*/
|
*/
|
||||||
virtual bool parse_error(std::size_t position, const std::string& last_token) = 0;
|
virtual bool parse_error(std::size_t position,
|
||||||
|
const std::string& last_token,
|
||||||
|
const std::string& error_msg) = 0;
|
||||||
|
|
||||||
virtual ~json_sax() = default;
|
virtual ~json_sax() = default;
|
||||||
};
|
};
|
||||||
|
@ -3809,7 +3812,8 @@ class parser
|
||||||
if (JSON_UNLIKELY(last_token != token_type::value_string))
|
if (JSON_UNLIKELY(last_token != token_type::value_string))
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string());
|
m_lexer.get_token_string(),
|
||||||
|
exception_message(token_type::value_string));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3824,7 +3828,8 @@ class parser
|
||||||
if (JSON_UNLIKELY(last_token != token_type::name_separator))
|
if (JSON_UNLIKELY(last_token != token_type::name_separator))
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string());
|
m_lexer.get_token_string(),
|
||||||
|
exception_message(token_type::name_separator));
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse value
|
// parse value
|
||||||
|
@ -3850,7 +3855,8 @@ class parser
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string());
|
m_lexer.get_token_string(),
|
||||||
|
exception_message(token_type::end_object));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3896,7 +3902,8 @@ class parser
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string());
|
m_lexer.get_token_string(),
|
||||||
|
exception_message(token_type::end_array));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3908,7 +3915,8 @@ class parser
|
||||||
if (JSON_UNLIKELY(not std::isfinite(res)))
|
if (JSON_UNLIKELY(not std::isfinite(res)))
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string());
|
m_lexer.get_token_string(),
|
||||||
|
"number overflow");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3946,10 +3954,19 @@ class parser
|
||||||
return sax->number_unsigned(m_lexer.get_number_unsigned());
|
return sax->number_unsigned(m_lexer.get_number_unsigned());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case token_type::parse_error:
|
||||||
|
{
|
||||||
|
// using "uninitialized" to avoid "expected" message
|
||||||
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
|
m_lexer.get_token_string(),
|
||||||
|
exception_message(token_type::uninitialized));
|
||||||
|
}
|
||||||
|
|
||||||
default: // the last token was unexpected
|
default: // the last token was unexpected
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string());
|
m_lexer.get_token_string(),
|
||||||
|
exception_message(token_type::literal_or_value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3968,10 +3985,9 @@ class parser
|
||||||
if (JSON_UNLIKELY(t != last_token))
|
if (JSON_UNLIKELY(t != last_token))
|
||||||
{
|
{
|
||||||
errored = true;
|
errored = true;
|
||||||
expected = t;
|
|
||||||
if (allow_exceptions)
|
if (allow_exceptions)
|
||||||
{
|
{
|
||||||
throw_exception();
|
JSON_THROW(parse_error::create(101, m_lexer.get_position(), exception_message(t)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3982,7 +3998,7 @@ class parser
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[noreturn]] void throw_exception() const
|
std::string exception_message(const token_type expected)
|
||||||
{
|
{
|
||||||
std::string error_msg = "syntax error - ";
|
std::string error_msg = "syntax error - ";
|
||||||
if (last_token == token_type::parse_error)
|
if (last_token == token_type::parse_error)
|
||||||
|
@ -4000,7 +4016,7 @@ class parser
|
||||||
error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
|
error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg));
|
return error_msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -4014,8 +4030,6 @@ class parser
|
||||||
lexer_t m_lexer;
|
lexer_t m_lexer;
|
||||||
/// whether a syntax error occurred
|
/// whether a syntax error occurred
|
||||||
bool errored = false;
|
bool errored = false;
|
||||||
/// possible reason for the syntax error
|
|
||||||
token_type expected = token_type::uninitialized;
|
|
||||||
/// whether to throw exceptions in case of errors
|
/// whether to throw exceptions in case of errors
|
||||||
const bool allow_exceptions = true;
|
const bool allow_exceptions = true;
|
||||||
/// associated SAX parse event receiver
|
/// associated SAX parse event receiver
|
||||||
|
|
|
@ -123,7 +123,7 @@ class SaxEventLogger : public nlohmann::json::json_sax_t
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_error(std::size_t position, const std::string&) override
|
bool parse_error(std::size_t position, const std::string&, const std::string&) override
|
||||||
{
|
{
|
||||||
errored = true;
|
errored = true;
|
||||||
events.push_back("parse_error(" + std::to_string(position) + ")");
|
events.push_back("parse_error(" + std::to_string(position) + ")");
|
||||||
|
@ -208,7 +208,7 @@ class SaxDomParser : public nlohmann::json::json_sax_t
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_error(std::size_t position, const std::string&) override
|
bool parse_error(std::size_t position, const std::string&, const std::string&) override
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ struct SaxEventLogger : public nlohmann::json::json_sax_t
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_error(std::size_t position, const std::string&) override
|
bool parse_error(std::size_t position, const std::string&, const std::string&) override
|
||||||
{
|
{
|
||||||
events.push_back("parse_error(" + std::to_string(position) + ")");
|
events.push_back("parse_error(" + std::to_string(position) + ")");
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in a new issue