From 8c9c9d90da4533a4336b80e41a54195fa45fcc98 Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Thu, 29 Oct 2009 19:41:46 +0000 Subject: [PATCH] Added ability to read compact maps in a flow sequence --- src/map.cpp | 30 ++++++++++++++++++++++++++++++ src/map.h | 1 + src/node.cpp | 1 + src/scanner.cpp | 24 +++++++++++++++++------- src/scanner.h | 2 ++ src/scantoken.cpp | 18 +++++++++++++----- src/simplekey.cpp | 16 +++++++++------- src/token.h | 2 ++ 8 files changed, 75 insertions(+), 19 deletions(-) diff --git a/src/map.cpp b/src/map.cpp index 4607966..7159d42 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -65,6 +65,7 @@ namespace YAML switch(pScanner->peek().type) { case Token::BLOCK_MAP_START: ParseBlock(pScanner, state); break; case Token::FLOW_MAP_START: ParseFlow(pScanner, state); break; + case Token::FLOW_MAP_COMPACT: ParseCompact(pScanner, state); break; default: break; } } @@ -148,6 +149,35 @@ namespace YAML } } + // ParseCompact + // . Single key: value pair in a flow sequence + void Map::ParseCompact(Scanner *pScanner, const ParserState& state) + { + // eat start token + pScanner->pop(); + + if(pScanner->empty()) + throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW); + + Token& token = pScanner->peek(); + std::auto_ptr pKey(new Node), pValue(new Node); + + // grab key (if non-null) + if(token.type == Token::KEY) { + pScanner->pop(); + pKey->Parse(pScanner, state); + } + + // now grab value (optional) + if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) { + pScanner->pop(); + pValue->Parse(pScanner, state); + } + + // assign the map with the actual pointers + m_data[pKey.release()] = pValue.release(); + } + void Map::Write(Emitter& out) const { out << BeginMap; diff --git a/src/map.h b/src/map.h index 8cb67cb..c92b05f 100644 --- a/src/map.h +++ b/src/map.h @@ -41,6 +41,7 @@ namespace YAML private: void ParseBlock(Scanner *pScanner, const ParserState& state); void ParseFlow(Scanner *pScanner, const ParserState& state); + void ParseCompact(Scanner *pScanner, const ParserState& state); private: node_map m_data; diff --git a/src/node.cpp b/src/node.cpp index 178377f..f2fa118 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -97,6 +97,7 @@ namespace YAML break; case Token::FLOW_MAP_START: case Token::BLOCK_MAP_START: + case Token::FLOW_MAP_COMPACT: m_pContent = new Map; break; default: diff --git a/src/scanner.cpp b/src/scanner.cpp index 877c404..81900d0 100644 --- a/src/scanner.cpp +++ b/src/scanner.cpp @@ -253,6 +253,22 @@ namespace YAML m_endedStream = true; } + Token *Scanner::PushToken(Token::TYPE type) + { + m_tokens.push(Token(type, INPUT.mark())); + return &m_tokens.back(); + } + + Token::TYPE Scanner::GetStartTokenFor(IndentMarker::INDENT_TYPE type) const + { + switch(type) { + case IndentMarker::SEQ: return Token::BLOCK_SEQ_START; + case IndentMarker::MAP: return Token::BLOCK_MAP_START; + case IndentMarker::NONE: assert(false); break; + } + assert(false); + } + // PushIndentTo // . Pushes an indentation onto the stack, and enqueues the // proper token (sequence start or mapping start). @@ -274,13 +290,7 @@ namespace YAML return 0; // push a start token - if(type == IndentMarker::SEQ) - m_tokens.push(Token(Token::BLOCK_SEQ_START, INPUT.mark())); - else if(type == IndentMarker::MAP) - m_tokens.push(Token(Token::BLOCK_MAP_START, INPUT.mark())); - else - assert(false); - indent.pStartToken = &m_tokens.back(); + indent.pStartToken = PushToken(GetStartTokenFor(type)); // and then the indent m_indents.push(&indent); diff --git a/src/scanner.h b/src/scanner.h index ddae0de..a0ac7ee 100644 --- a/src/scanner.h +++ b/src/scanner.h @@ -54,11 +54,13 @@ namespace YAML void ScanToNextToken(); void StartStream(); void EndStream(); + Token *PushToken(Token::TYPE type); bool InFlowContext() const { return !m_flows.empty(); } bool InBlockContext() const { return m_flows.empty(); } int GetFlowLevel() const { return m_flows.size(); } + Token::TYPE GetStartTokenFor(IndentMarker::INDENT_TYPE type) const; IndentMarker *PushIndentTo(int column, IndentMarker::INDENT_TYPE type); void PopIndentToHere(); void PopAllIndents(); diff --git a/src/scantoken.cpp b/src/scantoken.cpp index c1551ac..b026356 100644 --- a/src/scantoken.cpp +++ b/src/scantoken.cpp @@ -103,8 +103,12 @@ namespace YAML throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END); // we might have a solo entry in the flow context - if(VerifySimpleKey()) - m_tokens.push(Token(Token::VALUE, INPUT.mark())); + if(InFlowContext()) { + if(m_flows.top() == FLOW_MAP && VerifySimpleKey()) + m_tokens.push(Token(Token::VALUE, INPUT.mark())); + else if(m_flows.top() == FLOW_SEQ) + InvalidateSimpleKey(); + } m_simpleKeyAllowed = false; @@ -125,9 +129,13 @@ namespace YAML // FlowEntry void Scanner::ScanFlowEntry() { - // we might have a solo entry in the flow context - if(VerifySimpleKey()) - m_tokens.push(Token(Token::VALUE, INPUT.mark())); + // we might have a solo entry in the flow context + if(InFlowContext()) { + if(m_flows.top() == FLOW_MAP && VerifySimpleKey()) + m_tokens.push(Token(Token::VALUE, INPUT.mark())); + else if(m_flows.top() == FLOW_SEQ) + InvalidateSimpleKey(); + } m_simpleKeyAllowed = true; diff --git a/src/simplekey.cpp b/src/simplekey.cpp index f99cea6..fe308ed 100644 --- a/src/simplekey.cpp +++ b/src/simplekey.cpp @@ -38,9 +38,6 @@ namespace YAML { if(!m_simpleKeyAllowed) return false; - - if(InFlowContext() && m_flows.top() != FLOW_MAP) - return false; return !ExistsActiveSimpleKey(); } @@ -68,10 +65,15 @@ namespace YAML SimpleKey key(INPUT.mark(), GetFlowLevel()); // first add a map start, if necessary - key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP); - if(key.pIndent) { - key.pIndent->status = IndentMarker::UNKNOWN; - key.pMapStart = key.pIndent->pStartToken; + if(InBlockContext()) { + key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP); + if(key.pIndent) { + key.pIndent->status = IndentMarker::UNKNOWN; + key.pMapStart = key.pIndent->pStartToken; + key.pMapStart->status = Token::UNVERIFIED; + } + } else if(m_flows.top() == FLOW_SEQ) { + key.pMapStart = PushToken(Token::FLOW_MAP_COMPACT); key.pMapStart->status = Token::UNVERIFIED; } diff --git a/src/token.h b/src/token.h index ff1a457..cf7c0fe 100644 --- a/src/token.h +++ b/src/token.h @@ -24,6 +24,7 @@ namespace YAML "FLOW_MAP_START", "FLOW_SEQ_END", "FLOW_MAP_END", + "FLOW_MAP_COMPACT", "FLOW_ENTRY", "KEY", "VALUE", @@ -49,6 +50,7 @@ namespace YAML FLOW_MAP_START, FLOW_SEQ_END, FLOW_MAP_END, + FLOW_MAP_COMPACT, FLOW_ENTRY, KEY, VALUE,