mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 12:41:17 +00:00
Added ability to read compact maps in a flow sequence
This commit is contained in:
30
src/map.cpp
30
src/map.cpp
@@ -65,6 +65,7 @@ namespace YAML
|
|||||||
switch(pScanner->peek().type) {
|
switch(pScanner->peek().type) {
|
||||||
case Token::BLOCK_MAP_START: ParseBlock(pScanner, state); break;
|
case Token::BLOCK_MAP_START: ParseBlock(pScanner, state); break;
|
||||||
case Token::FLOW_MAP_START: ParseFlow(pScanner, state); break;
|
case Token::FLOW_MAP_START: ParseFlow(pScanner, state); break;
|
||||||
|
case Token::FLOW_MAP_COMPACT: ParseCompact(pScanner, state); break;
|
||||||
default: 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 <Node> 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
|
void Map::Write(Emitter& out) const
|
||||||
{
|
{
|
||||||
out << BeginMap;
|
out << BeginMap;
|
||||||
|
@@ -41,6 +41,7 @@ namespace YAML
|
|||||||
private:
|
private:
|
||||||
void ParseBlock(Scanner *pScanner, const ParserState& state);
|
void ParseBlock(Scanner *pScanner, const ParserState& state);
|
||||||
void ParseFlow(Scanner *pScanner, const ParserState& state);
|
void ParseFlow(Scanner *pScanner, const ParserState& state);
|
||||||
|
void ParseCompact(Scanner *pScanner, const ParserState& state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
node_map m_data;
|
node_map m_data;
|
||||||
|
@@ -97,6 +97,7 @@ namespace YAML
|
|||||||
break;
|
break;
|
||||||
case Token::FLOW_MAP_START:
|
case Token::FLOW_MAP_START:
|
||||||
case Token::BLOCK_MAP_START:
|
case Token::BLOCK_MAP_START:
|
||||||
|
case Token::FLOW_MAP_COMPACT:
|
||||||
m_pContent = new Map;
|
m_pContent = new Map;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@@ -253,6 +253,22 @@ namespace YAML
|
|||||||
m_endedStream = true;
|
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
|
// PushIndentTo
|
||||||
// . Pushes an indentation onto the stack, and enqueues the
|
// . Pushes an indentation onto the stack, and enqueues the
|
||||||
// proper token (sequence start or mapping start).
|
// proper token (sequence start or mapping start).
|
||||||
@@ -274,13 +290,7 @@ namespace YAML
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// push a start token
|
// push a start token
|
||||||
if(type == IndentMarker::SEQ)
|
indent.pStartToken = PushToken(GetStartTokenFor(type));
|
||||||
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();
|
|
||||||
|
|
||||||
// and then the indent
|
// and then the indent
|
||||||
m_indents.push(&indent);
|
m_indents.push(&indent);
|
||||||
|
@@ -54,11 +54,13 @@ namespace YAML
|
|||||||
void ScanToNextToken();
|
void ScanToNextToken();
|
||||||
void StartStream();
|
void StartStream();
|
||||||
void EndStream();
|
void EndStream();
|
||||||
|
Token *PushToken(Token::TYPE type);
|
||||||
|
|
||||||
bool InFlowContext() const { return !m_flows.empty(); }
|
bool InFlowContext() const { return !m_flows.empty(); }
|
||||||
bool InBlockContext() const { return m_flows.empty(); }
|
bool InBlockContext() const { return m_flows.empty(); }
|
||||||
int GetFlowLevel() const { return m_flows.size(); }
|
int GetFlowLevel() const { return m_flows.size(); }
|
||||||
|
|
||||||
|
Token::TYPE GetStartTokenFor(IndentMarker::INDENT_TYPE type) const;
|
||||||
IndentMarker *PushIndentTo(int column, IndentMarker::INDENT_TYPE type);
|
IndentMarker *PushIndentTo(int column, IndentMarker::INDENT_TYPE type);
|
||||||
void PopIndentToHere();
|
void PopIndentToHere();
|
||||||
void PopAllIndents();
|
void PopAllIndents();
|
||||||
|
@@ -103,8 +103,12 @@ namespace YAML
|
|||||||
throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END);
|
throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END);
|
||||||
|
|
||||||
// we might have a solo entry in the flow context
|
// we might have a solo entry in the flow context
|
||||||
if(VerifySimpleKey())
|
if(InFlowContext()) {
|
||||||
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
|
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;
|
m_simpleKeyAllowed = false;
|
||||||
|
|
||||||
@@ -125,9 +129,13 @@ namespace YAML
|
|||||||
// FlowEntry
|
// FlowEntry
|
||||||
void Scanner::ScanFlowEntry()
|
void Scanner::ScanFlowEntry()
|
||||||
{
|
{
|
||||||
// we might have a solo entry in the flow context
|
// we might have a solo entry in the flow context
|
||||||
if(VerifySimpleKey())
|
if(InFlowContext()) {
|
||||||
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
|
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;
|
m_simpleKeyAllowed = true;
|
||||||
|
|
||||||
|
@@ -38,9 +38,6 @@ namespace YAML
|
|||||||
{
|
{
|
||||||
if(!m_simpleKeyAllowed)
|
if(!m_simpleKeyAllowed)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(InFlowContext() && m_flows.top() != FLOW_MAP)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return !ExistsActiveSimpleKey();
|
return !ExistsActiveSimpleKey();
|
||||||
}
|
}
|
||||||
@@ -68,10 +65,15 @@ namespace YAML
|
|||||||
SimpleKey key(INPUT.mark(), GetFlowLevel());
|
SimpleKey key(INPUT.mark(), GetFlowLevel());
|
||||||
|
|
||||||
// first add a map start, if necessary
|
// first add a map start, if necessary
|
||||||
key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
|
if(InBlockContext()) {
|
||||||
if(key.pIndent) {
|
key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
|
||||||
key.pIndent->status = IndentMarker::UNKNOWN;
|
if(key.pIndent) {
|
||||||
key.pMapStart = key.pIndent->pStartToken;
|
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;
|
key.pMapStart->status = Token::UNVERIFIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,6 +24,7 @@ namespace YAML
|
|||||||
"FLOW_MAP_START",
|
"FLOW_MAP_START",
|
||||||
"FLOW_SEQ_END",
|
"FLOW_SEQ_END",
|
||||||
"FLOW_MAP_END",
|
"FLOW_MAP_END",
|
||||||
|
"FLOW_MAP_COMPACT",
|
||||||
"FLOW_ENTRY",
|
"FLOW_ENTRY",
|
||||||
"KEY",
|
"KEY",
|
||||||
"VALUE",
|
"VALUE",
|
||||||
@@ -49,6 +50,7 @@ namespace YAML
|
|||||||
FLOW_MAP_START,
|
FLOW_MAP_START,
|
||||||
FLOW_SEQ_END,
|
FLOW_SEQ_END,
|
||||||
FLOW_MAP_END,
|
FLOW_MAP_END,
|
||||||
|
FLOW_MAP_COMPACT,
|
||||||
FLOW_ENTRY,
|
FLOW_ENTRY,
|
||||||
KEY,
|
KEY,
|
||||||
VALUE,
|
VALUE,
|
||||||
|
Reference in New Issue
Block a user