diff --git a/include/nlohmann/detail/input/json_sax.hpp b/include/nlohmann/detail/input/json_sax.hpp
index 06227e70..e2b8baad 100644
--- a/include/nlohmann/detail/input/json_sax.hpp
+++ b/include/nlohmann/detail/input/json_sax.hpp
@@ -275,5 +275,79 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
     const bool allow_exceptions = true;
 };
 
+template<typename BasicJsonType>
+class json_sax_acceptor : public json_sax<BasicJsonType>
+{
+  public:
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+
+    bool null() override
+    {
+        return true;
+    }
+
+    bool boolean(bool) override
+    {
+        return true;
+    }
+
+    bool number_integer(number_integer_t) override
+    {
+        return true;
+    }
+
+    bool number_unsigned(number_unsigned_t) override
+    {
+        return true;
+    }
+
+    bool number_float(number_float_t, const std::string&) override
+    {
+        return true;
+    }
+
+    bool string(std::string&&) override
+    {
+        return true;
+    }
+
+    bool start_object(std::size_t) override
+    {
+        return true;
+    }
+
+    bool key(std::string&&) override
+    {
+        return true;
+    }
+
+    bool end_object() override
+    {
+        return true;
+    }
+
+    bool start_array(std::size_t) override
+    {
+        return true;
+    }
+
+    bool end_array() override
+    {
+        return true;
+    }
+
+    bool binary(const std::vector<uint8_t>&) override
+    {
+        return true;
+    }
+
+    bool parse_error(std::size_t, const std::string&, const std::string&) override
+    {
+        return false;
+    }
+};
+
 }
 
diff --git a/include/nlohmann/detail/input/parser.hpp b/include/nlohmann/detail/input/parser.hpp
index 23fac952..5c0c2e94 100644
--- a/include/nlohmann/detail/input/parser.hpp
+++ b/include/nlohmann/detail/input/parser.hpp
@@ -137,7 +137,9 @@ class parser
     */
     bool accept(const bool strict = true)
     {
-        if (not accept_internal())
+        json_sax_acceptor<BasicJsonType> sax_acceptor;
+
+        if (not sax_parse_internal(&sax_acceptor))
         {
             return false;
         }
@@ -436,119 +438,6 @@ class parser
         }
     }
 
-    /*!
-    @brief the actual acceptor
-
-    @invariant 1. The last token is not yet processed. Therefore, the caller
-                  of this function must make sure a token has been read.
-               2. When this function returns, the last token is processed.
-                  That is, the last read character was already considered.
-
-    This invariant makes sure that no token needs to be "unput".
-    */
-    bool accept_internal()
-    {
-        switch (last_token)
-        {
-            case token_type::begin_object:
-            {
-                // read next token
-                get_token();
-
-                // closing } -> we are done
-                if (last_token == token_type::end_object)
-                {
-                    return true;
-                }
-
-                // parse values
-                while (true)
-                {
-                    // parse key
-                    if (last_token != token_type::value_string)
-                    {
-                        return false;
-                    }
-
-                    // parse separator (:)
-                    get_token();
-                    if (last_token != token_type::name_separator)
-                    {
-                        return false;
-                    }
-
-                    // parse value
-                    get_token();
-                    if (not accept_internal())
-                    {
-                        return false;
-                    }
-
-                    // comma -> next value
-                    get_token();
-                    if (last_token == token_type::value_separator)
-                    {
-                        get_token();
-                        continue;
-                    }
-
-                    // closing }
-                    return (last_token == token_type::end_object);
-                }
-            }
-
-            case token_type::begin_array:
-            {
-                // read next token
-                get_token();
-
-                // closing ] -> we are done
-                if (last_token == token_type::end_array)
-                {
-                    return true;
-                }
-
-                // parse values
-                while (true)
-                {
-                    // parse value
-                    if (not accept_internal())
-                    {
-                        return false;
-                    }
-
-                    // comma -> next value
-                    get_token();
-                    if (last_token == token_type::value_separator)
-                    {
-                        get_token();
-                        continue;
-                    }
-
-                    // closing ]
-                    return (last_token == token_type::end_array);
-                }
-            }
-
-            case token_type::value_float:
-            {
-                // reject infinity or NAN
-                return std::isfinite(m_lexer.get_number_float());
-            }
-
-            case token_type::literal_false:
-            case token_type::literal_null:
-            case token_type::literal_true:
-            case token_type::value_integer:
-            case token_type::value_string:
-            case token_type::value_unsigned:
-                return true;
-
-            default: // the last token was unexpected
-                return false;
-        }
-    }
-
     bool sax_parse_internal(json_sax_t* sax)
     {
         switch (last_token)
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index 9fc301e2..ff992269 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -3409,6 +3409,80 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
     const bool allow_exceptions = true;
 };
 
