diff options
| author | bnagaev <[email protected]> | 2022-02-10 16:47:04 +0300 |
|---|---|---|
| committer | Daniil Cherednik <[email protected]> | 2022-02-10 16:47:04 +0300 |
| commit | c74559fb88da8adac0d9186cfa55a6b13c47695f (patch) | |
| tree | b83306b6e37edeea782e9eed673d89286c4fef35 /contrib/libs/yaml-cpp/src/singledocparser.cpp | |
| parent | d6449ba66291ff0c0d352c82e6eb3efb4c8a7e8d (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.cpp | 824 |
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; +} +} |
