Skip to content

Commit

Permalink
Merge pull request #203 from aaubry/issue-149
Browse files Browse the repository at this point in the history
Fix EventReader limitations.
  • Loading branch information
aaubry authored Aug 31, 2016
2 parents 5dbf200 + 2bededd commit 796f91f
Show file tree
Hide file tree
Showing 28 changed files with 151 additions and 190 deletions.
4 changes: 2 additions & 2 deletions YamlDotNet.Test/Serialization/SerializationTestHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ protected TextReader UsingReaderFor(string text)
return new StringReader(text);
}

protected static EventReader EventReaderFor(string yaml)
protected static IParser ParserFor(string yaml)
{
return new EventReader(new Parser(new StringReader(yaml)));
return new Parser(new StringReader(yaml));
}

protected string Lines(params string[] lines)
Expand Down
10 changes: 5 additions & 5 deletions YamlDotNet.Test/Serialization/SerializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ public void DeserializeListOfDictionaries()
[Fact]
public void DeserializeTwoDocuments()
{
var reader = EventReaderFor(Lines(
var reader = ParserFor(Lines(
"---",
"aaa: 111",
"---",
Expand All @@ -613,7 +613,7 @@ public void DeserializeTwoDocuments()
[Fact]
public void DeserializeThreeDocuments()
{
var reader = EventReaderFor(Lines(
var reader = ParserFor(Lines(
"---",
"aaa: 111",
"---",
Expand Down Expand Up @@ -963,7 +963,7 @@ public void BackreferencesAreMergedWithMappings()
var stream = Yaml.StreamFrom("backreference.yaml");

var parser = new MergingParser(new Parser(stream));
var result = Deserializer.Deserialize<Dictionary<string, Dictionary<string, string>>>(new EventReader(parser));
var result = Deserializer.Deserialize<Dictionary<string, Dictionary<string, string>>>(parser);

var alias = result["alias"];
alias.Should()
Expand All @@ -986,7 +986,7 @@ public void MergingDoesNotProduceDuplicateAnchors()
useMyValue:
key: *myValue
"));
var result = Deserializer.Deserialize<Dictionary<string, Dictionary<string, string>>>(new EventReader(parser));
var result = Deserializer.Deserialize<Dictionary<string, Dictionary<string, string>>>(parser);

var alias = result["alias"];
alias.Should()
Expand Down Expand Up @@ -1037,7 +1037,7 @@ public void ExampleFromSpecificationIsHandledCorrectly()
label: center/big
"));

var result = Deserializer.Deserialize<Dictionary<string, List<Dictionary<string, string>>>>(new EventReader(parser));
var result = Deserializer.Deserialize<Dictionary<string, List<Dictionary<string, string>>>>(parser);

int index = 0;
foreach (var mapping in result["results"])
Expand Down
11 changes: 6 additions & 5 deletions YamlDotNet/Core/IParser.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
// This file is part of YamlDotNet - A .NET library for YAML.
// Copyright (c) Antoine Aubry and contributors

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Expand All @@ -19,7 +19,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

using YamlDotNet.Core.Events;
using YamlDotNet.Core.Events;

namespace YamlDotNet.Core
{
Expand All @@ -29,7 +29,8 @@ namespace YamlDotNet.Core
public interface IParser
{
/// <summary>
/// Gets the current event.
/// Gets the current event. Returns null before the first call to <see cref="MoveNext" />,
/// and also after <see cref="MoveNext" /> returns false.
/// </summary>
ParsingEvent Current { get; }

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
// This file is part of YamlDotNet - A .NET library for YAML.
// Copyright (c) Antoine Aubry and contributors

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Expand All @@ -19,51 +19,26 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

using System.IO;
using System.Globalization;
using System.IO;
using YamlDotNet.Core.Events;

namespace YamlDotNet.Core
{
/// <summary>
/// Reads events from a sequence of <see cref="ParsingEvent" />.
/// Extension methods that provide useful abstractions over <see cref="IParser"/>.
/// </summary>
public class EventReader
public static class ParserExtensions
{
private readonly IParser parser;
private bool endOfStream;

/// <summary>
/// Initializes a new instance of the <see cref="EventReader"/> class.
/// </summary>
/// <param name="parser">The parser that provides the events.</param>
public EventReader(IParser parser)
{
this.parser = parser;
MoveNext();
}

/// <summary>
/// Gets the underlying parser.
/// </summary>
/// <value>The parser.</value>
public IParser Parser
{
get
{
return parser;
}
}

/// <summary>
/// Ensures that the current event is of the specified type, returns it and moves to the next event.
/// </summary>
/// <typeparam name="T">Type of the <see cref="ParsingEvent"/>.</typeparam>
/// <returns>Returns the current event.</returns>
/// <exception cref="YamlException">If the current event is not of the specified type.</exception>
public T Expect<T>() where T : ParsingEvent
public static T Expect<T>(this IParser parser) where T : ParsingEvent
{
var expectedEvent = Allow<T>();
var expectedEvent = parser.Allow<T>();
if (expectedEvent == null)
{
// TODO: Throw a better exception
Expand All @@ -79,18 +54,16 @@ public T Expect<T>() where T : ParsingEvent
/// </summary>
/// <typeparam name="T">Type of the event.</typeparam>
/// <returns>Returns true if the current event is of type <typeparamref name="T"/>. Otherwise returns false.</returns>
public bool Accept<T>() where T : ParsingEvent
public static bool Accept<T>(this IParser parser) where T : ParsingEvent
{
ThrowIfAtEndOfStream();
return parser.Current is T;
}

private void ThrowIfAtEndOfStream()
{
if (endOfStream)
if(parser.Current == null)
{
throw new EndOfStreamException();
if (!parser.MoveNext())
{
throw new EndOfStreamException();
}
}
return parser.Current is T;
}

/// <summary>
Expand All @@ -100,14 +73,14 @@ private void ThrowIfAtEndOfStream()
/// </summary>
/// <typeparam name="T">Type of the <see cref="ParsingEvent"/>.</typeparam>
/// <returns>Returns the current event if it is of type T; otherwise returns null.</returns>
public T Allow<T>() where T : ParsingEvent
public static T Allow<T>(this IParser parser) where T : ParsingEvent
{
if (!Accept<T>())
if (!parser.Accept<T>())
{
return null;
}
var @event = (T) parser.Current;
MoveNext();
var @event = (T)parser.Current;
parser.MoveNext();
return @event;
}

Expand All @@ -116,32 +89,27 @@ public T Allow<T>() where T : ParsingEvent
/// </summary>
/// <typeparam name="T">Type of the <see cref="ParsingEvent"/>.</typeparam>
/// <returns>Returns the current event if it is of type T; otherwise returns null.</returns>
public T Peek<T>() where T : ParsingEvent
public static T Peek<T>(this IParser parser) where T : ParsingEvent
{
if (!Accept<T>())
if (!parser.Accept<T>())
{
return null;
}
return (T) parser.Current;
return (T)parser.Current;
}

/// <summary>
/// Skips the current event and any nested event.
/// </summary>
public void SkipThisAndNestedEvents()
public static void SkipThisAndNestedEvents(this IParser parser)
{
var depth = 0;
do
{
depth += Peek<ParsingEvent>().NestingIncrease;
MoveNext();
depth += parser.Peek<ParsingEvent>().NestingIncrease;
parser.MoveNext();
}
while(depth > 0);
}

private void MoveNext()
{
endOfStream = !parser.MoveNext();
while (depth > 0);
}
}
}
11 changes: 5 additions & 6 deletions YamlDotNet/RepresentationModel/YamlDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,16 @@ public YamlDocument(string rootNode)
/// <summary>
/// Initializes a new instance of the <see cref="YamlDocument"/> class.
/// </summary>
/// <param name="events">The events.</param>
internal YamlDocument(EventReader events)
internal YamlDocument(IParser parser)
{
DocumentLoadingState state = new DocumentLoadingState();

events.Expect<DocumentStart>();
parser.Expect<DocumentStart>();

while (!events.Accept<DocumentEnd>())
while (!parser.Accept<DocumentEnd>())
{
Debug.Assert(RootNode == null);
RootNode = YamlNode.ParseNode(events, state);
RootNode = YamlNode.ParseNode(parser, state);

if (RootNode is YamlAliasNode)
{
Expand All @@ -89,7 +88,7 @@ internal YamlDocument(EventReader events)
}
#endif

events.Expect<DocumentEnd>();
parser.Expect<DocumentEnd>();
}

/// <summary>
Expand Down
22 changes: 10 additions & 12 deletions YamlDotNet/RepresentationModel/YamlMappingNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,24 +59,22 @@ public IDictionary<YamlNode, YamlNode> Children
/// <summary>
/// Initializes a new instance of the <see cref="YamlMappingNode"/> class.
/// </summary>
/// <param name="events">The events.</param>
/// <param name="state">The state.</param>
internal YamlMappingNode(EventReader events, DocumentLoadingState state)
internal YamlMappingNode(IParser parser, DocumentLoadingState state)
{
Load(events, state);
Load(parser, state);
}

private void Load(EventReader events, DocumentLoadingState state)
private void Load(IParser parser, DocumentLoadingState state)
{
MappingStart mapping = events.Expect<MappingStart>();
MappingStart mapping = parser.Expect<MappingStart>();
base.Load(mapping, state);
Style = mapping.Style;

bool hasUnresolvedAliases = false;
while (!events.Accept<MappingEnd>())
while (!parser.Accept<MappingEnd>())
{
YamlNode key = ParseNode(events, state);
YamlNode value = ParseNode(events, state);
YamlNode key = ParseNode(parser, state);
YamlNode value = ParseNode(parser, state);

try
{
Expand Down Expand Up @@ -111,7 +109,7 @@ private void Load(EventReader events, DocumentLoadingState state)
}
#endif

events.Expect<MappingEnd>();
parser.Expect<MappingEnd>();
}

/// <summary>
Expand Down Expand Up @@ -394,9 +392,9 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()

#endregion

void IYamlConvertible.Read(EventReader reader, Type expectedType, Func<EventReader, Type, object> nestedObjectDeserializer)
void IYamlConvertible.Read(IParser parser, Type expectedType, Func<IParser, Type, object> nestedObjectDeserializer)
{
Load(reader, new DocumentLoadingState());
Load(parser, new DocumentLoadingState());
}

void IYamlConvertible.Write(IEmitter emitter)
Expand Down
22 changes: 10 additions & 12 deletions YamlDotNet/RepresentationModel/YamlNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,31 +73,29 @@ internal void Load(NodeEvent yamlEvent, DocumentLoadingState state)
}

/// <summary>
/// Parses the node represented by the next event in <paramref name="events" />.
/// Parses the node represented by the next event in <paramref name="parser" />.
/// </summary>
/// <param name="events">The events.</param>
/// <param name="state">The state.</param>
/// <returns>Returns the node that has been parsed.</returns>
static internal YamlNode ParseNode(EventReader events, DocumentLoadingState state)
static internal YamlNode ParseNode(IParser parser, DocumentLoadingState state)
{
if (events.Accept<Scalar>())
if (parser.Accept<Scalar>())
{
return new YamlScalarNode(events, state);
return new YamlScalarNode(parser, state);
}

if (events.Accept<SequenceStart>())
if (parser.Accept<SequenceStart>())
{
return new YamlSequenceNode(events, state);
return new YamlSequenceNode(parser, state);
}

if (events.Accept<MappingStart>())
if (parser.Accept<MappingStart>())
{
return new YamlMappingNode(events, state);
return new YamlMappingNode(parser, state);
}

if (events.Accept<AnchorAlias>())
if (parser.Accept<AnchorAlias>())
{
AnchorAlias alias = events.Expect<AnchorAlias>();
AnchorAlias alias = parser.Expect<AnchorAlias>();
return state.GetNode(alias.Value, false, alias.Start, alias.End) ?? new YamlAliasNode(alias.Value);
}

Expand Down
Loading

0 comments on commit 796f91f

Please sign in to comment.