Fixed null key/value bug, added tests

This commit is contained in:
Jesse Beder
2009-07-30 06:49:09 +00:00
parent 382f1ba3c7
commit 7a89920441
8 changed files with 87 additions and 16 deletions

View File

@@ -7,6 +7,9 @@
namespace YAML namespace YAML
{ {
struct _Null {}; struct _Null {};
inline bool operator == (const _Null&, const _Null&) { return true; }
inline bool operator != (const _Null&, const _Null&) { return false; }
extern _Null Null; extern _Null Null;
} }

View File

@@ -33,10 +33,10 @@ namespace YAML
const RegEx DocStart = RegEx("---") + (BlankOrBreak || RegEx()); const RegEx DocStart = RegEx("---") + (BlankOrBreak || RegEx());
const RegEx DocEnd = RegEx("...") + (BlankOrBreak || RegEx()); const RegEx DocEnd = RegEx("...") + (BlankOrBreak || RegEx());
const RegEx DocIndicator = DocStart || DocEnd; const RegEx DocIndicator = DocStart || DocEnd;
const RegEx BlockEntry = RegEx('-') + BlankOrBreak; const RegEx BlockEntry = RegEx('-') + (BlankOrBreak || RegEx());
const RegEx Key = RegEx('?'), const RegEx Key = RegEx('?'),
KeyInFlow = RegEx('?') + BlankOrBreak; KeyInFlow = RegEx('?') + BlankOrBreak;
const RegEx Value = RegEx(':') + BlankOrBreak, const RegEx Value = RegEx(':') + (BlankOrBreak || RegEx()),
ValueInFlow = RegEx(':') + BlankOrBreak; ValueInFlow = RegEx(':') + BlankOrBreak;
const RegEx Comment = RegEx('#'); const RegEx Comment = RegEx('#');
const RegEx AnchorEnd = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak; const RegEx AnchorEnd = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak;
@@ -48,7 +48,7 @@ namespace YAML
// . In the flow context ? is illegal and : and - must not be followed with a space. // . In the flow context ? is illegal and : and - must not be followed with a space.
const RegEx PlainScalar = !(BlankOrBreak || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-?:", REGEX_OR) + Blank)), const RegEx PlainScalar = !(BlankOrBreak || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-?:", REGEX_OR) + Blank)),
PlainScalarInFlow = !(BlankOrBreak || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-:", REGEX_OR) + Blank)); PlainScalarInFlow = !(BlankOrBreak || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-:", REGEX_OR) + Blank));
const RegEx EndScalar = RegEx(':') + BlankOrBreak, const RegEx EndScalar = RegEx(':') + (BlankOrBreak || RegEx()),
EndScalarInFlow = (RegEx(':') + BlankOrBreak) || RegEx(",?[]{}", REGEX_OR); EndScalarInFlow = (RegEx(':') + BlankOrBreak) || RegEx(",?[]{}", REGEX_OR);
const RegEx EscSingleQuote = RegEx("\'\'"); const RegEx EscSingleQuote = RegEx("\'\'");

View File

