Skip to content

Commit

Permalink
Reintroduce C# files in all projects, now that the .NET Core project …
Browse files Browse the repository at this point in the history
…structure has been set up to house them.
  • Loading branch information
plioi committed Jun 14, 2016
1 parent cef137a commit 6fe0e1e
Show file tree
Hide file tree
Showing 50 changed files with 3,551 additions and 0 deletions.
43 changes: 43 additions & 0 deletions src/Parsley.Tests/AssertionExtensions.cs
@@ -0,0 +1,43 @@
namespace Parsley.Tests
{
using System;
using System.Collections.Generic;
using System.Linq;
using Shouldly;

public static class AssertionExtensions
{
public static void ShouldThrow<TException>(this Action shouldThrow, string expectedMessage) where TException : Exception
{
bool threw = false;

try
{
shouldThrow();
}
catch (TException ex)
{
ex.Message.ShouldBe(expectedMessage);
threw = true;
}

threw.ShouldBeTrue($"Expected {typeof (TException).Name}.");
}

public static void ShouldThrow<TException>(this Func<object> shouldThrow, string expectedMessage) where TException : Exception
{
Action action = () => shouldThrow();
action.ShouldThrow<TException>(expectedMessage);
}

public static void ShouldList<T>(this IEnumerable<T> actual, params Action<T>[] itemExpectations)
{
var array = actual.ToArray();

array.Length.ShouldBe(itemExpectations.Length);

for (int i = 0; i < array.Length; i++)
itemExpectations[i](array[i]);
}
}
}
8 changes: 8 additions & 0 deletions src/Parsley.Tests/CharLexer.cs
@@ -0,0 +1,8 @@
namespace Parsley.Tests
{
public class CharLexer : Lexer
{
public CharLexer()
: base(new Pattern("Character", @".")) { }
}
}
140 changes: 140 additions & 0 deletions src/Parsley.Tests/ErrorMessageListTests.cs
@@ -0,0 +1,140 @@
namespace Parsley.Tests
{
using Shouldly;
using Xunit;
using ErrorMessage = Parsley.ErrorMessage;

public class ErrorMessageListTests
{
[Fact]
public void ShouldProvideSharedEmptyInstance()
{
ErrorMessageList.Empty.ShouldBeSameAs(ErrorMessageList.Empty);
}

[Fact]
public void CanBeEmpty()
{
ErrorMessageList.Empty.ToString().ShouldBe("");
}

[Fact]
public void CreatesNewCollectionWhenAddingItems()
{
ErrorMessageList list = ErrorMessageList.Empty.With(ErrorMessage.Expected("expectation"));

list.ToString().ShouldBe("expectation expected");
list.ShouldNotBeSameAs(ErrorMessageList.Empty);
}

[Fact]
public void CanIncludeUnknownErrors()
{
ErrorMessageList.Empty
.With(ErrorMessage.Unknown())
.ToString().ShouldBe("Parse error.");
}

[Fact]
public void CanIncludeMultipleExpectations()
{
ErrorMessageList.Empty
.With(ErrorMessage.Expected("A"))
.With(ErrorMessage.Expected("B"))
.ToString().ShouldBe("A or B expected");

ErrorMessageList.Empty
.With(ErrorMessage.Expected("A"))
.With(ErrorMessage.Expected("B"))
.With(ErrorMessage.Expected("C"))
.ToString().ShouldBe("A, B or C expected");

ErrorMessageList.Empty
.With(ErrorMessage.Expected("A"))
.With(ErrorMessage.Expected("B"))
.With(ErrorMessage.Expected("C"))
.With(ErrorMessage.Expected("D"))
.ToString().ShouldBe("A, B, C or D expected");
}

[Fact]
public void OmitsDuplicateExpectationsFromExpectationLists()
{
ErrorMessageList.Empty
.With(ErrorMessage.Expected("A"))
.With(ErrorMessage.Expected("A"))
.With(ErrorMessage.Expected("B"))
.With(ErrorMessage.Expected("C"))
.With(ErrorMessage.Unknown())
.With(ErrorMessage.Expected("C"))
.With(ErrorMessage.Expected("C"))
.With(ErrorMessage.Expected("A"))
.ToString().ShouldBe("A, B or C expected");
}

[Fact]
public void CanIncludeBacktrackErrors()
{
var deepBacktrack = ErrorMessage.Backtrack(new Position(3, 4),
ErrorMessageList.Empty
.With(ErrorMessage.Expected("A"))
.With(ErrorMessage.Expected("B")));

var shallowBacktrack = ErrorMessage.Backtrack(new Position(2, 3),
ErrorMessageList.Empty
.With(ErrorMessage.Expected("C"))
.With(ErrorMessage.Expected("D"))
.With(deepBacktrack));

var unrelatedBacktrack = ErrorMessage.Backtrack(new Position(1, 2),
ErrorMessageList.Empty
.With(ErrorMessage.Expected("E"))
.With(ErrorMessage.Expected("F")));

ErrorMessageList.Empty
.With(deepBacktrack)
.ToString().ShouldBe("[(3, 4): A or B expected]");

ErrorMessageList.Empty
.With(shallowBacktrack)
.ToString().ShouldBe("[(2, 3): C or D expected [(3, 4): A or B expected]]");

ErrorMessageList.Empty
.With(ErrorMessage.Expected("G"))
.With(ErrorMessage.Expected("H"))
.With(shallowBacktrack)
.With(unrelatedBacktrack)
.ToString().ShouldBe("G or H expected [(1, 2): E or F expected] [(2, 3): C or D expected [(3, 4): A or B expected]]");
}

[Fact]
public void CanMergeTwoLists()
{
var first = ErrorMessageList.Empty
.With(ErrorMessage.Expected("A"))
.With(ErrorMessage.Expected("B"))
.With(ErrorMessage.Unknown())
.With(ErrorMessage.Expected("C"));

var second = ErrorMessageList.Empty
.With(ErrorMessage.Expected("D"))
.With(ErrorMessage.Expected("B"))
.With(ErrorMessage.Unknown())
.With(ErrorMessage.Expected("E"));

first.Merge(second)
.ToString().ShouldBe("A, B, C, D or E expected");
}

[Fact]
public void OmitsUnknownErrorsWhenAdditionalErrorsExist()
{
ErrorMessageList.Empty
.With(ErrorMessage.Expected("A"))
.With(ErrorMessage.Expected("B"))
.With(ErrorMessage.Unknown())
.With(ErrorMessage.Expected("C"))
.ToString().ShouldBe("A, B or C expected");
}
}
}
38 changes: 38 additions & 0 deletions src/Parsley.Tests/ErrorMessageTests.cs
@@ -0,0 +1,38 @@
namespace Parsley.Tests
{
using Shouldly;
using Xunit;
using ErrorMessage = Parsley.ErrorMessage;

public class ErrorMessageTests
{
[Fact]
public void CanIndicateGenericErrors()
{
var error = ErrorMessage.Unknown();
error.ToString().ShouldBe("Parse error.");
}

[Fact]
public void CanIndicateSpecificExpectation()
{
var error = (ExpectedErrorMessage)ErrorMessage.Expected("statement");
error.Expectation.ShouldBe("statement");
error.ToString().ShouldBe("statement expected");
}

[Fact]
public void CanIndicateErrorsWhichCausedBacktracking()
{
var position = new Position(3, 4);
ErrorMessageList errors = ErrorMessageList.Empty
.With(ErrorMessage.Expected("a"))
.With(ErrorMessage.Expected("b"));

var error = (BacktrackErrorMessage) ErrorMessage.Backtrack(position, errors);
error.Position.ShouldBe(position);
error.Errors.ShouldBe(errors);
error.ToString().ShouldBe("(3, 4): a or b expected");
}
}
}
57 changes: 57 additions & 0 deletions src/Parsley.Tests/ErrorTests.cs
@@ -0,0 +1,57 @@
namespace Parsley.Tests
{
using System;
using Shouldly;
using Xunit;
using ErrorMessage = Parsley.ErrorMessage;

public class ErrorTests
{
readonly TokenStream x;
readonly TokenStream endOfInput;

public ErrorTests()
{
var lexer = new Lexer();
x = new TokenStream(lexer.Tokenize("x"));
endOfInput = new TokenStream(lexer.Tokenize(""));
}

[Fact]
public void CanIndicateErrorsAtTheCurrentPosition()
{
new Error<object>(endOfInput, ErrorMessage.Unknown()).ErrorMessages.ToString().ShouldBe("Parse error.");
new Error<object>(endOfInput, ErrorMessage.Expected("statement")).ErrorMessages.ToString().ShouldBe("statement expected");
}

[Fact]
public void CanIndicateMultipleErrorsAtTheCurrentPosition()
{
var errors = ErrorMessageList.Empty
.With(ErrorMessage.Expected("A"))
.With(ErrorMessage.Expected("B"));

new Error<object>(endOfInput, errors).ErrorMessages.ToString().ShouldBe("A or B expected");
}

[Fact]
public void ThrowsWhenAttemptingToGetParsedValue()
{
Func<object> inspectParsedValue = () => new Error<object>(x, ErrorMessage.Unknown()).Value;
inspectParsedValue.ShouldThrow<MemberAccessException>("(1, 1): Parse error.");
}

[Fact]
public void HasRemainingUnparsedTokens()
{
new Error<object>(x, ErrorMessage.Unknown()).UnparsedTokens.ShouldBe(x);
new Error<object>(endOfInput, ErrorMessage.Unknown()).UnparsedTokens.ShouldBe(endOfInput);
}

[Fact]
public void ReportsErrorState()
{
new Error<object>(x, ErrorMessage.Unknown()).Success.ShouldBeFalse();
}
}
}
45 changes: 45 additions & 0 deletions src/Parsley.Tests/GrammarRuleTests.cs
@@ -0,0 +1,45 @@
namespace Parsley.Tests
{
using System.Linq;
using Shouldly;
using Xunit;

public class GrammarRuleTests : Grammar
{
[Fact]
public void CanDefineMutuallyRecursiveRules()
{
var tokens = new CharLexer().Tokenize("(A)");
var expression = new GrammarRule<string>();
var alpha = new GrammarRule<string>();
var parenthesizedExpresion = new GrammarRule<string>();

expression.Rule = Choice(alpha, parenthesizedExpresion);
alpha.Rule = from a in Token("A") select a.Literal;
parenthesizedExpresion.Rule = Between(Token("("), expression, Token(")"));

expression.Parses(tokens).WithValue("A");
}

[Fact]
public void HasAnOptionallyProvidedName()
{
var unnamed = new GrammarRule<string>();
var named = new GrammarRule<string>("Named");

unnamed.Name.ShouldBeNull();
named.Name.ShouldBe("Named");
}

[Fact]
public void ProvidesAdviceWhenRuleIsUsedBeforeBeingInitialized()
{
var tokens = new CharLexer().Tokenize("123").ToArray();
var numeric = new GrammarRule<string>();
var alpha = new GrammarRule<string>("Alpha");

numeric.FailsToParse(tokens).WithMessage("(1, 1): An anonymous GrammarRule has not been initialized. Try setting the Rule property.");
alpha.FailsToParse(tokens).WithMessage("(1, 1): GrammarRule 'Alpha' has not been initialized. Try setting the Rule property.");
}
}
}

0 comments on commit 6fe0e1e

Please sign in to comment.