Skip to content

Commit 7a7cd1e

Browse files
committed
Simplify parsers
1 parent eb9bc54 commit 7a7cd1e

16 files changed

+108
-105
lines changed

src/SimpleStateMachine.StructuralSearch.Tests/StructuralSearchTests.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ public static void StructuralSearchShouldBeSuccess2(string filePath)
4747
var configuration = new Configuration
4848
{
4949
FindTemplate = "$Modificator$ $ReturnType$ $MethodName$($params$)",
50-
FindRules = new List<string>
51-
{
50+
FindRules =
51+
[
5252
"$Modificator$ in (\"public\", \"private\", \"internal\")",
5353
"$ReturnType$ is var",
5454
"$MethodName$ is var"
55-
}
55+
]
5656
};
5757

5858
var parser = new StructuralSearchParser(configuration);

src/SimpleStateMachine.StructuralSearch/Constant.cs

+18-20
Original file line numberDiff line numberDiff line change
@@ -153,26 +153,24 @@ internal static class Constant
153153
RightCurlyParenthesis
154154
};
155155

156-
public static class FindTemplate
156+
public static readonly IReadOnlySet<char> InvalidStringLiteralChars = new HashSet<char>(AllParenthesis)
157157
{
158-
public static readonly IReadOnlySet<char> All = new HashSet<char>(AllParenthesis)
159-
{
160-
PlaceholderSeparator,
161-
CarriageReturn,
162-
LineFeed,
163-
Space
164-
};
165-
}
166-
167-
public static class Parameter
158+
CarriageReturn,
159+
LineFeed,
160+
Space
161+
};
162+
163+
public static readonly IReadOnlySet<char> All = new HashSet<char>(InvalidStringLiteralChars)
168164
{
169-
public static readonly IReadOnlySet<char> Escape = new HashSet<char>
170-
{
171-
DoubleQuotes,
172-
PlaceholderSeparator,
173-
Dote
174-
};
175-
176-
public static readonly IReadOnlySet<char> Excluded = AllParenthesis.Union(Escape).ToHashSet();
177-
}
165+
PlaceholderSeparator,
166+
};
167+
168+
public static readonly IReadOnlySet<char> CharsToEscape = new HashSet<char>
169+
{
170+
DoubleQuotes,
171+
PlaceholderSeparator,
172+
Dote
173+
};
174+
175+
public static readonly IReadOnlySet<char> LanguageSyntaxChars = AllParenthesis.Union(CharsToEscape).ToHashSet();
178176
}

src/SimpleStateMachine.StructuralSearch/Extensions/StringParserExtensions.cs

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Generic;
33
using Pidgin;
4-
using static Pidgin.Parser;
54

65
namespace SimpleStateMachine.StructuralSearch.Extensions;
76

