Skip to content

Commit

Permalink
Merge pull request #9 from canro91/refactor-factories
Browse files Browse the repository at this point in the history
Add a Flatten parser to aggreagate output from multi-line parsers
  • Loading branch information
canro91 authored Jan 7, 2023
2 parents da0420e + ef5709d commit c9a794a
Show file tree
Hide file tree
Showing 18 changed files with 240 additions and 206 deletions.
27 changes: 18 additions & 9 deletions Parsinator.Sample/FrameTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ public void Parse_PositionFrame_ParsesBody()
new ParseFromLineWithCountAfterPosition(key: "IMEI", lineNumber: 1, startPosition: 8, charCount: 14),
new ParseFromLineWithCountAfterPosition(key: "Cmd", lineNumber: 1, startPosition: 22, charCount: 4),
new ParseFromOutput(
parseFrom: new ParseFromLineWithCountAfterPosition(key: "Body", lineNumber: 1, startPosition: 26, charCount: -8, factory: (str) => ConvertHexToAscii(str)),
parseFrom:
new Flatten(
(parsed) => ConvertHexToAscii(parsed["Body"]),
new ParseFromLineWithCountAfterPosition(key: "Body", lineNumber: 1, startPosition: 26, charCount: -8)),
parsers: new List<IParse>
{
new ParseFromMultiGroupRegex(pattern: new Regex(@"(?<TimeStamp>\d{6}\.\d{2}),(?<Validity>A|V),(?<Latitude>\d{4,5}\.\d{5}),(?<NorthSouth>N|S),(?<Longitude>\d{4,5}\.\d{5}),(?<EastWest>E|W),(?<SpeedInKnots>\d+\.\d+),(?<TrueCourse>\d+\.\d+)?,(?<DateStamp>\d{6})\|(?<Custom>\S*)"))
Expand Down Expand Up @@ -130,15 +133,21 @@ public void Parse_EventFrame_ParsesBody()
predicate: (str) => str == "9999",
@if: new ParseFromLineWithCountAfterPosition(key: "Cmd", lineNumber: 1, startPosition: 22, charCount: 4),
then: new AndThen(
first: new ParseFromLineWithCountAfterPosition(key: "Event", lineNumber: 1, startPosition: 26, charCount: 2),
second: new ParseFromOutput(
parseFrom: new ParseFromLineWithCountAfterPosition(key: "Body", lineNumber: 1, startPosition: 28, charCount: -8, factory: (str) => ConvertHexToAscii(str)),
parsers: new List<IParse>
{
new ParseFromMultiGroupRegex(pattern: new Regex(@"(?<TimeStamp>\d{6}(\.\d{2})?),(?<Validity>A|V),(?<Latitude>\d{4,5}\.\d{4,5}),(?<NorthSouth>N|S),(?<Longitude>\d{4,5}\.\d{4,5}),(?<EastWest>E|W),(?<SpeedInKnots>\d+(\.\d+)?),(?<TrueCourse>\d+(\.\d+)?)?,(?<DateStamp>\d{6})\|(?<Custom>\S*)"))
})),
first: new ParseFromLineWithCountAfterPosition(key: "Event", lineNumber: 1, startPosition: 26, charCount: 2),
second: new ParseFromOutput(
parseFrom:
new Flatten(
parsed => ConvertHexToAscii(parsed["Body"]),
new ParseFromLineWithCountAfterPosition(key: "Body", lineNumber: 1, startPosition: 28, charCount: -8)),
parsers: new List<IParse>
{
new ParseFromMultiGroupRegex(pattern: new Regex(@"(?<TimeStamp>\d{6}(\.\d{2})?),(?<Validity>A|V),(?<Latitude>\d{4,5}\.\d{4,5}),(?<NorthSouth>N|S),(?<Longitude>\d{4,5}\.\d{4,5}),(?<EastWest>E|W),(?<SpeedInKnots>\d+(\.\d+)?),(?<TrueCourse>\d+(\.\d+)?)?,(?<DateStamp>\d{6})\|(?<Custom>\S*)"))
})),
@else: new ParseFromOutput(
parseFrom: new ParseFromLineWithCountAfterPosition(key: "Body", lineNumber: 1, startPosition: 26, charCount: -8, factory: (str) => ConvertHexToAscii(str)),
parseFrom:
new Flatten(
(parsed) => ConvertHexToAscii(parsed["Body"]),
new ParseFromLineWithCountAfterPosition(key: "Body", lineNumber: 1, startPosition: 26, charCount: -8)),
parsers: new List<IParse>
{
new ParseFromMultiGroupRegex(pattern: new Regex(@"(?<TimeStamp>\d{6}\.\d{2}),(?<Validity>A|V),(?<Latitude>\d{4,5}\.\d{5}),(?<NorthSouth>N|S),(?<Longitude>\d{4,5}\.\d{5}),(?<EastWest>E|W),(?<SpeedInKnots>\d+\.\d+),(?<TrueCourse>\d+\.\d+)?,(?<DateStamp>\d{6})\|(?<Custom>\S*)"))
Expand Down
19 changes: 14 additions & 5 deletions Parsinator.Tests/Fluent/ParseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ 2 value
var parser = new Parser(p);
var ds = parser.Parse(lines);

Assert.AreEqual("1 Any 2 value", ds["Key"]["Value"]);
Assert.AreEqual("1 Any", ds["Key"]["Value[0]"]);
Assert.AreEqual("2 value", ds["Key"]["Value[1]"]);
}

[Test]
Expand Down Expand Up @@ -127,7 +128,8 @@ This line will be ignored
var parser = new Parser(p);
var ds = parser.Parse(lines);

Assert.AreEqual("Any value", ds["Key"]["Value"]);
Assert.AreEqual("Any", ds["Key"]["Value[0]"]);
Assert.AreEqual("value", ds["Key"]["Value[1]"]);
}

[Test]
Expand All @@ -154,7 +156,9 @@ This line will be ignored
var parser = new Parser(p);
var ds = parser.Parse(lines);

Assert.AreEqual("--Begin-- Any value", ds["Key"]["Value"]);
Assert.AreEqual("--Begin--", ds["Key"]["Value[0]"]);
Assert.AreEqual("Any", ds["Key"]["Value[1]"]);
Assert.AreEqual("value", ds["Key"]["Value[2]"]);
}

