summaryrefslogtreecommitdiffstats
path: root/contrib/libs/yaml-cpp/src/singledocparser.cpp
diff options
context:
space:
mode:
authorbnagaev <[email protected]>2022-02-10 16:47:04 +0300
committerDaniil Cherednik <[email protected]>2022-02-10 16:47:04 +0300
commitc74559fb88da8adac0d9186cfa55a6b13c47695f (patch)
treeb83306b6e37edeea782e9eed673d89286c4fef35 /contrib/libs/yaml-cpp/src/singledocparser.cpp
parentd6449ba66291ff0c0d352c82e6eb3efb4c8a7e8d (diff)
Restoring authorship annotation for <[email protected]>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/yaml-cpp/src/singledocparser.cpp')
-rw-r--r--contrib/libs/yaml-cpp/src/singledocparser.cpp824
1 files changed, 412 insertions, 412 deletions
diff --git a/contrib/libs/yaml-cpp/src/singledocparser.cpp b/contrib/libs/yaml-cpp/src/singledocparser.cpp
index bf13a4b433e..a27c1c3b04d 100644
--- a/contrib/libs/yaml-cpp/src/singledocparser.cpp
+++ b/contrib/libs/yaml-cpp/src/singledocparser.cpp
@@ -1,414 +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 <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();
-
+
+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;
-}
-}
+ 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;
+}
+}