1c5f01b2fSopenharmony_ci//     __ _____ _____ _____
2c5f01b2fSopenharmony_ci//  __|  |   __|     |   | |  JSON for Modern C++
3c5f01b2fSopenharmony_ci// |  |  |__   |  |  | | | |  version 3.11.2
4c5f01b2fSopenharmony_ci// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5c5f01b2fSopenharmony_ci//
6c5f01b2fSopenharmony_ci// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7c5f01b2fSopenharmony_ci// SPDX-License-Identifier: MIT
8c5f01b2fSopenharmony_ci
9c5f01b2fSopenharmony_ci#pragma once
10c5f01b2fSopenharmony_ci
11c5f01b2fSopenharmony_ci#include <cmath> // isfinite
12c5f01b2fSopenharmony_ci#include <cstdint> // uint8_t
13c5f01b2fSopenharmony_ci#include <functional> // function
14c5f01b2fSopenharmony_ci#include <string> // string
15c5f01b2fSopenharmony_ci#include <utility> // move
16c5f01b2fSopenharmony_ci#include <vector> // vector
17c5f01b2fSopenharmony_ci
18c5f01b2fSopenharmony_ci#include <nlohmann/detail/exceptions.hpp>
19c5f01b2fSopenharmony_ci#include <nlohmann/detail/input/input_adapters.hpp>
20c5f01b2fSopenharmony_ci#include <nlohmann/detail/input/json_sax.hpp>
21c5f01b2fSopenharmony_ci#include <nlohmann/detail/input/lexer.hpp>
22c5f01b2fSopenharmony_ci#include <nlohmann/detail/macro_scope.hpp>
23c5f01b2fSopenharmony_ci#include <nlohmann/detail/meta/is_sax.hpp>
24c5f01b2fSopenharmony_ci#include <nlohmann/detail/string_concat.hpp>
25c5f01b2fSopenharmony_ci#include <nlohmann/detail/value_t.hpp>
26c5f01b2fSopenharmony_ci
27c5f01b2fSopenharmony_ciNLOHMANN_JSON_NAMESPACE_BEGIN
28c5f01b2fSopenharmony_cinamespace detail
29c5f01b2fSopenharmony_ci{
30c5f01b2fSopenharmony_ci////////////
31c5f01b2fSopenharmony_ci// parser //
32c5f01b2fSopenharmony_ci////////////
33c5f01b2fSopenharmony_ci
34c5f01b2fSopenharmony_cienum class parse_event_t : std::uint8_t
35c5f01b2fSopenharmony_ci{
36c5f01b2fSopenharmony_ci    /// the parser read `{` and started to process a JSON object
37c5f01b2fSopenharmony_ci    object_start,
38c5f01b2fSopenharmony_ci    /// the parser read `}` and finished processing a JSON object
39c5f01b2fSopenharmony_ci    object_end,
40c5f01b2fSopenharmony_ci    /// the parser read `[` and started to process a JSON array
41c5f01b2fSopenharmony_ci    array_start,
42c5f01b2fSopenharmony_ci    /// the parser read `]` and finished processing a JSON array
43c5f01b2fSopenharmony_ci    array_end,
44c5f01b2fSopenharmony_ci    /// the parser read a key of a value in an object
45c5f01b2fSopenharmony_ci    key,
46c5f01b2fSopenharmony_ci    /// the parser finished reading a JSON value
47c5f01b2fSopenharmony_ci    value
48c5f01b2fSopenharmony_ci};
49c5f01b2fSopenharmony_ci
50c5f01b2fSopenharmony_citemplate<typename BasicJsonType>
51c5f01b2fSopenharmony_ciusing parser_callback_t =
52c5f01b2fSopenharmony_ci    std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
53c5f01b2fSopenharmony_ci
54c5f01b2fSopenharmony_ci/*!
55c5f01b2fSopenharmony_ci@brief syntax analysis
56c5f01b2fSopenharmony_ci
57c5f01b2fSopenharmony_ciThis class implements a recursive descent parser.
58c5f01b2fSopenharmony_ci*/
59c5f01b2fSopenharmony_citemplate<typename BasicJsonType, typename InputAdapterType>
60c5f01b2fSopenharmony_ciclass parser
61c5f01b2fSopenharmony_ci{
62c5f01b2fSopenharmony_ci    using number_integer_t = typename BasicJsonType::number_integer_t;
63c5f01b2fSopenharmony_ci    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
64c5f01b2fSopenharmony_ci    using number_float_t = typename BasicJsonType::number_float_t;
65c5f01b2fSopenharmony_ci    using string_t = typename BasicJsonType::string_t;
66c5f01b2fSopenharmony_ci    using lexer_t = lexer<BasicJsonType, InputAdapterType>;
67c5f01b2fSopenharmony_ci    using token_type = typename lexer_t::token_type;
68c5f01b2fSopenharmony_ci
69c5f01b2fSopenharmony_ci  public:
70c5f01b2fSopenharmony_ci    /// a parser reading from an input adapter
71c5f01b2fSopenharmony_ci    explicit parser(InputAdapterType&& adapter,
72c5f01b2fSopenharmony_ci                    const parser_callback_t<BasicJsonType> cb = nullptr,
73c5f01b2fSopenharmony_ci                    const bool allow_exceptions_ = true,
74c5f01b2fSopenharmony_ci                    const bool skip_comments = false)
75c5f01b2fSopenharmony_ci        : callback(cb)
76c5f01b2fSopenharmony_ci        , m_lexer(std::move(adapter), skip_comments)
77c5f01b2fSopenharmony_ci        , allow_exceptions(allow_exceptions_)
78c5f01b2fSopenharmony_ci    {
79c5f01b2fSopenharmony_ci        // read first token
80c5f01b2fSopenharmony_ci        get_token();
81c5f01b2fSopenharmony_ci    }
82c5f01b2fSopenharmony_ci
83c5f01b2fSopenharmony_ci    /*!
84c5f01b2fSopenharmony_ci    @brief public parser interface
85c5f01b2fSopenharmony_ci
86c5f01b2fSopenharmony_ci    @param[in] strict      whether to expect the last token to be EOF
87c5f01b2fSopenharmony_ci    @param[in,out] result  parsed JSON value
88c5f01b2fSopenharmony_ci
89c5f01b2fSopenharmony_ci    @throw parse_error.101 in case of an unexpected token
90c5f01b2fSopenharmony_ci    @throw parse_error.102 if to_unicode fails or surrogate error
91c5f01b2fSopenharmony_ci    @throw parse_error.103 if to_unicode fails
92c5f01b2fSopenharmony_ci    */
93c5f01b2fSopenharmony_ci    void parse(const bool strict, BasicJsonType& result)
94c5f01b2fSopenharmony_ci    {
95c5f01b2fSopenharmony_ci        if (callback)
96c5f01b2fSopenharmony_ci        {
97c5f01b2fSopenharmony_ci            json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
98c5f01b2fSopenharmony_ci            sax_parse_internal(&sdp);
99c5f01b2fSopenharmony_ci
100c5f01b2fSopenharmony_ci            // in strict mode, input must be completely read
101c5f01b2fSopenharmony_ci            if (strict && (get_token() != token_type::end_of_input))
102c5f01b2fSopenharmony_ci            {
103c5f01b2fSopenharmony_ci                sdp.parse_error(m_lexer.get_position(),
104c5f01b2fSopenharmony_ci                                m_lexer.get_token_string(),
105c5f01b2fSopenharmony_ci                                parse_error::create(101, m_lexer.get_position(),
106c5f01b2fSopenharmony_ci                                                    exception_message(token_type::end_of_input, "value"), nullptr));
107c5f01b2fSopenharmony_ci            }
108c5f01b2fSopenharmony_ci
109c5f01b2fSopenharmony_ci            // in case of an error, return discarded value
110c5f01b2fSopenharmony_ci            if (sdp.is_errored())
111c5f01b2fSopenharmony_ci            {
112c5f01b2fSopenharmony_ci                result = value_t::discarded;
113c5f01b2fSopenharmony_ci                return;
114c5f01b2fSopenharmony_ci            }
115c5f01b2fSopenharmony_ci
116c5f01b2fSopenharmony_ci            // set top-level value to null if it was discarded by the callback
117c5f01b2fSopenharmony_ci            // function
118c5f01b2fSopenharmony_ci            if (result.is_discarded())
119c5f01b2fSopenharmony_ci            {
120c5f01b2fSopenharmony_ci                result = nullptr;
121c5f01b2fSopenharmony_ci            }
122c5f01b2fSopenharmony_ci        }
123c5f01b2fSopenharmony_ci        else
124c5f01b2fSopenharmony_ci        {
125c5f01b2fSopenharmony_ci            json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
126c5f01b2fSopenharmony_ci            sax_parse_internal(&sdp);
127c5f01b2fSopenharmony_ci
128c5f01b2fSopenharmony_ci            // in strict mode, input must be completely read
129c5f01b2fSopenharmony_ci            if (strict && (get_token() != token_type::end_of_input))
130c5f01b2fSopenharmony_ci            {
131c5f01b2fSopenharmony_ci                sdp.parse_error(m_lexer.get_position(),
132c5f01b2fSopenharmony_ci                                m_lexer.get_token_string(),
133c5f01b2fSopenharmony_ci                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
134c5f01b2fSopenharmony_ci            }
135c5f01b2fSopenharmony_ci
136c5f01b2fSopenharmony_ci            // in case of an error, return discarded value
137c5f01b2fSopenharmony_ci            if (sdp.is_errored())
138c5f01b2fSopenharmony_ci            {
139c5f01b2fSopenharmony_ci                result = value_t::discarded;
140c5f01b2fSopenharmony_ci                return;
141c5f01b2fSopenharmony_ci            }
142c5f01b2fSopenharmony_ci        }
143c5f01b2fSopenharmony_ci
144c5f01b2fSopenharmony_ci        result.assert_invariant();
145c5f01b2fSopenharmony_ci    }
146c5f01b2fSopenharmony_ci
147c5f01b2fSopenharmony_ci    /*!
148c5f01b2fSopenharmony_ci    @brief public accept interface
149c5f01b2fSopenharmony_ci
150c5f01b2fSopenharmony_ci    @param[in] strict  whether to expect the last token to be EOF
151c5f01b2fSopenharmony_ci    @return whether the input is a proper JSON text
152c5f01b2fSopenharmony_ci    */
153c5f01b2fSopenharmony_ci    bool accept(const bool strict = true)
154c5f01b2fSopenharmony_ci    {
155c5f01b2fSopenharmony_ci        json_sax_acceptor<BasicJsonType> sax_acceptor;
156c5f01b2fSopenharmony_ci        return sax_parse(&sax_acceptor, strict);
157c5f01b2fSopenharmony_ci    }
158c5f01b2fSopenharmony_ci
159c5f01b2fSopenharmony_ci    template<typename SAX>
160c5f01b2fSopenharmony_ci    JSON_HEDLEY_NON_NULL(2)
161c5f01b2fSopenharmony_ci    bool sax_parse(SAX* sax, const bool strict = true)
162c5f01b2fSopenharmony_ci    {
163c5f01b2fSopenharmony_ci        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
164c5f01b2fSopenharmony_ci        const bool result = sax_parse_internal(sax);
165c5f01b2fSopenharmony_ci
166c5f01b2fSopenharmony_ci        // strict mode: next byte must be EOF
167c5f01b2fSopenharmony_ci        if (result && strict && (get_token() != token_type::end_of_input))
168c5f01b2fSopenharmony_ci        {
169c5f01b2fSopenharmony_ci            return sax->parse_error(m_lexer.get_position(),
170c5f01b2fSopenharmony_ci                                    m_lexer.get_token_string(),
171c5f01b2fSopenharmony_ci                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
172c5f01b2fSopenharmony_ci        }
173c5f01b2fSopenharmony_ci
174c5f01b2fSopenharmony_ci        return result;
175c5f01b2fSopenharmony_ci    }
176c5f01b2fSopenharmony_ci
177c5f01b2fSopenharmony_ci  private:
178c5f01b2fSopenharmony_ci    template<typename SAX>
179c5f01b2fSopenharmony_ci    JSON_HEDLEY_NON_NULL(2)
180c5f01b2fSopenharmony_ci    bool sax_parse_internal(SAX* sax)
181c5f01b2fSopenharmony_ci    {
182c5f01b2fSopenharmony_ci        // stack to remember the hierarchy of structured values we are parsing
183c5f01b2fSopenharmony_ci        // true = array; false = object
184c5f01b2fSopenharmony_ci        std::vector<bool> states;
185c5f01b2fSopenharmony_ci        // value to avoid a goto (see comment where set to true)
186c5f01b2fSopenharmony_ci        bool skip_to_state_evaluation = false;
187c5f01b2fSopenharmony_ci
188c5f01b2fSopenharmony_ci        while (true)
189c5f01b2fSopenharmony_ci        {
190c5f01b2fSopenharmony_ci            if (!skip_to_state_evaluation)
191c5f01b2fSopenharmony_ci            {
192c5f01b2fSopenharmony_ci                // invariant: get_token() was called before each iteration
193c5f01b2fSopenharmony_ci                switch (last_token)
194c5f01b2fSopenharmony_ci                {
195c5f01b2fSopenharmony_ci                    case token_type::begin_object:
196c5f01b2fSopenharmony_ci                    {
197c5f01b2fSopenharmony_ci                        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
198c5f01b2fSopenharmony_ci                        {
199c5f01b2fSopenharmony_ci                            return false;
200c5f01b2fSopenharmony_ci                        }
201c5f01b2fSopenharmony_ci
202c5f01b2fSopenharmony_ci                        // closing } -> we are done
203c5f01b2fSopenharmony_ci                        if (get_token() == token_type::end_object)
204c5f01b2fSopenharmony_ci                        {
205c5f01b2fSopenharmony_ci                            if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
206c5f01b2fSopenharmony_ci                            {
207c5f01b2fSopenharmony_ci                                return false;
208c5f01b2fSopenharmony_ci                            }
209c5f01b2fSopenharmony_ci                            break;
210c5f01b2fSopenharmony_ci                        }
211c5f01b2fSopenharmony_ci
212c5f01b2fSopenharmony_ci                        // parse key
213c5f01b2fSopenharmony_ci                        if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
214c5f01b2fSopenharmony_ci                        {
215c5f01b2fSopenharmony_ci                            return sax->parse_error(m_lexer.get_position(),
216c5f01b2fSopenharmony_ci                                                    m_lexer.get_token_string(),
217c5f01b2fSopenharmony_ci                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
218c5f01b2fSopenharmony_ci                        }
219c5f01b2fSopenharmony_ci                        if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
220c5f01b2fSopenharmony_ci                        {
221c5f01b2fSopenharmony_ci                            return false;
222c5f01b2fSopenharmony_ci                        }
223c5f01b2fSopenharmony_ci
224c5f01b2fSopenharmony_ci                        // parse separator (:)
225c5f01b2fSopenharmony_ci                        if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
226c5f01b2fSopenharmony_ci                        {
227c5f01b2fSopenharmony_ci                            return sax->parse_error(m_lexer.get_position(),
228c5f01b2fSopenharmony_ci                                                    m_lexer.get_token_string(),
229c5f01b2fSopenharmony_ci                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
230c5f01b2fSopenharmony_ci                        }
231c5f01b2fSopenharmony_ci
232c5f01b2fSopenharmony_ci                        // remember we are now inside an object
233c5f01b2fSopenharmony_ci                        states.push_back(false);
234c5f01b2fSopenharmony_ci
235c5f01b2fSopenharmony_ci                        // parse values
236c5f01b2fSopenharmony_ci                        get_token();
237c5f01b2fSopenharmony_ci                        continue;
238c5f01b2fSopenharmony_ci                    }
239c5f01b2fSopenharmony_ci
240c5f01b2fSopenharmony_ci                    case token_type::begin_array:
241c5f01b2fSopenharmony_ci                    {
242c5f01b2fSopenharmony_ci                        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
243c5f01b2fSopenharmony_ci                        {
244c5f01b2fSopenharmony_ci                            return false;
245c5f01b2fSopenharmony_ci                        }
246c5f01b2fSopenharmony_ci
247c5f01b2fSopenharmony_ci                        // closing ] -> we are done
248c5f01b2fSopenharmony_ci                        if (get_token() == token_type::end_array)
249c5f01b2fSopenharmony_ci                        {
250c5f01b2fSopenharmony_ci                            if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
251c5f01b2fSopenharmony_ci                            {
252c5f01b2fSopenharmony_ci                                return false;
253c5f01b2fSopenharmony_ci                            }
254c5f01b2fSopenharmony_ci                            break;
255c5f01b2fSopenharmony_ci                        }
256c5f01b2fSopenharmony_ci
257c5f01b2fSopenharmony_ci                        // remember we are now inside an array
258c5f01b2fSopenharmony_ci                        states.push_back(true);
259c5f01b2fSopenharmony_ci
260c5f01b2fSopenharmony_ci                        // parse values (no need to call get_token)
261c5f01b2fSopenharmony_ci                        continue;
262c5f01b2fSopenharmony_ci                    }
263c5f01b2fSopenharmony_ci
264c5f01b2fSopenharmony_ci                    case token_type::value_float:
265c5f01b2fSopenharmony_ci                    {
266c5f01b2fSopenharmony_ci                        const auto res = m_lexer.get_number_float();
267c5f01b2fSopenharmony_ci
268c5f01b2fSopenharmony_ci                        if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
269c5f01b2fSopenharmony_ci                        {
270c5f01b2fSopenharmony_ci                            return sax->parse_error(m_lexer.get_position(),
271c5f01b2fSopenharmony_ci                                                    m_lexer.get_token_string(),
272c5f01b2fSopenharmony_ci                                                    out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
273c5f01b2fSopenharmony_ci                        }
274c5f01b2fSopenharmony_ci
275c5f01b2fSopenharmony_ci                        if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
276c5f01b2fSopenharmony_ci                        {
277c5f01b2fSopenharmony_ci                            return false;
278c5f01b2fSopenharmony_ci                        }
279c5f01b2fSopenharmony_ci
280c5f01b2fSopenharmony_ci                        break;
281c5f01b2fSopenharmony_ci                    }
282c5f01b2fSopenharmony_ci
283c5f01b2fSopenharmony_ci                    case token_type::literal_false:
284c5f01b2fSopenharmony_ci                    {
285c5f01b2fSopenharmony_ci                        if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
286c5f01b2fSopenharmony_ci                        {
287c5f01b2fSopenharmony_ci                            return false;
288c5f01b2fSopenharmony_ci                        }
289c5f01b2fSopenharmony_ci                        break;
290c5f01b2fSopenharmony_ci                    }
291c5f01b2fSopenharmony_ci
292c5f01b2fSopenharmony_ci                    case token_type::literal_null:
293c5f01b2fSopenharmony_ci                    {
294c5f01b2fSopenharmony_ci                        if (JSON_HEDLEY_UNLIKELY(!sax->null()))
295c5f01b2fSopenharmony_ci                        {
296c5f01b2fSopenharmony_ci                            return false;
297c5f01b2fSopenharmony_ci                        }
298c5f01b2fSopenharmony_ci                        break;
299c5f01b2fSopenharmony_ci                    }
300c5f01b2fSopenharmony_ci
301c5f01b2fSopenharmony_ci                    case token_type::literal_true:
302c5f01b2fSopenharmony_ci                    {
303c5f01b2fSopenharmony_ci                        if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
304c5f01b2fSopenharmony_ci                        {
305c5f01b2fSopenharmony_ci                            return false;
306c5f01b2fSopenharmony_ci                        }
307c5f01b2fSopenharmony_ci                        break;
308c5f01b2fSopenharmony_ci                    }
309c5f01b2fSopenharmony_ci
310c5f01b2fSopenharmony_ci                    case token_type::value_integer:
311c5f01b2fSopenharmony_ci                    {
312c5f01b2fSopenharmony_ci                        if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
313c5f01b2fSopenharmony_ci                        {
314c5f01b2fSopenharmony_ci                            return false;
315c5f01b2fSopenharmony_ci                        }
316c5f01b2fSopenharmony_ci                        break;
317c5f01b2fSopenharmony_ci                    }
318c5f01b2fSopenharmony_ci
319c5f01b2fSopenharmony_ci                    case token_type::value_string:
320c5f01b2fSopenharmony_ci                    {
321c5f01b2fSopenharmony_ci                        if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
322c5f01b2fSopenharmony_ci                        {
323c5f01b2fSopenharmony_ci                            return false;
324c5f01b2fSopenharmony_ci                        }
325c5f01b2fSopenharmony_ci                        break;
326c5f01b2fSopenharmony_ci                    }
327c5f01b2fSopenharmony_ci
328c5f01b2fSopenharmony_ci                    case token_type::value_unsigned:
329c5f01b2fSopenharmony_ci                    {
330c5f01b2fSopenharmony_ci                        if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
331c5f01b2fSopenharmony_ci                        {
332c5f01b2fSopenharmony_ci                            return false;
333c5f01b2fSopenharmony_ci                        }
334c5f01b2fSopenharmony_ci                        break;
335c5f01b2fSopenharmony_ci                    }
336c5f01b2fSopenharmony_ci
337c5f01b2fSopenharmony_ci                    case token_type::parse_error:
338c5f01b2fSopenharmony_ci                    {
339c5f01b2fSopenharmony_ci                        // using "uninitialized" to avoid "expected" message
340c5f01b2fSopenharmony_ci                        return sax->parse_error(m_lexer.get_position(),
341c5f01b2fSopenharmony_ci                                                m_lexer.get_token_string(),
342c5f01b2fSopenharmony_ci                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
343c5f01b2fSopenharmony_ci                    }
344c5f01b2fSopenharmony_ci
345c5f01b2fSopenharmony_ci                    case token_type::uninitialized:
346c5f01b2fSopenharmony_ci                    case token_type::end_array:
347c5f01b2fSopenharmony_ci                    case token_type::end_object:
348c5f01b2fSopenharmony_ci                    case token_type::name_separator:
349c5f01b2fSopenharmony_ci                    case token_type::value_separator:
350c5f01b2fSopenharmony_ci                    case token_type::end_of_input:
351c5f01b2fSopenharmony_ci                    case token_type::literal_or_value:
352c5f01b2fSopenharmony_ci                    default: // the last token was unexpected
353c5f01b2fSopenharmony_ci                    {
354c5f01b2fSopenharmony_ci                        return sax->parse_error(m_lexer.get_position(),
355c5f01b2fSopenharmony_ci                                                m_lexer.get_token_string(),
356c5f01b2fSopenharmony_ci                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
357c5f01b2fSopenharmony_ci                    }
358c5f01b2fSopenharmony_ci                }
359c5f01b2fSopenharmony_ci            }
360c5f01b2fSopenharmony_ci            else
361c5f01b2fSopenharmony_ci            {
362c5f01b2fSopenharmony_ci                skip_to_state_evaluation = false;
363c5f01b2fSopenharmony_ci            }
364c5f01b2fSopenharmony_ci
365c5f01b2fSopenharmony_ci            // we reached this line after we successfully parsed a value
366c5f01b2fSopenharmony_ci            if (states.empty())
367c5f01b2fSopenharmony_ci            {
368c5f01b2fSopenharmony_ci                // empty stack: we reached the end of the hierarchy: done
369c5f01b2fSopenharmony_ci                return true;
370c5f01b2fSopenharmony_ci            }
371c5f01b2fSopenharmony_ci
372c5f01b2fSopenharmony_ci            if (states.back())  // array
373c5f01b2fSopenharmony_ci            {
374c5f01b2fSopenharmony_ci                // comma -> next value
375c5f01b2fSopenharmony_ci                if (get_token() == token_type::value_separator)
376c5f01b2fSopenharmony_ci                {
377c5f01b2fSopenharmony_ci                    // parse a new value
378c5f01b2fSopenharmony_ci                    get_token();
379c5f01b2fSopenharmony_ci                    continue;
380c5f01b2fSopenharmony_ci                }
381c5f01b2fSopenharmony_ci
382c5f01b2fSopenharmony_ci                // closing ]
383c5f01b2fSopenharmony_ci                if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
384c5f01b2fSopenharmony_ci                {
385c5f01b2fSopenharmony_ci                    if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
386c5f01b2fSopenharmony_ci                    {
387c5f01b2fSopenharmony_ci                        return false;
388c5f01b2fSopenharmony_ci                    }
389c5f01b2fSopenharmony_ci
390c5f01b2fSopenharmony_ci                    // We are done with this array. Before we can parse a
391c5f01b2fSopenharmony_ci                    // new value, we need to evaluate the new state first.
392c5f01b2fSopenharmony_ci                    // By setting skip_to_state_evaluation to false, we
393c5f01b2fSopenharmony_ci                    // are effectively jumping to the beginning of this if.
394c5f01b2fSopenharmony_ci                    JSON_ASSERT(!states.empty());
395c5f01b2fSopenharmony_ci                    states.pop_back();
396c5f01b2fSopenharmony_ci                    skip_to_state_evaluation = true;
397c5f01b2fSopenharmony_ci                    continue;
398c5f01b2fSopenharmony_ci                }
399c5f01b2fSopenharmony_ci
400c5f01b2fSopenharmony_ci                return sax->parse_error(m_lexer.get_position(),
401c5f01b2fSopenharmony_ci                                        m_lexer.get_token_string(),
402c5f01b2fSopenharmony_ci                                        parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
403c5f01b2fSopenharmony_ci            }
404c5f01b2fSopenharmony_ci
405c5f01b2fSopenharmony_ci            // states.back() is false -> object
406c5f01b2fSopenharmony_ci
407c5f01b2fSopenharmony_ci            // comma -> next value
408c5f01b2fSopenharmony_ci            if (get_token() == token_type::value_separator)
409c5f01b2fSopenharmony_ci            {
410c5f01b2fSopenharmony_ci                // parse key
411c5f01b2fSopenharmony_ci                if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
412c5f01b2fSopenharmony_ci                {
413c5f01b2fSopenharmony_ci                    return sax->parse_error(m_lexer.get_position(),
414c5f01b2fSopenharmony_ci                                            m_lexer.get_token_string(),
415c5f01b2fSopenharmony_ci                                            parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
416c5f01b2fSopenharmony_ci                }
417c5f01b2fSopenharmony_ci
418c5f01b2fSopenharmony_ci                if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
419c5f01b2fSopenharmony_ci                {
420c5f01b2fSopenharmony_ci                    return false;
421c5f01b2fSopenharmony_ci                }
422c5f01b2fSopenharmony_ci
423c5f01b2fSopenharmony_ci                // parse separator (:)
424c5f01b2fSopenharmony_ci                if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
425c5f01b2fSopenharmony_ci                {
426c5f01b2fSopenharmony_ci                    return sax->parse_error(m_lexer.get_position(),
427c5f01b2fSopenharmony_ci                                            m_lexer.get_token_string(),
428c5f01b2fSopenharmony_ci                                            parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
429c5f01b2fSopenharmony_ci                }
430c5f01b2fSopenharmony_ci
431c5f01b2fSopenharmony_ci                // parse values
432c5f01b2fSopenharmony_ci                get_token();
433c5f01b2fSopenharmony_ci                continue;
434c5f01b2fSopenharmony_ci            }
435c5f01b2fSopenharmony_ci
436c5f01b2fSopenharmony_ci            // closing }
437c5f01b2fSopenharmony_ci            if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
438c5f01b2fSopenharmony_ci            {
439c5f01b2fSopenharmony_ci                if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
440c5f01b2fSopenharmony_ci                {
441c5f01b2fSopenharmony_ci                    return false;
442c5f01b2fSopenharmony_ci                }
443c5f01b2fSopenharmony_ci
444c5f01b2fSopenharmony_ci                // We are done with this object. Before we can parse a
445c5f01b2fSopenharmony_ci                // new value, we need to evaluate the new state first.
446c5f01b2fSopenharmony_ci                // By setting skip_to_state_evaluation to false, we
447c5f01b2fSopenharmony_ci                // are effectively jumping to the beginning of this if.
448c5f01b2fSopenharmony_ci                JSON_ASSERT(!states.empty());
449c5f01b2fSopenharmony_ci                states.pop_back();
450c5f01b2fSopenharmony_ci                skip_to_state_evaluation = true;
451c5f01b2fSopenharmony_ci                continue;
452c5f01b2fSopenharmony_ci            }
453c5f01b2fSopenharmony_ci
454c5f01b2fSopenharmony_ci            return sax->parse_error(m_lexer.get_position(),
455c5f01b2fSopenharmony_ci                                    m_lexer.get_token_string(),
456c5f01b2fSopenharmony_ci                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
457c5f01b2fSopenharmony_ci        }
458c5f01b2fSopenharmony_ci    }
459c5f01b2fSopenharmony_ci
460c5f01b2fSopenharmony_ci    /// get next token from lexer
461c5f01b2fSopenharmony_ci    token_type get_token()
462c5f01b2fSopenharmony_ci    {
463c5f01b2fSopenharmony_ci        return last_token = m_lexer.scan();
464c5f01b2fSopenharmony_ci    }
465c5f01b2fSopenharmony_ci
466c5f01b2fSopenharmony_ci    std::string exception_message(const token_type expected, const std::string& context)
467c5f01b2fSopenharmony_ci    {
468c5f01b2fSopenharmony_ci        std::string error_msg = "syntax error ";
469c5f01b2fSopenharmony_ci
470c5f01b2fSopenharmony_ci        if (!context.empty())
471c5f01b2fSopenharmony_ci        {
472c5f01b2fSopenharmony_ci            error_msg += concat("while parsing ", context, ' ');
473c5f01b2fSopenharmony_ci        }
474c5f01b2fSopenharmony_ci
475c5f01b2fSopenharmony_ci        error_msg += "- ";
476c5f01b2fSopenharmony_ci
477c5f01b2fSopenharmony_ci        if (last_token == token_type::parse_error)
478c5f01b2fSopenharmony_ci        {
479c5f01b2fSopenharmony_ci            error_msg += concat(m_lexer.get_error_message(), "; last read: '",
480c5f01b2fSopenharmony_ci                                m_lexer.get_token_string(), '\'');
481c5f01b2fSopenharmony_ci        }
482c5f01b2fSopenharmony_ci        else
483c5f01b2fSopenharmony_ci        {
484c5f01b2fSopenharmony_ci            error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
485c5f01b2fSopenharmony_ci        }
486c5f01b2fSopenharmony_ci
487c5f01b2fSopenharmony_ci        if (expected != token_type::uninitialized)
488c5f01b2fSopenharmony_ci        {
489c5f01b2fSopenharmony_ci            error_msg += concat("; expected ", lexer_t::token_type_name(expected));
490c5f01b2fSopenharmony_ci        }
491c5f01b2fSopenharmony_ci
492c5f01b2fSopenharmony_ci        return error_msg;
493c5f01b2fSopenharmony_ci    }
494c5f01b2fSopenharmony_ci
495c5f01b2fSopenharmony_ci  private:
496c5f01b2fSopenharmony_ci    /// callback function
497c5f01b2fSopenharmony_ci    const parser_callback_t<BasicJsonType> callback = nullptr;
498c5f01b2fSopenharmony_ci    /// the type of the last read token
499c5f01b2fSopenharmony_ci    token_type last_token = token_type::uninitialized;
500c5f01b2fSopenharmony_ci    /// the lexer
501c5f01b2fSopenharmony_ci    lexer_t m_lexer;
502c5f01b2fSopenharmony_ci    /// whether to throw exceptions in case of errors
503c5f01b2fSopenharmony_ci    const bool allow_exceptions = true;
504c5f01b2fSopenharmony_ci};
505c5f01b2fSopenharmony_ci
506c5f01b2fSopenharmony_ci}  // namespace detail
507c5f01b2fSopenharmony_ciNLOHMANN_JSON_NAMESPACE_END
508