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; }
private IEnumerable<ParsingEvent> Wrap(IEnumerable<ParsingEvent> events, ParsingEvent start, ParsingEvent end) { yield return start; foreach (var @event in events) { yield return @event; } yield return end; }
public void ACommentAsTheFirstEventAddsANewLine() { var events = new ParsingEvent[] { StandaloneComment("Top comment"), Scalar("first").ImplicitPlain, }; var yaml = EmittedTextFrom(StreamedDocumentWith(events)); yaml.Should() .Contain("# Top comment") .And.Contain("first") .And.NotContain("# Top commentfirst"); }
private void AssertCurrent(Parser parser, ParsingEvent expected) { Console.WriteLine(expected.GetType().Name); Assert.True(expected.GetType().IsAssignableFrom(parser.Current.GetType()), string.Format("The event is not of the expected type. Exprected: {0}, Actual: {1}", expected.GetType().Name, parser.Current.GetType().Name)); foreach (var property in expected.GetType().GetProperties()) { if(property.PropertyType != typeof(Mark) && property.CanRead) { object value = property.GetValue(parser.Current, null); object expectedValue = property.GetValue(expected, null); if(expectedValue != null && Type.GetTypeCode(expectedValue.GetType()) == TypeCode.Object && expectedValue is IEnumerable) { Console.Write("\t{0} = {{", property.Name); bool isFirst = true; foreach(var item in (IEnumerable)value) { if(isFirst) { isFirst = false; } else { Console.Write(", "); } Console.Write(item); } Console.WriteLine("}"); if(expectedValue is ICollection && value is ICollection) { Assert.Equal(((ICollection)expectedValue).Count, ((ICollection)value).Count); } IEnumerator values = ((IEnumerable)value).GetEnumerator(); IEnumerator expectedValues = ((IEnumerable)expectedValue).GetEnumerator(); while(expectedValues.MoveNext()) { Assert.True(values.MoveNext()); Assert.Equal(expectedValues.Current, values.Current); } Assert.False(values.MoveNext()); } else { Console.WriteLine("\t{0} = {1}", property.Name, value); Assert.Equal(expectedValue, value); } } } }
/// <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 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 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 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 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."); } }
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); continue; } var sequence = _allEvents[i + 1] as SequenceStart; if (sequence != null) { var mergedEvents = new List<IEnumerable<ParsingEvent>>(); var sequenceEndFound = false; for (var itemIndex = i + 2; itemIndex < _allEvents.Count; ++itemIndex) { anchorAlias = _allEvents[itemIndex] as AnchorAlias; if (anchorAlias != null) { mergedEvents.Add(GetMappingEvents(anchorAlias.Value)); continue; } if (_allEvents[itemIndex] is SequenceEnd) { _allEvents.RemoveRange(i, itemIndex - i + 1); _allEvents.InsertRange(i, mergedEvents.SelectMany(e => e)); sequenceEndFound = true; break; } } if (sequenceEndFound) { continue; } } throw new SemanticErrorException(merge.Start, merge.End, "Unrecognized merge key pattern"); } } } var nextIndex = _currentIndex + 1; if (nextIndex < _allEvents.Count) { Current = _allEvents[nextIndex]; _currentIndex = nextIndex; return true; } return false; }
void IParsingEventVisitor.Visit(MappingEnd e) { clonedEvent = new MappingEnd(e.Start, e.End); }
void IParsingEventVisitor.Visit(MappingStart e) { clonedEvent = new MappingStart(null, e.Tag, e.IsImplicit, e.Style, e.Start, e.End); }
void IParsingEventVisitor.Visit(SequenceEnd e) { clonedEvent = new SequenceEnd(e.Start, e.End); }
void IParsingEventVisitor.Visit(SequenceStart e) { clonedEvent = new SequenceStart(null, e.Tag, e.IsImplicit, e.Style, e.Start, e.End); }
void IParsingEventVisitor.Visit(Scalar e) { clonedEvent = new Scalar(null, e.Tag, e.Value, e.Style, e.IsPlainImplicit, e.IsQuotedImplicit, e.Start, e.End); }
/// <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 the root node. /// </summary> private void EmitDocumentContent(ParsingEvent evt) { states.Push(EmitterState.DocumentEnd); EmitNode(evt, true, false, false); }
private void AssertEvent(ParsingEvent expected, ParsingEvent actual, int eventNumber) { actual.GetType().Should().Be(expected.GetType(), "Parse event {0} is not of the expected type.", eventNumber); foreach (var property in expected.GetType().GetProperties()) { if (property.PropertyType == typeof(Mark) || !property.CanRead) { continue; } var value = property.GetValue(actual, null); var expectedValue = property.GetValue(expected, null); if (expectedValue is IEnumerable && !(expectedValue is string)) { Dump.Write("\t{0} = {{", property.Name); Dump.Write(string.Join(", ", (IEnumerable)value)); Dump.WriteLine("}"); if (expectedValue is ICollection && value is ICollection) { var expectedCount = ((ICollection)expectedValue).Count; var valueCount = ((ICollection)value).Count; valueCount.Should().Be(expectedCount, "Compared size of collections in property {0} in parse event {1}", property.Name, eventNumber); } var values = ((IEnumerable)value).GetEnumerator(); var expectedValues = ((IEnumerable)expectedValue).GetEnumerator(); while (expectedValues.MoveNext()) { values.MoveNext().Should().BeTrue("Property {0} in parse event {1} had too few elements", property.Name, eventNumber); values.Current.Should().Be(expectedValues.Current, "Compared element in property {0} in parse event {1}", property.Name, eventNumber); } values.MoveNext().Should().BeFalse("Property {0} in parse event {1} had too many elements", property.Name, eventNumber); } else { Dump.WriteLine("\t{0} = {1}", property.Name, value); value.Should().Be(expectedValue, "Compared property {0} in parse event {1}", property.Name, eventNumber); } } }
/// <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"); } }
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 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); }
private void StateMachine(ParsingEvent evt) { var comment = evt as Comment; if (comment != null) { EmitComment(comment); return; } 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(); } }
/// <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> /// Emit an evt. /// </summary> public void Emit(ParsingEvent @event) { events.Enqueue(@event); while (!NeedMoreEvents()) { var current = events.Peek(); try { AnalyzeEvent(current); StateMachine(current); } finally { // 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 SCALAR. /// </summary> private void EmitScalar(ParsingEvent evt) { SelectScalarStyle(evt); ProcessAnchor(); ProcessTag(); IncreaseIndent(true, false); ProcessScalar(); indent = indents.Pop(); state = states.Pop(); }
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); } AnalyzeAnchor(nodeEvent.Anchor, false); if (!string.IsNullOrEmpty(nodeEvent.Tag) && (isCanonical || nodeEvent.IsCanonical)) { AnalyzeTag(nodeEvent.Tag); } } }
/// <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; }
/// <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 AssertNext(Parser parser, ParsingEvent expected) { AssertHasNext(parser); AssertCurrent(parser, expected); }
/// <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); }