yaml-cpp

FORK: A YAML parser and emitter in C++
git clone https://git.neptards.moe/neptards/yaml-cpp.git
Log | Files | Refs | README | LICENSE

parser.cpp (3020B)


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