diff --git a/.idea/.idea.Sprache/.idea/.gitignore b/.idea/.idea.Sprache/.idea/.gitignore new file mode 100644 index 0000000..d8ebb05 --- /dev/null +++ b/.idea/.idea.Sprache/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/contentModel.xml +/modules.xml +/projectSettingsUpdater.xml +/.idea.Sprache.iml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/.idea.Sprache/.idea/.name b/.idea/.idea.Sprache/.idea/.name new file mode 100644 index 0000000..bc4fb0d --- /dev/null +++ b/.idea/.idea.Sprache/.idea/.name @@ -0,0 +1 @@ +Sprache \ No newline at end of file diff --git a/.idea/.idea.Sprache/.idea/encodings.xml b/.idea/.idea.Sprache/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.Sprache/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.Sprache/.idea/indexLayout.xml b/.idea/.idea.Sprache/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.Sprache/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.Sprache/.idea/vcs.xml b/.idea/.idea.Sprache/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/.idea.Sprache/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 06e433f..18059b1 100755 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ The best place to start is [this introductory article](http://nblumhardt.com/201 * [Parsing comma-separated values (CSV) into lists of strings](https://github.com/sprache/Sprache/blob/master/test/Sprache.Tests/Scenarios/CsvTests.cs) **Tutorials** explaining Sprache: - + * Overview of Sprache methods, [long guide by Justing Pealing](https://justinpealing.me.uk/post/2020-03-11-sprache1-chars/) * A great [CodeProject article by Alexey Yakovlev ](http://www.codeproject.com/Articles/795056/Sprache-Calc-building-yet-another-expression-evalu) (and [in Russian](http://habrahabr.ru/post/228037/)) * Mike Hadlow's example of [parsing connection strings](http://mikehadlow.blogspot.com.au/2012/09/parsing-connection-string-with-sprache.html) * Alexey Golub's article on [monadic parser combinators](https://tyrrrz.me/blog/monadic-parser-combinators) that shows how to build a JSON parser using Sprache diff --git a/appveyor.yml b/appveyor.yml index fe7180a..bf4d6fa 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,7 +3,7 @@ image: Visual Studio 2019 branches: only: - - master + - main - develop pull_requests: @@ -18,8 +18,8 @@ artifacts: deploy: - provider: NuGet api_key: - secure: tCEhrNs1q8bhXiGwKejajsjSyF+/66LwnPge1ntZKrI3mvfDf1Ab8iOrz1IuVRH2 + secure: LOSaZSy3ZL836xUIcCovdIt5kbL/aahbQPl2CvLCWxWaS+YSpKMB/OUAlbgLGp8Z skip_symbols: true artifact: /.*\.nupkg/ on: - branch: /^(master|develop)$/ + branch: /^(main|develop)$/ diff --git a/build.ps1 b/build.ps1 index 8239bff..705aa27 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,6 +1,6 @@ $branch = @{ $true = $env:APPVEYOR_REPO_BRANCH; $false = $(git symbolic-ref --short -q HEAD) }[$env:APPVEYOR_REPO_BRANCH -ne $NULL]; $revision = @{ $true = "{0:00000}" -f [convert]::ToInt32("0" + $env:APPVEYOR_BUILD_NUMBER, 10); $false = "local" }[$env:APPVEYOR_BUILD_NUMBER -ne $NULL]; -$suffix = @{ $true = ""; $false = "$($branch.Substring(0, [math]::Min(10,$branch.Length)))-$revision"}[$branch -eq "master" -and $revision -ne "local"] +$suffix = @{ $true = ""; $false = "$($branch.Substring(0, [math]::Min(10,$branch.Length)))-$revision"}[$branch -eq "main" -and $revision -ne "local"] echo "build: Version suffix is $suffix" diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..d7febe8 Binary files /dev/null and b/icon.png differ diff --git a/samples/LinqyCalculator/LinqyCalculator.csproj b/samples/LinqyCalculator/LinqyCalculator.csproj index 80895db..1035b4e 100644 --- a/samples/LinqyCalculator/LinqyCalculator.csproj +++ b/samples/LinqyCalculator/LinqyCalculator.csproj @@ -1,22 +1,12 @@  - net45;netcoreapp3.1 - LinqyCalculator + net5.0 Exe - LinqyCalculator - false - false - false - - - - - diff --git a/samples/LinqyCalculator/Program.cs b/samples/LinqyCalculator/Program.cs index af6f289..32aade2 100644 --- a/samples/LinqyCalculator/Program.cs +++ b/samples/LinqyCalculator/Program.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using Sprache; namespace LinqyCalculator diff --git a/samples/LinqyCalculator/Properties/AssemblyInfo.cs b/samples/LinqyCalculator/Properties/AssemblyInfo.cs deleted file mode 100644 index 5a037ad..0000000 --- a/samples/LinqyCalculator/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("LinqyCalculator")] -[assembly: AssemblyTrademark("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("d7a17f71-dd1e-4cd9-9cc8-66322fd8698e")] diff --git a/samples/TinyTemplates.Tests/Properties/AssemblyInfo.cs b/samples/TinyTemplates.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index b873fb0..0000000 --- a/samples/TinyTemplates.Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("TinyTemplates.Tests")] -[assembly: AssemblyTrademark("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("cb505fe2-4188-49d9-9bfd-1d1e213b4423")] diff --git a/samples/TinyTemplates.Tests/TinyTemplates.Tests.csproj b/samples/TinyTemplates.Tests/TinyTemplates.Tests.csproj index f4322a2..6ce32c5 100644 --- a/samples/TinyTemplates.Tests/TinyTemplates.Tests.csproj +++ b/samples/TinyTemplates.Tests/TinyTemplates.Tests.csproj @@ -1,13 +1,7 @@  - net461;netcoreapp3.1 - TinyTemplates.Tests - TinyTemplates.Tests - true - false - false - false + net5.0 @@ -16,9 +10,12 @@ - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/samples/TinyTemplates/Properties/AssemblyInfo.cs b/samples/TinyTemplates/Properties/AssemblyInfo.cs deleted file mode 100644 index 93d6bfd..0000000 --- a/samples/TinyTemplates/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("TinyTemplates")] -[assembly: AssemblyTrademark("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("a0410d8d-2d98-4ee4-a177-db31ca493d19")] diff --git a/samples/TinyTemplates/TinyTemplates.csproj b/samples/TinyTemplates/TinyTemplates.csproj index 5b3f4ae..ca86a18 100644 --- a/samples/TinyTemplates/TinyTemplates.csproj +++ b/samples/TinyTemplates/TinyTemplates.csproj @@ -1,25 +1,11 @@  - Copyright Sprache Contributors 2013 - TinyTemplates - 2.0.0 - Nicholas Blumhardt and Contributors - net45;netstandard2.1 - TinyTemplates - TinyTemplates - false - false - false + net5.0 - - - - - diff --git a/samples/XmlExample/Program.cs b/samples/XmlExample/Program.cs index c8e949e..4d2916a 100644 --- a/samples/XmlExample/Program.cs +++ b/samples/XmlExample/Program.cs @@ -4,7 +4,6 @@ using System.Text; using Sprache; using System.IO; -using System.Xml; namespace XmlExample { diff --git a/samples/XmlExample/Properties/AssemblyInfo.cs b/samples/XmlExample/Properties/AssemblyInfo.cs deleted file mode 100644 index 6782e9d..0000000 --- a/samples/XmlExample/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("XmlExample")] -[assembly: AssemblyTrademark("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("42f99bdf-5f43-40a6-a713-e84ee845f022")] diff --git a/samples/XmlExample/XmlExample.csproj b/samples/XmlExample/XmlExample.csproj index 81408cd..1035b4e 100644 --- a/samples/XmlExample/XmlExample.csproj +++ b/samples/XmlExample/XmlExample.csproj @@ -1,19 +1,10 @@  - netcoreapp3.1 - XmlExample + net5.0 Exe - XmlExample - false - false - false - - - - diff --git a/samples/XmlExample/app.config b/samples/XmlExample/app.config deleted file mode 100644 index 2f7cce7..0000000 --- a/samples/XmlExample/app.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/Sprache/CommentParser.cs b/src/Sprache/CommentParser.cs index 72bb8d3..2c003b3 100644 --- a/src/Sprache/CommentParser.cs +++ b/src/Sprache/CommentParser.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Sprache +namespace Sprache { /// /// Constructs customizable comment parsers. diff --git a/src/Sprache/IComment.cs b/src/Sprache/IComment.cs index f2491c1..039cb47 100644 --- a/src/Sprache/IComment.cs +++ b/src/Sprache/IComment.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Sprache +namespace Sprache { /// /// Represents a customizable comment parser. diff --git a/src/Sprache/IInput.cs b/src/Sprache/IInput.cs index ce57d5e..b6c77c5 100644 --- a/src/Sprache/IInput.cs +++ b/src/Sprache/IInput.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Sprache { diff --git a/src/Sprache/Input.cs b/src/Sprache/Input.cs index 75d8ae9..05e642f 100644 --- a/src/Sprache/Input.cs +++ b/src/Sprache/Input.cs @@ -16,7 +16,7 @@ public class Input : IInput /// /// Gets the list of memos assigned to the instance. /// - public IDictionary Memos { get; private set; } + public IDictionary Memos { get; } /// /// Initializes a new instance of the class. diff --git a/src/Sprache/Parse.cs b/src/Sprache/Parse.cs index 9ca958e..c36cfff 100644 --- a/src/Sprache/Parse.cs +++ b/src/Sprache/Parse.cs @@ -2,6 +2,9 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable InconsistentNaming +// ReSharper disable UnusedMember.Global namespace Sprache { @@ -10,6 +13,11 @@ namespace Sprache /// public static partial class Parse { + /// + /// Message for a failure result when left recursion is detected. + /// + public const string LeftRecursionErrorMessage = "Left recursion in the grammar."; + /// /// TryParse a single character matching 'predicate' /// @@ -284,7 +292,7 @@ public static Parser> Many(this Parser parser) /// unqualified counterparts. /// /// - /// + /// public static Parser> XMany(this Parser parser) { if (parser == null) throw new ArgumentNullException(nameof(parser)); @@ -389,15 +397,15 @@ public static Parser Ref(Func> reference) if (i.Memos.ContainsKey(p)) { - var pResult = i.Memos[p] as IResult; - if (pResult.WasSuccessful) + var pResult = (IResult)i.Memos[p]; + if (pResult.WasSuccessful) return pResult; - throw new ParseException(pResult.ToString()); + + if (!pResult.WasSuccessful && pResult.Message == LeftRecursionErrorMessage) + throw new ParseException(pResult.ToString()); } - i.Memos[p] = Result.Failure(i, - "Left recursion in the grammar.", - new string[0]); + i.Memos[p] = Result.Failure(i, LeftRecursionErrorMessage, new string[0]); var result = p(i); i.Memos[p] = result; return result; @@ -593,7 +601,7 @@ public static Parser Except(this Parser parser, Parser except) /// public static Parser> Until(this Parser parser, Parser until) { - return parser.Except(until).Many().Then(r => until.Return(r)); + return parser.Except(until).Many().Then(until.Return); } /// @@ -610,7 +618,7 @@ public static Parser Where(this Parser parser, Func predicate) return i => parser(i).IfSuccess(s => predicate(s.Value) ? s : Result.Failure(i, - string.Format("Unexpected {0}.", s.Value), + $"Unexpected {s.Value}.", new string[0])); } @@ -686,9 +694,9 @@ static Parser ChainOperatorRest( if (op == null) throw new ArgumentNullException(nameof(op)); if (operand == null) throw new ArgumentNullException(nameof(operand)); if (apply == null) throw new ArgumentNullException(nameof(apply)); - return or(op.Then(opvalue => + return or(op.Then(opValue => operand.Then(operandValue => - ChainOperatorRest(apply(opvalue, firstOperand, operandValue), op, operand, apply, or))), + ChainOperatorRest(apply(opValue, firstOperand, operandValue), op, operand, apply, or))), Return(firstOperand)); } @@ -742,10 +750,10 @@ static Parser ChainRightOperatorRest( if (op == null) throw new ArgumentNullException(nameof(op)); if (operand == null) throw new ArgumentNullException(nameof(operand)); if (apply == null) throw new ArgumentNullException(nameof(apply)); - return or(op.Then(opvalue => + return or(op.Then(opValue => operand.Then(operandValue => ChainRightOperatorRest(operandValue, op, operand, apply, or)).Then(r => - Return(apply(opvalue, lastOperand, r)))), + Return(apply(opValue, lastOperand, r)))), Return(lastOperand)); } diff --git a/src/Sprache/Position.cs b/src/Sprache/Position.cs index a300dc0..b58285c 100644 --- a/src/Sprache/Position.cs +++ b/src/Sprache/Position.cs @@ -1,4 +1,5 @@ using System; +// ReSharper disable MemberCanBePrivate.Global namespace Sprache { @@ -36,7 +37,6 @@ public static Position FromInput(IInput input) public int Pos { get; - private set; } /// @@ -45,7 +45,6 @@ public int Pos public int Line { get; - private set; } /// @@ -54,7 +53,6 @@ public int Line public int Column { get; - private set; } /// diff --git a/src/Sprache/Properties/AssemblyInfo.cs b/src/Sprache/Properties/AssemblyInfo.cs index d7148c6..22470eb 100644 --- a/src/Sprache/Properties/AssemblyInfo.cs +++ b/src/Sprache/Properties/AssemblyInfo.cs @@ -1,4 +1,3 @@ -using System.Reflection; -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Sprache.Tests")] diff --git a/src/Sprache/Sprache.csproj b/src/Sprache/Sprache.csproj index f4699a4..43e50d7 100644 --- a/src/Sprache/Sprache.csproj +++ b/src/Sprache/Sprache.csproj @@ -1,82 +1,32 @@ - + Sprache is a simple, lightweight library for constructing parsers directly in C# code. - Copyright Sprache Contributors 2017 - Sprache - 2.3.1 - Nicholas Blumhardt;Contributors - sl5;net35;net40;net45;netstandard1.0;netstandard2.0;netstandard2.1 + Copyright © Sprache Contributors + 3.0.0 + netstandard2.0;netstandard2.1;net5.0 + $(DefineConstants);STRING_IS_ENUMERABLE;STRING_JOIN_ENUMERABLE true - Sprache - Sprache Parser;Parsers - https://avatars1.githubusercontent.com/u/1999078 + icon.png https://github.com/sprache/Sprache - https://github.com/sprache/Sprache/blob/master/licence.txt + Apache-2.0 git https://github.com/sprache/Sprache + true + true + true + snupkg - - - - - - - - - - - - - - - - - - - - - - - - - $(DefineConstants);STRING_IS_ENUMERABLE;STRING_JOIN_ENUMERABLE - .NETFramework - v4.5 - - - - $(DefineConstants);STRING_IS_ENUMERABLE - C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v3.5\Profile\Client - - - - $(DefineConstants);STRING_JOIN_ENUMERABLE - true - - - - $(DefineConstants);STRING_IS_ENUMERABLE;STRING_JOIN_ENUMERABLE - true - .NETFramework - v4.5 - - - - - - - - + + + - - - - - - + + + PreserveNewest + diff --git a/src/Sprache/StringExtensions.cs b/src/Sprache/StringExtensions.cs index 07fe214..7e081eb 100644 --- a/src/Sprache/StringExtensions.cs +++ b/src/Sprache/StringExtensions.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; namespace Sprache { diff --git a/test/Sprache.Tests/AssertInput.cs b/test/Sprache.Tests/AssertInput.cs index d5debd5..5ae4285 100644 --- a/test/Sprache.Tests/AssertInput.cs +++ b/test/Sprache.Tests/AssertInput.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; + namespace Sprache.Tests { static class AssertInput diff --git a/test/Sprache.Tests/AssertParser.cs b/test/Sprache.Tests/AssertParser.cs index 0fc153d..4357dd8 100644 --- a/test/Sprache.Tests/AssertParser.cs +++ b/test/Sprache.Tests/AssertParser.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Sprache; using Xunit; namespace Sprache.Tests diff --git a/test/Sprache.Tests/DecimalTests.cs b/test/Sprache.Tests/DecimalTests.cs index 3df05f4..2b30ba6 100644 --- a/test/Sprache.Tests/DecimalTests.cs +++ b/test/Sprache.Tests/DecimalTests.cs @@ -1,6 +1,5 @@ using System; using System.Globalization; -using System.Threading; using Xunit; namespace Sprache.Tests diff --git a/test/Sprache.Tests/InputTests.cs b/test/Sprache.Tests/InputTests.cs index a256adb..43eb9da 100644 --- a/test/Sprache.Tests/InputTests.cs +++ b/test/Sprache.Tests/InputTests.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using Xunit; namespace Sprache.Tests diff --git a/test/Sprache.Tests/OptionTests.cs b/test/Sprache.Tests/OptionTests.cs index d8634ed..e52fcc5 100644 --- a/test/Sprache.Tests/OptionTests.cs +++ b/test/Sprache.Tests/OptionTests.cs @@ -1,4 +1,3 @@ -using Sprache; using Xunit; namespace Sprache.Tests diff --git a/test/Sprache.Tests/Parse.Ref.Tests.cs b/test/Sprache.Tests/Parse.Ref.Tests.cs new file mode 100644 index 0000000..533fbaa --- /dev/null +++ b/test/Sprache.Tests/Parse.Ref.Tests.cs @@ -0,0 +1,110 @@ +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace Sprache.Tests +{ + public class ParseRefTests + { + private static Parser ParserHash = Parse.String("#").Text().Named("something"); + + private static Parser ParserIdentifier = (from id in Parse.String("id").Text() select id).Named("identifier"); + + private static Parser Parser1UnderTest = + (from _0 in Parse.Ref(() => ParserIdentifier) + from _1 in Parse.Ref(() => ParserHash) + from _2 in Parse.String("_") + select "alternative_1") + .Or(from _0 in Parse.Ref(() => ParserIdentifier) + from _1 in Parse.Ref(() => ParserHash) + select "alternative_2") + .Or(from _0 in ParserIdentifier select _0); + + private static Parser Parser2UnderTest = + (from _0 in Parse.String("a").Text() + from _1 in Parse.Ref(() => Parser2UnderTest) + select _0 + _1) + .Or(from _0 in Parse.String("b").Text() + from _1 in Parse.Ref(() => Parser2UnderTest) + select _0 + _1) + .Or(from _0 in Parse.String("0").Text() select _0); + + private static Parser Parser3UnderTest = + (from _0 in Parse.Ref(() => Parser3UnderTest) + from _1 in Parse.String("a").Text() + select _0 + _1) + .Or(from _0 in Parse.String("b").Text() + from _1 in Parse.Ref(() => Parser3UnderTest) + select _0 + _1) + .Or(from _0 in Parse.String("0").Text() select _0); + + private static Parser Parser4UnderTest = + from _0 in Parse.Ref(() => Parser4UnderTest) + select "simplest left recursion"; + + private static Parser Parser5UnderTest = + (from _0 in Parse.String("_").Text() + from _1 in Parse.Ref(() => Parser5UnderTest) + select _0 + _1) + .Or(from _0 in Parse.String("+").Text() + from _1 in Parse.Ref(() => Parser5UnderTest) + select _0 + _1) + .Or(Parse.Return("")); + + [Fact] + public void MultipleRefs() => AssertParser.SucceedsWith(Parser1UnderTest, "id=1", o => Assert.Equal("id", o)); + + [Fact] + public void RecursiveParserWithoutLeftRecursion() => AssertParser.SucceedsWith(Parser2UnderTest, "ababba0", o => Assert.Equal("ababba0", o)); + + [Fact] + public void RecursiveParserWithLeftRecursion() => Assert.Throws(() => Parser3UnderTest.TryParse("b0")); + + [Fact] + public void SimplestLeftRecursion() => Assert.Throws(() => Parser4UnderTest.TryParse("test")); + + [Fact] + public void EmptyAlternative1() => AssertParser.SucceedsWith(Parser5UnderTest, "_+_+a", o => Assert.Equal("_+_+", o)); + + [Fact] + public void Issue166() + { + var letterA = Parse.Char('a'); + var letterReferenced = Parse.Ref(() => letterA); + var someAlternative = letterReferenced.Or(letterReferenced); + + Assert.False(someAlternative.TryParse("b").WasSuccessful); + } + + static readonly Parser> ASeq = + (from first in Parse.Ref(() => ASeq) + from comma in Parse.Char(',') + from rest in Parse.Char('a').Once() + select first.Concat(rest)) + .Or(Parse.Char('a').Once()); + + [Fact] + public void DetectsLeftRecursion() + { + Assert.Throws(() => ASeq.TryParse("a,a,a")); + } + + static readonly Parser> ABSeq = + (from first in Parse.Ref(() => BASeq) + from rest in Parse.Char('a').Once() + select first.Concat(rest)) + .Or(Parse.Char('a').Once()); + + static readonly Parser> BASeq = + (from first in Parse.Ref(() => ABSeq) + from rest in Parse.Char('b').Once() + select first.Concat(rest)) + .Or(Parse.Char('b').Once()); + + [Fact] + public void DetectsMutualLeftRecursion() + { + Assert.Throws(() => ABSeq.End().TryParse("baba")); + } + } +} diff --git a/test/Sprache.Tests/ParseTests.cs b/test/Sprache.Tests/ParseTests.cs index ea4af56..5336146 100644 --- a/test/Sprache.Tests/ParseTests.cs +++ b/test/Sprache.Tests/ParseTests.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using Xunit; @@ -145,37 +144,6 @@ public void ParsesString_AsSequenceOfChars() AssertParser.SucceedsWithAll(p, "abc"); } - static readonly Parser> ASeq = - (from first in Parse.Ref(() => ASeq) - from comma in Parse.Char(',') - from rest in Parse.Char('a').Once() - select first.Concat(rest)) - .Or(Parse.Char('a').Once()); - - [Fact] - public void DetectsLeftRecursion() - { - Assert.Throws(() => ASeq.TryParse("a,a,a")); - } - - static readonly Parser> ABSeq = - (from first in Parse.Ref(() => BASeq) - from rest in Parse.Char('a').Once() - select first.Concat(rest)) - .Or(Parse.Char('a').Once()); - - static readonly Parser> BASeq = - (from first in Parse.Ref(() => ABSeq) - from rest in Parse.Char('b').Once() - select first.Concat(rest)) - .Or(Parse.Char('b').Once()); - - [Fact] - public void DetectsMutualLeftRecursion() - { - Assert.Throws(() => ABSeq.End().TryParse("baba")); - } - [Fact] public void WithMany_WhenLastElementFails_FailureReportedAtLastElement() { @@ -521,7 +489,7 @@ public void DelimitedWithMinimum() public void DelimitedWithMaximum() { var sequence = Parse.Char('a').DelimitedBy(Parse.Char(','), null, 4); - Assert.Equal(1, sequence.TryParse("a").Value.Count()); + Assert.Single(sequence.TryParse("a").Value); Assert.Equal(3, sequence.TryParse("a,a,a").Value.Count()); Assert.Equal(4, sequence.TryParse("a,a,a,a").Value.Count()); Assert.Equal(4, sequence.TryParse("a,a,a,a,a").Value.Count()); diff --git a/test/Sprache.Tests/PosAwareStr.cs b/test/Sprache.Tests/PosAwareStr.cs index c32d062..c22c76b 100644 --- a/test/Sprache.Tests/PosAwareStr.cs +++ b/test/Sprache.Tests/PosAwareStr.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Sprache.Tests +namespace Sprache.Tests { class PosAwareStr : IPositionAware { diff --git a/test/Sprache.Tests/Properties/AssemblyInfo.cs b/test/Sprache.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index bee8c97..0000000 --- a/test/Sprache.Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Sprache.Tests")] -[assembly: AssemblyTrademark("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("5af7e4ae-efc0-485c-8560-c0785a21d28b")] diff --git a/test/Sprache.Tests/ResultTests.cs b/test/Sprache.Tests/ResultTests.cs index 772607c..9c30e36 100644 --- a/test/Sprache.Tests/ResultTests.cs +++ b/test/Sprache.Tests/ResultTests.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; using Xunit; namespace Sprache.Tests diff --git a/test/Sprache.Tests/Scenarios/AmqpErrorTests.cs b/test/Sprache.Tests/Scenarios/AmqpErrorTests.cs index a3204fb..156bb36 100644 --- a/test/Sprache.Tests/Scenarios/AmqpErrorTests.cs +++ b/test/Sprache.Tests/Scenarios/AmqpErrorTests.cs @@ -1,6 +1,5 @@ // ReSharper disable InconsistentNaming -using System; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -87,7 +86,7 @@ public class AmqpErrorItem public class AmqpStringItem : AmqpErrorItem { - public string Text { get; private set; } + public string Text { get; } public AmqpStringItem(string text) { @@ -102,8 +101,8 @@ public override string ToString() public class KeyValue : AmqpErrorItem { - public Value Value { get; private set; } - public string Key { get; private set; } + public Value Value { get; } + public string Key { get; } public KeyValue(string key, Value value) { @@ -124,7 +123,7 @@ public class Value public class StringValue : Value { - public string Text { get; private set; } + public string Text { get; } public StringValue(string text) { @@ -139,7 +138,7 @@ public override string ToString() public class IntValue : Value { - public int Value { get; private set; } + public int Value { get; } public IntValue(int value) { diff --git a/test/Sprache.Tests/Scenarios/StarDateTest.cs b/test/Sprache.Tests/Scenarios/StarDateTest.cs index 6d613b0..40c1433 100644 --- a/test/Sprache.Tests/Scenarios/StarDateTest.cs +++ b/test/Sprache.Tests/Scenarios/StarDateTest.cs @@ -1,8 +1,5 @@ using Xunit; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Sprache.Tests.Scenarios { diff --git a/test/Sprache.Tests/Sprache.Tests.csproj b/test/Sprache.Tests/Sprache.Tests.csproj index 2d868b9..8b8fb50 100644 --- a/test/Sprache.Tests/Sprache.Tests.csproj +++ b/test/Sprache.Tests/Sprache.Tests.csproj @@ -1,13 +1,7 @@  - net461;netcoreapp3.1 - Sprache.Tests - Sprache.Tests - true - false - false - false + net5.0 @@ -15,9 +9,12 @@ - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + +