From f5d3935f548c168e63e764aecd7e729425c08e5e Mon Sep 17 00:00:00 2001 From: GMIKE Date: Thu, 12 May 2022 03:11:01 +0300 Subject: [PATCH 1/7] Optimization replace rule --- .../ReplaceRuleParserTests.cs | 2 + .../ReplaceTemplateTests.cs | 14 +++++- .../Constant.cs | 45 ++++++++++--------- .../Rules/FindRule/EmptySubRule.cs | 14 ++++++ .../StructuralSearch/CommonParser.cs | 3 ++ .../StructuralSearch/ReplaceRuleParser.cs | 35 +++++++++------ .../StructuralSearch/ReplaceTemplateParser.cs | 2 +- .../StructuralSearch/SubRuleParser.cs | 3 +- 8 files changed, 80 insertions(+), 38 deletions(-) create mode 100644 src/SimpleStateMachine.StructuralSearch/Rules/FindRule/EmptySubRule.cs diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceRuleParserTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceRuleParserTests.cs index 577c23b..fc5392b 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceRuleParserTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceRuleParserTests.cs @@ -9,6 +9,8 @@ public class ReplaceRuleParserTests [Theory] [InlineData("$var1$ equals $var2$ then $var1$ => \"test $var3$\"")] [InlineData("$var1$ equals \"\\$\" then $var1$ => \"\\$\",$var2$ => \"132\"")] + [InlineData("_ then $var1$ => \"test $var3$.Lenght\"")] + [InlineData("_ then $var1$ => \"\\$\",$var2$ => \"132\"")] [InlineData("Not $var1$ equals $var$.Lenght then $var1$ => $var$.Lenght")] [InlineData("Not $var1$ equals $var$.offset.Start then $var1$ => $var$.offset.Start")] [InlineData("$var1$ equals $var$.Lenght and Not $var1$ StartsWith \"123\" then $var1$ => $var$.offset.Start.Trim")] diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs index db25cb1..2076e66 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs @@ -12,7 +12,7 @@ public class ReplaceTemplateTests [InlineData("ReplaceTemplate/NullUnionOperator.txt", 10)] [InlineData("ReplaceTemplate/AssignmentNullUnionOperator.txt", 6)] [InlineData("ReplaceTemplate/TernaryOperator.txt", 11)] - public void TemplateParsingShouldHaveStepCount(string templatePath, int stepsCount) + public void ReplaceTemplateParsingShouldHaveStepCount(string templatePath, int stepsCount) { var replaceTemplate = File.ReadAllText(templatePath); var replaceBuilder = StructuralSearch.ParseReplaceTemplate(replaceTemplate); @@ -50,5 +50,17 @@ public void ReplaceBuildShouldBeSuccess(string templatePath, string resultPath, Assert.NotNull(replaceResult); Assert.Equal(replaceResult, result); } + + [Theory] + [InlineData("test $var1$.Lenght")] + public void ReplaceTemplateParsingShouldBeSuccess(string templateStr) + { + var replaceBuilder = StructuralSearch.ParseReplaceTemplate(templateStr); + var t = replaceBuilder.ToString(); + var result = replaceBuilder.Build(new EmptyParsingContext()); + + // Assert.NotNull(replaceTemplate); + // Assert.Equal(replaceBuilder.Steps.Count(), stepsCount); + } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Constant.cs b/src/SimpleStateMachine.StructuralSearch/Constant.cs index 4466a87..a470b71 100644 --- a/src/SimpleStateMachine.StructuralSearch/Constant.cs +++ b/src/SimpleStateMachine.StructuralSearch/Constant.cs @@ -10,102 +10,107 @@ public static partial class Constant /// /// String: "Not" /// - public static readonly string Not ="Not"; + public const string Not ="Not"; /// /// String: "Then" /// - public static readonly string Then ="Then"; + public const string Then ="Then"; /// /// Parenthesis char: '(' /// - public static readonly char LeftParenthesis = '('; + public const char LeftParenthesis = '('; /// /// Parenthesis char: ')' /// - public static readonly char RightParenthesis = ')'; + public const char RightParenthesis = ')'; /// /// Parenthesis char: '[' /// - public static readonly char LeftSquareParenthesis = '['; + public const char LeftSquareParenthesis = '['; /// /// Parenthesis char: ']' /// - public static readonly char RightSquareParenthesis = ']'; + public const char RightSquareParenthesis = ']'; /// /// Parenthesis char: '{' /// - public static readonly char LeftCurlyParenthesis = '{'; + public const char LeftCurlyParenthesis = '{'; /// /// Parenthesis char: '}' /// - public static readonly char RightCurlyParenthesis = '}'; + public const char RightCurlyParenthesis = '}'; /// /// Char: '$' /// - public static readonly char PlaceholderSeparator = '$'; + public const char PlaceholderSeparator = '$'; /// /// Char: '\r' /// - public static readonly char CarriageReturn = '\r'; + public const char CarriageReturn = '\r'; /// /// Char: '\n' /// - public static readonly char LineFeed = '\n'; + public const char LineFeed = '\n'; /// /// Char: ' ' /// - public static readonly char Space = ' '; + public const char Space = ' '; /// /// Char: ',' /// - public static readonly char Comma = ','; + public const char Comma = ','; /// /// Char: '\'' /// - public static readonly char SingleQuotes = '\''; + public const char SingleQuotes = '\''; /// /// Char: '\"' /// - public static readonly char DoubleQuotes = '\"'; + public const char DoubleQuotes = '\"'; /// /// Char: '\"' /// - public static readonly char BackSlash = '\\'; + public const char BackSlash = '\\'; /// /// Char: '.' /// - public static readonly char Dote = '.'; + public const char Dote = '.'; /// /// Char: '=' /// - public static readonly char Equals = '='; + public const char Equals = '='; /// /// Char: '>' /// - public static readonly char More = '>'; + public const char More = '>'; + + /// + /// Char: '_' + /// + public const char Underscore = '_'; /// /// Char: ':' /// - public static readonly char Colon = ':'; + public const char Colon = ':'; /// /// String: "=>" diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/EmptySubRule.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/EmptySubRule.cs new file mode 100644 index 0000000..143e65e --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/EmptySubRule.cs @@ -0,0 +1,14 @@ +namespace SimpleStateMachine.StructuralSearch.Rules; + +public class EmptySubRule : IRule +{ + public bool Execute() + { + return true; + } + + public override string ToString() + { + return $"{Constant.Underscore}"; + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/CommonParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/CommonParser.cs index b809955..9d5d42d 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/CommonParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/CommonParser.cs @@ -45,6 +45,9 @@ internal static readonly Parser SingleQuotes internal static readonly Parser Dote = Char(Constant.Dote); + + internal static readonly Parser Underscore + = Char(Constant.Underscore); internal static Parser Parenthesised(Parser parser, Func, Parser> custom) { diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs index 1c8bf34..d0f010a 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs @@ -6,33 +6,40 @@ namespace SimpleStateMachine.StructuralSearch { public static class ReplaceRuleParser { - internal static readonly Parser ChangeParameter = - Parser.Map((parameter, changeType) => new ChangeParameter(parameter, changeType), - ParametersParser.Parameter.Before(CommonParser.Dote), - Parser.CIEnum()) - .As() - .Try() - .TrimStart(); - internal static readonly Parser Then = Parser.CIString(Constant.Then) .Try() .TrimStart(); - + + internal static readonly Parser ReplaceSubRuleParameter = + Parser.Map((parameter, changeType) => + changeType.HasValue ? new ChangeParameter(parameter, changeType.Value) : parameter, + ParametersParser.Parameter, + CommonParser.Dote.Then(Parser.CIEnum()).Optional()) + .Try() + .TrimStart(); + internal static readonly Parser ReplaceSubRule = - Parser.Map((placeholder, parameter) => new ReplaceSubRule(placeholder, parameter), - ParametersParser.PlaceholderParameter.Before(CommonTemplateParser.Should.TrimStart()), - Parser.OneOf(ChangeParameter.Try(), ParametersParser.Parameter.Try())) + Parser.Map((placeholder, _, parameter) => new ReplaceSubRule(placeholder, parameter), + ParametersParser.PlaceholderParameter.TrimStart(), + CommonTemplateParser.Should.TrimStart(), + ReplaceSubRuleParameter) + .Try() + .TrimStart(); + + internal static readonly Parser EmptySubRule = + CommonParser.Underscore.ThenReturn(new EmptySubRule()) + .As() .Try() .TrimStart(); internal static readonly Parser ReplaceRule = Parser.Map((rule, subRules) => new ReplaceRule(rule, subRules), - FindRuleParser.Expr, + Parser.OneOf(EmptySubRule, FindRuleParser.Expr), Then.Then(ReplaceSubRule.SeparatedAtLeastOnce(CommonParser.Comma))) .Try() .TrimStart(); - + internal static ReplaceRule ParseTemplate(string str) { return ReplaceRule.ParseOrThrow(str); diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs index 005d7ba..a786432 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs @@ -46,7 +46,7 @@ static ReplaceTemplateParser() internal static readonly Parser> Parenthesised; - private static readonly Parser> TemplateParser; + internal static readonly Parser> TemplateParser; internal static IReplaceBuilder ParseTemplate(string str) { diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubRuleParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubRuleParser.cs index 1d24283..7c7616e 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubRuleParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubRuleParser.cs @@ -30,8 +30,7 @@ public static Parser InSubRule(IRuleParameter left, SubRuleType rul .Select(args => new InSubRule(left, args)) .As() .Try(); - - + public static readonly Parser OneOfSubRule = Parser.Map((left, ruleType) => (left, ruleType), ParametersParser.Parameter, SubRuleType) From 86cf7f5d841eb7da043ee378168ed20c65f4bedb Mon Sep 17 00:00:00 2001 From: GMIKE Date: Thu, 12 May 2022 03:15:06 +0300 Subject: [PATCH 2/7] ReplaceBuilder string, ReplaceBuilder tests --- .../ReplaceTemplateTests.cs | 7 ++----- .../Templates/ReplaceTemplate/PlaceholderReplace.cs | 5 +++++ .../Templates/ReplaceTemplate/ReplaceBuilder.cs | 5 +++++ .../Templates/ReplaceTemplate/TokenReplace.cs | 5 +++++ 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs index 2076e66..bf1e064 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs @@ -56,11 +56,8 @@ public void ReplaceBuildShouldBeSuccess(string templatePath, string resultPath, public void ReplaceTemplateParsingShouldBeSuccess(string templateStr) { var replaceBuilder = StructuralSearch.ParseReplaceTemplate(templateStr); - var t = replaceBuilder.ToString(); - var result = replaceBuilder.Build(new EmptyParsingContext()); - - // Assert.NotNull(replaceTemplate); - // Assert.Equal(replaceBuilder.Steps.Count(), stepsCount); + var replaceStr = replaceBuilder.ToString().ToLower(); + Assert.Equal(replaceStr, templateStr.ToLower()); } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/PlaceholderReplace.cs b/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/PlaceholderReplace.cs index 986c0c5..639bb12 100644 --- a/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/PlaceholderReplace.cs +++ b/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/PlaceholderReplace.cs @@ -20,5 +20,10 @@ public void SetContext(ref IParsingContext context) { _context = context; } + + public override string ToString() + { + return $"{Constant.PlaceholderSeparator}{Name}{Constant.PlaceholderSeparator}"; + } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/ReplaceBuilder.cs b/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/ReplaceBuilder.cs index 81c0c35..cd62f29 100644 --- a/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/ReplaceBuilder.cs +++ b/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/ReplaceBuilder.cs @@ -29,5 +29,10 @@ public string Build(IParsingContext context) var result = stringBuilder.ToString(); return result; } + + public override string ToString() + { + return $"{string.Join(string.Empty, Steps)}"; + } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/TokenReplace.cs b/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/TokenReplace.cs index 6f8d247..8333b1b 100644 --- a/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/TokenReplace.cs +++ b/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/TokenReplace.cs @@ -12,5 +12,10 @@ public string GetValue() { return Token; } + + public override string ToString() + { + return $"{Token}"; + } } } \ No newline at end of file From 285a698163d1db571a324f0d8a8b8a2b161b8a8b Mon Sep 17 00:00:00 2001 From: GMIKE Date: Thu, 12 May 2022 19:51:04 +0300 Subject: [PATCH 3/7] Fix parsers, check on EOF --- .../FindRuleParserTests.cs | 14 +++++++------- .../FindTemplateParserTests.cs | 9 ++++++++- .../ReplaceRuleParserTests.cs | 19 +++++++++++++++++++ .../ReplaceTemplateTests.cs | 12 ++++++++++++ .../StructuralSearch/CommonParser.cs | 3 +++ .../StructuralSearch/FindRulesParser.cs | 2 +- .../StructuralSearch/FindTemplateParser.cs | 2 +- .../StructuralSearch/ReplaceRuleParser.cs | 2 +- .../StructuralSearch/ReplaceTemplateParser.cs | 2 +- 9 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/FindRuleParserTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/FindRuleParserTests.cs index 64987c9..860e65a 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/FindRuleParserTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/FindRuleParserTests.cs @@ -49,17 +49,17 @@ public void FindRuleExprParsingShouldBeEqualsCustomResult(string ruleStr, string Assert.NotNull(rule); Assert.Equal(_ruleStr, customResult.ToLower()); } - [Theory] - [InlineData("FindRule/NullUnionOperator.txt", "$sign$ In \"Is\",\"==\",\"!=\",\"is not\"")] + [InlineData("FindRule/NullUnionOperator.txt", "$sign$ In \"Is\",\"==\",\"!=\",\"is not\"", "$value$ In $value1$,\"$value1$.Value\",$value2$,\"$value2$.Value\"")] [InlineData("FindRule/AssignmentNullUnionOperator.txt", "$sign$ In \"Is\",\"==\",\"!=\",\"is not\"")] - public void FindRuleParsingFromFileShouldBeSuccess(string filePath, string customResult) + public void FindRuleParsingFromFileShouldBeSuccess(string filePath, params string[] customResult) { var ruleStr = File.ReadAllText(filePath); - var rule = StructuralSearch.ParseFindRule(ruleStr); - var _ruleStr = rule.ToString()?.ToLower(); - Assert.NotNull(rule); - Assert.Equal(_ruleStr, customResult.ToLower()); + var rules = ruleStr.Split(Constant.LineFeed) + .Select(StructuralSearch.ParseFindRule); + var rulesAsStr = rules.Select(x => x.ToString()).ToArray(); + + Assert.True(customResult.SequenceEqual(rulesAsStr)); } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/FindTemplateParserTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/FindTemplateParserTests.cs index 4abc086..274f9ab 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/FindTemplateParserTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/FindTemplateParserTests.cs @@ -12,7 +12,7 @@ public class FindTemplateTests [InlineData("FindTemplate/AssignmentNullUnionOperator.txt")] [InlineData("FindTemplate/NestedParenthesised.txt")] [InlineData("FindTemplate/TernaryOperator.txt")] - public void TemplateParsingShouldBeSuccess(string templatePath) + public void FindTemplateParsingShouldBeSuccess(string templatePath) { var findTemplate = File.ReadAllText(templatePath); var template = StructuralSearch.ParseFindTemplate(findTemplate); @@ -40,5 +40,12 @@ public void SourceParsingBeFindTemplateShouldBeSuccess(string templatePath, stri Assert.NotNull(findParser); Assert.Equal(match.Match.Lenght, source.Length); } + + [Theory] + [InlineData("( $var$")] + public void FindTemplateParsingShouldBeFail(string templateStr) + { + Assert.Throws(() => StructuralSearch.ParseFindTemplate(templateStr)); + } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceRuleParserTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceRuleParserTests.cs index fc5392b..0100154 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceRuleParserTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceRuleParserTests.cs @@ -24,5 +24,24 @@ public void ReplaceRuleParsingShouldBeSuccess(string replaceRule) Assert.Equal(ruleStr, replaceRule.ToLower()); } + [Theory] + [InlineData("($var1$ equals $var2$) then $var1$ => \"test $var3$\"", "$var1$ equals $var2$ then $var1$ => \"test $var3$\"")] + public void ReplaceRuleShouldBeEqualsString(string replaceRule, string customResult) + { + var rule = StructuralSearch.ParseReplaceRule(replaceRule); + var ruleStr = rule.ToString().ToLower(); + Assert.NotNull(rule); + Assert.Equal(ruleStr, customResult.ToLower()); + } + + [Theory] + [InlineData("$var1$ equals $var2$ then $var1$ => (\"test $var3$\"")] + [InlineData("($var1$ equals $var2$ then $var1$ => \"test $var3$\"")] + [InlineData("$var1$ equals $var2$ then ($var1$) => \"test $var3$\"")] + public void ReplaceRuleParsingShouldBeFail(string replaceRuleStr) + { + Assert.Throws(() => StructuralSearch.ParseReplaceRule(replaceRuleStr)); + } + } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs index bf1e064..1a14588 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Pidgin; using SimpleStateMachine.StructuralSearch.Tests.Mock; using Xunit; @@ -53,11 +54,22 @@ public void ReplaceBuildShouldBeSuccess(string templatePath, string resultPath, [Theory] [InlineData("test $var1$.Lenght")] + [InlineData("(test $var1$.Lenght)")] + [InlineData("test ($var1$.Lenght)")] public void ReplaceTemplateParsingShouldBeSuccess(string templateStr) { var replaceBuilder = StructuralSearch.ParseReplaceTemplate(templateStr); var replaceStr = replaceBuilder.ToString().ToLower(); Assert.Equal(replaceStr, templateStr.ToLower()); } + + [Theory] + [InlineData("(test $var1$.Lenght")] + [InlineData("test ($var1$.Lenght")] + [InlineData("test $var1$.Lenght)")] + public void ReplaceTemplateParsingShouldBeFail(string templateStr) + { + Assert.Throws(() => StructuralSearch.ParseReplaceTemplate(templateStr)); + } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/CommonParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/CommonParser.cs index 9d5d42d..fc0e401 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/CommonParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/CommonParser.cs @@ -15,6 +15,9 @@ internal static readonly Parser AnyChar internal static readonly Parser Space = Char(Constant.Space); + internal static readonly Parser EOF + = Parser.End; + internal static readonly Parser AnyString = AnyChar.AtLeastOnceString(); diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/FindRulesParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/FindRulesParser.cs index bce825c..8ed2ab6 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/FindRulesParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/FindRulesParser.cs @@ -71,7 +71,7 @@ internal static readonly Parser> Not internal static IRule ParseTemplate(string str) { - return Expr.ParseOrThrow(str); + return Expr.Before(CommonParser.EOF).ParseOrThrow(str); } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/FindTemplateParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/FindTemplateParser.cs index d8f6bbb..c3c0b0b 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/FindTemplateParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/FindTemplateParser.cs @@ -17,7 +17,7 @@ static FindTemplateParser() .MergerMany(); TemplateParser = Parser.OneOf(Parenthesised, Token) - .AtLeastOnce() + .AtLeastOnceUntil(CommonParser.EOF) .MergerMany(); SeriesParser = TemplateParser.Select(parsers => new SeriesParser(parsers)); diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs index d0f010a..3f430d8 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs @@ -42,7 +42,7 @@ public static class ReplaceRuleParser internal static ReplaceRule ParseTemplate(string str) { - return ReplaceRule.ParseOrThrow(str); + return ReplaceRule.Before(CommonParser.EOF).ParseOrThrow(str); } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs index a786432..99fdb76 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs @@ -18,7 +18,7 @@ static ReplaceTemplateParser() .MergerMany(); TemplateParser = Parser.OneOf(Parenthesised, Token) - .AtLeastOnce() + .AtLeastOnceUntil(CommonParser.EOF) .MergerMany(); } From e9cd5d845f549779f9ef75161363e69cf75acabe Mon Sep 17 00:00:00 2001 From: GMIKE Date: Fri, 13 May 2022 03:58:44 +0300 Subject: [PATCH 4/7] Optimization parameters, escape dote for string parameter, new replace template parsing --- .../Expr.cs | 1 + .../ConfigurationFile/FullConfig.yml | 2 +- .../ConfigurationFile/ShortConfig.yml | 2 +- .../FindRule/NullUnionOperator.txt | 2 +- .../FindRuleParserTests.cs | 2 +- .../ReplaceTemplateTests.cs | 6 +- .../Constant.cs | 17 +++- .../Extensions/ArrayExpression.cs | 13 +++ .../FindRule/{SubRule.cs => BinarySubRule.cs} | 4 +- .../Parameters/PlaceholderPropertyParser.cs | 20 ++-- .../Rules/Parameters/StringParameter.cs | 3 +- .../StructuralSearch/CommonParser.cs | 2 +- .../ParametersParser.cs | 32 +++++-- .../StructuralSearch/ReplaceRuleParser.cs | 17 ++-- .../StructuralSearch/ReplaceTemplateParser.cs | 96 +++++++++++-------- .../StructuralSearch/SubRuleParser.cs | 13 +-- .../FindTemplate/ConstantFindTemplate.cs | 40 ++++---- .../ReplaceTemplate/IReplaceBuilder.cs | 3 +- .../ReplaceTemplate/ReplaceBuilder.cs | 5 +- 19 files changed, 173 insertions(+), 107 deletions(-) create mode 100644 src/SimpleStateMachine.StructuralSearch/Extensions/ArrayExpression.cs rename src/SimpleStateMachine.StructuralSearch/Rules/FindRule/{SubRule.cs => BinarySubRule.cs} (89%) rename src/SimpleStateMachine.StructuralSearch/{Rules/Parameters => StructuralSearch}/ParametersParser.cs (54%) diff --git a/src/SimpleStateMachine.StructuralSearch.Sandbox/Expr.cs b/src/SimpleStateMachine.StructuralSearch.Sandbox/Expr.cs index 5f72bd0..f72d2f4 100644 --- a/src/SimpleStateMachine.StructuralSearch.Sandbox/Expr.cs +++ b/src/SimpleStateMachine.StructuralSearch.Sandbox/Expr.cs @@ -137,6 +137,7 @@ public double Invoke() BinaryOperatorType.Mul => Left.Invoke() * Right.Invoke(), BinaryOperatorType.Div => Left.Invoke() / Right.Invoke(), BinaryOperatorType.Sub => Left.Invoke() - Right.Invoke(), + _ => throw new ArgumentOutOfRangeException() }; } } diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/ConfigurationFile/FullConfig.yml b/src/SimpleStateMachine.StructuralSearch.Tests/ConfigurationFile/FullConfig.yml index 4c6daaa..2f78c66 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/ConfigurationFile/FullConfig.yml +++ b/src/SimpleStateMachine.StructuralSearch.Tests/ConfigurationFile/FullConfig.yml @@ -20,7 +20,7 @@ $var$ = $value1$; FindRules: - $sign$ In ("Is", "==", "!=", "is not") - - $value$ In ($value1$, "$value1$.Value", $value2$, "$value2$.Value") + - $value$ In ($value1$, "$value1$\.Value", $value2$, "$value2$\.Value") ReplaceTemplate: |- $var$ = $value1$ ?? $value2$; ReplaceRules: diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/ConfigurationFile/ShortConfig.yml b/src/SimpleStateMachine.StructuralSearch.Tests/ConfigurationFile/ShortConfig.yml index c673f23..673dc0e 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/ConfigurationFile/ShortConfig.yml +++ b/src/SimpleStateMachine.StructuralSearch.Tests/ConfigurationFile/ShortConfig.yml @@ -19,7 +19,7 @@ $var$ = $value1$; FindRules: - $sign$ In ("Is", "==", "!=", "is not") - - $value$ In ($value1$, "$value1$.Value", $value2$, "$value2$.Value") + - $value$ In ($value1$, "$value1$\.Value", $value2$, "$value2$\.Value") ReplaceTemplate: |- $var$ = $value1$ ?? $value2$; ReplaceRules: diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/FindRule/NullUnionOperator.txt b/src/SimpleStateMachine.StructuralSearch.Tests/FindRule/NullUnionOperator.txt index ca18854..c626822 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/FindRule/NullUnionOperator.txt +++ b/src/SimpleStateMachine.StructuralSearch.Tests/FindRule/NullUnionOperator.txt @@ -1,2 +1,2 @@ $sign$ In ("Is", "==", "!=", "is not") -$value$ In ($value1$, "$value1$.Value", $value2$, "$value2$.Value") \ No newline at end of file +$value$ In ($value1$, "$value1$\.Value", $value2$, "$value2$\.Value") \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/FindRuleParserTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/FindRuleParserTests.cs index 860e65a..3ca9d3f 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/FindRuleParserTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/FindRuleParserTests.cs @@ -50,7 +50,7 @@ public void FindRuleExprParsingShouldBeEqualsCustomResult(string ruleStr, string Assert.Equal(_ruleStr, customResult.ToLower()); } [Theory] - [InlineData("FindRule/NullUnionOperator.txt", "$sign$ In \"Is\",\"==\",\"!=\",\"is not\"", "$value$ In $value1$,\"$value1$.Value\",$value2$,\"$value2$.Value\"")] + [InlineData("FindRule/NullUnionOperator.txt", "$sign$ In \"Is\",\"==\",\"!=\",\"is not\"", "$value$ In $value1$,\"$value1$\\.Value\",$value2$,\"$value2$\\.Value\"")] [InlineData("FindRule/AssignmentNullUnionOperator.txt", "$sign$ In \"Is\",\"==\",\"!=\",\"is not\"")] public void FindRuleParsingFromFileShouldBeSuccess(string filePath, params string[] customResult) { diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs index 1a14588..e961654 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs @@ -10,9 +10,9 @@ namespace SimpleStateMachine.StructuralSearch.Tests public class ReplaceTemplateTests { [Theory] - [InlineData("ReplaceTemplate/NullUnionOperator.txt", 10)] - [InlineData("ReplaceTemplate/AssignmentNullUnionOperator.txt", 6)] - [InlineData("ReplaceTemplate/TernaryOperator.txt", 11)] + [InlineData("ReplaceTemplate/NullUnionOperator.txt", 6)] + [InlineData("ReplaceTemplate/AssignmentNullUnionOperator.txt", 4)] + [InlineData("ReplaceTemplate/TernaryOperator.txt", 7)] public void ReplaceTemplateParsingShouldHaveStepCount(string templatePath, int stepsCount) { var replaceTemplate = File.ReadAllText(templatePath); diff --git a/src/SimpleStateMachine.StructuralSearch/Constant.cs b/src/SimpleStateMachine.StructuralSearch/Constant.cs index a470b71..153d3a8 100644 --- a/src/SimpleStateMachine.StructuralSearch/Constant.cs +++ b/src/SimpleStateMachine.StructuralSearch/Constant.cs @@ -1,4 +1,6 @@ -namespace SimpleStateMachine.StructuralSearch +using System.Linq; + +namespace SimpleStateMachine.StructuralSearch { public static partial class Constant { @@ -136,5 +138,18 @@ public static partial class Constant /// Parenthesis chars: '(' and ')', '{ and '}', '{ and '}' /// public static readonly (char, char)[] AllParenthesised = { Parenthesis, SquareParenthesis, CurlyParenthesis }; + + /// + /// Parenthesis chars: '(' and ')', '{ and '}', '{ and '}' + /// + public static readonly char[] AllParenthesisArray = + { + LeftParenthesis, + RightParenthesis, + LeftSquareParenthesis, + RightSquareParenthesis, + LeftCurlyParenthesis, + RightCurlyParenthesis + }; } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Extensions/ArrayExpression.cs b/src/SimpleStateMachine.StructuralSearch/Extensions/ArrayExpression.cs new file mode 100644 index 0000000..256bed2 --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/Extensions/ArrayExpression.cs @@ -0,0 +1,13 @@ +using System.Linq; + +namespace SimpleStateMachine.StructuralSearch.Extensions; + +public static class ArrayExpression +{ + public static T[] Add(this T[] array, params T[] values) + { + var list = array.ToList(); + list.AddRange(values); + return list.ToArray(); + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/SubRule.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/BinarySubRule.cs similarity index 89% rename from src/SimpleStateMachine.StructuralSearch/Rules/FindRule/SubRule.cs rename to src/SimpleStateMachine.StructuralSearch/Rules/FindRule/BinarySubRule.cs index f670c7d..e4d5f5e 100644 --- a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/SubRule.cs +++ b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/BinarySubRule.cs @@ -3,7 +3,7 @@ namespace SimpleStateMachine.StructuralSearch.Rules { - public class SubRule : IRule + public class BinarySubRule : IRule { public SubRuleType Type { get; } @@ -11,7 +11,7 @@ public class SubRule : IRule public IRuleParameter Right { get; } - public SubRule(SubRuleType type, IRuleParameter left, IRuleParameter right) + public BinarySubRule(SubRuleType type, IRuleParameter left, IRuleParameter right) { Type = type; Left = left; diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/PlaceholderPropertyParser.cs b/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/PlaceholderPropertyParser.cs index 76e1c4a..7daafea 100644 --- a/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/PlaceholderPropertyParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/PlaceholderPropertyParser.cs @@ -45,13 +45,19 @@ public static class PlaceholderPropertyParser .Select(property => new Func(placeholder => new PlaceholderLenghtParameter(placeholder, property))) .Try(); - - public static readonly Parser PlaceholderPropertyParameter = - CommonTemplateParser.Placeholder.Before(CommonParser.Dote) - .Select(name => new PlaceholderParameter(name)) - .Then(Parser.OneOf(Lenght, File, Column, Offset, Line), - (placeholder, func) => func(placeholder)) - .TrimStart() + + public static readonly Parser> PlaceholderPropertyParameter = + CommonParser.Dote.Then(Parser.OneOf(Lenght, File, Column, Offset, Line)).Optional() + .Select(property => new Func(placeholder => + property.HasValue ? property.Value(placeholder) : placeholder)) .Try(); + + // public static readonly Parser PlaceholderPropertyParameter = + // CommonTemplateParser.Placeholder.Before(CommonParser.Dote) + // .Select(name => new PlaceholderParameter(name)) + // .Then(Parser.OneOf(Lenght, File, Column, Offset, Line), + // (placeholder, func) => func(placeholder)) + // .TrimStart() + // .Try(); } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/StringParameter.cs b/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/StringParameter.cs index 40f7bbb..b94bf9e 100644 --- a/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/StringParameter.cs +++ b/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/StringParameter.cs @@ -16,8 +16,7 @@ public string GetValue() public override string ToString() { - var value = EscapeHelper.EscapeChars(Value, c => $"{Constant.BackSlash}{c}", Constant.PlaceholderSeparator, - Constant.DoubleQuotes); + var value = EscapeHelper.EscapeChars(Value, c => $"{Constant.BackSlash}{c}", Constant.Parameter.Escape); return $"{value}"; } diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/CommonParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/CommonParser.cs index fc0e401..d7ec275 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/CommonParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/CommonParser.cs @@ -10,7 +10,7 @@ internal static readonly Parser Empty = Parsers.String(Constant.Empty, false); internal static readonly Parser AnyChar - = AnyCharExcept(Constant.FindTemplate.All()); + = AnyCharExcept(Constant.FindTemplate.All); internal static readonly Parser Space = Char(Constant.Space); diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/ParametersParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ParametersParser.cs similarity index 54% rename from src/SimpleStateMachine.StructuralSearch/Rules/Parameters/ParametersParser.cs rename to src/SimpleStateMachine.StructuralSearch/StructuralSearch/ParametersParser.cs index 82ca401..688bf0c 100644 --- a/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/ParametersParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ParametersParser.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Pidgin; using SimpleStateMachine.StructuralSearch.Extensions; using SimpleStateMachine.StructuralSearch.Rules; @@ -13,34 +14,45 @@ public static class ParametersParser .TrimStart() .Try(); - public static readonly Parser PlaceholderRuleParameter = - PlaceholderParameter - .As(); + // public static readonly Parser PlaceholderRuleParameter = + // PlaceholderParameter + // .As(); + + public static readonly Parser PlaceholderOrPropertyRuleParameter = + PlaceholderParameter.Then(PlaceholderPropertyParser.PlaceholderPropertyParameter, + (placeholder, func) => func(placeholder)) + .Try(); public static readonly Parser StringParameter = - CommonParser.Escaped(Constant.DoubleQuotes, Constant.PlaceholderSeparator) - .Or(Parser.AnyCharExcept(Constant.DoubleQuotes, Constant.PlaceholderSeparator)) + CommonParser.Escaped(Constant.Parameter.Escape) + .Or(Parser.AnyCharExcept(Constant.Parameter.Excluded)) .AtLeastOnceString() .Select(x => new StringParameter(x)) .As() .Try(); - + public static readonly Parser StringFormatParameter = - Parser.OneOf(StringParameter, PlaceholderPropertyParser.PlaceholderPropertyParameter, PlaceholderRuleParameter) + Parser.OneOf(PlaceholderOrPropertyRuleParameter, StringParameter) .AtLeastOnce() .Between(CommonParser.DoubleQuotes) .Select(parameters => new StringFormatParameter(parameters)) .As() .TrimStart() .Try(); - + public static readonly Parser Parameter = - Parser.OneOf(PlaceholderPropertyParser.PlaceholderPropertyParameter, PlaceholderRuleParameter, StringFormatParameter) + Parser.OneOf(StringFormatParameter, PlaceholderOrPropertyRuleParameter) .TrimStart() .Try(); public static readonly Parser> Parameters = Parameter.SeparatedAtLeastOnce(CommonParser.Comma); + public static readonly Parser> ChangeTypeParameter = + CommonParser.Dote.Then(Parser.CIEnum()) + .Optional() + .Select(changeType => new Func(placeholder => + changeType.HasValue ? new ChangeParameter(placeholder, changeType.Value) : placeholder)) + .Try(); } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs index 3f430d8..ff0cf5f 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs @@ -1,4 +1,6 @@ -using Pidgin; +using System; +using System.Collections.Generic; +using Pidgin; using SimpleStateMachine.StructuralSearch.Extensions; using SimpleStateMachine.StructuralSearch.Rules; @@ -10,20 +12,13 @@ public static class ReplaceRuleParser Parser.CIString(Constant.Then) .Try() .TrimStart(); - - internal static readonly Parser ReplaceSubRuleParameter = - Parser.Map((parameter, changeType) => - changeType.HasValue ? new ChangeParameter(parameter, changeType.Value) : parameter, - ParametersParser.Parameter, - CommonParser.Dote.Then(Parser.CIEnum()).Optional()) - .Try() - .TrimStart(); - + internal static readonly Parser ReplaceSubRule = Parser.Map((placeholder, _, parameter) => new ReplaceSubRule(placeholder, parameter), ParametersParser.PlaceholderParameter.TrimStart(), CommonTemplateParser.Should.TrimStart(), - ReplaceSubRuleParameter) + ParametersParser.Parameter + .Then(ParametersParser.ChangeTypeParameter, (parameter, func) => func(parameter))) .Try() .TrimStart(); diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs index 99fdb76..797b737 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs @@ -2,55 +2,73 @@ using Pidgin; using SimpleStateMachine.StructuralSearch.Extensions; using SimpleStateMachine.StructuralSearch.ReplaceTemplate; +using SimpleStateMachine.StructuralSearch.Rules; namespace SimpleStateMachine.StructuralSearch { internal class ReplaceTemplateParser { - static ReplaceTemplateParser() - { - Parenthesised = Parsers.BetweenOneOfChars(x=> ParserToReplace.Stringc(x), - Parser.Rec(() => Term), - Constant.AllParenthesised); - - Term = Parser.OneOf(Parenthesised, Token) - .Many() - .MergerMany(); - - TemplateParser = Parser.OneOf(Parenthesised, Token) - .AtLeastOnceUntil(CommonParser.EOF) - .MergerMany(); - } - - internal static readonly Parser Empty = - ParserToReplace.ResultAsReplace(CommonParser.Empty); - - internal static readonly Parser AnyString = - ParserToReplace.ResultAsReplace(CommonParser.AnyString) + // static ReplaceTemplateParser() + // { + // Parenthesised = Parsers.BetweenOneOfChars(x=> ParserToReplace.Stringc(x), + // Parser.Rec(() => Term), + // Constant.AllParenthesised); + // + // Term = Parser.OneOf(Parenthesised, Token) + // .Many() + // .MergerMany(); + // + // TemplateParser = Parser.OneOf(Parenthesised, Token) + // .AtLeastOnceUntil(CommonParser.EOF) + // .MergerMany(); + // } + // + // internal static readonly Parser Empty = + // ParserToReplace.ResultAsReplace(CommonParser.Empty); + // + // internal static readonly Parser AnyString = + // ParserToReplace.ResultAsReplace(CommonParser.AnyString) + // .Try(); + // + // internal static readonly Parser WhiteSpaces = + // ParserToReplace.ResultAsReplace(CommonParser.WhiteSpaces) + // .Try(); + // + // internal static readonly Parser Placeholder = + // CommonTemplateParser.Placeholder.Select(name=> new PlaceholderReplace(name)) + // .As() + // .Try(); + // + // internal static readonly Parser> Token = + // Parser.OneOf(AnyString, Placeholder, WhiteSpaces) + // .AsMany(); + // + // internal static readonly Parser> Term; + // + // internal static readonly Parser> Parenthesised; + // + // internal static readonly Parser> TemplateParser; + // + // internal static IReplaceBuilder ParseTemplate(string str) + // { + // return TemplateParser + // .Select(steps => new ReplaceBuilder(steps)) + // .ParseOrThrow(str); + // } + + public static readonly Parser Parameter = + Parser.OneOf(ParametersParser.StringParameter, + ParametersParser.PlaceholderOrPropertyRuleParameter) + .Then(ParametersParser.ChangeTypeParameter, (parameter, func) => func(parameter)) .Try(); - internal static readonly Parser WhiteSpaces = - ParserToReplace.ResultAsReplace(CommonParser.WhiteSpaces) + public static readonly Parser> Parameters = + Parameter.AtLeastOnceUntil(CommonParser.EOF) .Try(); - - internal static readonly Parser Placeholder = - CommonTemplateParser.Placeholder.Select(name=> new PlaceholderReplace(name)) - .As() - .Try(); - - internal static readonly Parser> Token = - Parser.OneOf(AnyString, Placeholder, WhiteSpaces) - .AsMany(); - - internal static readonly Parser> Term; - - internal static readonly Parser> Parenthesised; - - internal static readonly Parser> TemplateParser; - + internal static IReplaceBuilder ParseTemplate(string str) { - return TemplateParser + return Parameters .Select(steps => new ReplaceBuilder(steps)) .ParseOrThrow(str); } diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubRuleParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubRuleParser.cs index 7c7616e..f3f1581 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubRuleParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubRuleParser.cs @@ -10,9 +10,9 @@ public static class SubRuleParser public static readonly Parser SubRuleType = Parser.CIEnum().TrimStart(); - public static Parser SubRule(IRuleParameter left, SubRuleType ruleType) => - ParametersParser.Parameter.Select(right => new SubRule(ruleType, left, right)) - .As() + public static Parser BinarySubRule(IRuleParameter left, SubRuleType ruleType) => + ParametersParser.Parameter.Select(right => new BinarySubRule(ruleType, left, right)) + .As() .Try(); public static readonly Parser PlaceholderType = @@ -25,8 +25,9 @@ public static Parser IsSubRule(IRuleParameter left, SubRuleType rul .Try(); public static Parser InSubRule(IRuleParameter left, SubRuleType ruleType) => - Parser.OneOf(ParametersParser.Parameters, - CommonParser.Parenthesised(ParametersParser.Parameters, x => x.Trim())) + Parser.OneOf(CommonParser.Parenthesised(ParametersParser.Parameters, x => x.Trim()) + .Try(), + ParametersParser.Parameters) .Select(args => new InSubRule(left, args)) .As() .Try(); @@ -38,7 +39,7 @@ public static Parser InSubRule(IRuleParameter left, SubRuleType rul { Rules.SubRuleType.In => InSubRule(x.left, x.ruleType), Rules.SubRuleType.Is => IsSubRule(x.left, x.ruleType), - _ => SubRule(x.left, x.ruleType) + _ => BinarySubRule(x.left, x.ruleType) }); } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Templates/FindTemplate/ConstantFindTemplate.cs b/src/SimpleStateMachine.StructuralSearch/Templates/FindTemplate/ConstantFindTemplate.cs index 19db4d3..af08b28 100644 --- a/src/SimpleStateMachine.StructuralSearch/Templates/FindTemplate/ConstantFindTemplate.cs +++ b/src/SimpleStateMachine.StructuralSearch/Templates/FindTemplate/ConstantFindTemplate.cs @@ -1,4 +1,5 @@ using System.Linq; +using SimpleStateMachine.StructuralSearch.Extensions; namespace SimpleStateMachine.StructuralSearch { @@ -6,28 +7,31 @@ public static partial class Constant { public static class FindTemplate { - public static char[] All() - { - var all = new char[]{ - LeftParenthesis, - RightParenthesis, - LeftSquareParenthesis, - RightSquareParenthesis, - LeftCurlyParenthesis, - RightCurlyParenthesis, - PlaceholderSeparator, - CarriageReturn, - LineFeed, - Space - }; + public static readonly char[] All = AllParenthesisArray.Add + ( + PlaceholderSeparator, + CarriageReturn, + LineFeed, + Space + ); - return all; - } - public static char[] AllExclude(params char[] excluded) { - return All().Where(x => !excluded.Contains(x)).ToArray(); + return All.Where(x => !excluded.Contains(x)).ToArray(); } } + + public static class Parameter + { + public static readonly char[] Escape = + { + DoubleQuotes, + PlaceholderSeparator, + Dote, + }; + + public static readonly char[] Excluded = AllParenthesisArray + .Add(Escape); + } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/IReplaceBuilder.cs b/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/IReplaceBuilder.cs index ab1aa34..0a9fc50 100644 --- a/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/IReplaceBuilder.cs +++ b/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/IReplaceBuilder.cs @@ -1,10 +1,11 @@ using System.Collections.Generic; +using SimpleStateMachine.StructuralSearch.Rules; namespace SimpleStateMachine.StructuralSearch.ReplaceTemplate { public interface IReplaceBuilder { - IEnumerable Steps { get; } + IEnumerable Steps { get; } string Build(IParsingContext context); } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/ReplaceBuilder.cs b/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/ReplaceBuilder.cs index cd62f29..4ebe621 100644 --- a/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/ReplaceBuilder.cs +++ b/src/SimpleStateMachine.StructuralSearch/Templates/ReplaceTemplate/ReplaceBuilder.cs @@ -1,13 +1,14 @@ using System.Collections.Generic; using System.Text; +using SimpleStateMachine.StructuralSearch.Rules; namespace SimpleStateMachine.StructuralSearch.ReplaceTemplate { public class ReplaceBuilder : IReplaceBuilder { - public IEnumerable Steps { get; } + public IEnumerable Steps { get; } - public ReplaceBuilder(IEnumerable steps) + public ReplaceBuilder(IEnumerable steps) { Steps = steps; } From 177c8bfbcaf320d9582b579cf5065ab1e2198cf7 Mon Sep 17 00:00:00 2001 From: GMIKE Date: Fri, 13 May 2022 04:07:39 +0300 Subject: [PATCH 5/7] ChangeParameter to all placeholder parameters --- .../StructuralSearch/ParametersParser.cs | 15 +++++++++------ .../StructuralSearch/ReplaceRuleParser.cs | 3 +-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ParametersParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ParametersParser.cs index 688bf0c..2454e1b 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ParametersParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ParametersParser.cs @@ -18,9 +18,18 @@ public static class ParametersParser // PlaceholderParameter // .As(); + + public static readonly Parser> ChangeParameter = + CommonParser.Dote.Then(Parser.CIEnum()) + .Optional() + .Select(changeType => new Func(placeholder => + changeType.HasValue ? new ChangeParameter(placeholder, changeType.Value) : placeholder)) + .Try(); + public static readonly Parser PlaceholderOrPropertyRuleParameter = PlaceholderParameter.Then(PlaceholderPropertyParser.PlaceholderPropertyParameter, (placeholder, func) => func(placeholder)) + .Then(ChangeParameter, (parameter, func) => func(parameter)) .Try(); public static readonly Parser StringParameter = @@ -48,11 +57,5 @@ public static class ParametersParser public static readonly Parser> Parameters = Parameter.SeparatedAtLeastOnce(CommonParser.Comma); - public static readonly Parser> ChangeTypeParameter = - CommonParser.Dote.Then(Parser.CIEnum()) - .Optional() - .Select(changeType => new Func(placeholder => - changeType.HasValue ? new ChangeParameter(placeholder, changeType.Value) : placeholder)) - .Try(); } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs index ff0cf5f..22cfcdd 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs @@ -17,8 +17,7 @@ public static class ReplaceRuleParser Parser.Map((placeholder, _, parameter) => new ReplaceSubRule(placeholder, parameter), ParametersParser.PlaceholderParameter.TrimStart(), CommonTemplateParser.Should.TrimStart(), - ParametersParser.Parameter - .Then(ParametersParser.ChangeTypeParameter, (parameter, func) => func(parameter))) + ParametersParser.Parameter) .Try() .TrimStart(); From 53e42ecb7919b79fc8a4b121f89850d552e9a64b Mon Sep 17 00:00:00 2001 From: GMIKE Date: Fri, 13 May 2022 04:07:56 +0300 Subject: [PATCH 6/7] ChangeTypeParameter => ChangeParameter --- .../StructuralSearch/ReplaceTemplateParser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs index 797b737..3c20ee0 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs @@ -59,7 +59,7 @@ internal class ReplaceTemplateParser public static readonly Parser Parameter = Parser.OneOf(ParametersParser.StringParameter, ParametersParser.PlaceholderOrPropertyRuleParameter) - .Then(ParametersParser.ChangeTypeParameter, (parameter, func) => func(parameter)) + .Then(ParametersParser.ChangeParameter, (parameter, func) => func(parameter)) .Try(); public static readonly Parser> Parameters = From d97d7ced610b0eaec22a8b560fcb7e4553d03196 Mon Sep 17 00:00:00 2001 From: GMIKE Date: Sat, 14 May 2022 18:21:03 +0300 Subject: [PATCH 7/7] add action project --- .dockerignore | 25 +++++ Dockerfile | 18 +++ .../ActionInputs.cs | 58 ++++++++++ .../Program.cs | 105 ++++++++++++++++++ ...tateMachine.StructuralSearch.Action.csproj | 20 ++++ SimpleStateMachine.StructuralSearch.sln | 17 +++ action.yml | 43 +++++++ .../FindTemplateParserTests.cs | 9 +- .../ReplaceTemplateTests.cs | 2 + .../Extensions/ParserExtensions.cs | 5 + .../Parsers/Parsers.cs | 10 +- .../StructuralSearch/ParametersParser.cs | 40 ++++++- .../StructuralSearch/ReplaceTemplateParser.cs | 2 +- .../StructuralSearch/SubRuleParser.cs | 5 +- 14 files changed, 348 insertions(+), 11 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 SimpleStateMachine.StructuralSearch.Action/ActionInputs.cs create mode 100644 SimpleStateMachine.StructuralSearch.Action/Program.cs create mode 100644 SimpleStateMachine.StructuralSearch.Action/SimpleStateMachine.StructuralSearch.Action.csproj create mode 100644 action.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..cd967fc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d0d7a46 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base +WORKDIR /app + +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build +WORKDIR /src +COPY ["SimpleStateMachine.StructuralSearch.Action/SimpleStateMachine.StructuralSearch.Action.csproj", "SimpleStateMachine.StructuralSearch.Action/"] +RUN dotnet restore "SimpleStateMachine.StructuralSearch.Action/SimpleStateMachine.StructuralSearch.Action.csproj" +COPY . . +WORKDIR "/src/SimpleStateMachine.StructuralSearch.Action" +RUN dotnet build "SimpleStateMachine.StructuralSearch.Action.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "SimpleStateMachine.StructuralSearch.Action.csproj" -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "SimpleStateMachine.StructuralSearch.Action.dll"] diff --git a/SimpleStateMachine.StructuralSearch.Action/ActionInputs.cs b/SimpleStateMachine.StructuralSearch.Action/ActionInputs.cs new file mode 100644 index 0000000..85050f0 --- /dev/null +++ b/SimpleStateMachine.StructuralSearch.Action/ActionInputs.cs @@ -0,0 +1,58 @@ +using CommandLine; + +namespace SimpleStateMachine.StructuralSearch.Action; + + public class ActionInputs + { + string _repositoryName = null!; + string _branchName = null!; + + public ActionInputs() + { + if (Environment.GetEnvironmentVariable("GREETINGS") is { Length: > 0 } greetings) + { + Console.WriteLine(greetings); + } + } + + [Option('o', "owner", + Required = true, + HelpText = "The owner, for example: \"dotnet\". Assign from `github.repository_owner`.")] + public string Owner { get; set; } = null!; + + [Option('n', "name", + Required = true, + HelpText = "The repository name, for example: \"samples\". Assign from `github.repository`.")] + public string Name + { + get => _repositoryName; + set => ParseAndAssign(value, str => _repositoryName = str); + } + + [Option('b', "branch", + Required = true, + HelpText = "The branch name, for example: \"refs/heads/main\". Assign from `github.ref`.")] + public string Branch + { + get => _branchName; + set => ParseAndAssign(value, str => _branchName = str); + } + + [Option('d', "dir", + Required = true, + HelpText = "The root directory to start recursive searching from.")] + public string Directory { get; set; } = null!; + + [Option('w', "workspace", + Required = true, + HelpText = "The workspace directory, or repository root directory.")] + public string WorkspaceDirectory { get; set; } = null!; + + static void ParseAndAssign(string? value, Action assign) + { + if (value is { Length: > 0 } && assign is not null) + { + assign(value.Split("/")[^1]); + } + } + } \ No newline at end of file diff --git a/SimpleStateMachine.StructuralSearch.Action/Program.cs b/SimpleStateMachine.StructuralSearch.Action/Program.cs new file mode 100644 index 0000000..3e72de0 --- /dev/null +++ b/SimpleStateMachine.StructuralSearch.Action/Program.cs @@ -0,0 +1,105 @@ +using System.Text; +using SimpleStateMachine.StructuralSearch.Action; +using System.Web; +using CommandLine; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.FileSystemGlobbing; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using static CommandLine.Parser; + +using IHost host = Host.CreateDefaultBuilder(args) + .ConfigureServices((_, services) => + { + + }) + .Build(); + +static TService Get(IHost host) + where TService : notnull => + host.Services.GetRequiredService(); + +static async Task StartAnalysisAsync(ActionInputs inputs, IHost host) +{ + // using ProjectWorkspace workspace = Get(host); + using CancellationTokenSource tokenSource = new(); + + Console.CancelKeyPress += delegate { tokenSource.Cancel(); }; + + // var projectAnalyzer = Get(host); + + Matcher matcher = new(); + matcher.AddIncludePatterns(new[] { "**/*.csproj", "**/*.vbproj" }); + + // Dictionary metricData = new(StringComparer.OrdinalIgnoreCase); + var projects = matcher.GetResultsInFullPath(inputs.Directory); + + foreach (var project in projects) + { + // var metrics = + // await projectAnalyzer.AnalyzeAsync( + // workspace, project, tokenSource.Token); + // + // foreach (var (path, metric) in metrics) + // { + // metricData[path] = metric; + // } + } + + // var updatedMetrics = false; + // var title = ""; + // StringBuilder summary = new(); + // if (metricData is { Count: > 0 }) + // { + // var fileName = "CODE_METRICS.md"; + // var fullPath = Path.Combine(inputs.Directory, fileName); + // var logger = Get(host).CreateLogger(nameof(StartAnalysisAsync)); + // var fileExists = File.Exists(fullPath); + // + // logger.LogInformation( + // $"{(fileExists ? "Updating" : "Creating")} {fileName} markdown file with latest code metric data."); + // + // summary.AppendLine( + // title = + // $"{(fileExists ? "Updated" : "Created")} {fileName} file, analyzed metrics for {metricData.Count} projects."); + // + // foreach (var (path, _) in metricData) + // { + // summary.AppendLine($"- *{path}*"); + // } + // + // var contents = metricData.ToMarkDownBody(inputs); + // await File.WriteAllTextAsync( + // fullPath, + // contents, + // tokenSource.Token); + // + // updatedMetrics = true; + // } + // else + // { + // summary.Append("No metrics were determined."); + // } + // + // // https://docs.github.com/actions/reference/workflow-commands-for-github-actions#setting-an-output-parameter + // Console.WriteLine($"::set-output name=updated-metrics::{updatedMetrics}"); + // Console.WriteLine($"::set-output name=summary-title::{title}"); + // Console.WriteLine($"::set-output name=summary-details::{summary}"); + + Environment.Exit(0); +} + +var parser = Default.ParseArguments(() => new ActionInputs(), args); +parser.WithNotParsed( + errors => + { + Get(host) + .CreateLogger("DotNet.GitHubAction.Program") + .LogError( + string.Join(Environment.NewLine, errors.Select(error => error.ToString()))); + + Environment.Exit(2); + }); + +await parser.WithParsedAsync(options => StartAnalysisAsync(options, host)); +await host.RunAsync(); \ No newline at end of file diff --git a/SimpleStateMachine.StructuralSearch.Action/SimpleStateMachine.StructuralSearch.Action.csproj b/SimpleStateMachine.StructuralSearch.Action/SimpleStateMachine.StructuralSearch.Action.csproj new file mode 100644 index 0000000..7b29f5a --- /dev/null +++ b/SimpleStateMachine.StructuralSearch.Action/SimpleStateMachine.StructuralSearch.Action.csproj @@ -0,0 +1,20 @@ + + + + Exe + net6.0 + enable + enable + Windows + + + + + + + + + + + + diff --git a/SimpleStateMachine.StructuralSearch.sln b/SimpleStateMachine.StructuralSearch.sln index e4bd165..dba3167 100644 --- a/SimpleStateMachine.StructuralSearch.sln +++ b/SimpleStateMachine.StructuralSearch.sln @@ -9,6 +9,19 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleStateMachine.Structur EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleStateMachine.StructuralSearch.Sandbox", "src\SimpleStateMachine.StructuralSearch.Sandbox\SimpleStateMachine.StructuralSearch.Sandbox.csproj", "{263ABF7D-9728-4224-A584-5412E158D4BB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleStateMachine.StructuralSearch.Action", "SimpleStateMachine.StructuralSearch.Action\SimpleStateMachine.StructuralSearch.Action.csproj", "{E22FFF76-E929-4E01-B2B3-4B9283705EDE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6CB879CC-E497-41C0-AEBD-864E9D3807A6}" + ProjectSection(SolutionItems) = preProject + Dockerfile = Dockerfile + .dockerignore = .dockerignore + .gitignore = .gitignore + LICENSE = LICENSE + README.md = README.md + global.json = global.json + action.yml = action.yml + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -31,6 +44,10 @@ Global {263ABF7D-9728-4224-A584-5412E158D4BB}.Debug|Any CPU.Build.0 = Debug|Any CPU {263ABF7D-9728-4224-A584-5412E158D4BB}.Release|Any CPU.ActiveCfg = Release|Any CPU {263ABF7D-9728-4224-A584-5412E158D4BB}.Release|Any CPU.Build.0 = Release|Any CPU + {E22FFF76-E929-4E01-B2B3-4B9283705EDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E22FFF76-E929-4E01-B2B3-4B9283705EDE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E22FFF76-E929-4E01-B2B3-4B9283705EDE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E22FFF76-E929-4E01-B2B3-4B9283705EDE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..ca6c334 --- /dev/null +++ b/action.yml @@ -0,0 +1,43 @@ +name: 'Structural search' +description: 'A Github action that maintains a CODE_METRICS.md file, reporting cyclomatic complexity, maintainability index, etc.' +branding: + icon: sliders + color: purple +inputs: + owner: + description: 'The owner of the repo. Assign from github.repository_owner. Example, "dotnet".' + required: true + name: + description: 'The repository name. Example, "samples".' + required: true + branch: + description: 'The branch name. Assign from github.ref. Example, "refs/heads/main".' + required: true + dir: + description: 'The root directory to work from. Example, "path/to/code".' + required: true + workspace: + description: 'The workspace directory.' + required: false + default: '/github/workspace' +outputs: + summary-title: + description: 'The title of the code metrics action.' + summary-details: + description: 'A detailed summary of all the projects that were flagged.' + updated-metrics: + description: 'A boolean value, indicating whether or not the CODE_METRICS.md was updated as a result of running this action.' +runs: + using: 'docker' + image: 'Dockerfile' + args: + - '-o' + - ${{ inputs.owner }} + - '-n' + - ${{ inputs.name }} + - '-b' + - ${{ inputs.branch }} + - '-d' + - ${{ inputs.dir }} + - '-w' + - ${{ inputs.workspace }} diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/FindTemplateParserTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/FindTemplateParserTests.cs index 274f9ab..e1a6e9b 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/FindTemplateParserTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/FindTemplateParserTests.cs @@ -12,7 +12,7 @@ public class FindTemplateTests [InlineData("FindTemplate/AssignmentNullUnionOperator.txt")] [InlineData("FindTemplate/NestedParenthesised.txt")] [InlineData("FindTemplate/TernaryOperator.txt")] - public void FindTemplateParsingShouldBeSuccess(string templatePath) + public void FindTemplateFromFileParsingShouldBeSuccess(string templatePath) { var findTemplate = File.ReadAllText(templatePath); var template = StructuralSearch.ParseFindTemplate(findTemplate); @@ -47,5 +47,12 @@ public void FindTemplateParsingShouldBeFail(string templateStr) { Assert.Throws(() => StructuralSearch.ParseFindTemplate(templateStr)); } + + [Theory] + [InlineData("( $var$ )")] + public void FindTemplateParsingShouldBeSuccess(string templateStr) + { + var template = StructuralSearch.ParseFindTemplate(templateStr); + } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs index e961654..89d4fc7 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs @@ -52,6 +52,8 @@ public void ReplaceBuildShouldBeSuccess(string templatePath, string resultPath, Assert.Equal(replaceResult, result); } + // TODO validation parenthesis for parameters + [Theory] [InlineData("test $var1$.Lenght")] [InlineData("(test $var1$.Lenght)")] diff --git a/src/SimpleStateMachine.StructuralSearch/Extensions/ParserExtensions.cs b/src/SimpleStateMachine.StructuralSearch/Extensions/ParserExtensions.cs index 4a46019..35e2f5d 100644 --- a/src/SimpleStateMachine.StructuralSearch/Extensions/ParserExtensions.cs +++ b/src/SimpleStateMachine.StructuralSearch/Extensions/ParserExtensions.cs @@ -113,5 +113,10 @@ public static Parser After(this Parser parse { return parserAfter.Then(parser, (u, t) => t); } + + public static Parser ParenthesisedOptional(this Parser parser, Func, Parser> custom) + { + return OneOf(CommonParser.Parenthesised(parser, custom).Try(), parser); + } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Parsers/Parsers.cs b/src/SimpleStateMachine.StructuralSearch/Parsers/Parsers.cs index e64b0d9..2640500 100644 --- a/src/SimpleStateMachine.StructuralSearch/Parsers/Parsers.cs +++ b/src/SimpleStateMachine.StructuralSearch/Parsers/Parsers.cs @@ -91,11 +91,11 @@ public static Parser> BetweenOneOfChars(Func BetweenOneOf(Func> leftRight, - Parser expr, params (char, char)[] values) - { - return OneOf(values.Select(x => expr.Between(leftRight(x.Item1), leftRight(x.Item2)))); - } + // public static Parser BetweenOneOf(Func> leftRight, + // Parser expr, params (char, char)[] values) + // { + // return OneOf(values.Select(x => expr.Between(leftRight(x.Item1), leftRight(x.Item2)))); + // } public static Parser> BetweenOneOfChars(Func> leftRight, Parser expr, params (char, char)[] values) diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ParametersParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ParametersParser.cs index 2454e1b..bb1464b 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ParametersParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ParametersParser.cs @@ -8,6 +8,44 @@ namespace SimpleStateMachine.StructuralSearch { public static class ParametersParser { + + static ParametersParser() + { + Parenthesised = Parsers.BetweenOneOfChars(Parser.Char, + Parser.Rec(() => Test), + Constant.AllParenthesised); + + Test = Parser.OneOf(Parenthesised, String); + + Str = Test.AsString() + .Select(x => new StringParameter(x)) + .As() + .Try(); + + + // Term = Parser.OneOf(Parenthesised, Token) + // .Many() + // .MergerMany(); + } + + public static readonly Parser> String = + CommonParser.Escaped(Constant.Parameter.Escape) + .Or(Parser.AnyCharExcept(Constant.Parameter.Excluded)) + .AtLeastOnce(); + + public static readonly Parser> Parenthesised; + + public static readonly Parser> Test; + + + + public static readonly Parser Str; + + + // .Select(x => new StringParameter(x)) + // .As() + // .Try(); + public static readonly Parser PlaceholderParameter = CommonTemplateParser.Placeholder .Select(x => new PlaceholderParameter(x)) @@ -41,7 +79,7 @@ public static class ParametersParser .Try(); public static readonly Parser StringFormatParameter = - Parser.OneOf(PlaceholderOrPropertyRuleParameter, StringParameter) + Parser.OneOf(PlaceholderOrPropertyRuleParameter, Str) .AtLeastOnce() .Between(CommonParser.DoubleQuotes) .Select(parameters => new StringFormatParameter(parameters)) diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs index 3c20ee0..583eabc 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceTemplateParser.cs @@ -57,7 +57,7 @@ internal class ReplaceTemplateParser // } public static readonly Parser Parameter = - Parser.OneOf(ParametersParser.StringParameter, + Parser.OneOf(ParametersParser.Str, ParametersParser.PlaceholderOrPropertyRuleParameter) .Then(ParametersParser.ChangeParameter, (parameter, func) => func(parameter)) .Try(); diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubRuleParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubRuleParser.cs index f3f1581..be94c6e 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubRuleParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubRuleParser.cs @@ -25,9 +25,8 @@ public static Parser IsSubRule(IRuleParameter left, SubRuleType rul .Try(); public static Parser InSubRule(IRuleParameter left, SubRuleType ruleType) => - Parser.OneOf(CommonParser.Parenthesised(ParametersParser.Parameters, x => x.Trim()) - .Try(), - ParametersParser.Parameters) + ParametersParser.Parameters + .ParenthesisedOptional(x => x.Trim()) .Select(args => new InSubRule(left, args)) .As() .Try();