Moved the simple key validation to before each token scan (plus at newlines of scalars).

This commit is contained in:
Jesse Beder 2008-06-28 16:46:37 +00:00
parent 11706abbb7
commit c63ebbd878
4 changed files with 66 additions and 34 deletions

View file

@ -146,17 +146,6 @@ namespace YAML
m_limboTokens.insert(pToken); m_limboTokens.insert(pToken);
m_tokens.push(ScanToken(pToken)); m_tokens.push(ScanToken(pToken));
m_limboTokens.erase(pToken); m_limboTokens.erase(pToken);
// then remove impossible tokens
std::queue <Token *> temp;
while(!m_tokens.empty()) {
Token *pToken = m_tokens.front();
m_tokens.pop();
if(pToken->isPossible)
temp.push(pToken);
}
m_tokens = temp;
} }
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
@ -171,7 +160,7 @@ namespace YAML
return ScanAndEnqueue(new StreamStartToken); return ScanAndEnqueue(new StreamStartToken);
ScanToNextToken(); ScanToNextToken();
// TODO: remove "obsolete potential simple keys" ValidateSimpleKey();
PopIndentTo(m_column); PopIndentTo(m_column);
if(INPUT.peek() == EOF) if(INPUT.peek() == EOF)
@ -318,23 +307,56 @@ namespace YAML
} }
} }
// GetNextToken
// . Returns the next token on the queue, and scans if only we need to.
Token *Scanner::GetNextToken()
{
while(1) {
Token *pToken = 0;
// is there a token in the queue?
if(!m_tokens.empty())
pToken = m_tokens.front();
// ... that's possible
// (here's where we clean up the impossible tokens)
if(pToken && !pToken->isPossible) {
m_tokens.pop();
delete pToken;
continue;
}
// and valid
if(pToken && !pToken->isValid)
pToken = 0;
// then that's what we want
if(pToken) {
m_tokens.pop();
return pToken;
}
// no token? maybe we've actually finished
if(m_endedStream)
break;
// no? then scan...
ScanNextToken();
}
return 0;
}
// temporary function for testing // temporary function for testing
void Scanner::Scan() void Scanner::Scan()
{ {
while(1) { while(1) {
ScanNextToken(); Token *pToken = GetNextToken();
if(m_tokens.empty()) if(!pToken)
break; break;
while(!m_tokens.empty()) {
Token *pToken = m_tokens.front();
if(!pToken->isValid) // gotta wait on the invalid tokens - they might become valid!
break;
m_tokens.pop();
std::cout << typeid(*pToken).name() << ": " << *pToken << std::endl; std::cout << typeid(*pToken).name() << ": " << *pToken << std::endl;
delete pToken; delete pToken;
} }
} }
}
} }

View file

@ -16,6 +16,8 @@ namespace YAML
Scanner(std::istream& in); Scanner(std::istream& in);
~Scanner(); ~Scanner();
Token *GetNextToken();
void ScanNextToken(); void ScanNextToken();
void ScanToNextToken(); void ScanToNextToken();
Token *PushIndentTo(int column, bool sequence); Token *PushIndentTo(int column, bool sequence);
@ -55,12 +57,12 @@ namespace YAML
}; };
struct SimpleKey { struct SimpleKey {
SimpleKey(int pos_, int line_, int column_); SimpleKey(int pos_, int line_, int column_, int flowLevel_);
void Validate(); void Validate();
void Invalidate(); void Invalidate();
int pos, line, column; int pos, line, column, flowLevel;
bool required; bool required;
Token *pMapStart, *pKey; Token *pMapStart, *pKey;
}; };
@ -81,6 +83,7 @@ namespace YAML
bool m_startedStream, m_endedStream; bool m_startedStream, m_endedStream;
bool m_simpleKeyAllowed; bool m_simpleKeyAllowed;
int m_flowLevel; // number of unclosed '[' and '{' indicators int m_flowLevel; // number of unclosed '[' and '{' indicators
bool m_isLastKeyValid;
std::stack <SimpleKey> m_simpleKeys; std::stack <SimpleKey> m_simpleKeys;
std::stack <int> m_indents; std::stack <int> m_indents;
}; };