@@ -61,17 +61,21 @@ namespace YAML
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP); throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP);
Token token = pScanner->peek(); Token token = pScanner->peek();
if(token.type != TT_KEY && token.type != TT_BLOCK_END) if(token.type != TT_KEY && token.type != TT_VALUE && token.type != TT_BLOCK_END)
throw ParserException(token.mark, ErrorMsg::END_OF_MAP); throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
pScanner->pop(); if(token.type == TT_BLOCK_END) {
if(token.type == TT_BLOCK_END) pScanner->pop();
break; break;
}
std::auto_ptr <Node> pKey(new Node), pValue(new Node); std::auto_ptr <Node> pKey(new Node), pValue(new Node);
// grab key // grab key (if non-null)
pKey->Parse(pScanner, state); if(token.type == TT_KEY) {
pScanner->pop();
pKey->Parse(pScanner, state);
}
// now grab value (optional) // now grab value (optional)
if(!pScanner->empty() && pScanner->peek().type == TT_VALUE) { if(!pScanner->empty() && pScanner->peek().type == TT_VALUE) {

View File

@@ -243,8 +243,11 @@ namespace YAML
bool Node::GetScalar(std::string& s) const bool Node::GetScalar(std::string& s) const
{ {
if(!m_pContent) if(!m_pContent) {
return false; s = "~";
return true;
}
return m_pContent->GetScalar(s); return m_pContent->GetScalar(s);
} }

View File

@@ -30,8 +30,7 @@ namespace YAML
TT_ANCHOR, TT_ANCHOR,
TT_ALIAS, TT_ALIAS,
TT_TAG, TT_TAG,
TT_SCALAR, TT_SCALAR
TT_NULL
}; };
const std::string TokenNames[] = { const std::string TokenNames[] = {
@@ -52,8 +51,7 @@ namespace YAML
"ANCHOR", "ANCHOR",
"ALIAS", "ALIAS",
"TAG", "TAG",
"SCALAR", "SCALAR"
"NULL"
}; };
struct Token { struct Token {

View File

@@ -247,5 +247,62 @@ namespace Test
return true; return true;
} }
bool NullBlockSeqEntry()
{
std::string input = "- hello\n-\n- world";
std::stringstream stream(input);
YAML::Parser parser(stream);
YAML::Node doc;
parser.GetNextDocument(doc);
std::string output;
doc[0] >> output;
if(output != "hello")
return false;
doc[1] >> output;
if(output != "~")
return false;
doc[2] >> output;
if(output != "world")
return false;
return true;
}
bool NullBlockMapKey()
{
std::string input = ": empty key";
std::stringstream stream(input);
YAML::Parser parser(stream);
YAML::Node doc;
parser.GetNextDocument(doc);
std::string output;
doc[YAML::Null] >> output;
if(output != "empty key")
return false;
return true;
}
bool NullBlockMapValue()
{
std::string input = "empty value:";
std::stringstream stream(input);
YAML::Parser parser(stream);
YAML::Node doc;
parser.GetNextDocument(doc);
std::string output;
doc["empty value"] >> output;
if(output != "~")
return false;
return true;
}
} }
} }

View File

@@ -263,7 +263,10 @@ namespace Test
RunParserTest(&Parser::FlowSeq, "flow seq", passed); RunParserTest(&Parser::FlowSeq, "flow seq", passed);
RunParserTest(&Parser::FlowMap, "flow map", passed); RunParserTest(&Parser::FlowMap, "flow map", passed);
RunParserTest(&Parser::QuotedSimpleKeys, "quoted simple keys", passed); RunParserTest(&Parser::QuotedSimpleKeys, "quoted simple keys", passed);
RunParserTest(&Parser::NullBlockSeqEntry, "null block seq entry", passed);
RunParserTest(&Parser::NullBlockMapKey, "null block map key", passed);
RunParserTest(&Parser::NullBlockMapValue, "null block map value", passed);
RunEncodingTest(&EncodeToUtf8, false, "UTF-8, no BOM", passed); RunEncodingTest(&EncodeToUtf8, false, "UTF-8, no BOM", passed);
RunEncodingTest(&EncodeToUtf8, true, "UTF-8 with BOM", passed); RunEncodingTest(&EncodeToUtf8, true, "UTF-8 with BOM", passed);
RunEncodingTest(&EncodeToUtf16LE, false, "UTF-16LE, no BOM", passed); RunEncodingTest(&EncodeToUtf16LE, false, "UTF-16LE, no BOM", passed);

View File

@@ -34,6 +34,9 @@ namespace Test {
bool FlowSeq(); bool FlowSeq();
bool FlowMap(); bool FlowMap();
bool QuotedSimpleKeys(); bool QuotedSimpleKeys();
bool NullBlockSeqEntry();
bool NullBlockMapKey();
bool NullBlockMapValue();
} }
namespace Emitter { namespace Emitter {