+template<typename BasicJsonType>
+class json_sax_acceptor : public json_sax<BasicJsonType>
+{
+  public:
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+
+    bool null() override
+    {
+        return true;
+    }
+
+    bool boolean(bool) override
+    {
+        return true;
+    }
+
+    bool number_integer(number_integer_t) override
+    {
+        return true;
+    }
+
+    bool number_unsigned(number_unsigned_t) override
+    {
+        return true;
+    }
+
+    bool number_float(number_float_t, const std::string&) override
+    {
+        return true;
+    }
+
+    bool string(std::string&&) override
+    {
+        return true;
+    }
+
+    bool start_object(std::size_t) override
+    {
+        return true;
+    }
+
+    bool key(std::string&&) override
+    {
+        return true;
+    }
+
+    bool end_object() override
+    {
+        return true;
+    }
+
+    bool start_array(std::size_t) override
+    {
+        return true;
+    }
+
+    bool end_array() override
+    {
+        return true;
+    }
+
+    bool binary(const std::vector<uint8_t>&) override
+    {
+        return true;
+    }
+
+    bool parse_error(std::size_t, const std::string&, const std::string&) override
+    {
+        return false;
+    }
+};
+
 }
 
 
@@ -3540,7 +3614,9 @@ class parser
     */
     bool accept(const bool strict = true)
     {
-        if (not accept_internal())
+        json_sax_acceptor<BasicJsonType> sax_acceptor;
+
+        if (not sax_parse_internal(&sax_acceptor))
         {
             return false;
         }
@@ -3839,119 +3915,6 @@ class parser
         }
     }
 
-    /*!
-    @brief the actual acceptor
-
-    @invariant 1. The last token is not yet processed. Therefore, the caller
-                  of this function must make sure a token has been read.
-               2. When this function returns, the last token is processed.
-                  That is, the last read character was already considered.
-
-    This invariant makes sure that no token needs to be "unput".
-    */
-    bool accept_internal()
-    {
-        switch (last_token)
-        {
-            case token_type::begin_object:
-            {
-                // read next token
-                get_token();
-
-                // closing } -> we are done
-                if (last_token == token_type::end_object)
-                {
-                    return true;
-                }
-
-                // parse values
-                while (true)
-                {
-                    // parse key
-                    if (last_token != token_type::value_string)
-                    {
-                        return false;
-                    }
-
-                    // parse separator (:)
-                    get_token();
-                    if (last_token != token_type::name_separator)
-                    {
-                        return false;
-                    }
-
-                    // parse value
-                    get_token();
-                    if (not accept_internal())
-                    {
-                        return false;
-                    }
-
-                    // comma -> next value
-                    get_token();
-                    if (last_token == token_type::value_separator)
-                    {
-                        get_token();
-                        continue;
-                    }
-
-                    // closing }
-                    return (last_token == token_type::end_object);
-                }
-            }
-
-            case token_type::begin_array:
-            {
-                // read next token
-                get_token();
-
-                // closing ] -> we are done
-                if (last_token == token_type::end_array)
-                {
-                    return true;
-                }
-
-                // parse values
-                while (true)
-                {
-                    // parse value
-                    if (not accept_internal())
-                    {
-                        return false;
-                    }
-
-                    // comma -> next value
-                    get_token();
-                    if (last_token == token_type::value_separator)
-                    {
-                        get_token();
-                        continue;
-                    }
-
-                    // closing ]
-                    return (last_token == token_type::end_array);
-                }
-            }
-
-            case token_type::value_float:
-            {
-                // reject infinity or NAN
-                return std::isfinite(m_lexer.get_number_float());
-            }
-
-            case token_type::literal_false:
-            case token_type::literal_null:
-            case token_type::literal_true:
-            case token_type::value_integer:
-            case token_type::value_string:
-            case token_type::value_unsigned:
-                return true;
-
-            default: // the last token was unexpected
-                return false;
-        }
-    }
-
     bool sax_parse_internal(json_sax_t* sax)
     {
         switch (last_token)