diff --git a/src/exp.h b/src/exp.h index 1b5ac74..e7a96b5 100644 --- a/src/exp.h +++ b/src/exp.h @@ -37,7 +37,7 @@ namespace YAML const RegEx Key = RegEx('?'), KeyInFlow = RegEx('?') + BlankOrBreak; const RegEx Value = RegEx(':') + (BlankOrBreak || RegEx()), - ValueInFlow = RegEx(':') + BlankOrBreak; + ValueInFlow = RegEx(':') + (BlankOrBreak || RegEx(",}", REGEX_OR)); const RegEx Comment = RegEx('#'); const RegEx AnchorEnd = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak; @@ -49,7 +49,7 @@ namespace YAML const RegEx PlainScalar = !(BlankOrBreak || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-?:", REGEX_OR) + Blank)), PlainScalarInFlow = !(BlankOrBreak || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-:", REGEX_OR) + Blank)); const RegEx EndScalar = RegEx(':') + (BlankOrBreak || RegEx()), - EndScalarInFlow = (RegEx(':') + BlankOrBreak) || RegEx(",?[]{}", REGEX_OR); + EndScalarInFlow = (RegEx(':') + (BlankOrBreak || RegEx(",]}", REGEX_OR))) || RegEx(",?[]{}", REGEX_OR); const RegEx EscSingleQuote = RegEx("\'\'"); const RegEx EscBreak = RegEx('\\') + Break; diff --git a/src/scanner.cpp b/src/scanner.cpp index 7429084..407abf2 100644 --- a/src/scanner.cpp +++ b/src/scanner.cpp @@ -104,7 +104,7 @@ namespace YAML // ***** // And now branch based on the next few characters! // ***** - + // end of stream if(!INPUT) return EndStream(); diff --git a/src/scantoken.cpp b/src/scantoken.cpp index 22b9712..9f1fda1 100644 --- a/src/scantoken.cpp +++ b/src/scantoken.cpp @@ -181,6 +181,12 @@ 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 diff --git a/yaml-reader/parsertests.cpp b/yaml-reader/parsertests.cpp index 3fbc457..e3410df 100644 --- a/yaml-reader/parsertests.cpp +++ b/yaml-reader/parsertests.cpp @@ -220,6 +220,42 @@ namespace Test return true; } + bool FlowMapWithOmittedKey() + { + std::string input = "{: omitted key}"; + std::stringstream stream(input); + YAML::Parser parser(stream); + YAML::Node doc; + parser.GetNextDocument(doc); + + std::string output; + doc[YAML::Null] >> output; + if(output != "omitted key") + return false; + + return true; + } + + bool FlowMapWithOmittedValue() + { + std::string input = "{a: b, c:, d:}"; + std::stringstream stream(input); + YAML::Parser parser(stream); + YAML::Node doc; + parser.GetNextDocument(doc); + + std::string output; + doc["a"] >> output; + if(output != "b") + return false; + if(!IsNull(doc["c"])) + return false; + if(!IsNull(doc["d"])) + return false; + + return true; + } + bool QuotedSimpleKeys() { std::string KeyValue[3] = { "\"double\": double\n", "'single': single\n", "plain: plain\n" }; diff --git a/yaml-reader/tests.cpp b/yaml-reader/tests.cpp index 5193a90..89d7c20 100644 --- a/yaml-reader/tests.cpp +++ b/yaml-reader/tests.cpp @@ -262,6 +262,8 @@ namespace Test RunParserTest(&Parser::SimpleMap, "simple map", passed); RunParserTest(&Parser::FlowSeq, "flow seq", passed); RunParserTest(&Parser::FlowMap, "flow map", passed); + RunParserTest(&Parser::FlowMapWithOmittedKey, "flow map with omitted key", passed); + RunParserTest(&Parser::FlowMapWithOmittedValue, "flow map with omitted value", passed); RunParserTest(&Parser::QuotedSimpleKeys, "quoted simple keys", passed); RunParserTest(&Parser::CompressedMapAndSeq, "compressed map and seq", passed); RunParserTest(&Parser::NullBlockSeqEntry, "null block seq entry", passed); diff --git a/yaml-reader/tests.h b/yaml-reader/tests.h index 67e6361..9aa9578 100644 --- a/yaml-reader/tests.h +++ b/yaml-reader/tests.h @@ -33,6 +33,8 @@ namespace Test { bool SimpleMap(); bool FlowSeq(); bool FlowMap(); + bool FlowMapWithOmittedKey(); + bool FlowMapWithOmittedValue(); bool QuotedSimpleKeys(); bool CompressedMapAndSeq(); bool NullBlockSeqEntry();