yaml-cpp/src/parser.cpp

122 lines
3.0 KiB
C++
Raw Normal View History

2014-03-23 07:46:04 +04:00
#include <cstdio>
#include <sstream>
#include "directives.h" // IWYU pragma: keep
2014-03-24 05:08:54 +04:00
#include "scanner.h" // IWYU pragma: keep
#include "singledocparser.h"
#include "token.h"
2014-03-23 07:46:04 +04:00
#include "yaml-cpp/exceptions.h" // IWYU pragma: keep
#include "yaml-cpp/parser.h"
2014-03-22 21:49:16 +04:00
namespace YAML {
2014-03-23 07:46:04 +04:00
class EventHandler;
Parser::Parser() : m_pScanner{}, m_pDirectives{} {}
2014-03-22 21:49:16 +04:00
Parser::Parser(std::istream& in) : Parser() { Load(in); }
2014-03-22 21:49:16 +04:00
Parser::~Parser() = default;
2014-03-22 21:49:16 +04:00
Parser::operator bool() const {
return m_pScanner && !m_pScanner->empty();
2014-03-22 21:49:16 +04:00
}
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)
2014-03-22 21:49:16 +04:00
return false;
ParseDirectives();
2016-05-13 07:13:55 +03:00
if (m_pScanner->empty()) {
2014-03-22 21:49:16 +04:00
return false;
2016-05-13 07:13:55 +03:00
}
2014-03-22 21:49:16 +04:00
SingleDocParser sdp(*m_pScanner, *m_pDirectives);
sdp.HandleDocument(eventHandler);
return true;
}
void Parser::ParseDirectives() {
bool readDirective = false;
while (!m_pScanner->empty()) {
2014-03-22 21:49:16 +04:00
Token& token = m_pScanner->peek();
2016-05-13 07:13:55 +03:00
if (token.type != Token::DIRECTIVE) {
2014-03-22 21:49:16 +04:00
break;
2016-05-13 07:13:55 +03:00
}
2014-03-22 21:49:16 +04:00
// we keep the directives from the last document if none are specified;
// but if any directives are specific, then we reset them
2016-05-13 07:13:55 +03:00
if (!readDirective) {
2014-03-22 21:49:16 +04:00
m_pDirectives.reset(new Directives);
2016-05-13 07:13:55 +03:00
}
2014-03-22 21:49:16 +04:00
readDirective = true;
HandleDirective(token);
m_pScanner->pop();
}
}
void Parser::HandleDirective(const Token& token) {
2016-05-13 07:13:55 +03:00
if (token.value == "YAML") {
2014-03-22 21:49:16 +04:00
HandleYamlDirective(token);
2016-05-13 07:13:55 +03:00
} else if (token.value == "TAG") {
2014-03-22 21:49:16 +04:00
HandleTagDirective(token);
2016-05-13 07:13:55 +03:00
}
2014-03-22 21:49:16 +04:00
}
void Parser::HandleYamlDirective(const Token& token) {
2016-05-13 07:13:55 +03:00
if (token.params.size() != 1) {
2014-03-22 21:49:16 +04:00
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
2016-05-13 07:13:55 +03:00
}
2014-03-22 21:49:16 +04:00
2016-05-13 07:13:55 +03:00
if (!m_pDirectives->version.isDefault) {
2014-03-22 21:49:16 +04:00
throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
2016-05-13 07:13:55 +03:00
}
2014-03-22 21:49:16 +04:00
std::stringstream str(token.params[0]);
str >> m_pDirectives->version.major;
str.get();
str >> m_pDirectives->version.minor;
2016-05-13 07:13:55 +03:00
if (!str || str.peek() != EOF) {
2014-03-22 21:49:16 +04:00
throw ParserException(
token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]);
2016-05-13 07:13:55 +03:00
}
2014-03-22 21:49:16 +04:00
2016-05-13 07:13:55 +03:00
if (m_pDirectives->version.major > 1) {
2014-03-22 21:49:16 +04:00
throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
2016-05-13 07:13:55 +03:00
}
2014-03-22 21:49:16 +04:00
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];
2016-05-13 07:13:55 +03:00
if (m_pDirectives->tags.find(handle) != m_pDirectives->tags.end()) {
2014-03-22 21:49:16 +04:00
throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
2016-05-13 07:13:55 +03:00
}
2014-03-22 21:49:16 +04:00
m_pDirectives->tags[handle] = prefix;
}
void Parser::PrintTokens(std::ostream& out) {
if (!m_pScanner) {
2014-03-22 21:49:16 +04:00
return;
2016-05-13 07:13:55 +03:00
}
2014-03-22 21:49:16 +04:00
while (!m_pScanner->empty()) {
2014-03-22 21:49:16 +04:00
out << m_pScanner->peek() << "\n";
m_pScanner->pop();
}
}
} // namespace YAML