Finished refactoring of simple keys so that they can refer to multiple tokens at a single level

This commit is contained in:
Jesse Beder 2009-09-05 03:49:38 +00:00
parent 0e1638d7b5
commit 75477ade65
7 changed files with 126 additions and 44 deletions

View File

@ -46,7 +46,13 @@ namespace YAML
assert(!m_tokens.empty()); // should we be asserting here? I mean, we really just be checking
// if it's empty before peeking.
// std::cerr << "peek: (" << &m_tokens.front() << ") " << m_tokens.front() << "\n";
#if 0
static Token *pLast = 0;
if(pLast != &m_tokens.front())
std::cerr << "peek: " << m_tokens.front() << "\n";
pLast = &m_tokens.front();
#endif
return m_tokens.front();
}
@ -98,9 +104,6 @@ namespace YAML
// maybe need to end some blocks
PopIndentToHere();
// check the latest simple key
VerifySimpleKey();
// *****
// And now branch based on the next few characters!
// *****
@ -187,7 +190,7 @@ namespace YAML
INPUT.eat(n);
// oh yeah, and let's get rid of that simple key
VerifySimpleKey();
InvalidateSimpleKey();
// new line - we may be able to accept a simple key now
if(m_flowLevel == 0)
@ -235,7 +238,7 @@ namespace YAML
INPUT.ResetColumn();
PopAllIndents();
VerifyAllSimpleKeys();
PopAllSimpleKeys();
m_simpleKeyAllowed = false;
m_endedStream = true;
@ -321,8 +324,10 @@ namespace YAML
IndentMarker indent = m_indents.top();
IndentMarker::INDENT_TYPE type = indent.type;
m_indents.pop();
if(!indent.isValid)
if(!indent.isValid) {
InvalidateSimpleKey();
return;
}
if(type == IndentMarker::SEQ)
m_tokens.push(Token(Token::BLOCK_SEQ_END, INPUT.mark()));

View File

@ -58,9 +58,12 @@ namespace YAML
int GetTopIndent() const;
// checking input
void InsertSimpleKey();
bool VerifySimpleKey(bool force = false);
void VerifyAllSimpleKeys();
bool ExistsActiveSimpleKey() const;
void InsertPotentialSimpleKey();
void InvalidateSimpleKey();
bool VerifySimpleKey();
void PopAllSimpleKeys();
void ThrowParserException(const std::string& msg) const;
bool IsWhitespaceToBeEaten(char ch);

View File

