Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix compilation issues #60

Merged
merged 3 commits into from
Jan 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion docs/parsers.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> ElseError(string message)
Expand All @@ -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<T> Error(string message)
Parser<U> Error<U>(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.
Expand Down
51 changes: 26 additions & 25 deletions src/Parlot/Fluent/Error.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,32 +37,36 @@ 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);

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;
Expand Down Expand Up @@ -96,31 +100,27 @@ 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,
parserCompileResult.Body
.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))
)
)
);
Expand Down Expand Up @@ -153,24 +153,25 @@ public override bool Parse(ParseContext context, ref ParseResult<U> 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,
Expand Down
2 changes: 1 addition & 1 deletion src/Parlot/Fluent/OneOf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
15 changes: 14 additions & 1 deletion test/Parlot.Tests/CompileTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<int>("'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<int>("'a' was not expected").Compile().TryParse("b", out _, out error));
Assert.Null(error);
}

[Fact]
Expand Down
24 changes: 22 additions & 2 deletions test/Parlot.Tests/FluentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<int>("'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<int>("'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()
{
Expand Down