aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/3rdparty/yaml-cpp/src/singledocparser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/3rdparty/yaml-cpp/src/singledocparser.cpp')
-rw-r--r--src/libs/3rdparty/yaml-cpp/src/singledocparser.cpp414
1 files changed, 414 insertions, 0 deletions
diff --git a/src/libs/3rdparty/yaml-cpp/src/singledocparser.cpp b/src/libs/3rdparty/yaml-cpp/src/singledocparser.cpp
new file mode 100644
index 00000000000..a27c1c3b04d
--- /dev/null
+++ b/src/libs/3rdparty/yaml-cpp/src/singledocparser.cpp
@@ -0,0 +1,414 @@
+#include <algorithm>
+#include <cstdio>
+#include <sstream>
+
+#include "collectionstack.h" // IWYU pragma: keep
+#include "scanner.h"
+#include "singledocparser.h"
+#include "tag.h"
+#include "token.h"
+#include "yaml-cpp/emitterstyle.h"
+#include "yaml-cpp/eventhandler.h"
+#include "yaml-cpp/exceptions.h" // IWYU pragma: keep
+#include "yaml-cpp/mark.h"
+#include "yaml-cpp/null.h"
+
+namespace YAML {
+SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives)
+ : m_scanner(scanner),
+ m_directives(directives),
+ m_pCollectionStack(new CollectionStack),
+ m_curAnchor(0) {}
+
+SingleDocParser::~SingleDocParser() {}
+
+// HandleDocument
+// . Handles the next document
+// . Throws a ParserException on error.
+void SingleDocParser::HandleDocument(EventHandler& eventHandler) {
+ assert(!m_scanner.empty()); // guaranteed that there are tokens
+ assert(!m_curAnchor);
+
+ eventHandler.OnDocumentStart(m_scanner.peek().mark);
+
+ // eat doc start
+ if (m_scanner.peek().type == Token::DOC_START)
+ m_scanner.pop();
+
+ // recurse!
+ HandleNode(eventHandler);
+
+ eventHandler.OnDocumentEnd();
+
+ // and finally eat any doc ends we see
+ while (!m_scanner.empty() && m_scanner.peek().type == Token::DOC_END)
+ m_scanner.pop();
+}
+
+void SingleDocParser::HandleNode(EventHandler& eventHandler) {
+ // an empty node *is* a possibility
+ if (m_scanner.empty()) {
+ eventHandler.OnNull(m_scanner.mark(), NullAnchor);
+ return;
+ }
+
+ // save location
+ Mark mark = m_scanner.peek().mark;
+
+ // special case: a value node by itself must be a map, with no header
+ if (m_scanner.peek().type == Token::VALUE) {
+ eventHandler.OnMapStart(mark, "?", NullAnchor, EmitterStyle::Default);
+ HandleMap(eventHandler);
+ eventHandler.OnMapEnd();
+ return;
+ }
+
+ // special case: an alias node
+ if (m_scanner.peek().type == Token::ALIAS) {
+ eventHandler.OnAlias(mark, LookupAnchor(mark, m_scanner.peek().value));
+ m_scanner.pop();
+ return;
+ }
+
+ std::string tag;
+ anchor_t anchor;
+ ParseProperties(tag, anchor);
+
+ const Token& token = m_scanner.peek();
+
+ if (token.type == Token::PLAIN_SCALAR && IsNullString(token.value)) {
+ eventHandler.OnNull(mark, anchor);
+ m_scanner.pop();
+ return;
+ }
+
+ // add non-specific tags
+ if (tag.empty())
+ tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
+
+ // now split based on what kind of node we should be
+ switch (token.type) {
+ case Token::PLAIN_SCALAR:
+ case Token::NON_PLAIN_SCALAR:
+ eventHandler.OnScalar(mark, tag, anchor, token.value);
+ m_scanner.pop();
+ return;
+ case Token::FLOW_SEQ_START:
+ eventHandler.OnSequenceStart(mark, tag, anchor, EmitterStyle::Flow);
+ HandleSequence(eventHandler);
+ eventHandler.OnSequenceEnd();
+ return;
+ case Token::BLOCK_SEQ_START:
+ eventHandler.OnSequenceStart(mark, tag, anchor, EmitterStyle::Block);
+ HandleSequence(eventHandler);
+ eventHandler.OnSequenceEnd();
+ return;
+ case Token::FLOW_MAP_START:
+ eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Flow);
+ HandleMap(eventHandler);
+ eventHandler.OnMapEnd();
+ return;
+ case Token::BLOCK_MAP_START:
+ eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Block);
+ HandleMap(eventHandler);
+ eventHandler.OnMapEnd();
+ return;
+ case Token::KEY:
+ // compact maps can only go in a flow sequence
+ if (m_pCollectionStack->GetCurCollectionType() ==
+ CollectionType::FlowSeq) {
+ eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Flow);
+ HandleMap(eventHandler);
+ eventHandler.OnMapEnd();
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (tag == "?")
+ eventHandler.OnNull(mark, anchor);
+ else
+ eventHandler.OnScalar(mark, tag, anchor, "");
+}
+
+void SingleDocParser::HandleSequence(EventHandler& eventHandler) {
+ // split based on start token
+ switch (m_scanner.peek().type) {
+ case Token::BLOCK_SEQ_START:
+ HandleBlockSequence(eventHandler);
+ break;
+ case Token::FLOW_SEQ_START:
+ HandleFlowSequence(eventHandler);
+ break;
+ default:
+ break;
+ }
+}
+
+void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler) {
+ // eat start token
+ m_scanner.pop();
+ m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq);
+
+ while (1) {
+ if (m_scanner.empty())
+ throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ);
+
+ Token token = m_scanner.peek();
+ if (token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
+ throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);
+
+ m_scanner.pop();
+ if (token.type == Token::BLOCK_SEQ_END)
+ break;
+
+ // check for null
+ if (!m_scanner.empty()) {
+ const Token& token = m_scanner.peek();
+ if (token.type == Token::BLOCK_ENTRY ||
+ token.type == Token::BLOCK_SEQ_END) {
+ eventHandler.OnNull(token.mark, NullAnchor);
+ continue;
+ }
+ }
+
+ HandleNode(eventHandler);
+ }
+
+ m_pCollectionStack->PopCollectionType(CollectionType::BlockSeq);
+}
+
+void SingleDocParser::HandleFlowSequence(EventHandler& eventHandler) {
+ // eat start token
+ m_scanner.pop();
+ m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq);
+
+ while (1) {
+ if (m_scanner.empty())
+ throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
+
+ // first check for end
+ if (m_scanner.peek().type == Token::FLOW_SEQ_END) {
+ m_scanner.pop();
+ break;
+ }
+
+ // then read the node
+ HandleNode(eventHandler);
+
+ if (m_scanner.empty())
+ throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
+
+ // now eat the separator (or could be a sequence end, which we ignore - but
+ // if it's neither, then it's a bad node)
+ Token& token = m_scanner.peek();
+ if (token.type == Token::FLOW_ENTRY)
+ m_scanner.pop();
+ else if (token.type != Token::FLOW_SEQ_END)
+ throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
+ }
+
+ m_pCollectionStack->PopCollectionType(CollectionType::FlowSeq);
+}
+
+void SingleDocParser::HandleMap(EventHandler& eventHandler) {
+ // split based on start token
+ switch (m_scanner.peek().type) {
+ case Token::BLOCK_MAP_START:
+ HandleBlockMap(eventHandler);
+ break;
+ case Token::FLOW_MAP_START:
+ HandleFlowMap(eventHandler);
+ break;
+ case Token::KEY:
+ HandleCompactMap(eventHandler);
+ break;
+ case Token::VALUE:
+ HandleCompactMapWithNoKey(eventHandler);
+ break;
+ default:
+ break;
+ }
+}
+
+void SingleDocParser::HandleBlockMap(EventHandler& eventHandler) {
+ // eat start token
+ m_scanner.pop();
+ m_pCollectionStack->PushCollectionType(CollectionType::BlockMap);
+
+ while (1) {
+ if (m_scanner.empty())
+ throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP);
+
+ Token token = m_scanner.peek();
+ if (token.type != Token::KEY && token.type != Token::VALUE &&
+ token.type != Token::BLOCK_MAP_END)
+ throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
+
+ if (token.type == Token::BLOCK_MAP_END) {
+ m_scanner.pop();
+ break;
+ }
+
+ // grab key (if non-null)
+ if (token.type == Token::KEY) {
+ m_scanner.pop();
+ HandleNode(eventHandler);
+ } else {
+ eventHandler.OnNull(token.mark, NullAnchor);
+ }
+
+ // now grab value (optional)
+ if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
+ m_scanner.pop();
+ HandleNode(eventHandler);
+ } else {
+ eventHandler.OnNull(token.mark, NullAnchor);
+ }
+ }
+
+ m_pCollectionStack->PopCollectionType(CollectionType::BlockMap);
+}
+
+void SingleDocParser::HandleFlowMap(EventHandler& eventHandler) {
+ // eat start token
+ m_scanner.pop();
+ m_pCollectionStack->PushCollectionType(CollectionType::FlowMap);
+
+ while (1) {
+ if (m_scanner.empty())
+ throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
+
+ Token& token = m_scanner.peek();
+ const Mark mark = token.mark;
+ // first check for end
+ if (token.type == Token::FLOW_MAP_END) {
+ m_scanner.pop();
+ break;
+ }
+
+ // grab key (if non-null)
+ if (token.type == Token::KEY) {
+ m_scanner.pop();
+ HandleNode(eventHandler);
+ } else {
+ eventHandler.OnNull(mark, NullAnchor);
+ }
+
+ // now grab value (optional)
+ if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
+ m_scanner.pop();
+ HandleNode(eventHandler);
+ } else {
+ eventHandler.OnNull(mark, NullAnchor);
+ }
+
+ if (m_scanner.empty())
+ throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
+
+ // now eat the separator (or could be a map end, which we ignore - but if
+ // it's neither, then it's a bad node)
+ Token& nextToken = m_scanner.peek();
+ if (nextToken.type == Token::FLOW_ENTRY)
+ m_scanner.pop();
+ else if (nextToken.type != Token::FLOW_MAP_END)
+ throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
+ }
+
+ m_pCollectionStack->PopCollectionType(CollectionType::FlowMap);
+}
+
+// . Single "key: value" pair in a flow sequence
+void SingleDocParser::HandleCompactMap(EventHandler& eventHandler) {
+ m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
+
+ // grab key
+ Mark mark = m_scanner.peek().mark;
+ m_scanner.pop();
+ HandleNode(eventHandler);
+
+ // now grab value (optional)
+ if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
+ m_scanner.pop();
+ HandleNode(eventHandler);
+ } else {
+ eventHandler.OnNull(mark, NullAnchor);
+ }
+
+ m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
+}
+
+// . Single ": value" pair in a flow sequence
+void SingleDocParser::HandleCompactMapWithNoKey(EventHandler& eventHandler) {
+ m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
+
+ // null key
+ eventHandler.OnNull(m_scanner.peek().mark, NullAnchor);
+
+ // grab value
+ m_scanner.pop();
+ HandleNode(eventHandler);
+
+ m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
+}
+
+// ParseProperties
+// . Grabs any tag or anchor tokens and deals with them.
+void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor) {
+ tag.clear();
+ anchor = NullAnchor;
+
+ while (1) {
+ if (m_scanner.empty())
+ return;
+
+ switch (m_scanner.peek().type) {
+ case Token::TAG:
+ ParseTag(tag);
+ break;
+ case Token::ANCHOR:
+ ParseAnchor(anchor);
+ break;
+ default:
+ return;
+ }
+ }
+}
+
+void SingleDocParser::ParseTag(std::string& tag) {
+ Token& token = m_scanner.peek();
+ if (!tag.empty())
+ throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
+
+ Tag tagInfo(token);
+ tag = tagInfo.Translate(m_directives);
+ m_scanner.pop();
+}
+
+void SingleDocParser::ParseAnchor(anchor_t& anchor) {
+ Token& token = m_scanner.peek();
+ if (anchor)
+ throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
+
+ anchor = RegisterAnchor(token.value);
+ m_scanner.pop();
+}
+
+anchor_t SingleDocParser::RegisterAnchor(const std::string& name) {
+ if (name.empty())
+ return NullAnchor;
+
+ return m_anchors[name] = ++m_curAnchor;
+}
+
+anchor_t SingleDocParser::LookupAnchor(const Mark& mark,
+ const std::string& name) const {
+ Anchors::const_iterator it = m_anchors.find(name);
+ if (it == m_anchors.end())
+ throw ParserException(mark, ErrorMsg::UNKNOWN_ANCHOR);
+
+ return it->second;
+}
+}