// EmitKey void Emitter::EmitKey() { if(!good()) return; EMITTER_STATE curState = m_pState->GetCurState(); FLOW_TYPE flowType = m_pState->GetCurGroupFlowType(); if(curState != ES_WAITING_FOR_BLOCK_MAP_ENTRY && curState != ES_DONE_WITH_BLOCK_MAP_VALUE && curState != ES_WAITING_FOR_FLOW_MAP_ENTRY && curState != ES_DONE_WITH_FLOW_MAP_VALUE) return m_pState->SetError(ErrorMsg::UNEXPECTED_KEY_TOKEN); if(flowType == FT_BLOCK) { if(curState == ES_DONE_WITH_BLOCK_MAP_VALUE) m_stream << '\n'; unsigned curIndent = m_pState->GetCurIndent(); m_stream << IndentTo(curIndent); m_pState->SwitchState(ES_WAITING_FOR_BLOCK_MAP_KEY); } else if(flowType == FT_FLOW) { if(curState == ES_DONE_WITH_FLOW_MAP_VALUE) { m_stream << ','; m_pState->RequireSeparation(); } m_pState->SwitchState(ES_WAITING_FOR_FLOW_MAP_KEY); } else assert(false); if(m_pState->GetMapKeyFormat() == LongKey) m_pState->StartLongKey(); else if(m_pState->GetMapKeyFormat() == Auto) m_pState->StartSimpleKey(); else assert(false); }
void Emitter::BlockMapPrepareLongKeyValue(EmitterNodeType::value child) { const unsigned curIndent = m_pState->CurIndent(); if (child == EmitterNodeType::None) return; if (!m_pState->HasBegunContent()) { m_stream << "\n"; m_stream << IndentTo(curIndent); m_stream << ":"; } switch (child) { case EmitterNodeType::None: break; case EmitterNodeType::Property: case EmitterNodeType::Scalar: case EmitterNodeType::FlowSeq: case EmitterNodeType::FlowMap: case EmitterNodeType::BlockSeq: case EmitterNodeType::BlockMap: SpaceOrIndentTo(true, curIndent + 1); break; } }
// EmitEndMap void Emitter::EmitEndMap() { if(!good()) return; if(m_pState->GetCurGroupType() != GT_MAP) return m_pState->SetError(ErrorMsg::UNEXPECTED_END_MAP); EMITTER_STATE curState = m_pState->GetCurState(); FLOW_TYPE flowType = m_pState->GetCurGroupFlowType(); if(flowType == FT_BLOCK) { // Note: block sequences are *not* allowed to be empty, but we convert it // to a flow sequence if it is assert(curState == ES_DONE_WITH_BLOCK_MAP_VALUE || curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY); if(curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY) { // Note: only one of these will actually output anything for a given situation EmitSeparationIfNecessary(); unsigned curIndent = m_pState->GetCurIndent(); m_stream << IndentTo(curIndent); m_stream << "{}"; } } else if(flowType == FT_FLOW) { // Note: flow maps are allowed to be empty assert(curState == ES_DONE_WITH_FLOW_MAP_VALUE || curState == ES_WAITING_FOR_FLOW_MAP_ENTRY); m_stream << "}"; } else assert(false); m_pState->PopState(); m_pState->EndGroup(GT_MAP); PostAtomicWrite(); }
// SpaceOrIndentTo // . Prepares for some more content by proper spacing void Emitter::SpaceOrIndentTo(bool requireSpace, unsigned indent) { if (m_stream.comment()) m_stream << "\n"; if (m_stream.col() > 0 && requireSpace) m_stream << " "; m_stream << IndentTo(indent); }
void Emitter::BlockMapPrepareLongKey(EmitterNodeType::value child) { const unsigned curIndent = m_pState->CurIndent(); const std::size_t childCount = m_pState->CurGroupChildCount(); if (child == EmitterNodeType::None) return; if (!m_pState->HasBegunContent()) { if (childCount > 0) { m_stream << "\n"; } if (m_stream.comment()) { m_stream << "\n"; } m_stream << IndentTo(curIndent); m_stream << "?"; } switch (child) { case EmitterNodeType::None: break; case EmitterNodeType::Property: case EmitterNodeType::Scalar: case EmitterNodeType::FlowSeq: case EmitterNodeType::FlowMap: SpaceOrIndentTo(true, curIndent + 1); break; case EmitterNodeType::BlockSeq: case EmitterNodeType::BlockMap: break; } }
void Emitter::FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child) { const unsigned lastIndent = m_pState->LastIndent(); if (!m_pState->HasBegunNode()) { if (m_stream.comment()) m_stream << "\n"; m_stream << IndentTo(lastIndent); m_stream << ":"; } switch (child) { case EmitterNodeType::None: break; case EmitterNodeType::Property: case EmitterNodeType::Scalar: case EmitterNodeType::FlowSeq: case EmitterNodeType::FlowMap: SpaceOrIndentTo( m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0, lastIndent); break; case EmitterNodeType::BlockSeq: case EmitterNodeType::BlockMap: assert(false); break; } }
void Emitter::BlockSeqPrepareNode(EmitterNodeType::value child) { const unsigned curIndent = m_pState->CurIndent(); const unsigned nextIndent = curIndent + m_pState->CurGroupIndent(); if (child == EmitterNodeType::None) return; if (!m_pState->HasBegunContent()) { if (m_pState->CurGroupChildCount() > 0 || m_stream.comment()) { m_stream << "\n"; } m_stream << IndentTo(curIndent); m_stream << "-"; } switch (child) { case EmitterNodeType::None: break; case EmitterNodeType::Property: case EmitterNodeType::Scalar: case EmitterNodeType::FlowSeq: case EmitterNodeType::FlowMap: SpaceOrIndentTo(m_pState->HasBegunContent(), nextIndent); break; case EmitterNodeType::BlockSeq: m_stream << "\n"; break; case EmitterNodeType::BlockMap: if (m_pState->HasBegunContent() || m_stream.comment()) m_stream << "\n"; break; } }
// EmitEndMap void Emitter::EmitEndMap() { if (!good()) return; if (m_pState->CurGroupChildCount() == 0) m_pState->ForceFlow(); if (m_pState->CurGroupFlowType() == FlowType::Flow) { if (m_stream.comment()) m_stream << "\n"; m_stream << IndentTo(m_pState->CurIndent()); if (m_pState->CurGroupChildCount() == 0) m_stream << "{"; m_stream << "}"; } m_pState->EndedGroup(GroupType::Map); }
// EmitValue void Emitter::EmitValue() { if(!good()) return; EMITTER_STATE curState = m_pState->GetCurState(); FLOW_TYPE flowType = m_pState->GetCurGroupFlowType(); if(curState != ES_DONE_WITH_BLOCK_MAP_KEY && curState != ES_DONE_WITH_FLOW_MAP_KEY) return m_pState->SetError(ErrorMsg::UNEXPECTED_VALUE_TOKEN); if(flowType == FT_BLOCK) { if(m_pState->CurrentlyInLongKey()) { m_stream << '\n'; m_stream << IndentTo(m_pState->GetCurIndent()); m_stream << ':'; m_pState->RequireSoftSeparation(); } m_pState->SwitchState(ES_WAITING_FOR_BLOCK_MAP_VALUE); } else if(flowType == FT_FLOW) { m_pState->SwitchState(ES_WAITING_FOR_FLOW_MAP_VALUE); } else assert(false); }
// GotoNextPreAtomicState // . Runs the state machine, emitting if necessary, and returns 'true' if done (i.e., ready to emit an atom) bool Emitter::GotoNextPreAtomicState() { if(!good()) return true; unsigned curIndent = m_pState->GetCurIndent(); EMITTER_STATE curState = m_pState->GetCurState(); switch(curState) { // document-level case ES_WAITING_FOR_DOC: m_stream << "---"; m_pState->RequireSeparation(); m_pState->SwitchState(ES_WRITING_DOC); return true; case ES_WRITING_DOC: return true; // block sequence case ES_WAITING_FOR_BLOCK_SEQ_ENTRY: m_stream << IndentTo(curIndent) << "-"; m_pState->RequireSeparation(); m_pState->SwitchState(ES_WRITING_BLOCK_SEQ_ENTRY); return true; case ES_WRITING_BLOCK_SEQ_ENTRY: return true; case ES_DONE_WITH_BLOCK_SEQ_ENTRY: m_stream << '\n'; m_pState->SwitchState(ES_WAITING_FOR_BLOCK_SEQ_ENTRY); return false; // flow sequence case ES_WAITING_FOR_FLOW_SEQ_ENTRY: m_pState->SwitchState(ES_WRITING_FLOW_SEQ_ENTRY); return true; case ES_WRITING_FLOW_SEQ_ENTRY: return true; case ES_DONE_WITH_FLOW_SEQ_ENTRY: m_stream << ','; m_pState->RequireSeparation(); m_pState->SwitchState(ES_WAITING_FOR_FLOW_SEQ_ENTRY); return false; // block map case ES_WAITING_FOR_BLOCK_MAP_ENTRY: m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN); return true; case ES_WAITING_FOR_BLOCK_MAP_KEY: if(m_pState->CurrentlyInLongKey()) { m_stream << IndentTo(curIndent) << '?'; m_pState->RequireSeparation(); } m_pState->SwitchState(ES_WRITING_BLOCK_MAP_KEY); return true; case ES_WRITING_BLOCK_MAP_KEY: return true; case ES_DONE_WITH_BLOCK_MAP_KEY: m_pState->SetError(ErrorMsg::EXPECTED_VALUE_TOKEN); return true; case ES_WAITING_FOR_BLOCK_MAP_VALUE: if(m_pState->CurrentlyInLongKey()) m_stream << IndentTo(curIndent); m_stream << ':'; m_pState->RequireSeparation(); m_pState->SwitchState(ES_WRITING_BLOCK_MAP_VALUE); return true; case ES_WRITING_BLOCK_MAP_VALUE: return true; case ES_DONE_WITH_BLOCK_MAP_VALUE: m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN); return true; // flow map case ES_WAITING_FOR_FLOW_MAP_ENTRY: m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN); return true; case ES_WAITING_FOR_FLOW_MAP_KEY: m_pState->SwitchState(ES_WRITING_FLOW_MAP_KEY); if(m_pState->CurrentlyInLongKey()) { EmitSeparationIfNecessary(); m_stream << '?'; m_pState->RequireSeparation(); } return true; case ES_WRITING_FLOW_MAP_KEY: return true; case ES_DONE_WITH_FLOW_MAP_KEY: m_pState->SetError(ErrorMsg::EXPECTED_VALUE_TOKEN); return true; case ES_WAITING_FOR_FLOW_MAP_VALUE: m_stream << ':'; m_pState->RequireSeparation(); m_pState->SwitchState(ES_WRITING_FLOW_MAP_VALUE); return true; case ES_WRITING_FLOW_MAP_VALUE: return true; case ES_DONE_WITH_FLOW_MAP_VALUE: m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN); return true; default: assert(false); } assert(false); return true; }