mirror of https://github.com/axmolengine/axmol.git
120 lines
2.9 KiB
C++
120 lines
2.9 KiB
C++
#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() : m_pScanner{}, m_pDirectives{} {}
|
|
|
|
Parser::Parser(std::istream& in) : Parser() { Load(in); }
|
|
|
|
Parser::~Parser() = default;
|
|
|
|
Parser::operator bool() const { return m_pScanner && !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)
|
|
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 (!m_pScanner->empty()) {
|
|
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) {
|
|
return;
|
|
}
|
|
|
|
while (!m_pScanner->empty()) {
|
|
out << m_pScanner->peek() << "\n";
|
|
m_pScanner->pop();
|
|
}
|
|
}
|
|
} // namespace YAML
|