Coverage Report

Created: 2026-09-03 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/yaml-cpp/src/parser.cpp
Line
Count
Source
1
#include <cstdio>
2
#include <sstream>
3
4
#include "directives.h"  // IWYU pragma: keep
5
#include "scanner.h"     // IWYU pragma: keep
6
#include "singledocparser.h"
7
#include "token.h"
8
#include "yaml-cpp/exceptions.h"  // IWYU pragma: keep
9
#include "yaml-cpp/parser.h"
10
11
namespace YAML {
12
class EventHandler;
13
14
6.15k
Parser::Parser() : m_pScanner{}, m_pDirectives{} {}
15
16
6.15k
Parser::Parser(std::istream& in) : Parser() { Load(in); }
17
18
6.15k
Parser::~Parser() = default;
19
20
0
Parser::operator bool() const { return m_pScanner && !m_pScanner->empty(); }
21
22
6.15k
void Parser::Load(std::istream& in) {
23
6.15k
  m_pScanner.reset(new Scanner(in));
24
6.15k
  m_pDirectives.reset(new Directives);
25
6.15k
}
26
27
342k
bool Parser::HandleNextDocument(EventHandler& eventHandler) {
28
342k
  if (!m_pScanner)
29
0
    return false;
30
31
342k
  ParseDirectives();
32
342k
  if (m_pScanner->empty()) {
33
2.67k
    return false;
34
2.67k
  }
35
36
340k
  auto oldPos = m_pScanner->peek().mark.pos;
37
38
340k
  SingleDocParser sdp(*m_pScanner, *m_pDirectives);
39
340k
  sdp.HandleDocument(eventHandler);
40
41
  // checks if progress was made
42
  // 1. if scanner has no more tokens, progress was made
43
340k
  if (m_pScanner->empty()) {
44
1.97k
    return true;
45
1.97k
  }
46
47
  // 2. if token position has changed, progress was made
48
338k
  auto newPos = m_pScanner->peek().mark.pos;
49
338k
  if (newPos != oldPos) {
50
334k
    return true;
51
334k
  }
52
  // No progress was made, no further processing
53
3.47k
  return false;
54
338k
}
55
56
342k
void Parser::ParseDirectives() {
57
342k
  bool readDirective = false;
58
59
354k
  while (!m_pScanner->empty()) {
60
350k
    Token& token = m_pScanner->peek();
61
350k
    if (token.type != Token::DIRECTIVE) {
62
339k
      break;
63
339k
    }
64
65
    // we keep the directives from the last document if none are specified;
66
    // but if any directives are specific, then we reset them
67
11.4k
    if (!readDirective) {
68
3.78k
      m_pDirectives.reset(new Directives);
69
3.78k
    }
70
71
11.4k
    readDirective = true;
72
11.4k
    HandleDirective(token);
73
11.4k
    m_pScanner->pop();
74
11.4k
  }
75
342k
}
76
77
11.4k
void Parser::HandleDirective(const Token& token) {
78
11.4k
  if (token.value == "YAML") {
79
1.22k
    HandleYamlDirective(token);
80
10.2k
  } else if (token.value == "TAG") {
81
5.86k
    HandleTagDirective(token);
82
5.86k
  }
83
11.4k
}
84
85
1.22k
void Parser::HandleYamlDirective(const Token& token) {
86
1.22k
  if (token.params.size() != 1) {
87
19
    throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
88
19
  }
89
90
1.20k
  if (!m_pDirectives->version.isDefault) {
91
3
    throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
92
3
  }
93
94
1.20k
  std::stringstream str(token.params[0]);
95
1.20k
  str.imbue(std::locale::classic());
96
1.20k
  str >> m_pDirectives->version.major;
97
1.20k
  str.get();
98
1.20k
  str >> m_pDirectives->version.minor;
99
1.20k
  if (!str || str.peek() != EOF) {
100
27
    throw ParserException(
101
27
        token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]);
102
27
  }
103
104
1.17k
  if (m_pDirectives->version.major > 1) {
105
11
    throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
106
11
  }
107
108
1.16k
  m_pDirectives->version.isDefault = false;
109
  // TODO: warning on major == 1, minor > 2?
110
1.16k
}
111
112
5.86k
void Parser::HandleTagDirective(const Token& token) {
113
5.86k
  if (token.params.size() != 2)
114
25
    throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
115
116
5.83k
  const std::string& handle = token.params[0];
117
5.83k
  const std::string& prefix = token.params[1];
118
5.83k
  if (m_pDirectives->tags.find(handle) != m_pDirectives->tags.end()) {
119
8
    throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
120
8
  }
121
122
5.82k
  m_pDirectives->tags[handle] = prefix;
123
5.82k
}
124
125
0
void Parser::PrintTokens(std::ostream& out) {
126
0
  if (!m_pScanner) {
127
0
    return;
128
0
  }
129
130
0
  while (!m_pScanner->empty()) {
131
0
    out << m_pScanner->peek() << "\n";
132
0
    m_pScanner->pop();
133
0
  }
134
0
}
135
}  // namespace YAML