View file

@ -99,7 +99,7 @@ namespace YAML
// FlowMapEndToken // FlowMapEndToken
template <> FlowMapEndToken *Scanner::ScanToken(FlowMapEndToken *pToken) template <> FlowMapEndToken *Scanner::ScanToken(FlowMapEndToken *pToken)
{ {
ValidateSimpleKey(); //ValidateSimpleKey();
DecreaseFlowLevel(); DecreaseFlowLevel();
m_simpleKeyAllowed = false; m_simpleKeyAllowed = false;
@ -111,7 +111,7 @@ namespace YAML
// FlowEntryToken // FlowEntryToken
template <> FlowEntryToken *Scanner::ScanToken(FlowEntryToken *pToken) template <> FlowEntryToken *Scanner::ScanToken(FlowEntryToken *pToken)
{ {
ValidateSimpleKey(); //ValidateSimpleKey();
m_simpleKeyAllowed = true; m_simpleKeyAllowed = true;
// eat // eat
@ -122,7 +122,7 @@ namespace YAML
// BlockEntryToken // BlockEntryToken
template <> BlockEntryToken *Scanner::ScanToken(BlockEntryToken *pToken) template <> BlockEntryToken *Scanner::ScanToken(BlockEntryToken *pToken)
{ {
ValidateSimpleKey(); //ValidateSimpleKey();
// we better be in the block context! // we better be in the block context!
if(m_flowLevel == 0) { if(m_flowLevel == 0) {
@ -170,9 +170,9 @@ namespace YAML
template <> ValueToken *Scanner::ScanToken(ValueToken *pToken) template <> ValueToken *Scanner::ScanToken(ValueToken *pToken)
{ {
// does this follow a simple key? // does this follow a simple key?
bool isValidKey = ValidateSimpleKey(); // bool isValidKey = ValidateSimpleKey();
if(isValidKey) { if(m_isLastKeyValid) {
// can't follow a simple key with another simple key (dunno why, though - it seems fine) // can't follow a simple key with another simple key (dunno why, though - it seems fine)
m_simpleKeyAllowed = false; m_simpleKeyAllowed = false;
} else { } else {

View file

@ -5,8 +5,8 @@
namespace YAML namespace YAML
{ {
Scanner::SimpleKey::SimpleKey(int pos_, int line_, int column_) Scanner::SimpleKey::SimpleKey(int pos_, int line_, int column_, int flowLevel_)
: pos(pos_), line(line_), column(column_), required(false), pMapStart(0), pKey(0) : pos(pos_), line(line_), column(column_), flowLevel(flowLevel_), required(false), pMapStart(0), pKey(0)
{ {
} }
@ -34,7 +34,7 @@ namespace YAML
// and saves it on a stack. // and saves it on a stack.
void Scanner::InsertSimpleKey() void Scanner::InsertSimpleKey()
{ {
SimpleKey key(INPUT.tellg(), m_line, m_column); SimpleKey key(INPUT.tellg(), m_line, m_column, m_flowLevel);
// first add a map start, if necessary // first add a map start, if necessary
key.pMapStart = PushIndentTo(m_column, false); key.pMapStart = PushIndentTo(m_column, false);
@ -57,11 +57,17 @@ namespace YAML
// and if so, makes it valid. // and if so, makes it valid.
bool Scanner::ValidateSimpleKey() bool Scanner::ValidateSimpleKey()
{ {
m_isLastKeyValid = false;
if(m_simpleKeys.empty()) if(m_simpleKeys.empty())
return false; return m_isLastKeyValid;
// grab top key // grab top key
SimpleKey key = m_simpleKeys.top(); SimpleKey key = m_simpleKeys.top();
// only validate if we're in the correct flow level
if(key.flowLevel != m_flowLevel)
return false;
m_simpleKeys.pop(); m_simpleKeys.pop();
bool isValid = true; bool isValid = true;
@ -89,6 +95,7 @@ namespace YAML
if(!isValid && m_flowLevel == 0) if(!isValid && m_flowLevel == 0)
m_indents.pop(); m_indents.pop();
m_isLastKeyValid = isValid;
return isValid; return isValid;
} }