parser.cpp 3.0 KB

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