diff --git a/src/Ramstack.Parsing/Parser.Fold.cs b/src/Ramstack.Parsing/Parser.Fold.cs
index da8c7c1..4266260 100644
--- a/src/Ramstack.Parsing/Parser.Fold.cs
+++ b/src/Ramstack.Parsing/Parser.Fold.cs
@@ -2,6 +2,14 @@ namespace Ramstack.Parsing;
partial class Parser
{
+ ///
+ /// Creates a left-associative parser. This method is equivalent to .
+ ///
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static Parser Fold(this Parser parser, Parser op, Func reduce) =>
+ parser.FoldL(op, reduce);
+
///
/// Creates a left-associative parser.
///
@@ -9,7 +17,7 @@ partial class Parser
///
/// // Example: Number ([+-] Number)*
/// // 1 + 2 + 3 + 4 => (((1 + 2) + 3) + 4)
- /// var sum = number.Fold(OneOf("+-"), (l, r, op) => op == '+' ? l + r : l - r);
+ /// var sum = number.FoldL(OneOf("+-"), (l, r, op) => op == '+' ? l + r : l - r);
///
/// If an operator-operand pair consumes no input, it is discarded and parsing stops
/// without calling the reduction function for that pair.
@@ -22,8 +30,8 @@ partial class Parser
///
/// A parser that performs left-associative folding.
///
- public static Parser Fold(this Parser parser, Parser op, Func reduce) =>
- new FoldParser(parser, op, reduce);
+ public static Parser FoldL(this Parser parser, Parser op, Func reduce) =>
+ new FoldLParser(parser, op, reduce);
///
/// Creates a right-associative parser.
@@ -50,7 +58,7 @@ public static Parser Fold(this Parser parser, Parser FoldR(this Parser parser, Parser op, Func reduce) =>
new FoldRParser(parser, op, reduce);
- #region Inner type: FoldParser
+ #region Inner type: FoldLParser
///
/// Represents a left-associative parser.
@@ -60,7 +68,7 @@ public static Parser FoldR(this Parser parser, ParserThe main parser that matches a value.
/// The operator parser that matches an operator token.
/// A reduction function.
- private sealed class FoldParser(Parser parser, Parser op, Func reduce) : Parser
+ private sealed class FoldLParser(Parser parser, Parser op, Func reduce) : Parser
{
///
public override bool TryParse(ref ParseContext context, [NotNullWhen(true)] out T? value)
diff --git a/src/Ramstack.Parsing/Parser`1.cs b/src/Ramstack.Parsing/Parser`1.cs
index d078cd4..b2d14da 100644
--- a/src/Ramstack.Parsing/Parser`1.cs
+++ b/src/Ramstack.Parsing/Parser`1.cs
@@ -41,7 +41,7 @@ protected Parser(string? name) =>
///
///
/// Exceptions thrown by user-provided functions, such as the callbacks passed to
- /// Map, Do, or Fold, are not suppressed and propagate to the caller.
+ /// Map, Do, or FoldL, are not suppressed and propagate to the caller.
/// Use to capture them in
/// instead.
///
diff --git a/tests/Ramstack.Parsing.Tests/ParsersTests.Fold.cs b/tests/Ramstack.Parsing.Tests/ParsersTests.Fold.cs
index bea7a1a..ea1bda7 100644
--- a/tests/Ramstack.Parsing.Tests/ParsersTests.Fold.cs
+++ b/tests/Ramstack.Parsing.Tests/ParsersTests.Fold.cs
@@ -12,16 +12,37 @@ partial class ParsersTests
[TestCase("1+2-", 3, 3)]
[TestCase("1+2+3+4-2", 8, 9)]
[TestCase("1+2+3+4-2$", 8, 9)]
- public void FoldTest(string expr, int result, int length)
+ public void FoldLTest(string expr, int result, int length)
{
var number = Literal.Number();
- var parser = number.Fold(OneOf("+-"), (l, r, o) => o == '+' ? l + r : l - r);
+ var parser = number.FoldL(OneOf("+-"), (l, r, o) => o == '+' ? l + r : l - r);
Assert.That(parser.Parse(expr).Success, Is.True);
Assert.That(parser.Parse(expr).Value, Is.EqualTo(result));
Assert.That(parser.Map(m => (m.Index, m.Length)).Parse(expr).Value, Is.EqualTo((0, length)));
}
+ [TestCase("8", 8, 1)]
+ [TestCase("8-3-1", 4, 5)]
+ [TestCase("8-3-", 5, 3)]
+ public void Fold_EquivalentToFoldL(string expr, int expected, int length)
+ {
+ var number = Literal.Number();
+ var op = L('-');
+ var reduce = (int l, int r, char _) => l - r;
+
+ var parsers = new[] { number.Fold(op, reduce), number.FoldL(op, reduce) };
+
+ foreach (var parser in parsers)
+ {
+ var result = parser.Parse(expr);
+
+ Assert.That(result.Success, Is.True);
+ Assert.That(result.Value, Is.EqualTo(expected));
+ Assert.That(result.Length, Is.EqualTo(length));
+ }
+ }
+
[TestCase("2", "2", 1)]
[TestCase("2$", "2", 1)]
[TestCase("2**", "2", 1)]
@@ -39,7 +60,7 @@ public void FoldRTest(string expr, string result, int length)
}
[Test]
- public void Fold_NoInputConsumed_StopsWithoutReducing([Values] bool rightAssociative)
+ public void FoldL_NoInputConsumed_StopsWithoutReducing([Values] bool rightAssociative)
{
var operand = new BoundedParser(Return(2));
var op = Return('-');
@@ -53,7 +74,7 @@ public void Fold_NoInputConsumed_StopsWithoutReducing([Values] bool rightAssocia
var parser = rightAssociative
? operand.FoldR(op, reduce)
- : operand.Fold(op, reduce);
+ : operand.FoldL(op, reduce);
var context = new ParseContext("!tail");
context.Advance(1);
@@ -71,7 +92,7 @@ public void Fold_NoInputConsumed_StopsWithoutReducing([Values] bool rightAssocia
}
[Test]
- public void FoldVoid_NoInputConsumed_StopsWithoutReducing([Values] bool rightAssociative)
+ public void FoldLVoid_NoInputConsumed_StopsWithoutReducing([Values] bool rightAssociative)
{
var operand = new BoundedParser(Return(2));
var op = Return('-');
@@ -85,7 +106,7 @@ public void FoldVoid_NoInputConsumed_StopsWithoutReducing([Values] bool rightAss
var parser = rightAssociative
? operand.FoldR(op, reduce)
- : operand.Fold(op, reduce);
+ : operand.FoldL(op, reduce);
var context = new ParseContext("!tail");
context.Advance(1);
@@ -103,7 +124,7 @@ public void FoldVoid_NoInputConsumed_StopsWithoutReducing([Values] bool rightAss
[TestCase(false, 6)]
[TestCase(true, 8)]
- public void Fold_TrailingEmptyPair_StopsWithoutReducing(bool rightAssociative, int expected)
+ public void FoldL_TrailingEmptyPair_StopsWithoutReducing(bool rightAssociative, int expected)
{
var operand = new BoundedParser(
Literal.Number().DefaultOnFail(2)
@@ -120,7 +141,7 @@ public void Fold_TrailingEmptyPair_StopsWithoutReducing(bool rightAssociative, i
var parser = rightAssociative
? operand.FoldR(op, reduce)
- : operand.Fold(op, reduce);
+ : operand.FoldL(op, reduce);
var result = parser.Parse("10-3-1!");
@@ -131,7 +152,7 @@ public void Fold_TrailingEmptyPair_StopsWithoutReducing(bool rightAssociative, i
}
[Test]
- public void FoldVoid_TrailingEmptyPair_StopsWithoutReducing([Values] bool rightAssociative)
+ public void FoldLVoid_TrailingEmptyPair_StopsWithoutReducing([Values] bool rightAssociative)
{
var operand = new BoundedParser(
Literal.Number().DefaultOnFail(2)
@@ -148,7 +169,7 @@ public void FoldVoid_TrailingEmptyPair_StopsWithoutReducing([Values] bool rightA
var parser = rightAssociative
? operand.FoldR(op, reduce)
- : operand.Fold(op, reduce);
+ : operand.FoldL(op, reduce);
var result = parser.Void().Parse("10-3-1!");
@@ -159,14 +180,14 @@ public void FoldVoid_TrailingEmptyPair_StopsWithoutReducing([Values] bool rightA
[TestCase(false, -4)]
[TestCase(true, 2)]
- public void Fold_OnlyOperandConsumesInput_ContinuesParsing(bool rightAssociative, int expected)
+ public void FoldL_OnlyOperandConsumesInput_ContinuesParsing(bool rightAssociative, int expected)
{
var operand = Set('0', '9').Do(c => c - '0');
var op = Return('-');
var parser = rightAssociative
? operand.FoldR(op, (l, r, _) => l - r)
- : operand.Fold(op, (l, r, _) => l - r);
+ : operand.FoldL(op, (l, r, _) => l - r);
var result = parser.Parse("123!");
@@ -176,14 +197,14 @@ public void Fold_OnlyOperandConsumesInput_ContinuesParsing(bool rightAssociative
}
[Test]
- public void FoldVoid_OnlyOperandConsumesInput_ContinuesParsing([Values] bool rightAssociative)
+ public void FoldLVoid_OnlyOperandConsumesInput_ContinuesParsing([Values] bool rightAssociative)
{
var operand = Set('0', '9').Do(c => c - '0');
var op = Return('-');
var parser = rightAssociative
? operand.FoldR(op, (l, r, _) => l - r)
- : operand.Fold(op, (l, r, _) => l - r);
+ : operand.FoldL(op, (l, r, _) => l - r);
var result = parser.Void().Parse("123!");
@@ -193,14 +214,14 @@ public void FoldVoid_OnlyOperandConsumesInput_ContinuesParsing([Values] bool rig
[TestCase(false, -2)]
[TestCase(true, 2)]
- public void Fold_OnlyOperatorConsumesInput_ContinuesParsing(bool rightAssociative, int expected)
+ public void FoldL_OnlyOperatorConsumesInput_ContinuesParsing(bool rightAssociative, int expected)
{
var operand = Return(2);
var op = L('-');
var parser = rightAssociative
? operand.FoldR(op, (l, r, _) => l - r)
- : operand.Fold(op, (l, r, _) => l - r);
+ : operand.FoldL(op, (l, r, _) => l - r);
var result = parser.Parse("--!");
@@ -210,14 +231,14 @@ public void Fold_OnlyOperatorConsumesInput_ContinuesParsing(bool rightAssociativ
}
[Test]
- public void FoldVoid_OnlyOperatorConsumesInput_ContinuesParsing([Values] bool rightAssociative)
+ public void FoldLVoid_OnlyOperatorConsumesInput_ContinuesParsing([Values] bool rightAssociative)
{
var operand = Return(2);
var op = L('-');
var parser = rightAssociative
? operand.FoldR(op, (l, r, _) => l - r)
- : operand.Fold(op, (l, r, _) => l - r);
+ : operand.FoldL(op, (l, r, _) => l - r);
var result = parser.Void().Parse("--!");