From 09257a24ba092427f6af52ed46737ccf1a12b31d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Ros?= Date: Tue, 4 Jan 2022 16:40:56 -0800 Subject: [PATCH] Fix compilation issues (#60) --- docs/parsers.md | 19 +++++++++++- src/Parlot/Fluent/Error.cs | 51 ++++++++++++++++--------------- src/Parlot/Fluent/OneOf.cs | 2 +- test/Parlot.Tests/CompileTests.cs | 15 ++++++++- test/Parlot.Tests/FluentTests.cs | 24 +++++++++++++-- 5 files changed, 81 insertions(+), 30 deletions(-) diff --git a/docs/parsers.md b/docs/parsers.md index e8e7a12..6058927 100644 --- a/docs/parsers.md +++ b/docs/parsers.md @@ -619,7 +619,7 @@ Point { x: 1, y: 2} ### ElseError -Fails parsing with a custom error message. +Fails parsing with a custom error message when the inner parser didn't match. ```c# Parser ElseError(string message) @@ -645,12 +645,29 @@ failure: "Expected an integer at (1:3) ### Error +Fails parsing with a custom error message when the inner parser matched. + ```c# Parser Error(string message) Parser Error(string message) ``` +Usage: +```c# +var parser = + Terms.Char('a') + .Or(Terms.Char('b') + .Or(Terms.Char('c').Error("Unexpected char c") + +parser.Parse("1,"); +``` + +Result: + +``` +failure: "Expected an integer at (1:3) +``` ### When Adds some additional logic for a parser to succeed. diff --git a/src/Parlot/Fluent/Error.cs b/src/Parlot/Fluent/Error.cs index cfb3e4e..5316825 100644 --- a/src/Parlot/Fluent/Error.cs +++ b/src/Parlot/Fluent/Error.cs @@ -37,13 +37,16 @@ public CompilationResult Compile(CompilationContext context) var value = context.DeclareValueVariable(result, Expression.Default(typeof(T))); // parse1 instructions + // success = true // - // if (!parser1.Success) + // if (parser1.Success) + // { + // value = parser1.Value + // } + // else // { // throw new ParseException(_message, context.Scanner.Cursor.Position); // } - // - // value = parser1.Value // var parserCompileResult = _parser.Build(context, requireResult: true); @@ -51,18 +54,19 @@ public CompilationResult Compile(CompilationContext context) var block = Expression.Block( parserCompileResult.Variables, parserCompileResult.Body + .Append(Expression.Assign(value, parserCompileResult.Value)) .Append( - Expression.IfThen( - Expression.Not(parserCompileResult.Success), + Expression.IfThenElse( + parserCompileResult.Success, + context.DiscardResult + ? Expression.Empty() + : Expression.Assign(value, parserCompileResult.Value), context.ThrowParseException(Expression.Constant(_message)) - ) - ).Append( - context.DiscardResult - ? Expression.Empty() - : Expression.Assign(value, parserCompileResult.Value) - ) + + + )) ); - + result.Body.Add(block); return result; @@ -96,18 +100,19 @@ public CompilationResult Compile(CompilationContext context) { var result = new CompilationResult(); - _ = context.DeclareSuccessVariable(result, true); - var value = context.DeclareValueVariable(result, Expression.Default(typeof(T))); + _ = context.DeclareSuccessVariable(result, false); + _ = context.DeclareValueVariable(result, Expression.Default(typeof(T))); // parse1 instructions - // + // success = false; + // // if (parser1.Success) // { // value = parser1.Value; // throw new ParseException(_message, context.Scanner.Cursor.Position); // } - var parserCompileResult = _parser.Build(context, requireResult: true); + var parserCompileResult = _parser.Build(context, requireResult: false); var block = Expression.Block( parserCompileResult.Variables, @@ -115,12 +120,7 @@ public CompilationResult Compile(CompilationContext context) .Append( Expression.IfThen( parserCompileResult.Success, - Expression.Block( - context.DiscardResult - ? Expression.Empty() - : Expression.Assign(value, parserCompileResult.Value), - context.ThrowParseException(Expression.Constant(_message)) - ) + context.ThrowParseException(Expression.Constant(_message)) ) ) ); @@ -153,24 +153,25 @@ public override bool Parse(ParseContext context, ref ParseResult result) throw new ParseException(_message, context.Scanner.Cursor.Position); } - return true; + return false; } public CompilationResult Compile(CompilationContext context) { var result = new CompilationResult(); - _ = context.DeclareSuccessVariable(result, true); + _ = context.DeclareSuccessVariable(result, false); _ = context.DeclareValueVariable(result, Expression.Default(typeof(U))); // parse1 instructions + // success = false; // // if (parser1.Success) // { // throw new ParseException(_message, context.Scanner.Cursor.Position); // } - var parserCompileResult = _parser.Build(context, requireResult: true); + var parserCompileResult = _parser.Build(context, requireResult: false); var block = Expression.Block( parserCompileResult.Variables, diff --git a/src/Parlot/Fluent/OneOf.cs b/src/Parlot/Fluent/OneOf.cs index e1773cd..f9333ca 100644 --- a/src/Parlot/Fluent/OneOf.cs +++ b/src/Parlot/Fluent/OneOf.cs @@ -171,7 +171,7 @@ public CompilationResult Compile(CompilationContext context) var start = context.DeclarePositionVariable(result); block = Expression.Block( - context.SkipWhiteSpace(), + context.ParserSkipWhiteSpace(), switchExpr, Expression.IfThen( Expression.IsFalse(success), diff --git a/test/Parlot.Tests/CompileTests.cs b/test/Parlot.Tests/CompileTests.cs index 0710b07..a0ed5f6 100644 --- a/test/Parlot.Tests/CompileTests.cs +++ b/test/Parlot.Tests/CompileTests.cs @@ -439,12 +439,25 @@ public void CompiledWhenShouldResetPositionWhenFalse() Assert.True(evenIntegers.TryParse("1235", out var result1)); Assert.Equal(1235, result1.Item2); } - + [Fact] public void ErrorShouldThrowIfParserSucceeds() { Assert.False(Literals.Char('a').Error("'a' was not expected").Compile().TryParse("a", out _, out var error)); Assert.Equal("'a' was not expected", error.Message); + + Assert.False(Literals.Char('a').Error("'a' was not expected").Compile().TryParse("a", out _, out error)); + Assert.Equal("'a' was not expected", error.Message); + } + + [Fact] + public void ErrorShouldReturnFalseThrowIfParserFails() + { + Assert.False(Literals.Char('a').Error("'a' was not expected").Compile().TryParse("b", out _, out var error)); + Assert.Null(error); + + Assert.False(Literals.Char('a').Error("'a' was not expected").Compile().TryParse("b", out _, out error)); + Assert.Null(error); } [Fact] diff --git a/test/Parlot.Tests/FluentTests.cs b/test/Parlot.Tests/FluentTests.cs index 32ce5a3..79879fc 100644 --- a/test/Parlot.Tests/FluentTests.cs +++ b/test/Parlot.Tests/FluentTests.cs @@ -514,15 +514,35 @@ public void ErrorShouldThrowIfParserSucceeds() { Assert.False(Literals.Char('a').Error("'a' was not expected").TryParse("a", out _, out var error)); Assert.Equal("'a' was not expected", error.Message); + + Assert.False(Literals.Char('a').Error("'a' was not expected").TryParse("a", out _, out error)); + Assert.Equal("'a' was not expected", error.Message); } - + + [Fact] + public void ErrorShouldReturnFalseThrowIfParserFails() + { + Assert.False(Literals.Char('a').Error("'a' was not expected").TryParse("b", out _, out var error)); + Assert.Null(error); + + Assert.False(Literals.Char('a').Error("'a' was not expected").TryParse("b", out _, out error)); + Assert.Null(error); + } + [Fact] public void ErrorShouldThrow() { Assert.False(Literals.Char('a').Error("'a' was not expected").TryParse("a", out _, out var error)); Assert.Equal("'a' was not expected", error.Message); } - + + [Fact] + public void ErrorShouldResetPosition() + { + Assert.False(Literals.Char('a').Error("'a' was not expected").TryParse("a", out _, out var error)); + Assert.Equal("'a' was not expected", error.Message); + } + [Fact] public void ElseErrorShouldThrowIfParserFails() {