[Test]
Expand All @@ -181,7 +185,9 @@ This line will be ignored
var parser = new Parser(p);
var ds = parser.Parse(lines);

Assert.AreEqual("Any value --End--", ds["Key"]["Value"]);
Assert.AreEqual("Any", ds["Key"]["Value[0]"]);
Assert.AreEqual("value", ds["Key"]["Value[1]"]);
Assert.AreEqual("--End--", ds["Key"]["Value[2]"]);
}

[Test]
Expand All @@ -208,7 +214,10 @@ This line will be ignored
var parser = new Parser(p);
var ds = parser.Parse(lines);

Assert.AreEqual("--Begin-- Any value --End--", ds["Key"]["Value"]);
Assert.AreEqual("--Begin--", ds["Key"]["Value[0]"]);
Assert.AreEqual("Any", ds["Key"]["Value[1]"]);
Assert.AreEqual("value", ds["Key"]["Value[2]"]);
Assert.AreEqual("--End--", ds["Key"]["Value[3]"]);
}

[Test]
Expand Down
4 changes: 3 additions & 1 deletion Parsinator.Tests/ParseTests.Details.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public void Parse_Details_ApplyDetailsInEveryLine()
Value: 20
-- Details --
1 Item1 10
2 Item2 10
2 Item2 20
-- End of Details --");

var parser = new Parser(p, s, t, d);
Expand All @@ -52,9 +52,11 @@ 2 Item2 10

Assert.IsTrue(ds.ContainsKey("Details[1]"));
Assert.AreEqual("Item1", ds["Details[1]"]["Name"]);
Assert.AreEqual("10", ds["Details[1]"]["Value"]);

Assert.IsTrue(ds.ContainsKey("Details[2]"));
Assert.AreEqual("Item2", ds["Details[2]"]["Name"]);
Assert.AreEqual("20", ds["Details[2]"]["Value"]);
}

[Test]
Expand Down
7 changes: 4 additions & 3 deletions Parsinator.Tests/ParseTests.Page.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,11 @@ public void Parse_AndThenAndMatchInBothParsersWithPages_ParsersValueFromBothPars
"Key",
new List<IParse>
{
new AndThen(
new Flatten(
(output) => $"{string.Join("", output.Values)}",
new ParseFromRegex(key: "Value", pageNumber: 2, pattern: new Regex(@"Value:\s*(\d+)")),
new ParseFromRegex(key: "Result", pageNumber: 3, pattern: new Regex(@"Result:\s*(\d+)")))
new AndThen(
new ParseFromRegex(key: "Value", pageNumber: 2, pattern: new Regex(@"Value:\s*(\d+)")),
new ParseFromRegex(key: "Result", pageNumber: 3, pattern: new Regex(@"Result:\s*(\d+)"))))
}
}
};
Expand Down
67 changes: 43 additions & 24 deletions Parsinator.Tests/ParseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ public void Parse_MultipleLineStringUntilRegex_ParseStringFromLineNumberUntilReg
"Key",
new List<IParse>
{
new ParseFromLineNumberUntilFirstMatchOfRegex(key: "Value", lineNumber: 1, pattern: new Regex(@"--End--"), factory: (allLines) => string.Join(" ", allLines.Values)),
new Flatten(
parsed => string.Join(" ", parsed.Values),
new ParseFromLineNumberUntilFirstMatchOfRegex(key: "Value", lineNumber: 1, pattern: new Regex(@"--End--")))
}
}
};
Expand All @@ -131,7 +133,7 @@ public void Parse_MultipleLineStringUntilRegex_ParseStringFromLineNumberUntilReg
}

