diff --git a/src/scanner.cpp b/src/scanner.cpp index 988ed43..893bb31 100644 --- a/src/scanner.cpp +++ b/src/scanner.cpp @@ -95,12 +95,12 @@ namespace YAML // get rid of whitespace, etc. (in between tokens it should be irrelevent) ScanToNextToken(); - // check the latest simple key - VerifySimpleKey(); - // maybe need to end some blocks PopIndentToHere(); + // check the latest simple key + VerifySimpleKey(); + // ***** // And now branch based on the next few characters! // ***** @@ -244,8 +244,8 @@ namespace YAML // PushIndentTo // . Pushes an indentation onto the stack, and enqueues the // proper token (sequence start or mapping start). - // . Returns the token it generates (if any). - Token *Scanner::PushIndentTo(int column, IndentMarker::INDENT_TYPE type) + // . Returns the indent marker it generates (if any). + Scanner::IndentMarker *Scanner::PushIndentTo(int column, IndentMarker::INDENT_TYPE type) { // are we in flow? if(m_flowLevel > 0) @@ -260,16 +260,18 @@ namespace YAML if(indent.column == lastIndent.column && !(indent.type == IndentMarker::SEQ && lastIndent.type == IndentMarker::MAP)) return 0; - // now push - m_indents.push(indent); + // push a start token if(type == IndentMarker::SEQ) 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(); - return &m_tokens.back(); + // and then the indent + m_indents.push(indent); + return &m_indents.top(); } // PopIndentToHere @@ -316,8 +318,12 @@ namespace YAML // . Pops a single indent, pushing the proper token void Scanner::PopIndent() { - IndentMarker::INDENT_TYPE type = m_indents.top().type; + IndentMarker indent = m_indents.top(); + IndentMarker::INDENT_TYPE type = indent.type; m_indents.pop(); + if(!indent.isValid) + return; + if(type == IndentMarker::SEQ) m_tokens.push(Token(Token::BLOCK_SEQ_END, INPUT.mark())); else if(type == IndentMarker::MAP) diff --git a/src/scanner.h b/src/scanner.h index 853fa64..d0e0135 100644 --- a/src/scanner.h +++ b/src/scanner.h @@ -36,10 +36,12 @@ namespace YAML private: struct IndentMarker { enum INDENT_TYPE { MAP, SEQ, NONE }; - IndentMarker(int column_, INDENT_TYPE type_): column(column_), type(type_) {} + IndentMarker(int column_, INDENT_TYPE type_): column(column_), type(type_), isValid(true), pStartToken(0) {} int column; INDENT_TYPE type; + bool isValid; + Token *pStartToken; }; private: @@ -49,7 +51,7 @@ namespace YAML void ScanToNextToken(); void StartStream(); void EndStream(); - Token *PushIndentTo(int column, IndentMarker::INDENT_TYPE type); + IndentMarker *PushIndentTo(int column, IndentMarker::INDENT_TYPE type); void PopIndentToHere(); void PopAllIndents(); void PopIndent(); @@ -71,6 +73,7 @@ namespace YAML Mark mark; int flowLevel; + IndentMarker *pIndent; Token *pMapStart, *pKey; }; diff --git a/src/simplekey.cpp b/src/simplekey.cpp index bdfbda4..cf4d1b4 100644 --- a/src/simplekey.cpp +++ b/src/simplekey.cpp @@ -7,12 +7,15 @@ namespace YAML { Scanner::SimpleKey::SimpleKey(const Mark& mark_, int flowLevel_) - : mark(mark_), flowLevel(flowLevel_), pMapStart(0), pKey(0) + : mark(mark_), flowLevel(flowLevel_), pIndent(0), pMapStart(0), pKey(0) { } void Scanner::SimpleKey::Validate() { + // Note: pIndent will *not* be garbage here; see below + if(pIndent) + pIndent->isValid = true; if(pMapStart) pMapStart->status = Token::VALID; if(pKey) @@ -21,6 +24,8 @@ namespace YAML void Scanner::SimpleKey::Invalidate() { + // Note: pIndent might be a garbage pointer here, but that's ok + // An indent will only be popped if the simple key is invalid if(pMapStart) pMapStart->status = Token::INVALID; if(pKey) @@ -35,9 +40,12 @@ namespace YAML SimpleKey key(INPUT.mark(), m_flowLevel); // first add a map start, if necessary - key.pMapStart = PushIndentTo(INPUT.column(), IndentMarker::MAP); - if(key.pMapStart) + key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP); + if(key.pIndent) { + key.pIndent->isValid = false; + key.pMapStart = key.pIndent->pStartToken; key.pMapStart->status = Token::UNVERIFIED; + } // then add the (now unverified) key m_tokens.push(Token(Token::KEY, INPUT.mark())); @@ -87,13 +95,6 @@ namespace YAML else key.Invalidate(); - // In block style, remember that we've pushed an indent for this potential simple key (if it was starting). - // If it was invalid, then we need to pop it off. - // Note: we're guaranteed to be popping the right one (i.e., there couldn't have been anything in - // between) since keys have to be inline, and will be invalidated immediately on a newline. - if(!isValid && m_flowLevel == 0) - m_indents.pop(); - m_isLastKeyValid = isValid; return isValid; }