aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/yaml-cpp/src/parser.cpp
blob: 1c5ff53c89a5238de2161806f6597d7d7f3a05a1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <cstdio> 
#include <sstream> 
 
#include "directives.h"  // IWYU pragma: keep 
#include "scanner.h"     // IWYU pragma: keep 
#include "singledocparser.h" 
#include "token.h" 
#include "yaml-cpp/exceptions.h"  // IWYU pragma: keep 
#include "yaml-cpp/parser.h" 
 
namespace YAML { 
class EventHandler; 
 
Parser::Parser() {} 
 
Parser::Parser(std::istream& in) { Load(in); } 
 
Parser::~Parser() {} 
 
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(); 
  if (m_pScanner->empty()) {
    return false; 
  }
 
  SingleDocParser sdp(*m_pScanner, *m_pDirectives); 
  sdp.HandleDocument(eventHandler); 
  return true; 
} 
 
void Parser::ParseDirectives() { 
  bool readDirective = false; 
 
  while (1) { 
    if (m_pScanner->empty()) {
      break; 
    }
 
    Token& token = m_pScanner->peek(); 
    if (token.type != Token::DIRECTIVE) {
      break; 
    }
 
    // we keep the directives from the last document if none are specified; 
    // but if any directives are specific, then we reset them 
    if (!readDirective) {
      m_pDirectives.reset(new Directives); 
    }
 
    readDirective = true; 
    HandleDirective(token); 
    m_pScanner->pop(); 
  } 
} 
 
void Parser::HandleDirective(const Token& token) { 
  if (token.value == "YAML") {
    HandleYamlDirective(token); 
  } else if (token.value == "TAG") {
    HandleTagDirective(token); 
  }
} 
 
void Parser::HandleYamlDirective(const Token& token) { 
  if (token.params.size() != 1) {
    throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS); 
  }
 
  if (!m_pDirectives->version.isDefault) {
    throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE); 
  }
 
  std::stringstream str(token.params[0]); 
  str >> m_pDirectives->version.major; 
  str.get(); 
  str >> m_pDirectives->version.minor; 
  if (!str || str.peek() != EOF) {
    throw ParserException( 
        token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]); 
  }
 
  if (m_pDirectives->version.major > 1) {
    throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION); 
  }
 
  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]; 
  if (m_pDirectives->tags.find(handle) != m_pDirectives->tags.end()) {
    throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE); 
  }
 
  m_pDirectives->tags[handle] = prefix; 
} 
 
void Parser::PrintTokens(std::ostream& out) { 
  if (!m_pScanner.get()) {
    return; 
  }
 
  while (1) { 
    if (m_pScanner->empty()) {
      break; 
    }
 
    out << m_pScanner->peek() << "\n"; 
    m_pScanner->pop(); 
  } 
} 
}