"tests/fixtures/vscode:/vscode.git/clone" did not exist on "d9c449ea30a4a3e8ed73883b45ae07a7177f60a5"
parser.cpp 3.03 KB
Newer Older
Jesse Beder's avatar
Jesse Beder committed
1
2
3
4
#include <cstdio>
#include <sstream>

#include "directives.h"  // IWYU pragma: keep
Jesse Beder's avatar
Jesse Beder committed
5
#include "scanner.h"     // IWYU pragma: keep
6
#include "singledocparser.h"
7
#include "token.h"
Jesse Beder's avatar
Jesse Beder committed
8
9
#include "yaml-cpp/exceptions.h"  // IWYU pragma: keep
#include "yaml-cpp/parser.h"
10

Jesse Beder's avatar
Jesse Beder committed
11
namespace YAML {
Jesse Beder's avatar
Jesse Beder committed
12
13
class EventHandler;

14
Parser::Parser() : m_pScanner{}, m_pDirectives{} {}
Jesse Beder's avatar
Jesse Beder committed
15

16
Parser::Parser(std::istream& in) : Parser() { Load(in); }
Jesse Beder's avatar
Jesse Beder committed
17

18
Parser::~Parser() = default;
Jesse Beder's avatar
Jesse Beder committed
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

Parser::operator bool() const {
  return m_pScanner.get() && !m_pScanner->empty();
}

void Parser::Load(std::istream& in) {
  m_pScanner.reset(new Scanner(in));
  m_pDirectives.reset(new Directives);
}

bool Parser::HandleNextDocument(EventHandler& eventHandler) {
  if (!m_pScanner.get())
    return false;

  ParseDirectives();
34
  if (m_pScanner->empty()) {
Jesse Beder's avatar
Jesse Beder committed
35
    return false;
36
  }
Jesse Beder's avatar
Jesse Beder committed
37
38
39
40
41
42
43
44
45
46

  SingleDocParser sdp(*m_pScanner, *m_pDirectives);
  sdp.HandleDocument(eventHandler);
  return true;
}

void Parser::ParseDirectives() {
  bool readDirective = false;

  while (1) {
47
    if (m_pScanner->empty()) {
Jesse Beder's avatar
Jesse Beder committed
48
      break;
49
    }
Jesse Beder's avatar
Jesse Beder committed
50
51

    Token& token = m_pScanner->peek();
52
    if (token.type != Token::DIRECTIVE) {
Jesse Beder's avatar
Jesse Beder committed
53
      break;
54
    }
Jesse Beder's avatar
Jesse Beder committed
55
56
57

    // we keep the directives from the last document if none are specified;
    // but if any directives are specific, then we reset them
58
    if (!readDirective) {
Jesse Beder's avatar
Jesse Beder committed
59
      m_pDirectives.reset(new Directives);
60
    }
Jesse Beder's avatar
Jesse Beder committed
61
62
63
64
65
66
67
68

    readDirective = true;
    HandleDirective(token);
    m_pScanner->pop();
  }
}

void Parser::HandleDirective(const Token& token) {
69
  if (token.value == "YAML") {
Jesse Beder's avatar
Jesse Beder committed
70
    HandleYamlDirective(token);
71
  } else if (token.value == "TAG") {
Jesse Beder's avatar
Jesse Beder committed
72
    HandleTagDirective(token);
73
  }
Jesse Beder's avatar
Jesse Beder committed
74
75
76
}

void Parser::HandleYamlDirective(const Token& token) {
77
  if (token.params.size() != 1) {
Jesse Beder's avatar
Jesse Beder committed
78
    throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
79
  }
Jesse Beder's avatar
Jesse Beder committed
80

81
  if (!m_pDirectives->version.isDefault) {
Jesse Beder's avatar
Jesse Beder committed
82
    throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
83
  }
Jesse Beder's avatar
Jesse Beder committed
84
85
86
87
88

  std::stringstream str(token.params[0]);
  str >> m_pDirectives->version.major;
  str.get();
  str >> m_pDirectives->version.minor;
89
  if (!str || str.peek() != EOF) {
Jesse Beder's avatar
Jesse Beder committed
90
91
    throw ParserException(
        token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]);
92
  }
Jesse Beder's avatar
Jesse Beder committed
93

94
  if (m_pDirectives->version.major > 1) {
Jesse Beder's avatar
Jesse Beder committed
95
    throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
96
  }
Jesse Beder's avatar
Jesse Beder committed
97
98
99
100
101
102
103
104
105
106
107

  m_pDirectives->version.isDefault = false;
  // TODO: warning on major == 1, minor > 2?
}

void Parser::HandleTagDirective(const Token& token) {
  if (token.params.size() != 2)
    throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);

  const std::string& handle = token.params[0];
  const std::string& prefix = token.params[1];
108
  if (m_pDirectives->tags.find(handle) != m_pDirectives->tags.end()) {
Jesse Beder's avatar
Jesse Beder committed
109
    throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
110
  }
Jesse Beder's avatar
Jesse Beder committed
111
112
113
114
115

  m_pDirectives->tags[handle] = prefix;
}

void Parser::PrintTokens(std::ostream& out) {
116
  if (!m_pScanner.get()) {
Jesse Beder's avatar
Jesse Beder committed
117
    return;
118
  }
Jesse Beder's avatar
Jesse Beder committed
119
120

  while (1) {
121
    if (m_pScanner->empty()) {
Jesse Beder's avatar
Jesse Beder committed
122
      break;
123
    }
Jesse Beder's avatar
Jesse Beder committed
124
125
126
127
128

    out << m_pScanner->peek() << "\n";
    m_pScanner->pop();
  }
}
129
}  // namespace YAML