[Test]
public void Parse_MultipleLineStringUntilRegex_ParseStringsAndConcatenateThemByDefault()
public void Parse_MultipleLineStringUntilRegex_ParseStringsAndEnumerateThem()
{
var p = new Dictionary<string, IEnumerable<IParse>>
{
Expand All @@ -151,7 +153,8 @@ public void Parse_MultipleLineStringUntilRegex_ParseStringsAndConcatenateThemByD
var parser = new Parser(p);
var ds = parser.Parse(lines);

Assert.AreEqual("Any value", ds["Key"]["Value"]);
Assert.AreEqual("Any", ds["Key"]["Value[0]"]);
Assert.AreEqual("value", ds["Key"]["Value[1]"]);
}

[Test]
Expand Down Expand Up @@ -235,7 +238,9 @@ public void Parse_MultipleLineStringBetweenTwoRegexes_ParseStringBetweenRegexes(
"Key",
new List<IParse>
{
new ParseFromRegexToRegex(key: "Value", first: new Regex(@"--Begin--"), second: new Regex(@"--End--"), factory: (allLines) => string.Join(" ", allLines.Values)),
new Flatten(
parsed => string.Join(" ", parsed.Values),
new ParseFromRegexToRegex(key: "Value", first: new Regex(@"--Begin--"), second: new Regex(@"--End--"))),
}
}
};
Expand All @@ -254,7 +259,7 @@ This line will be ignored
}

[Test]
public void Parse_MultipleLineStringBetweenTwoRegexes_ParseStringBetweenRegexesAndConcatenateThemByDefault()
public void Parse_MultipleLineStringBetweenTwoRegexes_ParseStringBetweenRegexesAndEnumerateThem()
{
var p = new Dictionary<string, IEnumerable<IParse>>
{
Expand All @@ -277,7 +282,8 @@ This line will be ignored
var parser = new Parser(p);
var ds = parser.Parse(lines);

Assert.AreEqual("Any value", ds["Key"]["Value"]);
Assert.AreEqual("Any", ds["Key"]["Value[0]"]);
Assert.AreEqual("value", ds["Key"]["Value[1]"]);
}

[Test]
Expand All @@ -289,7 +295,9 @@ public void Parse_MultipleLineStringBetweenTwoRegexes_ParseStringBetweenRegexesI
"Key",
new List<IParse>
{
new ParseFromFirstRegexToRegex(key: "Value", first: new Regex(@"--Begin--"), second: new Regex(@"--End--")),
new Flatten(
parsed => string.Join(" ", parsed.Values),
new ParseFromFirstRegexToRegex(key: "Value", first: new Regex(@"--Begin--"), second: new Regex(@"--End--")))
}
}
};
Expand All @@ -316,7 +324,9 @@ public void Parse_MultipleLineStringBetweenTwoRegexes_ParseStringBetweenRegexesI
"Key",
new List<IParse>
{
new ParseFromRegexToLastRegex(key: "Value", first: new Regex(@"--Begin--"), second: new Regex(@"--End--")),
new Flatten(
parsed => string.Join(" ", parsed.Values),
new ParseFromRegexToLastRegex(key: "Value", first: new Regex(@"--Begin--"), second: new Regex(@"--End--")))
}
}
};
Expand All @@ -343,7 +353,9 @@ public void Parse_MultipleLineStringBetweenTwoRegexes_ParseStringBetweenRegexesI
"Key",
new List<IParse>
{
new ParseFromFirstRegexToLastRegex(key: "Value", first: new Regex(@"--Begin--"), second: new Regex(@"--End--")),
new Flatten(
allLines => string.Join(" ", allLines.Values),
new ParseFromFirstRegexToLastRegex(key: "Value", first: new Regex(@"--Begin--"), second: new Regex(@"--End--")))
}
}
};
Expand Down Expand Up @@ -550,15 +562,17 @@ public void Parse_PositionAndZeroCountInLine_DoesNotParse()
}