@ -20,7 +20,7 @@ namespace YAML
// pop indents and simple keys
PopAllIndents();
VerifyAllSimpleKeys();
PopAllSimpleKeys();
m_simpleKeyAllowed = false;
@ -60,7 +60,7 @@ namespace YAML
void Scanner::ScanDocStart()
{
PopAllIndents();
VerifyAllSimpleKeys();
PopAllSimpleKeys();
m_simpleKeyAllowed = false;
// eat
@ -73,7 +73,7 @@ namespace YAML
void Scanner::ScanDocEnd()
{
PopAllIndents();
VerifyAllSimpleKeys();
PopAllSimpleKeys();
m_simpleKeyAllowed = false;
// eat
@ -86,7 +86,7 @@ namespace YAML
void Scanner::ScanFlowStart()
{
// flows can be simple keys
InsertSimpleKey();
InsertPotentialSimpleKey();
m_flowLevel++;
m_simpleKeyAllowed = true;
@ -103,6 +103,7 @@ namespace YAML
if(m_flowLevel == 0)
throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END);
InvalidateSimpleKey();
m_flowLevel--;
m_simpleKeyAllowed = false;
@ -170,8 +171,13 @@ namespace YAML
// Value
void Scanner::ScanValue()
{
// does this follow a simple key?
if(m_isLastKeyValid) {
// just in case we have an empty key
InsertPotentialSimpleKey();
// and check that simple key
bool isSimpleKey = VerifySimpleKey();
if(isSimpleKey) {
// can't follow a simple key with another simple key (dunno why, though - it seems fine)
m_simpleKeyAllowed = false;
} else {
@ -181,19 +187,10 @@ namespace YAML
throw ParserException(INPUT.mark(), ErrorMsg::MAP_VALUE);
PushIndentTo(INPUT.column(), IndentMarker::MAP);
} else {
// we might have an empty key, so we should add it (as a simple key)
if(m_simpleKeyAllowed) {
InsertSimpleKey();
VerifySimpleKey();
}
}
// can only put a simple key here if we're in block context
if(m_flowLevel == 0)
m_simpleKeyAllowed = true;
else
m_simpleKeyAllowed = false;
m_simpleKeyAllowed = (m_flowLevel == 0);
}
// eat
@ -210,7 +207,7 @@ namespace YAML
// insert a potential simple key
if(m_simpleKeyAllowed)
InsertSimpleKey();
InsertPotentialSimpleKey();
m_simpleKeyAllowed = false;
// eat the indicator
@ -243,7 +240,7 @@ namespace YAML
// insert a potential simple key
if(m_simpleKeyAllowed)
InsertSimpleKey();
InsertPotentialSimpleKey();
m_simpleKeyAllowed = false;
// eat the indicator
@ -293,7 +290,7 @@ namespace YAML
// insert a potential simple key
if(m_simpleKeyAllowed)
InsertSimpleKey();
InsertPotentialSimpleKey();
Mark mark = INPUT.mark();
scalar = ScanScalar(INPUT, params);
@ -333,7 +330,7 @@ namespace YAML
// insert a potential simple key
if(m_simpleKeyAllowed)
InsertSimpleKey();
InsertPotentialSimpleKey();
Mark mark = INPUT.mark();

View File

@ -32,11 +32,26 @@ namespace YAML
pKey->status = Token::INVALID;
}
// InsertSimpleKey
// . Adds a potential simple key to the queue,
// and saves it on a stack.
void Scanner::InsertSimpleKey()
// ExistsActiveSimpleKey
// . Returns true if there's a potential simple key at our flow level
// (there's allowed at most one per flow level, i.e., at the start of the flow start token)
bool Scanner::ExistsActiveSimpleKey() const
{
if(m_simpleKeys.empty())
return false;
const SimpleKey& key = m_simpleKeys.top();
return key.flowLevel == m_flowLevel;
}
// InsertPotentialSimpleKey
// . If we can, add a potential simple key to the queue,
// and save it on a stack.
void Scanner::InsertPotentialSimpleKey()
{
if(ExistsActiveSimpleKey())
return;
SimpleKey key(INPUT.mark(), m_flowLevel);
// first add a map start, if necessary
@ -55,11 +70,26 @@ namespace YAML
m_simpleKeys.push(key);
}
// InvalidateSimpleKey
// . Automatically invalidate the simple key in our flow level
void Scanner::InvalidateSimpleKey()
{
if(m_simpleKeys.empty())
return;
// grab top key
SimpleKey& key = m_simpleKeys.top();
if(key.flowLevel != m_flowLevel)
return;
key.Invalidate();
m_simpleKeys.pop();
}
// VerifySimpleKey
// . Determines whether the latest simple key to be added is valid,
// and if so, makes it valid.
// . If 'force' is true, then we'll pop no matter what (whether we can verify it or not).
bool Scanner::VerifySimpleKey(bool force)
bool Scanner::VerifySimpleKey()
{
m_isLastKeyValid = false;
if(m_simpleKeys.empty())
@ -69,11 +99,8 @@ namespace YAML
SimpleKey key = m_simpleKeys.top();
// only validate if we're in the correct flow level
if(key.flowLevel != m_flowLevel) {
if(force)
m_simpleKeys.pop();
if(key.flowLevel != m_flowLevel)
return false;
}
m_simpleKeys.pop();
@ -99,11 +126,9 @@ namespace YAML
return isValid;
}
// VerifyAllSimplyKeys
// . Pops all simple keys (with checking, but if we can't verify one, then pop it anyways).
void Scanner::VerifyAllSimpleKeys()
void Scanner::PopAllSimpleKeys()
{
while(!m_simpleKeys.empty())
VerifySimpleKey(true);
m_simpleKeys.pop();
}
}

View File

@ -407,6 +407,54 @@ namespace Test
return true;
}
bool AnchorInSimpleKey()
{
std::string input = "- &a b: c\n- *a";
std::stringstream stream(input);
YAML::Parser parser(stream);
YAML::Node doc;
parser.GetNextDocument(doc);
if(doc.size() != 2)
return false;
std::string output;
doc[0]["b"] >> output;
if(output != "c")
return false;
doc[1] >> output;
if(output != "b")
return false;
return true;
}
bool AliasAsSimpleKey()
{
std::string input = "- &a b\n- *a: c";
std::stringstream stream(input);
YAML::Parser parser(stream);
YAML::Node doc;
parser.GetNextDocument(doc);
if(doc.size() != 2)
return false;
std::string output;
doc[0] >> output;
if(output != "b")
return false;
doc[1]["b"] >> output;
if(output != "c")
return false;
return true;
}
bool ExplicitDoc()
{
std::string input = "---\n- one\n- two";

View File

@ -275,6 +275,8 @@ namespace Test
RunParserTest(&Parser::NullBlockMapValue, "null block map value", passed);
RunParserTest(&Parser::SimpleAlias, "simple alias", passed);
RunParserTest(&Parser::AliasWithNull, "alias with null", passed);
RunParserTest(&Parser::AnchorInSimpleKey, "anchor in simple key", passed);
RunParserTest(&Parser::AliasAsSimpleKey, "alias as simple key", passed);
RunParserTest(&Parser::ExplicitDoc, "explicit doc", passed);
RunParserTest(&Parser::MultipleDocs, "multiple docs", passed);
RunParserTest(&Parser::ExplicitEndDoc, "explicit end doc", passed);

View File

@ -42,6 +42,8 @@ namespace Test {
bool NullBlockMapValue();
bool SimpleAlias();
bool AliasWithNull();
bool AnchorInSimpleKey();
bool AliasAsSimpleKey();
bool ExplicitDoc();
bool MultipleDocs();
bool ExplicitEndDoc();