public bool MoveNext() { if (_currentIndex < 0) { while (_innerParser.MoveNext()) { _allEvents.Add(_innerParser.Current); } for (int i = _allEvents.Count - 2; i >= 0; --i) { var merge = _allEvents[i] as Scalar; if (merge != null && merge.Value == "<<") { var anchorAlias = _allEvents[i + 1] as AnchorAlias; if (anchorAlias != null) { var mergedEvents = GetMappingEvents(anchorAlias.Value); _allEvents.RemoveRange(i, 2); _allEvents.InsertRange(i, mergedEvents); } } } } var nextIndex = _currentIndex + 1; if (nextIndex < _allEvents.Count) { Current = _allEvents[nextIndex]; _currentIndex = nextIndex; return true; } return false; }
/// <summary> /// Expect DOCUMENT-START or STREAM-END. /// </summary> private void EmitDocumentStart(ParsingEvent evt, bool isFirst) { var documentStart = evt as DocumentStart; if (documentStart != null) { var isImplicit = documentStart.IsImplicit && isFirst && !isCanonical; var documentTagDirectives = NonDefaultTagsAmong(documentStart.Tags); if (!isFirst && !isDocumentEndWritten && (documentStart.Version != null || documentTagDirectives.Count > 0)) { isDocumentEndWritten = false; WriteIndicator("...", true, false, false); WriteIndent(); } if (documentStart.Version != null) { AnalyzeVersionDirective(documentStart.Version); isImplicit = false; WriteIndicator("%YAML", true, false, false); WriteIndicator(string.Format(CultureInfo.InvariantCulture, "{0}.{1}", Constants.MajorVersion, Constants.MinorVersion), true, false, false); WriteIndent(); } foreach (var tagDirective in documentTagDirectives) { AppendTagDirectiveTo(tagDirective, false, tagDirectives); } foreach (var tagDirective in Constants.DefaultTagDirectives) { AppendTagDirectiveTo(tagDirective, true, tagDirectives); } if (documentTagDirectives.Count > 0) { isImplicit = false; foreach (var tagDirective in Constants.DefaultTagDirectives) { AppendTagDirectiveTo(tagDirective, true, documentTagDirectives); } foreach (var tagDirective in documentTagDirectives) { WriteIndicator("%TAG", true, false, false); WriteTagHandle(tagDirective.Handle); WriteTagContent(tagDirective.Prefix, true); WriteIndent(); } } if (CheckEmptyDocument()) { isImplicit = false; } if (!isImplicit) { WriteIndent(); WriteIndicator("---", true, false, false); if (isCanonical) { WriteIndent(); } } state = EmitterState.DocumentContent; } else if (evt is StreamEnd) { if (isOpenEnded) { WriteIndicator("...", true, false, false); WriteIndent(); } state = EmitterState.StreamEnd; } else { throw new YamlException("Expected DOCUMENT-START or STREAM-END"); } }
/// <summary> /// Expect STREAM-START. /// </summary> private void EmitStreamStart(ParsingEvent evt) { if (!(evt is StreamStart)) { throw new ArgumentException("Expected STREAM-START.", "evt"); } indent = -1; column = 0; isWhitespace = true; isIndentation = true; state = EmitterState.FirstDocumentStart; }
private void StateMachine(ParsingEvent evt) { switch (state) { case EmitterState.StreamStart: EmitStreamStart(evt); break; case EmitterState.FirstDocumentStart: EmitDocumentStart(evt, true); break; case EmitterState.DocumentStart: EmitDocumentStart(evt, false); break; case EmitterState.DocumentContent: EmitDocumentContent(evt); break; case EmitterState.DocumentEnd: EmitDocumentEnd(evt); break; case EmitterState.FlowSequenceFirstItem: EmitFlowSequenceItem(evt, true); break; case EmitterState.FlowSequenceItem: EmitFlowSequenceItem(evt, false); break; case EmitterState.FlowMappingFirstKey: EmitFlowMappingKey(evt, true); break; case EmitterState.FlowMappingKey: EmitFlowMappingKey(evt, false); break; case EmitterState.FlowMappingSimpleValue: EmitFlowMappingValue(evt, true); break; case EmitterState.FlowMappingValue: EmitFlowMappingValue(evt, false); break; case EmitterState.BlockSequenceFirstItem: EmitBlockSequenceItem(evt, true); break; case EmitterState.BlockSequenceItem: EmitBlockSequenceItem(evt, false); break; case EmitterState.BlockMappingFirstKey: EmitBlockMappingKey(evt, true); break; case EmitterState.BlockMappingKey: EmitBlockMappingKey(evt, false); break; case EmitterState.BlockMappingSimpleValue: EmitBlockMappingValue(evt, true); break; case EmitterState.BlockMappingValue: EmitBlockMappingValue(evt, false); break; case EmitterState.StreamEnd: throw new YamlException("Expected nothing after STREAM-END"); default: throw new InvalidOperationException(); } }
private void AnalyzeEvent(ParsingEvent evt) { anchorData.anchor = null; tagData.handle = null; tagData.suffix = null; var alias = evt as AnchorAlias; if (alias != null) { AnalyzeAnchor(alias.Value, true); return; } var nodeEvent = evt as NodeEvent; if (nodeEvent != null) { var scalar = evt as Scalar; if (scalar != null) { AnalyzeScalar(scalar.Value); } AnalyzeAnchor(nodeEvent.Anchor, false); if (!string.IsNullOrEmpty(nodeEvent.Tag) && (isCanonical || nodeEvent.IsCanonical)) { AnalyzeTag(nodeEvent.Tag); } } }
/// <summary> /// Emit an evt. /// </summary> public void Emit(ParsingEvent @event) { events.Enqueue(@event); while (!NeedMoreEvents()) { var current = events.Peek(); AnalyzeEvent(current); StateMachine(current); // Only dequeue after calling state_machine because it checks how many events are in the queue. // Todo: well, move into StateMachine() then events.Dequeue(); } }
/// <summary> /// Expect SEQUENCE-START. /// </summary> private void EmitSequenceStart(ParsingEvent evt) { ProcessAnchor(); ProcessTag(); var sequenceStart = (SequenceStart) evt; if (flowLevel != 0 || isCanonical || sequenceStart.Style == SequenceStyle.Flow || CheckEmptySequence()) { state = EmitterState.FlowSequenceFirstItem; } else { state = EmitterState.BlockSequenceFirstItem; } }
/// <summary> /// Expect SCALAR. /// </summary> private void EmitScalar(ParsingEvent evt) { SelectScalarStyle(evt); ProcessAnchor(); ProcessTag(); IncreaseIndent(true, false); ProcessScalar(); indent = indents.Pop(); state = states.Pop(); }
/// <summary> /// Expect a block item node. /// </summary> private void EmitBlockSequenceItem(ParsingEvent evt, bool isFirst) { if (isFirst) { IncreaseIndent(false, (isMappingContext && !isIndentation)); } if (evt is SequenceEnd) { indent = indents.Pop(); state = states.Pop(); return; } WriteIndent(); WriteIndicator("-", true, false, true); states.Push(EmitterState.BlockSequenceItem); EmitNode(evt, false, false, false); }
/// <summary> /// Expect a flow value node. /// </summary> private void EmitFlowMappingValue(ParsingEvent evt, bool isSimple) { if (isSimple) { WriteIndicator(":", false, false, false); } else { if (isCanonical || column > bestWidth) { WriteIndent(); } WriteIndicator(":", true, false, false); } states.Push(EmitterState.FlowMappingKey); EmitNode(evt, false, true, false); }
/// <summary> /// Expect a flow key node. /// </summary> private void EmitFlowMappingKey(ParsingEvent evt, bool isFirst) { if (isFirst) { WriteIndicator("{", true, true, false); IncreaseIndent(true, false); ++flowLevel; } if (evt is MappingEnd) { --flowLevel; indent = indents.Pop(); if (isCanonical && !isFirst) { WriteIndicator(",", false, false, false); WriteIndent(); } WriteIndicator("}", false, false, false); state = states.Pop(); return; } if (!isFirst) { WriteIndicator(",", false, false, false); } if (isCanonical || column > bestWidth) { WriteIndent(); } if (!isCanonical && CheckSimpleKey()) { states.Push(EmitterState.FlowMappingSimpleValue); EmitNode(evt, false, true, true); } else { WriteIndicator("?", true, false, false); states.Push(EmitterState.FlowMappingValue); EmitNode(evt, false, true, false); } }
/// <summary> /// Expect a flow item node. /// </summary> private void EmitFlowSequenceItem(ParsingEvent evt, bool isFirst) { if (isFirst) { WriteIndicator("[", true, true, false); IncreaseIndent(true, false); ++flowLevel; } if (evt is SequenceEnd) { --flowLevel; indent = indents.Pop(); if (isCanonical && !isFirst) { WriteIndicator(",", false, false, false); WriteIndent(); } WriteIndicator("]", false, false, false); state = states.Pop(); return; } if (!isFirst) { WriteIndicator(",", false, false, false); } if (isCanonical || column > bestWidth) { WriteIndent(); } states.Push(EmitterState.FlowSequenceItem); EmitNode(evt, false, false, false); }
/// <summary> /// Expect DOCUMENT-END. /// </summary> private void EmitDocumentEnd(ParsingEvent evt) { var documentEnd = evt as DocumentEnd; if (documentEnd != null) { WriteIndent(); if (!documentEnd.IsImplicit) { WriteIndicator("...", true, false, false); WriteIndent(); isDocumentEndWritten = true; } state = EmitterState.DocumentStart; tagDirectives.Clear(); } else { throw new YamlException("Expected DOCUMENT-END."); } }
/// <summary> /// Expect MAPPING-START. /// </summary> private void EmitMappingStart(ParsingEvent evt) { ProcessAnchor(); ProcessTag(); var mappingStart = (MappingStart) evt; if (flowLevel != 0 || isCanonical || mappingStart.Style == MappingStyle.Flow || CheckEmptyMapping()) { state = EmitterState.FlowMappingFirstKey; } else { state = EmitterState.BlockMappingFirstKey; } }
/// <summary> /// Expect the root node. /// </summary> private void EmitDocumentContent(ParsingEvent evt) { states.Push(EmitterState.DocumentEnd); EmitNode(evt, true, false, false); }
/// <summary> /// Expect a node. /// </summary> private void EmitNode(ParsingEvent evt, bool isRoot, bool isMapping, bool isSimpleKey) { isRootContext = isRoot; isMappingContext = isMapping; isSimpleKeyContext = isSimpleKey; switch (evt.Type) { case EventType.Alias: EmitAlias(); break; case EventType.Scalar: EmitScalar(evt); break; case EventType.SequenceStart: EmitSequenceStart(evt); break; case EventType.MappingStart: EmitMappingStart(evt); break; default: throw new YamlException(string.Format("Expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, got {0}", evt.Type)); } }
/// <summary> /// Expect a block key node. /// </summary> private void EmitBlockMappingKey(ParsingEvent evt, bool isFirst) { if (isFirst) { IncreaseIndent(false, false); } if (evt is MappingEnd) { indent = indents.Pop(); state = states.Pop(); return; } WriteIndent(); if (CheckSimpleKey()) { states.Push(EmitterState.BlockMappingSimpleValue); EmitNode(evt, false, true, true); } else { WriteIndicator("?", true, false, true); states.Push(EmitterState.BlockMappingValue); EmitNode(evt, false, true, false); } }
private void SelectScalarStyle(ParsingEvent evt) { var scalar = (Scalar)evt; var style = scalar.Style; var noTag = tagData.handle == null && tagData.suffix == null; if (noTag && !scalar.IsPlainImplicit && !scalar.IsQuotedImplicit) { throw new YamlException("Neither tag nor isImplicit flags are specified."); } if (style == ScalarStyle.Any) { style = scalarData.isMultiline ? ScalarStyle.Folded : ScalarStyle.Plain; } if (isCanonical) { style = ScalarStyle.DoubleQuoted; } if (isSimpleKeyContext && scalarData.isMultiline) { style = ScalarStyle.DoubleQuoted; } if (style == ScalarStyle.Plain) { if ((flowLevel != 0 && !scalarData.isFlowPlainAllowed) || (flowLevel == 0 && !scalarData.isBlockPlainAllowed)) { style = ScalarStyle.SingleQuoted; } if (string.IsNullOrEmpty(scalarData.value) && (flowLevel != 0 || isSimpleKeyContext)) { style = ScalarStyle.SingleQuoted; } if (noTag && !scalar.IsPlainImplicit) { style = ScalarStyle.SingleQuoted; } } if (style == ScalarStyle.SingleQuoted) { if (!scalarData.isSingleQuotedAllowed) { style = ScalarStyle.DoubleQuoted; } } if (style == ScalarStyle.Literal || style == ScalarStyle.Folded) { if (!scalarData.isBlockAllowed || flowLevel != 0 || isSimpleKeyContext) { style = ScalarStyle.DoubleQuoted; } } scalarData.style = style; }
/// <summary> /// Expect a block value node. /// </summary> private void EmitBlockMappingValue(ParsingEvent evt, bool isSimple) { if (isSimple) { WriteIndicator(":", false, false, false); } else { WriteIndent(); WriteIndicator(":", true, false, true); } states.Push(EmitterState.BlockMappingKey); EmitNode(evt, false, true, false); }