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