@@ -16,7 +15,7 @@ public static Parser<TToken, string> BetweenAsThen<TToken>(this Parser<TToken, s
1615
if (parser2 == null)
1716
throw new ArgumentNullException(nameof(parser2));
1817

19-
return Map<TToken, char, string, char, string>(
18+
return Parser.Map<TToken, char, string, char, string>(
2019
(before, str, after) => before + str + after,
2120
parser1, parser, parser2);
2221
}
@@ -30,7 +29,7 @@ public static Parser<TToken, string> BetweenAsThen<TToken>(this Parser<TToken, s
3029
if (parser2 == null)
3130
throw new ArgumentNullException(nameof(parser2));
3231

33-
return Map<TToken, string, string, string, string>(
32+
return Parser.Map<TToken, string, string, string, string>(
3433
(before, str, after) => before + str + after,
3534
parser1, parser, parser2);
3635
}
@@ -56,13 +55,13 @@ public static Parser<TToken, SourceMatch> AsMatch<TToken>(this Parser<TToken, st
5655
=> parser.Then(Parser<TToken>.CurrentOffset, (s, offset) => new SourceMatch(s, offset - s.Length, offset));
5756

5857
public static Parser<char, T> TrimEnd<T>(this Parser<char, T> parser)
59-
=> parser.Before(SkipWhitespaces);
58+
=> parser.Before(Parser.SkipWhitespaces);
6059

6160
public static Parser<char, T> TrimStart<T>(this Parser<char, T> parser)
62-
=> parser.After(SkipWhitespaces);
61+
=> parser.After(Parser.SkipWhitespaces);
6362

6463
public static Parser<char, T> Trim<T>(this Parser<char, T> parser)
65-
=> parser.Between(SkipWhitespaces);
64+
=> parser.Between(Parser.SkipWhitespaces);
6665

6766
public static Parser<char, TEnum> AsEnum<TEnum>(this Parser<char, string> parser, bool ignoreCase)
6867
where TEnum : struct, Enum

src/SimpleStateMachine.StructuralSearch/Parsers/DebugParser.cs

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using Pidgin;
22

3-
#pragma warning disable CS9074 // The 'scoped' modifier of parameter doesn't match overridden or implemented member.
4-
53
namespace SimpleStateMachine.StructuralSearch.Parsers;
64

75
internal class DebugParser<TToken, T> : Parser<TToken, T>

src/SimpleStateMachine.StructuralSearch/Parsers/EmptyStringParser.cs

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using Pidgin;
22

3-
#pragma warning disable CS9074 // The 'scoped' modifier of parameter doesn't match overridden or implemented member.
4-
53
namespace SimpleStateMachine.StructuralSearch.Parsers;
64

75
internal class EmptyStringParser : Parser<char, string>

src/SimpleStateMachine.StructuralSearch/Parsers/ParserWithLookahead.cs

-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
using System.Collections.Generic;
33
using Pidgin;
44

5-
#pragma warning disable CS9074 // The 'scoped' modifier of parameter doesn't match overridden or implemented member.
6-
75
namespace SimpleStateMachine.StructuralSearch.Parsers;
86

97
internal abstract class ParserWithLookahead<TToken, T> : Parser<TToken, T>

src/SimpleStateMachine.StructuralSearch/Parsers/Parsers.cs

+8-9
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@
33
using System.Linq;
44
using Pidgin;
55
using SimpleStateMachine.StructuralSearch.Extensions;
6-
using static Pidgin.Parser;
76

87
namespace SimpleStateMachine.StructuralSearch.Parsers;
98

109
internal static class Parsers
1110
{
1211
public static Parser<char, string> String(string value, bool ignoreCase)
13-
=> ignoreCase ? CIString(value): Parser.String(value);
12+
=> ignoreCase ? Parser.CIString(value): Parser.String(value);
1413

1514
public static Parser<char, TEnum> After<TEnum>(TEnum value, bool ignoreCase = false)
1615
where TEnum : struct, Enum
@@ -23,7 +22,7 @@ private static Parser<TToken, IEnumerable<T>> MapToMany<TToken, T>(Parser<TToken
2322
ArgumentNullException.ThrowIfNull(parser2);
2423
ArgumentNullException.ThrowIfNull(parser3);
2524

26-
return Map((arg1, arg2, arg3) => (IEnumerable<T>)new List<T> { arg1, arg2, arg3 }, parser1, parser2, parser3);
25+
return Parser.Map((arg1, arg2, arg3) => (IEnumerable<T>)new List<T> { arg1, arg2, arg3 }, parser1, parser2, parser3);
2726
}
2827

2928
private static Parser<TToken, IEnumerable<T>> MapToMany<TToken, T>(Parser<TToken, T> parser1,
@@ -33,7 +32,7 @@ private static Parser<TToken, IEnumerable<T>> MapToMany<TToken, T>(Parser<TToken
3332
ArgumentNullException.ThrowIfNull(parser2);
3433
ArgumentNullException.ThrowIfNull(parser3);
3534

36-
return Map((arg1, arg2, arg3) =>
35+
return Parser.Map((arg1, arg2, arg3) =>
3736
{
3837
var result = arg2.ToList();
3938
result.Insert(0, arg1);
@@ -50,7 +49,7 @@ public static Parser<TToken, IEnumerable<T>> MapToMany<TToken, T>(Parser<TToken,
5049
if (parser2 == null)
5150
throw new ArgumentNullException(nameof(parser2));
5251

53-
return Map((arg1, arg2) =>
52+
return Parser.Map((arg1, arg2) =>
5453
{
5554
var result = new List<T> { arg1, arg2 };
5655
return (IEnumerable<T>)result;
@@ -63,13 +62,13 @@ public static Parser<char, IEnumerable<T>> BetweenChars<T>(char left, char right
6362
=> MapToMany(leftRight(left), expr, leftRight(right));
6463

6564
public static Parser<char, IEnumerable<T>> BetweenOneOfChars<T>(Func<char, Parser<char, T>> leftRight, Parser<char, IEnumerable<T>> expr, params (char, char)[] values)
66-
=> OneOf(values.Select(x => MapToMany(leftRight(x.Item1), expr, leftRight(x.Item2))));
65+
=> Parser.OneOf(values.Select(x => MapToMany(leftRight(x.Item1), expr, leftRight(x.Item2))));
6766

6867
public static Parser<char, IEnumerable<T>> BetweenOneOfChars<T>(Func<char, Parser<char, T>> leftRight, Parser<char, T> expr, params (char, char)[] values)
69-
=> OneOf(values.Select(x => MapToMany(leftRight(x.Item1), expr, leftRight(x.Item2))));
68+
=> Parser.OneOf(values.Select(x => MapToMany(leftRight(x.Item1), expr, leftRight(x.Item2))));
7069

7170
public static Parser<char, (TResult, T)> BetweenOneOfChars<T, TResult>(Func<char, char, TResult> resultFunc, Parser<char, T> expr, params (char, char)[] values)
72-
=> OneOf(values.Select(x => Map((c1, res, c2) => (resultFunc(c1, c2), res), Char(x.Item1).Try(), expr, Char(x.Item2).Try())));
71+
=> Parser.OneOf(values.Select(x => Parser.Map((c1, res, c2) => (resultFunc(c1, c2), res), Parser.Char(x.Item1).Try(), expr, Parser.Char(x.Item2).Try())));
7372

7473
public static Parser<char, TEnum> EnumExcept<TEnum>(bool ignoreCase = false, params TEnum[] excluded)
7574
where TEnum : struct, Enum
@@ -80,7 +79,7 @@ public static Parser<char, TEnum> EnumValue<TEnum>(TEnum value, bool ignoreCase
8079
=> String(value.ToString(), ignoreCase).AsEnum<TEnum>(ignoreCase);
8180

8281
public static Parser<char, Match<T>> Match<T>(Parser<char, T> parser)
83-
=> Map((oldPos, oldOffset, result, newPos, newOffset) =>
82+
=> Parser.Map((oldPos, oldOffset, result, newPos, newOffset) =>
8483
{
8584
var line = new LinePosition(oldPos.Line, newPos.Line);
8685
var column = new ColumnPosition(oldPos.Col, newPos.Col);

src/SimpleStateMachine.StructuralSearch/Parsers/PlaceholderParser.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ protected override Parser<char, string> BuildParser(Func<Parser<char, string>?>
5353
}).Try());
5454
}
5555

56-
var anyString = CommonTemplateParser.AnyCharWithPlaceholder
56+
var anyString = CommonTemplateParser.StringLiteralChar
5757
.AtLeastOnceAsStringUntil(lookahead);
5858

59-
var simpleString = CommonTemplateParser.StringWithPlaceholder;
59+
var simpleString = CommonTemplateParser.StringLiteral;
6060
var token = Parser.OneOf(simpleString, CommonParser.WhiteSpaces).Try();
6161
Parser<char, string>? term = null;
6262

src/SimpleStateMachine.StructuralSearch/Parsers/SeriesParser.cs

-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
using Pidgin;
44
using SimpleStateMachine.StructuralSearch.Context;
55

6-
#pragma warning disable CS9074 // The 'scoped' modifier of parameter doesn't match overridden or implemented member.
7-
86
namespace SimpleStateMachine.StructuralSearch.Parsers;
97

108
internal class SeriesParser : Parser<char, IEnumerable<string>>, IContextDependent

src/SimpleStateMachine.StructuralSearch/Rules/Parameters/StringParameter.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public string GetValue(ref IParsingContext context)
1616

1717
public override string ToString()
1818
{
19-
var value = EscapeHelper.EscapeChars(_value, c => $"{Constant.BackSlash}{c}", Constant.Parameter.Escape);
19+
var value = EscapeHelper.EscapeChars(_value, c => $"{Constant.BackSlash}{c}", Constant.CharsToEscape);
2020
return $"{value}";
2121
}
2222
}
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Text;
34
using Pidgin;
4-
using static Pidgin.Parser;
55

66
namespace SimpleStateMachine.StructuralSearch.StructuralSearch;
77

88
internal static class CommonParser
99
{
1010
internal static readonly Parser<char, string> Empty = Parsers.Parsers.String(Constant.EmptyString, false);
11-
internal static readonly Parser<char, char> AnyChar = AnyCharExcept(Constant.FindTemplate.All);
12-
internal static readonly Parser<char, char> Space = Char(Constant.Space);
11+
internal static readonly Parser<char, char> Space = Parser.Char(Constant.Space);
12+
internal static readonly Parser<char, char> Underscore = Parser.Char(Constant.Underscore);
1313
internal static readonly Parser<char, Unit> Eof = Parser<char>.End;
14-
internal static readonly Parser<char, string> AnyString = AnyChar.AtLeastOnceString();
14+
internal static readonly Parser<char, string> AnyString = Parser.AnyCharExcept(Constant.All).AtLeastOnceString();
1515
internal static readonly Parser<char, string> Spaces = Space.AtLeastOnceString();
16-
internal static readonly Parser<char, string> LineEnds = EndOfLine.AtLeastOnceString();
17-
internal static readonly Parser<char, string> WhiteSpaces = OneOf(Spaces, LineEnds, LineEnds).AtLeastOnceString();
18-
internal static readonly Parser<char, string> Identifier = Letter.Then(AnyString, (h, t) => h + t);
19-
internal static readonly Parser<char, char> Comma = Char(Constant.Comma);
20-
internal static readonly Parser<char, char> Colon = Char(Constant.Colon);
21-
internal static readonly Parser<char, char> DoubleQuotes = Char(Constant.DoubleQuotes);
22-
internal static readonly Parser<char, char> SingleQuotes = Char(Constant.SingleQuotes);
23-
internal static readonly Parser<char, char> Dote = Char(Constant.Dote);
24-
internal static readonly Parser<char, char> Underscore = Char(Constant.Underscore);
25-
internal static readonly Parser<char, char> PlaceholderSeparator = Char(Constant.PlaceholderSeparator);
16+
internal static readonly Parser<char, string> LineEnds = Parser.EndOfLine.AtLeastOnceString();
17+
internal static readonly Parser<char, string> WhiteSpaces = Parser.OneOf(Spaces, LineEnds, LineEnds).AtLeastOnceString();
18+
internal static readonly Parser<char, string> Identifier = Parser.Letter.Then(Parser.OneOf(Parser.Letter, Parser.Digit, Underscore).AtLeastOnce(), BuildString);
19+
internal static readonly Parser<char, char> Comma = Parser.Char(Constant.Comma);
20+
internal static readonly Parser<char, char> Colon = Parser.Char(Constant.Colon);
21+
internal static readonly Parser<char, char> DoubleQuotes = Parser.Char(Constant.DoubleQuotes);
22+
internal static readonly Parser<char, char> SingleQuotes = Parser.Char(Constant.SingleQuotes);
23+
internal static readonly Parser<char, char> Dote = Parser.Char(Constant.Dote);
24+
25+
internal static readonly Parser<char, char> PlaceholderSeparator = Parser.Char(Constant.PlaceholderSeparator);
2626

2727
internal static Parser<char, T> Parenthesised<T, TResult>(Parser<char, T> parser,
2828
Func<char, Parser<char, TResult>> custom)
@@ -32,5 +32,17 @@ internal static Parser<char, T> Parenthesised<T, TResult>(Parser<char, T> parser
3232
custom(Constant.RightParenthesis)
3333
);
3434

35-
internal static Parser<char, char> Escaped(IEnumerable<char> chars) => Char(Constant.BackSlash).Then(OneOf(chars));
35+
internal static Parser<char, char> Escaped(IEnumerable<char> chars) =>
36+
Parser.Char(Constant.BackSlash).Then(Parser.OneOf(chars));
37+
38+
private static string BuildString(char c, IEnumerable<char> chars)
39+
{
40+
var builder = new StringBuilder();
41+
builder.Append(c);
42+
43+
foreach (var value in chars)
44+
builder.Append(value);
45+
46+
return builder.ToString();
47+
}
3648
}
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
using System.Linq;
22
using Pidgin;
3-
using static Pidgin.Parser;
43

54
namespace SimpleStateMachine.StructuralSearch.StructuralSearch;
65

76
internal static class CommonTemplateParser
87
{
9-
internal static readonly Parser<char, char> AnyCharWithPlaceholder = AnyCharExcept(Constant.FindTemplate.All.Except([Constant.PlaceholderSeparator]));
8+
internal static readonly Parser<char, char> StringLiteralChar = Parser.AnyCharExcept(Constant.InvalidStringLiteralChars);
109
internal static readonly Parser<char, string> Placeholder = CommonParser.Identifier.Between(CommonParser.PlaceholderSeparator);
11-
internal static readonly Parser<char, string> StringWithPlaceholder = AnyCharWithPlaceholder.AtLeastOnceString();
12-
internal static readonly Parser<char, string> Should = String(Constant.Should);
10+
internal static readonly Parser<char, string> StringLiteral = StringLiteralChar.AtLeastOnceString();
11+
internal static readonly Parser<char, string> Should = Parser.String(Constant.Should);
1312
}

src/SimpleStateMachine.StructuralSearch/StructuralSearch/FindRulesParser.cs

+9-10
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,15 @@ namespace SimpleStateMachine.StructuralSearch.StructuralSearch;
99

1010
internal static class FindRuleParser
1111
{
12-
private static Parser<char, Func<IFindRule, IFindRule>> UnaryOperation(UnaryRuleType ruleType)
13-
=> Parsers.Parsers.EnumValue(ruleType, true).Trim().Try()
14-
.Select<Func<IFindRule, IFindRule>>(type => param => new UnaryRule(type, param));
15-
16-
private static Parser<char, Func<IFindRule, IFindRule, IFindRule>> BinaryOperation(BinaryRuleType ruleType)
17-
=> Parsers.Parsers.EnumValue(ruleType, true).Trim().Try()
18-
.Select<Func<IFindRule, IFindRule, IFindRule>>(type => (left, right) => new BinaryRule(type, left, right));
19-
2012
private static readonly Parser<char, Func<IFindRule, IFindRule, IFindRule>> And = BinaryOperation(BinaryRuleType.And);
2113
private static readonly Parser<char, Func<IFindRule, IFindRule, IFindRule>> Or = BinaryOperation(BinaryRuleType.Or);
2214
private static readonly Parser<char, Func<IFindRule, IFindRule, IFindRule>> NOR = BinaryOperation(BinaryRuleType.NOR);
2315
private static readonly Parser<char, Func<IFindRule, IFindRule, IFindRule>> XOR = BinaryOperation(BinaryRuleType.XOR);
2416
private static readonly Parser<char, Func<IFindRule, IFindRule, IFindRule>> NAND = BinaryOperation(BinaryRuleType.NAND);
2517
private static readonly Parser<char, Func<IFindRule, IFindRule, IFindRule>> XNOR = BinaryOperation(BinaryRuleType.XNOR);
26-
2718
private static readonly Parser<char, Func<IFindRule, IFindRule>> Not = UnaryOperation(UnaryRuleType.Not);
2819

29-
public static readonly Parser<char, IFindRule> Expr = ExpressionParser.Build<char, IFindRule>
20+
internal static readonly Parser<char, IFindRule> Expr = ExpressionParser.Build<char, IFindRule>
3021
(
3122
rule =>
3223
(
@@ -51,4 +42,12 @@ internal static IFindRule ParseTemplate(string? str)
5142
=> string.IsNullOrEmpty(str)
5243
? Rule.Empty
5344
: Expr.Before(CommonParser.Eof).ParseOrThrow(str);
45+
46+
private static Parser<char, Func<IFindRule, IFindRule>> UnaryOperation(UnaryRuleType ruleType)
47+
=> Parsers.Parsers.EnumValue(ruleType, true).Trim().Try()
48+
.Select<Func<IFindRule, IFindRule>>(type => param => new UnaryRule(type, param));
49+
50+
private static Parser<char, Func<IFindRule, IFindRule, IFindRule>> BinaryOperation(BinaryRuleType ruleType)
51+
=> Parsers.Parsers.EnumValue(ruleType, true).Trim().Try()
52+
.Select<Func<IFindRule, IFindRule, IFindRule>>(type => (left, right) => new BinaryRule(type, left, right));
5453
}

src/SimpleStateMachine.StructuralSearch/StructuralSearch/FindTemplateParser.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ internal static class FindTemplateParser
1616
ParserToParser.ParserAsParser(CommonParser.WhiteSpaces).Try();
1717

1818
private static readonly Parser<char, Parser<char, string>> Placeholder =
19-
CommonTemplateParser.Placeholder.Select(name => new PlaceholderParser(name))
19+
CommonTemplateParser.Placeholder
20+
.Select(name => new PlaceholderParser(name))
2021
.As<char, PlaceholderParser, Parser<char, string>>();
2122

2223
private static readonly Parser<char, IEnumerable<Parser<char, string>>> Token =
@@ -30,7 +31,7 @@ internal static class FindTemplateParser
3031
values: Constant.AllParentheses
3132
);
3233

33-
internal static Parser<char, IEnumerable<Parser<char, string>>> Term =
34+
private static readonly Parser<char, IEnumerable<Parser<char, string>>> Term =
3435
Parser.OneOf(Parenthesised, Token).Many().SelectMany();
3536

3637
private static readonly Parser<char, IEnumerable<Parser<char, string>>> TemplateParser =

0 commit comments

Comments
 (0)