| 8991 | This class implements a recursive decent parser. |
| 8992 | */ |
| 8993 | class parser |
| 8994 | { |
| 8995 | public: |
| 8996 | /// a parser reading from a string literal |
| 8997 | parser(const char* buff, const parser_callback_t cb = nullptr) |
| 8998 | : callback(cb), |
| 8999 | m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), strlen(buff)) |
| 9000 | {} |
| 9001 | |
| 9002 | /// a parser reading from an input stream |
| 9003 | parser(std::istream& is, const parser_callback_t cb = nullptr) |
| 9004 | : callback(cb), m_lexer(is) |
| 9005 | {} |
| 9006 | |
| 9007 | /// a parser reading from an iterator range with contiguous storage |
| 9008 | template<class IteratorType, typename std::enable_if< |
| 9009 | std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value |
| 9010 | , int>::type |
| 9011 | = 0> |
| 9012 | parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr) |
| 9013 | : callback(cb), |
| 9014 | m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)), |
| 9015 | static_cast<size_t>(std::distance(first, last))) |
| 9016 | {} |
| 9017 | |
| 9018 | /// public parser interface |
| 9019 | basic_json parse() |
| 9020 | { |
| 9021 | // read first token |
| 9022 | get_token(); |
| 9023 | |
| 9024 | basic_json result = parse_internal(true); |
| 9025 | result.assert_invariant(); |
| 9026 | |
| 9027 | expect(lexer::token_type::end_of_input); |
| 9028 | |
| 9029 | // return parser result and replace it with null in case the |
| 9030 | // top-level value was discarded by the callback function |
| 9031 | return result.is_discarded() ? basic_json() : std::move(result); |
| 9032 | } |
| 9033 | |
| 9034 | private: |
| 9035 | /// the actual parser |
| 9036 | basic_json parse_internal(bool keep) |
| 9037 | { |
| 9038 | auto result = basic_json(value_t::discarded); |
| 9039 | |
| 9040 | switch (last_token) |
| 9041 | { |
| 9042 | case lexer::token_type::begin_object: |
| 9043 | { |
| 9044 | if (keep and (not callback |
| 9045 | or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0))) |
| 9046 | { |
| 9047 | // explicitly set result to object to cope with {} |
| 9048 | result.m_type = value_t::object; |
| 9049 | result.m_value = value_t::object; |
| 9050 | } |
no outgoing calls
no test coverage detected