🔨 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…
	
	Add table
		Add a link
		
	
		Reference in a new issue