Skip to content

Commit

Permalink
Fix back-tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastienros committed Jan 2, 2021
1 parent 1c17b47 commit 1ba6600
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/Parlot/Fluent/OneOf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,18 @@ public override bool Parse(ParseContext context, ref ParseResult<ParseResult<obj

var parsed = new ParseResult<object>();

var start = context.Scanner.Cursor.Position;

for (var i = 0; i < Parsers.Count; i++)
{
if (Parsers[i].Parse(context, ref parsed))
{
result.Set(parsed.Buffer, parsed.Start, parsed.End, parsed);
return true;
}

// If the choice as a subset of its parsers that succeeded, it might have advanced the cursor
context.Scanner.Cursor.ResetPosition(start);
}

return false;
Expand Down Expand Up @@ -61,12 +66,17 @@ public override bool Parse(ParseContext context, ref ParseResult<T> result)
return false;
}

var start = context.Scanner.Cursor.Position;

for (var i = 0; i < Parsers.Count; i++)
{
if (Parsers[i].Parse(context, ref result))
{
return true;
}

// If the choice as a subset of its parsers that succeeded, it might have advanced the cursor
context.Scanner.Cursor.ResetPosition(start);
}

return false;
Expand Down
15 changes: 15 additions & 0 deletions src/Parlot/Fluent/Sequence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public override bool Parse(ParseContext context, ref ParseResult<ValueTuple<T1,
result.Set(parseResult1.Buffer, parseResult1.Start, parseResult2.End, new ValueTuple<T1, T2>(parseResult1.Value, parseResult2.Value));
return true;
}

context.Scanner.Cursor.ResetPosition(parseResult1.Start);
}

return false;
Expand Down Expand Up @@ -69,6 +71,8 @@ public override bool Parse(ParseContext context, ref ParseResult<ValueTuple<T1,
result.Set(tupleResult.Buffer, tupleResult.Start, lastResult.End, tuple);
return true;
}

context.Scanner.Cursor.ResetPosition(tupleResult.Start);
}

return false;
Expand Down Expand Up @@ -108,6 +112,8 @@ public override bool Parse(ParseContext context, ref ParseResult<ValueTuple<T1,
result.Set(tupleResult.Buffer, tupleResult.Start, lastResult.End, tuple);
return true;
}

context.Scanner.Cursor.ResetPosition(tupleResult.Start);
}

return false;
Expand Down Expand Up @@ -148,6 +154,8 @@ public override bool Parse(ParseContext context, ref ParseResult<ValueTuple<T1,
result.Set(tupleResult.Buffer, tupleResult.Start, lastResult.End, tuple);
return true;
}

context.Scanner.Cursor.ResetPosition(tupleResult.Start);
}

return false;
Expand Down Expand Up @@ -189,6 +197,8 @@ public override bool Parse(ParseContext context, ref ParseResult<ValueTuple<T1,
result.Set(tupleResult.Buffer, tupleResult.Start, lastResult.End, tuple);
return true;
}

context.Scanner.Cursor.ResetPosition(tupleResult.Start);
}

return false;
Expand Down Expand Up @@ -232,6 +242,8 @@ public override bool Parse(ParseContext context, ref ParseResult<ValueTuple<T1,
result.Set(tupleResult.Buffer, tupleResult.Start, lastResult.End, tuple);
return true;
}

context.Scanner.Cursor.ResetPosition(tupleResult.Start);
}

return false;
Expand Down Expand Up @@ -261,6 +273,8 @@ public override bool Parse(ParseContext context, ref ParseResult<IList<ParseResu

var parsed = new ParseResult<object>();

var start = context.Scanner.Cursor.Position;

for (var i = 0; i < _parsers.Length; i++)
{
if (!_parsers[i].Parse(context, ref parsed))
Expand All @@ -279,6 +293,7 @@ public override bool Parse(ParseContext context, ref ParseResult<IList<ParseResu
}
else
{
context.Scanner.Cursor.ResetPosition(start);
return false;
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/Parlot/Fluent/SkipAnd.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public override bool Parse(ParseContext context, ref ParseResult<T> result)
result.Set(parseResult1.Buffer, parseResult1.Start, parseResult2.End, parseResult2.Value);
return true;
}

context.Scanner.Cursor.ResetPosition(parseResult1.Start);
}

return false;
Expand Down
12 changes: 12 additions & 0 deletions src/Parlot/Fluent/TextBefore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ public override bool Parse(ParseContext context, ref ParseResult<TextSpan> resul

var parsed = new ParseResult<T>();

if (_delimiter.Parse(context, ref parsed))
{
context.Scanner.Cursor.ResetPosition(start);
return false;
}

while (true)
{
if (_delimiter.Parse(context, ref parsed) || (!_failOnEof && context.Scanner.Cursor.Eof))
Expand Down Expand Up @@ -88,6 +94,12 @@ public override bool Parse(ParseContext context, ref ParseResult<TextSpan> resul

var parsed = new ParseResult<object>();

if (_delimiter.Parse(context, ref parsed))
{
context.Scanner.Cursor.ResetPosition(start);
return false;
}

while (true)
{
if (_delimiter.Parse(context, ref parsed) || (!_failOnEof && context.Scanner.Cursor.Eof))
Expand Down
12 changes: 12 additions & 0 deletions test/Parlot.Tests/FluentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -248,5 +248,17 @@ public void NumbersShouldAcceptSignIfAllowed()
Assert.Equal(-123, Terms.Decimal(NumberOptions.AllowSign).Parse("-123"));
Assert.Equal(-123, Terms.Integer(NumberOptions.AllowSign).Parse("-123"));
}

[Fact]
public void OneOfShouldRestorePosition()
{
var choice = OneOf(
Literals.Char('a').And(Literals.Char('b')).And(Literals.Char('c')).And(Literals.Char('d')),
Literals.Char('a').And(Literals.Char('b')).And(Literals.Char('e')).And(Literals.Char('d'))
).Then(x => x.Item1.ToString() + x.Item2.ToString() + x.Item3.ToString() + x.Item4.ToString());

Assert.Equal("abcd", choice.Parse("abcd"));
Assert.Equal("abed", choice.Parse("abed"));
}
}
}

0 comments on commit 1ba6600

Please sign in to comment.