Added ability to read compact maps in a flow sequence

This commit is contained in:
jbeder
2009-10-29 19:41:46 +00:00
parent cccbddb54c
commit 72413bafd4
8 changed files with 75 additions and 19 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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:

View File

@@ -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);

View File

@@ -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();

View File

@@ -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()) {
if(m_flows.top() == FLOW_MAP && VerifySimpleKey())
m_tokens.push(Token(Token::VALUE, INPUT.mark())); m_tokens.push(Token(Token::VALUE, INPUT.mark()));
else if(m_flows.top() == FLOW_SEQ)
InvalidateSimpleKey();
}
m_simpleKeyAllowed = false; m_simpleKeyAllowed = false;
@@ -126,8 +130,12 @@ namespace YAML
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()) {
if(m_flows.top() == FLOW_MAP && VerifySimpleKey())
m_tokens.push(Token(Token::VALUE, INPUT.mark())); m_tokens.push(Token(Token::VALUE, INPUT.mark()));
else if(m_flows.top() == FLOW_SEQ)
InvalidateSimpleKey();
}
m_simpleKeyAllowed = true; m_simpleKeyAllowed = true;

View File

@@ -39,9 +39,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,12 +65,17 @@ 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
if(InBlockContext()) {
key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP); key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
if(key.pIndent) { if(key.pIndent) {
key.pIndent->status = IndentMarker::UNKNOWN; key.pIndent->status = IndentMarker::UNKNOWN;
key.pMapStart = key.pIndent->pStartToken; key.pMapStart = key.pIndent->pStartToken;
key.pMapStart->status = Token::UNVERIFIED; key.pMapStart->status = Token::UNVERIFIED;
} }
} else if(m_flows.top() == FLOW_SEQ) {
key.pMapStart = PushToken(Token::FLOW_MAP_COMPACT);
key.pMapStart->status = Token::UNVERIFIED;
}
// then add the (now unverified) key // then add the (now unverified) key
m_tokens.push(Token(Token::KEY, INPUT.mark())); m_tokens.push(Token(Token::KEY, INPUT.mark()));

View File

@@ -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,