// PlainScalar void Scanner::ScanPlainScalar() { std::string scalar; // set up the scanning parameters ScanScalarParams params; params.end = (InFlowContext() ? Exp::EndScalarInFlow() : Exp::EndScalar()) || (Exp::BlankOrBreak() + Exp::Comment()); params.eatEnd = false; params.indent = (InFlowContext() ? 0 : GetTopIndent() + 1); params.fold = FOLD_FLOW; params.eatLeadingWhitespace = true; params.trimTrailingSpaces = true; params.chomp = STRIP; params.onDocIndicator = BREAK; params.onTabInIndentation = THROW; // insert a potential simple key InsertPotentialSimpleKey(); Mark mark = INPUT.mark(); scalar = ScanScalar(INPUT, params); // can have a simple key only if we ended the scalar by starting a new line m_simpleKeyAllowed = params.leadingSpaces; m_canBeJSONFlow = false; // finally, check and see if we ended on an illegal character //if(Exp::IllegalCharInScalar.Matches(INPUT)) // throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_SCALAR); Token token(Token::PLAIN_SCALAR, mark); token.value = scalar; m_tokens.push(token); }
void Scanner::PopIndentToHere() { // are we in flow? if (InFlowContext()) { return; } // now pop away while (!m_indents.empty()) { const IndentMarker& indent = *m_indents.top(); if (indent.column < INPUT.column()) { break; } if (indent.column == INPUT.column() && !(indent.type == IndentMarker::SEQ && !Exp::BlockEntry().Matches(INPUT))) { break; } PopIndent(); } while (!m_indents.empty() && m_indents.top()->status == IndentMarker::INVALID) { PopIndent(); } }
Scanner::IndentMarker* Scanner::PushIndentTo(int column, IndentMarker::INDENT_TYPE type) { // are we in flow? if (InFlowContext()) { return 0; } std::unique_ptr<IndentMarker> pIndent(new IndentMarker(column, type)); IndentMarker& indent = *pIndent; const IndentMarker& lastIndent = *m_indents.top(); // is this actually an indentation? if (indent.column < lastIndent.column) { return 0; } if (indent.column == lastIndent.column && !(indent.type == IndentMarker::SEQ && lastIndent.type == IndentMarker::MAP)) { return 0; } // push a start token indent.pStartToken = PushToken(GetStartTokenFor(type)); // and then the indent m_indents.push(&indent); m_indentRefs.push_back(std::move(pIndent)); return &m_indentRefs.back(); }
// FlowEnd void Scanner::ScanFlowEnd() { if(InBlockContext()) throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END); // we might have a solo entry in the flow context if(InFlowContext()) { if(m_flows.top() == FLOW_MAP && VerifySimpleKey()) m_tokens.push(Token(Token::VALUE, INPUT.mark())); else if(m_flows.top() == FLOW_SEQ) InvalidateSimpleKey(); } m_simpleKeyAllowed = false; m_canBeJSONFlow = true; // eat Mark mark = INPUT.mark(); char ch = INPUT.get(); // check that it matches the start FLOW_MARKER flowType = (ch == Keys::FlowSeqEnd ? FLOW_SEQ : FLOW_MAP); if(m_flows.top() != flowType) throw ParserException(mark, ErrorMsg::FLOW_END); m_flows.pop(); Token::TYPE type = (flowType ? Token::FLOW_SEQ_END : Token::FLOW_MAP_END); m_tokens.push(Token(type, mark)); }
// PopAllIndents // . Pops all indentations (except for the base empty one) off the stack, // and enqueues the proper token each time. void Scanner::PopAllIndents() { // are we in flow? if (InFlowContext()) return; // now pop away while (!m_indents.empty()) { const IndentMarker& indent = *m_indents.top(); if (indent.type == IndentMarker::NONE) break; PopIndent(); } }
// FlowEntry void Scanner::ScanFlowEntry() { // we might have a solo entry in the flow context if (InFlowContext()) { if (m_flows.top() == FLOW_MAP && VerifySimpleKey()) m_tokens.push(Token(Token::VALUE, INPUT.mark())); else if (m_flows.top() == FLOW_SEQ) InvalidateSimpleKey(); } m_simpleKeyAllowed = true; m_canBeJSONFlow = false; // eat Mark mark = INPUT.mark(); INPUT.eat(1); m_tokens.push(Token(Token::FLOW_ENTRY, mark)); }
// BlockEntry void Scanner::ScanBlockEntry() { // we better be in the block context! if (InFlowContext()) throw ParserException(INPUT.mark(), ErrorMsg::BLOCK_ENTRY); // can we put it here? if (!m_simpleKeyAllowed) throw ParserException(INPUT.mark(), ErrorMsg::BLOCK_ENTRY); PushIndentTo(INPUT.column(), IndentMarker::SEQ); m_simpleKeyAllowed = true; m_canBeJSONFlow = false; // eat Mark mark = INPUT.mark(); INPUT.eat(1); m_tokens.push(Token(Token::BLOCK_ENTRY, mark)); }