123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- #pragma once
- #include "reader.h"
- #include <util/generic/maybe.h>
- #include <util/generic/bt_exception.h>
- #include <util/generic/yexception.h>
- #include <util/system/yassert.h>
- /** Imperative recursive-descent parsing helpers.
- *
- * These functions help verify conditions and advance parser state.
- * For aggregate parsing functions, common precondition is to require Begin{X}
- * event prior to function invocation. Thus, parsers are composable by calling
- * sub-parser after dispatching on opening event, e.g.:
- *
- * if (reader.LastEvent().Type() == EEventType::BeginMap) {
- * ReadSomeMap(reader)
- * }
- *
- */
- namespace NYsonPull {
- namespace NReadOps {
- class TExpectationFailure: public TWithBackTrace<yexception> {
- };
- inline void Expect(const TEvent& got, EEventType expected) {
- Y_ENSURE_EX(
- got.Type() == expected,
- TExpectationFailure() << "expected " << expected << ", got " << got);
- }
- inline void Expect(const TScalar& got, EScalarType expected) {
- Y_ENSURE_EX(
- got.Type() == expected,
- TExpectationFailure() << "expected scalar " << expected << ", got " << got);
- }
- // ExpectBegin{X} functions verify that last event WAS X
- // SkipBegin{X} functions verify that next event WILL BE X and CONSUME it
- inline void ExpectBeginStream(TReader& reader) {
- Expect(reader.LastEvent(), EEventType::BeginStream);
- }
- inline void SkipBeginStream(TReader& reader) {
- Expect(reader.NextEvent(), EEventType::BeginStream);
- }
- inline void ExpectBeginMap(TReader& reader) {
- Expect(reader.LastEvent(), EEventType::BeginMap);
- }
- inline void SkipBeginMap(TReader& reader) {
- Expect(reader.NextEvent(), EEventType::BeginMap);
- }
- inline void ExpectBeginList(TReader& reader) {
- Expect(reader.LastEvent(), EEventType::BeginList);
- }
- inline void SkipBeginList(TReader& reader) {
- Expect(reader.NextEvent(), EEventType::BeginList);
- }
- inline bool ReadListItem(TReader& reader) {
- return reader.NextEvent().Type() != EEventType::EndList;
- }
- inline TMaybe<TStringBuf> ReadKey(TReader& reader) {
- const auto& event = reader.NextEvent();
- switch (event.Type()) {
- case EEventType::Key:
- return event.AsString();
- case EEventType::EndMap:
- return Nothing();
- default:
- ythrow yexception() << "Unexpected event: " << event;
- }
- }
- template <typename T = const TScalar&>
- inline T ReadScalar(TReader& reader);
- template <>
- inline const TScalar& ReadScalar<const TScalar&>(TReader& reader) {
- const auto& event = reader.NextEvent();
- Expect(event, EEventType::Scalar);
- return event.AsScalar();
- }
- template <>
- inline i64 ReadScalar<i64>(TReader& reader) {
- const auto& scalar = ReadScalar(reader);
- Expect(scalar, EScalarType::Int64);
- return scalar.AsInt64();
- }
- template <>
- inline ui64 ReadScalar<ui64>(TReader& reader) {
- const auto& scalar = ReadScalar(reader);
- Expect(scalar, EScalarType::UInt64);
- return scalar.AsUInt64();
- }
- template <>
- inline double ReadScalar<double>(TReader& reader) {
- const auto& scalar = ReadScalar(reader);
- Expect(scalar, EScalarType::Float64);
- return scalar.AsFloat64();
- }
- template <>
- inline TStringBuf ReadScalar<TStringBuf>(TReader& reader) {
- const auto& scalar = ReadScalar(reader);
- Expect(scalar, EScalarType::String);
- return scalar.AsString();
- }
- template <>
- inline TString ReadScalar<TString>(TReader& reader) {
- return TString(ReadScalar<TStringBuf>(reader));
- }
- template <>
- inline bool ReadScalar<bool>(TReader& reader) {
- const auto& scalar = ReadScalar(reader);
- Expect(scalar, EScalarType::Boolean);
- return scalar.AsBoolean();
- }
- // Skip value that was already started with `event`
- void SkipCurrentValue(const TEvent& event, TReader& reader);
- // Skip value that starts at `reader.next_event()`
- void SkipValue(TReader& reader);
- // Skip values with attributes, wait for map value
- void SkipControlRecords(TReader& reader);
- }
- }
|