[Test]
public void Parse_PositionAndCountInLineWithFactory_ParsesAndAppliesFactory()
public void Parse_PositionAndCountInLine_ParsesAndFlattensResult()
{
var p = new Dictionary<string, IEnumerable<IParse>>
{
{
"Key",
new List<IParse>
{
new ParseFromLineWithCountAfterPosition(key: "Value", lineNumber: 2, startPosition: 5, charCount: 9, factory: (str) => str.ToUpper())
new Flatten(
parsed => parsed["Value"].ToUpper(),
new ParseFromLineWithCountAfterPosition(key: "Value", lineNumber: 2, startPosition: 5, charCount: 9))
}
}
};
Expand Down Expand Up @@ -772,15 +786,17 @@ public void Parse_ValidationAndValueParseThatDoesNotSatisfyPredicate_ParsesValue
}

[Test]
public void Parse_ExceptionInCustomFactory_ThrowsException()
public void Parse_ExceptionInFlatten_ThrowsException()
{
var p = new Dictionary<string, IEnumerable<IParse>>
{
{
"Key",
new List<IParse>
{
new ParseFromRegex(key: "Value", pattern: new Regex(@"Value:\s*(\d+)"), factory: (groups) => throw new Exception("An exception"))
new Flatten(
parsed => throw new Exception("An unexpected exception"),
new ParseFromRegex(key: "Value", pattern: new Regex(@"Value:\s*(\d+)")))
}
}
};
Expand All @@ -804,10 +820,11 @@ public void Parse_AndThenAndMatchInBothParsers_ParsersValueFromBothParsers()
"Key",
new List<IParse>
{
new AndThen(
new Flatten(
(output) => $"{string.Join("", output.Values)}",
new ParseFromRegex(key: "Value", pattern: new Regex(@"Value:\s*(\d+)")),
new ParseFromRegex(key: "Result", pattern: new Regex(@"Result: \s*(\d+)")))
new AndThen(
new ParseFromRegex(key: "Value", pattern: new Regex(@"Value:\s*(\d+)")),
new ParseFromRegex(key: "Result", pattern: new Regex(@"Result: \s*(\d+)"))))
}
}
};
Expand All @@ -831,10 +848,11 @@ public void Parse_AndThenAndFirstParserDoesNotMatch_DoesNotParse()
"Key",
new List<IParse>
{
new AndThen(
new Flatten(
(output) => $"{string.Join("", output.Values)}",
new ParseFromRegex(key: "Value", pattern: new Regex(@"Value:\s*(\d+)")),
new ParseFromRegex(key: "Result", pattern: new Regex(@"Result: \s*(\d+)")))
new AndThen(
new ParseFromRegex(key: "Value", pattern: new Regex(@"Value:\s*(\d+)")),
new ParseFromRegex(key: "Result", pattern: new Regex(@"Result: \s*(\d+)"))))
}
}
};
Expand All @@ -858,10 +876,11 @@ public void Parse_AndThenAndSecondParserDoesNotMatch_DoesNotParse()
"Key",
new List<IParse>
{
new AndThen(
new Flatten(
(output) => $"{string.Join("", output.Values)}",
new ParseFromRegex(key: "Value", pattern: new Regex(@"Value:\s*(\d+)")),
new ParseFromRegex(key: "Result", pattern: new Regex(@"Result: \s*(\d+)")))
new AndThen(
new ParseFromRegex(key: "Value", pattern: new Regex(@"Value:\s*(\d+)")),
new ParseFromRegex(key: "Result", pattern: new Regex(@"Result: \s*(\d+)"))))
}
}
};
Expand Down Expand Up @@ -1350,12 +1369,12 @@ public void Parse_LineSeparatedByCommaAndIgnoreTwoSegments_ParsesValuesAfterTheS
Assert.AreEqual("Result: Foo", ds["Key"]["Value[1]"]);
}

private List<List<String>> FromPagesText(params String[] str)
private List<List<string>> FromPagesText(params string[] str)
{
return str.Select(t => t.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).ToList()).ToList();
}

private List<List<String>> FromText(String str)
private List<List<string>> FromText(string str)
{
return new List<List<string>> { str.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).Skip(1).ToList() };
}
Expand Down
70 changes: 0 additions & 70 deletions Parsinator/ParseWithFactory.cs

This file was deleted.

Loading

0 comments on commit c9a794a

Please sign in to comment.