diff --git a/global.json b/global.json index e5674e1..1bcf6c0 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "5.0.0", + "version": "6.0.0", "rollForward": "latestMinor", "allowPrerelease": false } diff --git a/src/SimpleStateMachine.StructuralSearch.Sandbox/Program.cs b/src/SimpleStateMachine.StructuralSearch.Sandbox/Program.cs index 56b4bf0..f291002 100644 --- a/src/SimpleStateMachine.StructuralSearch.Sandbox/Program.cs +++ b/src/SimpleStateMachine.StructuralSearch.Sandbox/Program.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Text; using System.Text.Json; using System.Text.RegularExpressions; using Pidgin; @@ -19,6 +21,24 @@ internal static class Program { static void Main(string[] args) { + + var source = "test;;;test;;;."; + var parser = Parser.OneOf(Parser.Any.ThenReturn(Unit.Value), Parser.End); + + + var t = Parser.Any.AtLeastOnceAsStringUntil(Lookahead(String(";").Then(Not(String(";"))).Try())).ParseOrThrow(source); + + + var path = "Test.txt"; + var oldText = "0123456789"; + var text = "test"; + File.WriteAllText(path, oldText); + + using var stringReader = text.AsStream(); + using var streamWriter = File.OpenWrite(path); + + stringReader.CopyPartTo(streamWriter, 0, 7); + // var config = YmlHelper.Parse( // @"C:\Users\roman\GitHub\SimpleStateMachine.StructuralSearch\src\SimpleStateMachine.StructuralSearch.Tests\ConfigurationFile\FullConfig.yml"); // diff --git a/src/SimpleStateMachine.StructuralSearch.Sandbox/SimpleStateMachine.StructuralSearch.Sandbox.csproj b/src/SimpleStateMachine.StructuralSearch.Sandbox/SimpleStateMachine.StructuralSearch.Sandbox.csproj index 5ae1b76..72e7851 100644 --- a/src/SimpleStateMachine.StructuralSearch.Sandbox/SimpleStateMachine.StructuralSearch.Sandbox.csproj +++ b/src/SimpleStateMachine.StructuralSearch.Sandbox/SimpleStateMachine.StructuralSearch.Sandbox.csproj @@ -5,11 +5,11 @@ net5.0 enable enable - 9 + 10 - + diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/ConfigurationFile/FullConfig.yml b/src/SimpleStateMachine.StructuralSearch.Tests/ConfigurationFile/FullConfig.yml index d1bafe5..4c6daaa 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/ConfigurationFile/FullConfig.yml +++ b/src/SimpleStateMachine.StructuralSearch.Tests/ConfigurationFile/FullConfig.yml @@ -14,19 +14,17 @@ # NullUnionOperator - FindTemplate: |- - if($value1$ $sign$ null) - { + if($value$ $sign$ null) $var$ = $value2$; - } else - { $var$ = $value1$; - } FindRules: - $sign$ In ("Is", "==", "!=", "is not") + - $value$ In ($value1$, "$value1$.Value", $value2$, "$value2$.Value") ReplaceTemplate: |- $var$ = $value1$ ?? $value2$; ReplaceRules: + - $sign$ In ("!=", "is not") then $var2$ => $var1$, $var1$ => $var2$ # TernaryOperator diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/ConfigurationFile/ShortConfig.yml b/src/SimpleStateMachine.StructuralSearch.Tests/ConfigurationFile/ShortConfig.yml index 04115a6..c673f23 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/ConfigurationFile/ShortConfig.yml +++ b/src/SimpleStateMachine.StructuralSearch.Tests/ConfigurationFile/ShortConfig.yml @@ -13,19 +13,17 @@ # NullUnionOperator - FindTemplate: |- - if($value1$ $sign$ null) - { + if($value$ $sign$ null) $var$ = $value2$; - } else - { $var$ = $value1$; - } FindRules: - $sign$ In ("Is", "==", "!=", "is not") + - $value$ In ($value1$, "$value1$.Value", $value2$, "$value2$.Value") ReplaceTemplate: |- $var$ = $value1$ ?? $value2$; - + ReplaceRules: + - $sign$ In ("!=", "is not") then $var2$ => $var1$, $var1$ => $var2$ # TernaryOperator - FindTemplate: |- diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/Examples/NullUnionOperator.cs b/src/SimpleStateMachine.StructuralSearch.Tests/Examples/NullUnionOperator.cs new file mode 100644 index 0000000..41be29b --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch.Tests/Examples/NullUnionOperator.cs @@ -0,0 +1,53 @@ +namespace SimpleStateMachine.StructuralSearch.Tests.Examples; + +public class NullUnionOperator +{ + public int Test1() + { + int? temp = 1; + + if(temp is null) + return 3; + else + return 4; + } + + public void Test2() + { + int? result; + int? temp1 = 5; + int? temp2 = 5; + if(temp1 is null) + result = temp2; + else + result = temp1; + } + + public void Test3() + { + int result; + int? temp1 = 5; + int? temp2 = 5; + if(temp1 is null) + result = temp2.Value; + else + result = temp1.Value; + } + + public int Test4() + { + int? temp3 = 5; + + if(temp3 is null) + return 7; + else if (temp3 == 8) + return 9; + else + return 10; + } + + public void Test5() + { + + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/Examples/TernaryOperator.cs b/src/SimpleStateMachine.StructuralSearch.Tests/Examples/TernaryOperator.cs new file mode 100644 index 0000000..8cd797b --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch.Tests/Examples/TernaryOperator.cs @@ -0,0 +1,54 @@ +using System; + +namespace SimpleStateMachine.StructuralSearch.Tests.Examples +{ + public class TernaryOperator + { + public int Test1() + { + var temp = 1; + + if(temp == 2) + return 3; + else + return 4; + } + + public int Test2() + { + var temp = 5; + + if(temp == 6) + return 7; + else + return 8; + } + + public int Test3() + { + var temp2 = 1; + + if(temp2 == 2) + return 3; + else + return 4; + } + + public int Test4() + { + var temp3 = 5; + + if(temp3 == 6) + return 7; + else if (temp3 == 8) + return 9; + else + return 10; + } + + public void Test5() + { + + } + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/FindRule/NullUnionOperator.txt b/src/SimpleStateMachine.StructuralSearch.Tests/FindRule/NullUnionOperator.txt index 3afde7b..ca18854 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/FindRule/NullUnionOperator.txt +++ b/src/SimpleStateMachine.StructuralSearch.Tests/FindRule/NullUnionOperator.txt @@ -1 +1,2 @@ -$sign$ In ("Is", "==", "!=", "is not") \ No newline at end of file +$sign$ In ("Is", "==", "!=", "is not") +$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 8c98cfc..64987c9 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/FindRuleParserTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/FindRuleParserTests.cs @@ -10,21 +10,24 @@ namespace SimpleStateMachine.StructuralSearch.Tests public class FindRuleParserTests { [Theory] - [InlineData("equals $var$")] - [InlineData("equals \"\\$\"")] - [InlineData("Not equals $var$.Lenght")] - [InlineData("Not equals $var$.offset.Start")] - [InlineData("equals $var$.Lenght and Not StartsWith \"123\"")] - [InlineData("equals $var$.Lenght and Not StartsWith \"\\\"Test\"")] - [InlineData("Contains $var$.Lenght")] - [InlineData("Contains \"123\"")] - [InlineData("StartsWith $var$.Lenght")] - [InlineData("StartsWith \"123\"")] - [InlineData("EndsWith $var$.Lenght")] - [InlineData("EndsWith \"123\"")] - [InlineData("Match $var$.Lenght")] - [InlineData("Is Int")] - [InlineData("Is DateTime")] + [InlineData("$var$ equals $var$")] + [InlineData("$var$ equals \"\\$\"")] + [InlineData("Not $var$ equals $var$.Lenght")] + [InlineData("Not $var$ equals $var$.offset.Start")] + [InlineData("$var$ equals $var$.Lenght and Not $var$ StartsWith \"123\"")] + [InlineData("Not $var$ equals $var$.Lenght and $var$ StartsWith \"123\"")] + [InlineData("$var$ equals $var$.Lenght and Not $var$ StartsWith \"\\\"Test\"")] + [InlineData("$var$ Contains $var$.Lenght")] + [InlineData("$var1$.Lenght Contains $var2$.Lenght")] + [InlineData("$var$ Contains \"123\"")] + [InlineData("$var$ StartsWith $var$.Lenght")] + [InlineData("$var$.Lenght Equals $var$.Lenght")] + [InlineData("$var$ StartsWith \"123\"")] + [InlineData("$var$ EndsWith $var$.Lenght")] + [InlineData("$var$ EndsWith \"123\"")] + [InlineData("$var$ Match $var$.Lenght")] + [InlineData("$var$ Is Int")] + [InlineData("$var$ Is DateTime")] public void FindRuleExprParsingShouldBeSuccess(string ruleStr) { @@ -35,8 +38,10 @@ public void FindRuleExprParsingShouldBeSuccess(string ruleStr) } [Theory] - [InlineData("In \"Is\", \"==\", \"!=\", \"is not\"", "In \"Is\",\"==\",\"!=\",\"is not\"")] - [InlineData("In (\"Is\", \"==\", \"!=\", \"is not\")", "In \"Is\",\"==\",\"!=\",\"is not\"")] + [InlineData("$var$ In \"Is\", \"==\", \"!=\", \"is not\"", "$var$ In \"Is\",\"==\",\"!=\",\"is not\"")] + [InlineData("$var$ In (\"Is\", \"==\", \"!=\", \"is not\")", "$var$ In \"Is\",\"==\",\"!=\",\"is not\"")] + [InlineData("Not ($var$ equals $var$.Lenght and $var$ StartsWith \"123\")", "Not $var$ equals $var$.Lenght and $var$ StartsWith \"123\"")] + [InlineData("Not ($var$ equals $var$.Lenght)", "Not $var$ equals $var$.Lenght")] public void FindRuleExprParsingShouldBeEqualsCustomResult(string ruleStr, string customResult) { var rule = FindRuleParser.Expr.ParseOrThrow(ruleStr); diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/FindTemplate/NullUnionOperator.txt b/src/SimpleStateMachine.StructuralSearch.Tests/FindTemplate/NullUnionOperator.txt index 24e5979..38d96cb 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/FindTemplate/NullUnionOperator.txt +++ b/src/SimpleStateMachine.StructuralSearch.Tests/FindTemplate/NullUnionOperator.txt @@ -1,8 +1,4 @@ -if($value1$ $sign$ null) -{ +if($value$ $sign$ null) $var$ = $value2$; -} else -{ - $var$ = $value1$; -} \ No newline at end of file + $var$ = $value1$; \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/FindTemplateTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/FindTemplateParserTests.cs similarity index 84% rename from src/SimpleStateMachine.StructuralSearch.Tests/FindTemplateTests.cs rename to src/SimpleStateMachine.StructuralSearch.Tests/FindTemplateParserTests.cs index d028e05..4abc086 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/FindTemplateTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/FindTemplateParserTests.cs @@ -1,4 +1,5 @@ using System.IO; +using System.Linq; using Pidgin; using Xunit; @@ -28,13 +29,16 @@ public void SourceParsingBeFindTemplateShouldBeSuccess(string templatePath, stri { var findTemplate = File.ReadAllText(templatePath); var source = File.ReadAllText(sourcePath); + var input = Input.String(source); var findParser = StructuralSearch.ParseFindTemplate(findTemplate); - IParsingContext parsingContext = new ParsingContext(); - var result = findParser.Parse(ref parsingContext, source); + IParsingContext parsingContext = new ParsingContext(input); + var matches = findParser.Parse(ref parsingContext); + Assert.Single(matches); + + var match = matches.First(); Assert.NotNull(findParser); - Assert.NotNull(result.Value); - Assert.Equal(result.Lenght, source.Length); + Assert.Equal(match.Match.Lenght, source.Length); } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/Mock/Configuration.cs b/src/SimpleStateMachine.StructuralSearch.Tests/Mock/Configuration.cs index 9242fdd..ab529ff 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/Mock/Configuration.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/Mock/Configuration.cs @@ -13,9 +13,8 @@ public static Configuration GetConfigurationFromFiles(string name) var fileRule = FileOrNull("FindRule", fileName) ; var replaceTemplate = FileOrNull("ReplaceTemplate", fileName); var replaceRule = FileOrNull("ReplaceRule", fileName); - - var fileRules = fileRule is null ? null : new List{ fileRule }; - var replaceRules = replaceRule is null ? null : new List{ replaceRule }; + var fileRules = fileRule is null ? null : new List(fileRule.Split(Constant.LineFeed.ToString())); + var replaceRules = replaceRule is null ? null : new List(replaceRule.Split(Constant.LineFeed.ToString())); var config = new Configuration { FindTemplate = findTemplate, diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/Mock/EmptyParsingContext.cs b/src/SimpleStateMachine.StructuralSearch.Tests/Mock/EmptyParsingContext.cs index 33bee37..2077175 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/Mock/EmptyParsingContext.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/Mock/EmptyParsingContext.cs @@ -1,8 +1,10 @@ -namespace SimpleStateMachine.StructuralSearch.Tests.Mock +using System.Collections.Generic; + +namespace SimpleStateMachine.StructuralSearch.Tests.Mock { public class EmptyParsingContext : IParsingContext { - public FileProperty File { get; } = new FileProperty(); + public IInput Input { get; } public bool TryGetPlaceholder(string name, out Placeholder value) { @@ -18,5 +20,20 @@ public Placeholder GetPlaceholder(string name) { return Placeholder.CreateEmpty(this, name, string.Empty); } + + public IReadOnlyDictionary SwitchOnNew() + { + throw new System.NotImplementedException(); + } + + public void Set(IReadOnlyDictionary placeholders) + { + throw new System.NotImplementedException(); + } + + public void Clear() + { + throw new System.NotImplementedException(); + } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/ParameterParserTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/ParameterParserTests.cs new file mode 100644 index 0000000..0115369 --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch.Tests/ParameterParserTests.cs @@ -0,0 +1,44 @@ +using Pidgin; +using Xunit; + +namespace SimpleStateMachine.StructuralSearch.Tests; + +public class ParameterParserTests +{ + [Theory] + [InlineData("\\\"132\\\"")] + public void StringParameterParsingShouldBeSuccess(string str) + { + var parameter = ParametersParser.StringParameter.ParseOrThrow(str); + var parameterStr = parameter.ToString().ToLower(); + Assert.Equal(parameterStr.ToLower(), str.ToLower()); + } + + [Theory] + [InlineData("\"132\"")] + public void StringParameterParsingShouldBeFail(string str) + { + Assert.Throws(() => ParametersParser.StringParameter.ParseOrThrow(str)); + } + + [Theory] + [InlineData("\"132\"")] + [InlineData("\"132$var1$\"")] + [InlineData("\"132 $var1$\"")] + [InlineData("\"132 $var1$ \"")] + [InlineData("\"123$var1$.Lenght456\"")] + [InlineData("\" \\\"132\\\" \"")] + public void StringFormatParameterParsingShouldBeSuccess(string str) + { + var parameter = ParametersParser.StringFormatParameter.ParseOrThrow(str); + var parameterStr = parameter.ToString().ToLower(); + Assert.Equal(parameterStr.ToLower(), str.ToLower()); + } + + [Theory] + [InlineData("\\\"132\\\"")] + public void StringFormatParameterParsingShouldBeFail(string str) + { + Assert.Throws(() => ParametersParser.StringFormatParameter.ParseOrThrow(str)); + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/PlaceholderParserTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/PlaceholderParserTests.cs index e44eb05..1ce567c 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/PlaceholderParserTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/PlaceholderParserTests.cs @@ -1,4 +1,7 @@ -using Pidgin; +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualBasic; +using Pidgin; using Xunit; namespace SimpleStateMachine.StructuralSearch.Tests @@ -18,23 +21,34 @@ public void FindTemplateShouldBeNotEmpty() [InlineData("($test$)", "(value (test) )", "value (test) ")] public void TemplateParsingShouldBeSuccess(string template, string source, string result) { - IParsingContext parsingContext = new ParsingContext(); + var input = Input.String(source); + IParsingContext parsingContext = new ParsingContext(input); var templateParser = StructuralSearch.ParseFindTemplate(template); - var res = templateParser.Parse(ref parsingContext, source); - var placeholder = parsingContext.GetPlaceholder("test"); + var matches = templateParser.Parse(ref parsingContext); + + Assert.Single(matches); + var match = matches.First(); + Assert.Single(match.Placeholders); + var placeholder = match.Placeholders.First(); - Assert.Equal(placeholder.Value, result); + Assert.Equal(placeholder.Value.Value, result); } [Theory] - [InlineData("$var$;$var2$;", "test;;;test;;;", "value ")] - public void TemplateParsingShouldBeSuccess2(string template, string source, string result) + [InlineData("$var$;", "test;;", "test")] + [InlineData("$var$;.", "test;;;.", "test;;")] + public void TemplateParsingShouldBeSuccess2(string template, string source, params string[] values) { - IParsingContext parsingContext = new ParsingContext(); + var input = Input.String(source); + IParsingContext parsingContext = new ParsingContext(input); var templateParser = StructuralSearch.ParseFindTemplate(template); - templateParser.Parse(ref parsingContext, source); - + var matches = templateParser.Parse(ref parsingContext); + Assert.Single(matches); + var match = matches.First(); + Assert.Equal(match.Placeholders.Count, values.Length); + Assert.Equal(match.Placeholders.Select(x=> x.Value.Value), values); + // var templateStr = File.ReadAllText(templatePath); // var template = StructuralSearch.ParseTemplate(templateStr); // diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceRule/NullUnionOperator.txt b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceRule/NullUnionOperator.txt new file mode 100644 index 0000000..082363d --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceRule/NullUnionOperator.txt @@ -0,0 +1 @@ +$sign$ In ("!=", "is not") then $var2$ => $var1$, $var1$ => $var2$ \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceRuleParserTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceRuleParserTests.cs index ba61dc1..577c23b 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceRuleParserTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceRuleParserTests.cs @@ -7,28 +7,13 @@ namespace SimpleStateMachine.StructuralSearch.Tests public class ReplaceRuleParserTests { [Theory] - [InlineData("$var$", "equals $var$", "$var$")] - [InlineData("$var$", "equals \"\\$\"", "\"\\$\"")] - [InlineData("$var$", "Not equals $var$.Lenght", "$var$.Lenght")] - [InlineData("$var$", "Not equals $var$.offset.Start", "$var$.offset.Start")] - [InlineData("$var$", "equals $var$.Lenght and Not StartsWith \"123\"", "$var$.offset.Start.Trim")] - [InlineData("$var$", "equals $var$.Lenght and Not StartsWith \"\\\"Test\"", "$var$.offset.Start.ToUpper")] - public void ReplaceRulePartsParsingShouldBeSuccess(string placeholder, string findRule, string replaceRule) - { - var replaceRuleStr = $"{placeholder} {findRule} => {replaceRule}"; - var rule = StructuralSearch.ParseReplaceRule(replaceRuleStr); - var ruleStr = rule.ToString().ToLower(); - Assert.NotNull(rule); - Assert.Equal(ruleStr, replaceRuleStr.ToLower()); - } - - [Theory] - [InlineData("$var1$ equals $var$ => $var2$")] - [InlineData("$var1$ equals \"\\$\" => \"\\$\"")] - [InlineData("$var1$ Not equals $var$.Lenght => $var$.Lenght")] - [InlineData("$var1$ Not equals $var$.offset.Start => $var$.offset.Start")] - [InlineData("$var1$ equals $var$.Lenght and Not StartsWith \"123\" => $var$.offset.Start.Trim")] - [InlineData("$var1$ equals $var$.Lenght and Not StartsWith \"\\\"Test\" => $var$.offset.Start.ToUpper")] + [InlineData("$var1$ equals $var2$ then $var1$ => \"test $var3$\"")] + [InlineData("$var1$ equals \"\\$\" 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")] + [InlineData("$var1$ equals $var$.Lenght and Not $var1$ StartsWith \"123\" then $var1$ => $var$.offset.Start.Trim,$var2$ => $var$.offset.Start.Trim")] + [InlineData("$var1$ equals $var$.Lenght and Not $var1$ StartsWith \"\\\"Test\" then $var1$ => $var$.offset.Start.ToUpper")] public void ReplaceRuleParsingShouldBeSuccess(string replaceRule) { var rule = StructuralSearch.ParseReplaceRule(replaceRule); @@ -36,5 +21,6 @@ public void ReplaceRuleParsingShouldBeSuccess(string replaceRule) Assert.NotNull(rule); Assert.Equal(ruleStr, replaceRule.ToLower()); } + } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs index d3a1662..db25cb1 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs @@ -38,7 +38,7 @@ public void ReplaceBuildShouldBeSuccess(string templatePath, string resultPath, var replaceResult = File.ReadAllText(resultPath); var replaceBuilder = StructuralSearch.ParseReplaceTemplate(replaceTemplate); - var parsingContext = new ParsingContext(); + var parsingContext = new ParsingContext(Input.Empty); for (int i = 0; i < keys.Length; i++) { parsingContext.AddPlaceholder(Placeholder.CreateEmpty(parsingContext, keys[i], values[i])); diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/SimpleStateMachine.StructuralSearch.Tests.csproj b/src/SimpleStateMachine.StructuralSearch.Tests/SimpleStateMachine.StructuralSearch.Tests.csproj index b90e87b..667de2e 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/SimpleStateMachine.StructuralSearch.Tests.csproj +++ b/src/SimpleStateMachine.StructuralSearch.Tests/SimpleStateMachine.StructuralSearch.Tests.csproj @@ -4,17 +4,17 @@ net5.0 enable false - 9 + 10 - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -25,6 +25,9 @@ + + Always + Always @@ -47,9 +50,5 @@ Always - - - - diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/Source/NullUnionOperator.txt b/src/SimpleStateMachine.StructuralSearch.Tests/Source/NullUnionOperator.txt index 0e7e960..df34cb0 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/Source/NullUnionOperator.txt +++ b/src/SimpleStateMachine.StructuralSearch.Tests/Source/NullUnionOperator.txt @@ -1,8 +1,4 @@ if(var1 is null) -{ temp = var2; -} else -{ - temp = var1; -} \ No newline at end of file + temp = var1; \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch.Tests/StructurSearchParserTests.cs b/src/SimpleStateMachine.StructuralSearch.Tests/StructurSearchParserTests.cs index 547f66f..0a341b0 100644 --- a/src/SimpleStateMachine.StructuralSearch.Tests/StructurSearchParserTests.cs +++ b/src/SimpleStateMachine.StructuralSearch.Tests/StructurSearchParserTests.cs @@ -1,4 +1,6 @@ -using SimpleStateMachine.StructuralSearch.Tests.Mock; +using System.IO; +using System.Linq; +using SimpleStateMachine.StructuralSearch.Tests.Mock; using Xunit; namespace SimpleStateMachine.StructuralSearch.Tests @@ -6,14 +8,20 @@ namespace SimpleStateMachine.StructuralSearch.Tests public class StructuralSearchParserTests { [Theory] - [InlineData("AssignmentNullUnionOperator")] - [InlineData("NullUnionOperator")] - [InlineData("TernaryOperator")] - public static void StructuralSearchShouldBeSuccess(string exampleName) + // [InlineData("AssignmentNullUnionOperator")] + [InlineData("NullUnionOperator", "Examples/NullUnionOperator.cs", 2)] + [InlineData("TernaryOperator", "Examples/TernaryOperator.cs", 3)] + public static void StructuralSearchShouldBeSuccess(string exampleName, string exampleFilePath, int matchesCount) { var config = ConfigurationMock.GetConfigurationFromFiles(exampleName); var parser = new StructuralSearchParser(config); - + + var fileInfo = new FileInfo(exampleFilePath); + var input = Input.File(fileInfo); + IParsingContext context = new ParsingContext(input); + + var matches = parser.Parse(ref context); + Assert.Equal(matches.Count(), matchesCount); } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Configurations/Configuration.cs b/src/SimpleStateMachine.StructuralSearch/Configurations/Configuration.cs index 6dba871..4cdf031 100644 --- a/src/SimpleStateMachine.StructuralSearch/Configurations/Configuration.cs +++ b/src/SimpleStateMachine.StructuralSearch/Configurations/Configuration.cs @@ -7,13 +7,13 @@ namespace SimpleStateMachine.StructuralSearch.Configurations { public class Configuration : IEquatable { - public string FindTemplate { get; set; } + public string FindTemplate { get; init; } - public List? FindRules { get; set; } + public List? FindRules { get; init; } - public string ReplaceTemplate { get; set; } + public string ReplaceTemplate { get; init; } - public List? ReplaceRules { get; set; } + public List? ReplaceRules { get; init; } public bool Equals(Configuration? other) { diff --git a/src/SimpleStateMachine.StructuralSearch/Constant.cs b/src/SimpleStateMachine.StructuralSearch/Constant.cs index 5a3ead5..4466a87 100644 --- a/src/SimpleStateMachine.StructuralSearch/Constant.cs +++ b/src/SimpleStateMachine.StructuralSearch/Constant.cs @@ -12,6 +12,11 @@ public static partial class Constant /// public static readonly string Not ="Not"; + /// + /// String: "Then" + /// + public static readonly string Then ="Then"; + /// /// Parenthesis char: '(' /// @@ -97,6 +102,11 @@ public static partial class Constant /// public static readonly char More = '>'; + /// + /// Char: ':' + /// + public static readonly char Colon = ':'; + /// /// String: "=>" /// diff --git a/src/SimpleStateMachine.StructuralSearch/Custom/StreamReplacer.cs b/src/SimpleStateMachine.StructuralSearch/Custom/StreamReplacer.cs new file mode 100644 index 0000000..474e309 --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/Custom/StreamReplacer.cs @@ -0,0 +1,53 @@ +using System.IO; +using System.Threading.Tasks; + +namespace SimpleStateMachine.StructuralSearch.Custom; + +// public class StreamReplacer : Stream +// { +// +// private readonly Stream _baseStream; +// +// public StreamReplacer(Stream baseStream) +// { +// _baseStream = baseStream; +// } +// +// public Task Replace(Stream stream, int fromStart, int fromEnd, int toStart, int toEnd) +// { +// stream.SetLength(); +// stream.Position = fromStart; +// stream. +// } +// +// public override void Flush() +// { +// throw new System.NotImplementedException(); +// } +// +// public override int Read(byte[] buffer, int offset, int count) +// { +// throw new System.NotImplementedException(); +// } +// +// public override long Seek(long offset, SeekOrigin origin) +// { +// throw new System.NotImplementedException(); +// } +// +// public override void SetLength(long value) +// { +// throw new System.NotImplementedException(); +// } +// +// public override void Write(byte[] buffer, int offset, int count) +// { +// throw new System.NotImplementedException(); +// } +// +// public override bool CanRead { get; } +// public override bool CanSeek { get; } +// public override bool CanWrite { get; } +// public override long Length { get; } +// public override long Position { get; set; } +// } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/EmptyInput.cs b/src/SimpleStateMachine.StructuralSearch/EmptyInput.cs new file mode 100644 index 0000000..1649fb4 --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/EmptyInput.cs @@ -0,0 +1,23 @@ +using Pidgin; + +namespace SimpleStateMachine.StructuralSearch +{ + public class EmptyInput : IInput + { + public Result ParseBy(Parser parser) + { + throw new System.NotImplementedException(); + } + + public void Replace(Match match, string value) + { + throw new System.NotImplementedException(); + } + + public string Extension => string.Empty; + public string Path => string.Empty; + public string Name => string.Empty; + public string Data => string.Empty; + public long Lenght => 0; + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Extensions/MatchExtensions.cs b/src/SimpleStateMachine.StructuralSearch/Extensions/MatchExtensions.cs new file mode 100644 index 0000000..6efb91b --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/Extensions/MatchExtensions.cs @@ -0,0 +1,9 @@ +namespace SimpleStateMachine.StructuralSearch.Extensions; + +public static class MatchExtensions +{ + public static bool IsEmpty(this Match match) + { + return string.IsNullOrEmpty(match.Value); + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Extensions/ParserExtensions.cs b/src/SimpleStateMachine.StructuralSearch/Extensions/ParserExtensions.cs index 9edcdcc..4a46019 100644 --- a/src/SimpleStateMachine.StructuralSearch/Extensions/ParserExtensions.cs +++ b/src/SimpleStateMachine.StructuralSearch/Extensions/ParserExtensions.cs @@ -42,40 +42,38 @@ public static bool TryParse(this Parser parser, string value, out result = res.Success ? res.Value : default; return res.Success; } + + public static Parser ThenInvoke(this Parser parser, Action action) + { + return parser.Select(x => + { + action.Invoke(x); + return x; + }); + } + public static Parser Contains(this Parser parser) { return parser != null ? parser.Optional().Select(x => x.HasValue) : throw new ArgumentNullException(nameof(parser)); } + + public static Parser> Match(this Parser parser) + { + return Map((oldPos, oldOffset, result, newPos, newOffset) => + { + var line = new LinePosition(oldPos.Line, newPos.Line); + var column = new ColumnPosition(oldPos.Col, newPos.Col); + var offset = new OffsetPosition(oldOffset, newOffset); + var lenght = newOffset - oldOffset; + return new Match(result, lenght, column, line, offset); + }, + Parser.CurrentPos, Parser.CurrentOffset, + parser, + Parser.CurrentPos, Parser.CurrentOffset); + } - // public static Parser WithResult(this Parser parser, Func transformResult) - // { - // = Parser.CurrentSourcePosDelta.Select((Func) (d => new SourcePos(1, 1) + d)); - // parser.Select() - // return this.Select((Func)(_ => result)); - // } - - // public static Parser BetweenWithLookahead(this Parser parser, Parser parser1, Parser parser2) - // { - // if (parser1 == null) - // throw new ArgumentNullException(nameof (parser1)); - // if (parser2 == null) - // throw new ArgumentNullException(nameof (parser2)); - // - // return Parser.Map((Func) ((_, t, _) => t), parser1, parser, parser2); - // } - - // public Parser Between( - // Parser parser1, - // Parser parser2) - // { - // if (parser1 == null) - // throw new ArgumentNullException(nameof (parser1)); - // if (parser2 == null) - // throw new ArgumentNullException(nameof (parser2)); - // return Parser.Map((Func) ((u, t, v) => t), parser1, this, parser2); - // } public static Parser WithDebug(this Parser parser, string label) { return Map((u, t, v) => @@ -115,33 +113,5 @@ public static Parser After(this Parser parse { return parserAfter.Then(parser, (u, t) => t); } - - // public static Parser BetweenAsThen(this Parser parser, Parser parser1, Parser parser2, Func func) - // { - // if (parser1 == null) - // throw new ArgumentNullException(nameof (parser1)); - // if (parser2 == null) - // throw new ArgumentNullException(nameof (parser2)); - // - // return Parser.Map(func, parser1, this, parser2); - // } - - // public static Parser Between(this Parser parser, - // Parser parser1, - // Parser parser2) - // { - // if (parser1 == null) - // throw new ArgumentNullException(nameof (parser1)); - // if (parser2 == null) - // throw new ArgumentNullException(nameof (parser2)); - // return Parser.Map((Func) ((u, t, v) => t), parser1, this, parser2); - // } - - // public static T ParseOrThrow(this Parser parser, - // string input, - // IConfiguration? configuration = null) - // { - // return ParserExtensions.GetValueOrThrow(parser.Parse(input, configuration)); - // } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Extensions/StringExtensions.cs b/src/SimpleStateMachine.StructuralSearch/Extensions/StringExtensions.cs new file mode 100644 index 0000000..0fcdc92 --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/Extensions/StringExtensions.cs @@ -0,0 +1,12 @@ +using System.IO; +using System.Text; + +namespace SimpleStateMachine.StructuralSearch.Extensions; + +public static class StringExtensions +{ + public static MemoryStream AsStream(this string str) + { + return new MemoryStream(Encoding.UTF8.GetBytes(str)); + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/FileInput.cs b/src/SimpleStateMachine.StructuralSearch/FileInput.cs new file mode 100644 index 0000000..d6d66c7 --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/FileInput.cs @@ -0,0 +1,39 @@ +using System.IO; +using System.Threading; +using Pidgin; +using SimpleStateMachine.StructuralSearch.Helper; + +namespace SimpleStateMachine.StructuralSearch +{ + public class FileInput : IInput + { + public readonly FileInfo FileInfo; + + public FileInput(FileInfo fileInfo) + { + FileInfo = fileInfo; + } + + public Result ParseBy(Parser parser) + { + return parser.Parse(FileInfo.OpenText()); + } + + public void Replace(Match match, string value) + { + using var valueReader = new StringReader(value); + using var streamWriter = new StreamWriter(FileInfo.FullName); + var emptyStart = match.Offset.Start + match.Lenght; + var emptyEnd = match.Offset.End; + valueReader.CopyPartTo(streamWriter, match.Offset.Start, match.Lenght); + + //return (emptyStart, emptyEnd); + } + + public string Extension => FileInfo.Extension; + public string Path => System.IO.Path.GetFullPath(FileInfo.FullName); + public string Name => System.IO.Path.GetFileNameWithoutExtension(FileInfo.Name); + public string Data => FileInfo.OpenText().ReadToEnd(); + public long Lenght => FileInfo.Length; + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/FindParser.cs b/src/SimpleStateMachine.StructuralSearch/FindParser.cs index ec1b7e7..106aa6a 100644 --- a/src/SimpleStateMachine.StructuralSearch/FindParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/FindParser.cs @@ -1,25 +1,50 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; using Pidgin; using SimpleStateMachine.StructuralSearch.Extensions; +using YamlDotNet.Core.Events; namespace SimpleStateMachine.StructuralSearch { public class FindParser : IFindParser { private SeriesParser Parser { get; } - public FindParser(SeriesParser parser) + public FindParser(SeriesParser parser) { Parser = parser; } - public SourceMatch Parse(ref IParsingContext context, string input) + public IEnumerable Parse(ref IParsingContext context) { + List matches = new(); + StringBuilder res = new(); Parser.SetContext(ref context); - var result = Parser.Select(x => string.Join(string.Empty, x)) - .AsMatch() - .Parse(input); - return result.Success ? result.Value : SourceMatch.Empty; + var parsingContext = context; + var parser = Parser.Select(x => string.Join(string.Empty, x)) + .Match() + .ThenInvoke(match => + { + var placeholders= parsingContext.SwitchOnNew(); + matches.Add(new FindParserMatch(match, placeholders)); + }) + .ThenReturn(Unit.Value) + .Try(); + + var empty = Parser.Any + .ThenInvoke(x => + { + res.Append(x); + parsingContext.SwitchOnNew(); + }) + .ThenReturn(Unit.Value); + + context.Input.ParseBy(Pidgin.Parser.OneOf(parser, empty).Many()); + + return matches.OrderBy(x=> x.Match.Offset.Start); } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/FindParserResult.cs b/src/SimpleStateMachine.StructuralSearch/FindParserResult.cs new file mode 100644 index 0000000..39ce87c --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/FindParserResult.cs @@ -0,0 +1,5 @@ +using System.Collections.Generic; + +namespace SimpleStateMachine.StructuralSearch; + +public readonly record struct FindParserMatch(Match Match, IReadOnlyDictionary Placeholders); \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Helper/StreamExtensions.cs b/src/SimpleStateMachine.StructuralSearch/Helper/StreamExtensions.cs new file mode 100644 index 0000000..4d9015b --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/Helper/StreamExtensions.cs @@ -0,0 +1,46 @@ +using System; +using System.Diagnostics.Contracts; +using System.IO; + +namespace SimpleStateMachine.StructuralSearch.Helper; + +public static class StreamExtensions + { + /// + /// Copies a specific number of bytes from the current position of the + /// source stream to the current position of the destination stream. + /// + /// The source stream. + /// The destination stream. + /// The number of bytes to copy. + /// The size of the buffer to use. + /// The default is 4096. + public static void CopyPartTo(this Stream source, Stream destination, int offset, int count, int bufferSize) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + if (destination == null) throw new ArgumentNullException(nameof(destination)); + + byte[] buffer = new byte[bufferSize]; + int read; + while (count > 0 && (read = source.Read(buffer, 0, Math.Min(buffer.Length, count))) > 0) + { + count -= read; + destination.Write(buffer, offset, read); + } + } + + /// + /// Copies a specific number of bytes from the current position of the + /// source stream to the current position of the destination stream. + /// + /// The source stream. + /// The destination stream. + /// The number of bytes to copy. + public static void CopyPartTo(this Stream source, Stream destination, int offset, int count) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + if (destination == null) throw new ArgumentNullException(nameof(destination)); + + CopyPartTo(source, destination, offset, count, 0x1000); + } + } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Helper/TextReaderExtensions.cs b/src/SimpleStateMachine.StructuralSearch/Helper/TextReaderExtensions.cs new file mode 100644 index 0000000..2577172 --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/Helper/TextReaderExtensions.cs @@ -0,0 +1,46 @@ +using System; +using System.IO; + +namespace SimpleStateMachine.StructuralSearch.Helper; + +public static class TextReaderExtensions +{ + /// + /// Copies a specific number of bytes from the current position of the + /// source stream to the current position of the destination stream. + /// + /// The source stream. + /// The destination stream. + /// The number of bytes to copy. + /// The size of the buffer to use. + /// The default is 4096. + public static void CopyPartTo(this TextReader source, TextWriter destination, int offset, int count, int bufferSize) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + if (destination == null) throw new ArgumentNullException(nameof(destination)); + + char[] buffer = new char[bufferSize]; + int read; + + while (count > 0 && (read = source.ReadBlock(buffer)) > 0) + { + count -= read; + destination.Write(buffer, offset, read); + } + } + + /// + /// Copies a specific number of bytes from the current position of the + /// source stream to the current position of the destination stream. + /// + /// The source stream. + /// The destination stream. + /// The number of bytes to copy. + public static void CopyPartTo(this TextReader source, TextWriter destination, int offset, int count) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + if (destination == null) throw new ArgumentNullException(nameof(destination)); + + CopyPartTo(source, destination, offset, count, 4096); + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/IFindParser.cs b/src/SimpleStateMachine.StructuralSearch/IFindParser.cs index ce74042..04ce8a2 100644 --- a/src/SimpleStateMachine.StructuralSearch/IFindParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/IFindParser.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.IO; using Pidgin; using SimpleStateMachine.StructuralSearch.ReplaceTemplate; @@ -6,6 +7,6 @@ namespace SimpleStateMachine.StructuralSearch { public interface IFindParser { - SourceMatch Parse(ref IParsingContext context, string input); + IEnumerable Parse(ref IParsingContext context); } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/IInput.cs b/src/SimpleStateMachine.StructuralSearch/IInput.cs new file mode 100644 index 0000000..7350a93 --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/IInput.cs @@ -0,0 +1,16 @@ +using Pidgin; + +namespace SimpleStateMachine.StructuralSearch +{ + public interface IInput + { + Result ParseBy(Parser parser); + void Replace(Match match, string value); + + string Extension { get; } + string Path { get; } + string Name { get; } + string Data { get; } + public long Lenght { get; } + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/IParsingContext.cs b/src/SimpleStateMachine.StructuralSearch/IParsingContext.cs index 497a16f..7cce05c 100644 --- a/src/SimpleStateMachine.StructuralSearch/IParsingContext.cs +++ b/src/SimpleStateMachine.StructuralSearch/IParsingContext.cs @@ -1,12 +1,19 @@ -namespace SimpleStateMachine.StructuralSearch +using System.Collections.Generic; + +namespace SimpleStateMachine.StructuralSearch { public interface IParsingContext { - FileProperty File { get; } + IInput Input { get; } + bool TryGetPlaceholder(string name, out Placeholder value); void AddPlaceholder(Placeholder placeholder); Placeholder GetPlaceholder(string name); + + IReadOnlyDictionary SwitchOnNew(); + void Set(IReadOnlyDictionaryplaceholders); + void Clear(); } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Input.cs b/src/SimpleStateMachine.StructuralSearch/Input.cs new file mode 100644 index 0000000..bd5e47f --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/Input.cs @@ -0,0 +1,13 @@ +using System.IO; + +namespace SimpleStateMachine.StructuralSearch +{ + public static class Input + { + public static readonly IInput Empty = new EmptyInput(); + + public static IInput String(string input) => new StringInput(input); + + public static IInput File(FileInfo fileInfo) => new FileInput(fileInfo); + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Parsers/LookaheadParser.cs b/src/SimpleStateMachine.StructuralSearch/Parsers/LookaheadParser.cs index de0854d..14df294 100644 --- a/src/SimpleStateMachine.StructuralSearch/Parsers/LookaheadParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/Parsers/LookaheadParser.cs @@ -7,7 +7,10 @@ internal sealed class LookaheadParser : Parser { private readonly Parser _parser; - public LookaheadParser(Parser parser) => this._parser = parser; + public LookaheadParser(Parser parser) + { + this._parser = parser; + } public override bool TryParse(ref ParseState state, ref PooledList> expecteds, out T result) { diff --git a/src/SimpleStateMachine.StructuralSearch/Parsers/ParserWithLookahead.cs b/src/SimpleStateMachine.StructuralSearch/Parsers/ParserWithLookahead.cs index 187e6e9..df34438 100644 --- a/src/SimpleStateMachine.StructuralSearch/Parsers/ParserWithLookahead.cs +++ b/src/SimpleStateMachine.StructuralSearch/Parsers/ParserWithLookahead.cs @@ -1,12 +1,14 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using Pidgin; +using SimpleStateMachine.StructuralSearch.Extensions; namespace SimpleStateMachine.StructuralSearch { public abstract class ParserWithLookahead : Parser { - private Func> _parser { get; set; } + protected Lazy> parser; public Func>> OnLookahead { get; set; } @@ -15,14 +17,13 @@ public abstract Parser BuildParser(Func?> next, public void Lookahead(Func?> next, Func?> nextNext) { - // lazy initialization - _parser = () => BuildParser(next, nextNext); + parser = new Lazy>(() => BuildParser(next, nextNext)); } public override bool TryParse(ref ParseState state, ref PooledList> expected, out T result) { - var res = _parser().TryParse(ref state, ref expected, out result); + var res = parser.Value.TryParse(ref state, ref expected, out result); return res; } } diff --git a/src/SimpleStateMachine.StructuralSearch/Parsers/Parsers.cs b/src/SimpleStateMachine.StructuralSearch/Parsers/Parsers.cs index 42d3fc9..e64b0d9 100644 --- a/src/SimpleStateMachine.StructuralSearch/Parsers/Parsers.cs +++ b/src/SimpleStateMachine.StructuralSearch/Parsers/Parsers.cs @@ -121,5 +121,44 @@ public static Parser Lookahead(Parser parser) = parser != null ? (Parser) new LookaheadParser(parser) : throw new ArgumentNullException(nameof (parser)); + + public static Parser> Match(Parser parser) + { + return Map((oldPos, oldOffset, result, newPos, newOffset) => + { + var line = new LinePosition(oldPos.Line, newPos.Line); + var column = new ColumnPosition(oldPos.Col, newPos.Col); + var offset = new OffsetPosition(oldOffset, newOffset); + var lenght = newOffset - oldOffset; + return new Match(result, lenght, column, line, offset); + }, + Parser.CurrentPos, Parser.CurrentOffset, + parser, + Parser.CurrentPos, Parser.CurrentOffset); + } + + + // public static string Match(Parser parser, ref ParseState state, + // ref PooledList> expected, out string result) + // { + // Parser.CurrentPos.Then(Parser.CurrentOffset, (pos, i) => (oldPos, oldOffset)) + // .Then() + // .TryParse(ref state, ref expected, out var oldPos); + // .TryParse(ref state, ref expected, out var oldOffset); + // var res = parser.TryParse(ref state, ref expected, out result); + // + // if (res) + // { + // Parser.CurrentPos.TryParse(ref state, ref expected, out var newPos); + // Parser.CurrentOffset.TryParse(ref state, ref expected, out var newOffset); + // + // var line = new LinePosition(oldPos.Line, newPos.Line); + // var column = new ColumnPosition(oldPos.Col, newPos.Col); + // var offset = new OffsetPosition(oldOffset, newOffset); + // + // } + // + // return null; + // } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Parsers/PlaceholderParser.cs b/src/SimpleStateMachine.StructuralSearch/Parsers/PlaceholderParser.cs index 7b2a78a..2d29dc9 100644 --- a/src/SimpleStateMachine.StructuralSearch/Parsers/PlaceholderParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/Parsers/PlaceholderParser.cs @@ -20,16 +20,35 @@ public override Parser BuildParser(Func?> nex Func?> nextNext) { var _next = next(); - var _nextNext = nextNext() ?? Parser.End.ThenReturn(string.Empty); - var lookahead = Parsers.Lookahead(_next.Then(_nextNext, (s1, s2) => + var _nextNext = nextNext(); + // ?? Parser.OneOf(Parser.End.ThenReturn(string.Empty), Parser.Any.ThenReturn(string.Empty)); + // Parser.End.ThenReturn(string.Empty) + + Parser lookahead; + if (_nextNext is not null) + { + lookahead = Parsers.Lookahead(_next.Then(_nextNext, (s1, s2) => + { + OnLookahead = () => new List> + { + new(_next, s1, s1.Length), + new(_nextNext, s2, s2.Length), + }; + return Unit.Value; + }).Try()); + } + else { - OnLookahead = () => new List> + lookahead = Parsers.Lookahead(_next.Select(s => { - new(_next, s1, s1.Length), - new(_nextNext, s2, s2.Length), - }; - return Unit.Value; - }).Try()); + OnLookahead = () => new List> + { + new(_next, s, s.Length) + }; + return Unit.Value; + }).Try()); + } + var anyString = CommonTemplateParser.AnyCharWithPlshd .AtLeastOnceAsStringUntil(lookahead); @@ -46,7 +65,7 @@ public override Parser BuildParser(Func?> nex //parenthesised and tokens and whiteSpaces var prdsAndTokens = Parser.OneOf(parenthesised, token) - .Until(lookahead) + .AtLeastOnceUntil(lookahead) .JoinToString() .Try(); @@ -66,22 +85,14 @@ public override bool TryParse(ref ParseState state, ref PooledList.CurrentPos.TryParse(ref state, ref expected, out var oldPos); - Parser.CurrentOffset.TryParse(ref state, ref expected, out var oldOffset); - res = base.TryParse(ref state, ref expected, out result); - + res = parser.Value.Match().TryParse(ref state, ref expected, out var match); + result = match.Value; if (res) { - Parser.CurrentSourcePosDelta.TryParse(ref state, ref expected, out var posDelta); - Parser.CurrentOffset.TryParse(ref state, ref expected, out var newOffset); - _context.AddPlaceholder(new Placeholder( context: _context, name: Name, - value: result, - line: new LineProperty(oldPos.Line, oldPos.Line + posDelta.Lines), - column: new ColumnProperty(oldPos.Col, oldPos.Col + posDelta.Cols), - offset: new OffsetProperty(oldOffset, newOffset))); + match: match)); } } diff --git a/src/SimpleStateMachine.StructuralSearch/ParsingContext.cs b/src/SimpleStateMachine.StructuralSearch/ParsingContext.cs index 4624fb9..7ed89af 100644 --- a/src/SimpleStateMachine.StructuralSearch/ParsingContext.cs +++ b/src/SimpleStateMachine.StructuralSearch/ParsingContext.cs @@ -1,12 +1,17 @@ using System.Collections.Generic; +using System.Linq; namespace SimpleStateMachine.StructuralSearch { public class ParsingContext : IParsingContext { - public Dictionary Placeholders { get; } = new(); + public ParsingContext(IInput input) + { + Input = input; + } + public readonly Dictionary Placeholders = new(); - public FileProperty File { get; } + public IInput Input { get; } public bool TryGetPlaceholder(string name, out Placeholder value) { @@ -22,5 +27,29 @@ public Placeholder GetPlaceholder(string name) { return Placeholders[name]; } + + public IReadOnlyDictionary SwitchOnNew() + { + var placeholders = Placeholders + .OrderBy(x=> x.Value.Offset.Start) + .ToDictionary(x=> x.Key, x=> x.Value); + Clear(); + return placeholders; + } + + public void Set(IReadOnlyDictionary placeholders) + { + Clear(); + + foreach (var placeholder in placeholders) + { + Placeholders.Add(placeholder.Key, placeholder.Value); + } + } + + public void Clear() + { + Placeholders.Clear(); + } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Placeholder/Column.cs b/src/SimpleStateMachine.StructuralSearch/Placeholder/Column.cs deleted file mode 100644 index 25c4480..0000000 --- a/src/SimpleStateMachine.StructuralSearch/Placeholder/Column.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace SimpleStateMachine.StructuralSearch -{ - public class ColumnProperty - { - public ColumnProperty(int start, int end) - { - Start = start; - End = end; - } - - public readonly int Start; - public readonly int End; - } -} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Placeholder/ColumnPosition.cs b/src/SimpleStateMachine.StructuralSearch/Placeholder/ColumnPosition.cs new file mode 100644 index 0000000..6776195 --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/Placeholder/ColumnPosition.cs @@ -0,0 +1,10 @@ +namespace SimpleStateMachine.StructuralSearch +{ + public readonly record struct ColumnPosition(int Start, int End) + { + public readonly int Start = Start; + public readonly int End = End; + + public static readonly ColumnPosition Empty = new(0, 0); + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Placeholder/FileProperty.cs b/src/SimpleStateMachine.StructuralSearch/Placeholder/FileProperty.cs deleted file mode 100644 index 1ef474e..0000000 --- a/src/SimpleStateMachine.StructuralSearch/Placeholder/FileProperty.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace SimpleStateMachine.StructuralSearch -{ - public class FileProperty - { - public readonly string Path; - public readonly string Data; - public readonly string Name; - public readonly string Directory; - public readonly int Lenght; - } -} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Placeholder/LinePosition.cs b/src/SimpleStateMachine.StructuralSearch/Placeholder/LinePosition.cs new file mode 100644 index 0000000..1ed42d1 --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/Placeholder/LinePosition.cs @@ -0,0 +1,10 @@ +namespace SimpleStateMachine.StructuralSearch +{ + public readonly record struct LinePosition(int Start, int End) + { + public readonly int Start = Start; + public readonly int End = End; + + public static readonly LinePosition Empty = new(0, 0); + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Placeholder/LineProperty.cs b/src/SimpleStateMachine.StructuralSearch/Placeholder/LineProperty.cs deleted file mode 100644 index 30aa306..0000000 --- a/src/SimpleStateMachine.StructuralSearch/Placeholder/LineProperty.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace SimpleStateMachine.StructuralSearch -{ - public class LineProperty - { - public LineProperty(int start, int end) - { - Start = start; - End = end; - } - - public readonly int Start; - public readonly int End; - } -} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Placeholder/MatchPosition.cs b/src/SimpleStateMachine.StructuralSearch/Placeholder/MatchPosition.cs new file mode 100644 index 0000000..d80ed3a --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/Placeholder/MatchPosition.cs @@ -0,0 +1,17 @@ +using System; + +namespace SimpleStateMachine.StructuralSearch +{ + public readonly record struct Match(T Value, int Lenght, ColumnPosition Column, LinePosition Line, + OffsetPosition Offset); + + public static class Match + { + public static readonly Match EmptyMatchString = new( + string.Empty, + 0, + ColumnPosition.Empty, + LinePosition.Empty, + OffsetPosition.Empty); + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Placeholder/OffsetPosition.cs b/src/SimpleStateMachine.StructuralSearch/Placeholder/OffsetPosition.cs new file mode 100644 index 0000000..7cd526b --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/Placeholder/OffsetPosition.cs @@ -0,0 +1,10 @@ +namespace SimpleStateMachine.StructuralSearch +{ + public readonly record struct OffsetPosition(int Start, int End) + { + public readonly int Start = Start; + public readonly int End = End; + + public static readonly OffsetPosition Empty = new(0, 0); + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Placeholder/OffsetProperty.cs b/src/SimpleStateMachine.StructuralSearch/Placeholder/OffsetProperty.cs deleted file mode 100644 index 4454d5f..0000000 --- a/src/SimpleStateMachine.StructuralSearch/Placeholder/OffsetProperty.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace SimpleStateMachine.StructuralSearch -{ - public class OffsetProperty - { - public OffsetProperty(int start, int end) - { - Start = start; - End = end; - } - - public readonly int Start; - public readonly int End; - } -} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Placeholder/Placeholder.cs b/src/SimpleStateMachine.StructuralSearch/Placeholder/Placeholder.cs index 76e2146..367631a 100644 --- a/src/SimpleStateMachine.StructuralSearch/Placeholder/Placeholder.cs +++ b/src/SimpleStateMachine.StructuralSearch/Placeholder/Placeholder.cs @@ -1,37 +1,35 @@ namespace SimpleStateMachine.StructuralSearch { - public class Placeholder + public readonly struct Placeholder { - private IParsingContext _context; - public Placeholder(IParsingContext context, string name, string value, LineProperty line, ColumnProperty column, OffsetProperty offset) + private readonly Match _match; + private readonly IParsingContext _context; + public Placeholder(IParsingContext context, string name, Match match) { _context = context; Name = name; - Lenght = value.Length; - Value = value; - Line = line; - Column = column; - Offset = offset; + _match = match; } public readonly string Name; - public readonly string Value; - public readonly int Lenght; - public FileProperty File => _context.File; - public readonly LineProperty Line; - public readonly ColumnProperty Column; - public readonly OffsetProperty Offset; - + public string Value => _match.Value; + public int Lenght => _match.Lenght; + public LinePosition Line => _match.Line; + public ColumnPosition Column => _match.Column; + public OffsetPosition Offset => _match.Offset; + public IInput Input => _context.Input; public static Placeholder CreateEmpty(IParsingContext context, string name, string value) { return new Placeholder( context: context, name: name, - value: value, - line: null, - column: null, - offset: null); + new Match( + value, + value.Length, + ColumnPosition.Empty, + LinePosition.Empty, + OffsetPosition.Empty)); } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/BinaryRule.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/BinaryRule.cs index 3003b1a..925df7f 100644 --- a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/BinaryRule.cs +++ b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/BinaryRule.cs @@ -17,10 +17,10 @@ public BinaryRule(BinaryRuleType type, IRule left, IRule right) Right = right; } - public bool Execute(string value) + public bool Execute() { - var left = Left.Execute(value); - var right = Right.Execute(value); + var left = Left.Execute(); + var right = Right.Execute(); return LogicalHelper.Calculate(Type, left, right); } diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/FindRule.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/FindRule.cs deleted file mode 100644 index 1760b14..0000000 --- a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/FindRule.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace SimpleStateMachine.StructuralSearch.Rules -{ - public class FindRule - { - public PlaceholderParameter Placeholder { get; } - - private IRule _rule { get; } - - public FindRule(PlaceholderParameter placeholder, IRule rule) - { - Placeholder = placeholder; - _rule = rule; - } - - public override string ToString() - { - return $"{Placeholder}{Constant.Space}{_rule}"; - } - } -} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/IRule.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/IRule.cs index df0ad49..1ef83c1 100644 --- a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/IRule.cs +++ b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/IRule.cs @@ -2,6 +2,6 @@ { public interface IRule { - bool Execute(string value); + bool Execute(); } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/InRule.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/InRule.cs deleted file mode 100644 index fb7a8d6..0000000 --- a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/InRule.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace SimpleStateMachine.StructuralSearch.Rules -{ - public class InRule : IRule - { - public SubRuleType Type { get; } - - public IEnumerable Parameters { get; } - - public InRule(SubRuleType type, IEnumerable parameters) - { - Type = type; - - Parameters = parameters; - } - - public bool Execute(string value) - { - return Parameters.Any(parameter => Equals(value, parameter.GetValue())); - } - - public override string ToString() - { - return $"{Type}{Constant.Space}{string.Join(Constant.Comma, Parameters.Select(x=>x.ToString()))}"; - } - } -} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/InSubRule.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/InSubRule.cs new file mode 100644 index 0000000..1b74255 --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/InSubRule.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.Linq; + +namespace SimpleStateMachine.StructuralSearch.Rules +{ + public class InSubRule : IRule + { + public IRuleParameter Parameter { get; } + + public IEnumerable Arguments { get; } + + public InSubRule(IRuleParameter parameter, IEnumerable arguments) + { + Parameter = parameter; + + Arguments = arguments; + } + + public bool Execute() + { + var value = Parameter.GetValue(); + return Arguments.Any(parameter => Equals(value, parameter.GetValue())); + } + + public override string ToString() + { + return $"{Parameter}{Constant.Space}{SubRuleType.In}{Constant.Space}{string.Join(Constant.Comma, Arguments.Select(x=>x.ToString()))}"; + } + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/IsRule.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/IsSubRule.cs similarity index 59% rename from src/SimpleStateMachine.StructuralSearch/Rules/FindRule/IsRule.cs rename to src/SimpleStateMachine.StructuralSearch/Rules/FindRule/IsSubRule.cs index f5f3eb1..e076ac1 100644 --- a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/IsRule.cs +++ b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/IsSubRule.cs @@ -3,21 +3,23 @@ namespace SimpleStateMachine.StructuralSearch.Rules { - public class IsRule : IRule + public class IsSubRule : IRule { - public SubRuleType Type { get; } + public PlaceholderType Argument { get; } - public PlaceholderType PlaceholderType { get; } + public IRuleParameter Parameter { get; } - public IsRule(SubRuleType type, PlaceholderType placeholderType) + public IsSubRule(IRuleParameter parameter, PlaceholderType argument) { - Type = type; - PlaceholderType = placeholderType; + Parameter = parameter; + Argument = argument; } - public bool Execute(string value) + public bool Execute() { - return PlaceholderType switch + var value = Parameter.GetValue(); + + return Argument switch { PlaceholderType.Var => CommonParser.Identifier.TryParse(value, out _), PlaceholderType.Int => int.TryParse(value, out _), @@ -30,7 +32,7 @@ public bool Execute(string value) public override string ToString() { - return $"{Type}{Constant.Space}{PlaceholderType}"; + return $"{Parameter}{Constant.Space}{SubRuleType.Is}{Constant.Space}{Argument}"; } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/SubRule.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/SubRule.cs new file mode 100644 index 0000000..f670c7d --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/SubRule.cs @@ -0,0 +1,42 @@ +using System; +using System.Text.RegularExpressions; + +namespace SimpleStateMachine.StructuralSearch.Rules +{ + public class SubRule : IRule + { + public SubRuleType Type { get; } + + public IRuleParameter Left { get; } + + public IRuleParameter Right { get; } + + public SubRule(SubRuleType type, IRuleParameter left, IRuleParameter right) + { + Type = type; + Left = left; + Right = right; + } + + public bool Execute() + { + var left = Right.GetValue(); + var right = Left.GetValue(); + + return Type switch + { + SubRuleType.Equals => left.Equals(right), + SubRuleType.Contains => left.Contains(right), + SubRuleType.StartsWith => left.StartsWith(right), + SubRuleType.EndsWith => left.EndsWith(right), + SubRuleType.Match => Regex.IsMatch(left, right), + _ => throw new ArgumentOutOfRangeException() + }; + } + + public override string ToString() + { + return $"{Left}{Constant.Space}{Type}{Constant.Space}{Right}"; + } + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/BinaryRuleType.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/Types/BinaryRuleType.cs similarity index 100% rename from src/SimpleStateMachine.StructuralSearch/Rules/FindRule/BinaryRuleType.cs rename to src/SimpleStateMachine.StructuralSearch/Rules/FindRule/Types/BinaryRuleType.cs diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/LineProperty.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/Types/LineProperty.cs similarity index 100% rename from src/SimpleStateMachine.StructuralSearch/Rules/FindRule/LineProperty.cs rename to src/SimpleStateMachine.StructuralSearch/Rules/FindRule/Types/LineProperty.cs diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/OffsetProperty.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/Types/OffsetProperty.cs similarity index 100% rename from src/SimpleStateMachine.StructuralSearch/Rules/FindRule/OffsetProperty.cs rename to src/SimpleStateMachine.StructuralSearch/Rules/FindRule/Types/OffsetProperty.cs diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/PlaceholderType.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/Types/PlaceholderType.cs similarity index 100% rename from src/SimpleStateMachine.StructuralSearch/Rules/FindRule/PlaceholderType.cs rename to src/SimpleStateMachine.StructuralSearch/Rules/FindRule/Types/PlaceholderType.cs diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/SubRuleType.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/Types/SubRuleType.cs similarity index 100% rename from src/SimpleStateMachine.StructuralSearch/Rules/FindRule/SubRuleType.cs rename to src/SimpleStateMachine.StructuralSearch/Rules/FindRule/Types/SubRuleType.cs diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/UnaryRuleType.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/Types/UnaryRuleType.cs similarity index 100% rename from src/SimpleStateMachine.StructuralSearch/Rules/FindRule/UnaryRuleType.cs rename to src/SimpleStateMachine.StructuralSearch/Rules/FindRule/Types/UnaryRuleType.cs diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/UnaryRule.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/UnaryRule.cs index a0c8649..d7af616 100644 --- a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/UnaryRule.cs +++ b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/UnaryRule.cs @@ -14,9 +14,9 @@ public UnaryRule(UnaryRuleType type, IRule parameter) Parameter = parameter; } - public bool Execute(string value) + public bool Execute() { - var result = Parameter.Execute(value); + var result = Parameter.Execute(); return Type switch { diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/UnarySubRule.cs b/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/UnarySubRule.cs deleted file mode 100644 index d86f6b6..0000000 --- a/src/SimpleStateMachine.StructuralSearch/Rules/FindRule/UnarySubRule.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Text.RegularExpressions; - -namespace SimpleStateMachine.StructuralSearch.Rules -{ - public class UnarySubRule : IRule - { - public SubRuleType Type { get; } - - public IRuleParameter Parameter { get; } - - public UnarySubRule(SubRuleType type, IRuleParameter parameter) - { - Type = type; - Parameter = parameter; - } - - public bool Execute(string value) - { - var param = Parameter.GetValue(); - - return Type switch - { - SubRuleType.Equals => value.Equals(param), - SubRuleType.Contains => value.Contains(param), - SubRuleType.StartsWith => value.StartsWith(param), - SubRuleType.EndsWith => value.EndsWith(param), - SubRuleType.Match => Regex.IsMatch(value, param), - _ => throw new ArgumentOutOfRangeException() - }; - } - - public override string ToString() - { - return $"{Type}{Constant.Space}{Parameter}"; - } - } -} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/FileProperty.cs b/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/FileProperty.cs index 3f039e1..78cef0d 100644 --- a/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/FileProperty.cs +++ b/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/FileProperty.cs @@ -4,8 +4,8 @@ public enum FileProperty { Path = 0, Data, + Extension, Name, - Directory, Lenght } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/ParametersParser.cs b/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/ParametersParser.cs index f027bea..82ca401 100644 --- a/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/ParametersParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/ParametersParser.cs @@ -23,7 +23,6 @@ public static class ParametersParser .AtLeastOnceString() .Select(x => new StringParameter(x)) .As() - .TrimStart() .Try(); public static readonly Parser StringFormatParameter = diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/PlaceholderFileParameter.cs b/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/PlaceholderFileParameter.cs index f49b03c..c1a6746 100644 --- a/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/PlaceholderFileParameter.cs +++ b/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/PlaceholderFileParameter.cs @@ -15,14 +15,14 @@ public PlaceholderFileParameter(PlaceholderParameter parameter, FileProperty pro public string GetValue() { - var file = PlaceholderParameter.GetPlaceholder().File; + var input = PlaceholderParameter.GetPlaceholder().Input; return Property switch { - FileProperty.Path => file.Path, - FileProperty.Data => file.Data, - FileProperty.Name => file.Name, - FileProperty.Directory => file.Directory, - FileProperty.Lenght => file.Lenght.ToString(), + FileProperty.Path => input.Path, + FileProperty.Data => input.Data, + FileProperty.Extension => input.Extension, + FileProperty.Name => input.Name, + FileProperty.Lenght => input.Lenght.ToString(), _ => throw new ArgumentOutOfRangeException() }; } diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/StringFormatParameter.cs b/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/StringFormatParameter.cs index 4bd1363..d2dd438 100644 --- a/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/StringFormatParameter.cs +++ b/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/StringFormatParameter.cs @@ -19,7 +19,7 @@ public string GetValue() public override string ToString() { - return $"{string.Join(Constant.Space, Parameters.Select(x=> x.ToString()))}"; + return $"{Constant.DoubleQuotes}{string.Join(string.Empty, Parameters.Select(x=> x.ToString()))}{Constant.DoubleQuotes}"; } } } \ 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 f4b12c8..40f7bbb 100644 --- a/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/StringParameter.cs +++ b/src/SimpleStateMachine.StructuralSearch/Rules/Parameters/StringParameter.cs @@ -19,7 +19,7 @@ public override string ToString() var value = EscapeHelper.EscapeChars(Value, c => $"{Constant.BackSlash}{c}", Constant.PlaceholderSeparator, Constant.DoubleQuotes); - return $"{Constant.DoubleQuotes}{value}{Constant.DoubleQuotes}"; + return $"{value}"; } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/ReplaceRule/ReplaceRule.cs b/src/SimpleStateMachine.StructuralSearch/Rules/ReplaceRule/ReplaceRule.cs index ee49fbe..88de028 100644 --- a/src/SimpleStateMachine.StructuralSearch/Rules/ReplaceRule/ReplaceRule.cs +++ b/src/SimpleStateMachine.StructuralSearch/Rules/ReplaceRule/ReplaceRule.cs @@ -1,4 +1,6 @@ -using Pidgin; +using System.Collections.Generic; +using System.Reflection.Metadata; +using Pidgin; using SimpleStateMachine.StructuralSearch.Extensions; using SimpleStateMachine.StructuralSearch.Rules; @@ -6,19 +8,19 @@ namespace SimpleStateMachine.StructuralSearch { public class ReplaceRule { - public FindRule FindRule { get; } - - public IRuleParameter Parameter { get; } - - public ReplaceRule(FindRule findRule, IRuleParameter parameter) + public IRule FindRule { get; } + + public IEnumerable Rules { get; } + + public ReplaceRule(IRule findRule, IEnumerable rules) { FindRule = findRule; - Parameter = parameter; + Rules = rules; } public override string ToString() { - return $"{FindRule}{Constant.Space}{Constant.Should}{Constant.Space}{Parameter}"; + return $"{FindRule}{Constant.Space}{Constant.Then}{Constant.Space}{string.Join(Constant.Comma, Rules)}"; } } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Rules/ReplaceRule/ReplaceSubRule.cs b/src/SimpleStateMachine.StructuralSearch/Rules/ReplaceRule/ReplaceSubRule.cs new file mode 100644 index 0000000..ef09293 --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/Rules/ReplaceRule/ReplaceSubRule.cs @@ -0,0 +1,20 @@ +using SimpleStateMachine.StructuralSearch.Rules; + +namespace SimpleStateMachine.StructuralSearch; + +public class ReplaceSubRule +{ + public PlaceholderParameter Placeholder { get; } + public IRuleParameter Parameter { get; } + + public ReplaceSubRule(PlaceholderParameter placeholder, IRuleParameter parameter) + { + Placeholder = placeholder; + Parameter = parameter; + } + + public override string ToString() + { + return $"{Placeholder}{Constant.Space}{Constant.Should}{Constant.Space}{Parameter}"; + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/SeriesParser.cs b/src/SimpleStateMachine.StructuralSearch/SeriesParser.cs index 4b68b35..85bf00a 100644 --- a/src/SimpleStateMachine.StructuralSearch/SeriesParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/SeriesParser.cs @@ -27,7 +27,7 @@ public override bool TryParse(ref ParseState state, ref PooledList(); + result = results; return false; } diff --git a/src/SimpleStateMachine.StructuralSearch/SimpleStateMachine.StructuralSearch.csproj b/src/SimpleStateMachine.StructuralSearch/SimpleStateMachine.StructuralSearch.csproj index 1e35bc2..e501e18 100644 --- a/src/SimpleStateMachine.StructuralSearch/SimpleStateMachine.StructuralSearch.csproj +++ b/src/SimpleStateMachine.StructuralSearch/SimpleStateMachine.StructuralSearch.csproj @@ -2,7 +2,7 @@ net5.0 - 9 + 10 enable diff --git a/src/SimpleStateMachine.StructuralSearch/StringInput.cs b/src/SimpleStateMachine.StructuralSearch/StringInput.cs new file mode 100644 index 0000000..7f30966 --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/StringInput.cs @@ -0,0 +1,30 @@ +using Pidgin; + +namespace SimpleStateMachine.StructuralSearch +{ + public class StringInput : IInput + { + public StringInput(string input) + { + Input = input; + } + + public readonly string Input; + + public Result ParseBy(Parser parser) + { + return parser.Parse(Input); + } + + public void Replace(Match match, string value) + { + throw new System.NotImplementedException(); + } + + public string Extension => string.Empty; + public string Path => string.Empty; + public string Name => string.Empty; + public string Data => string.Empty; + public long Lenght => Input.Length; + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/CommonParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/CommonParser.cs index 7ea026f..b809955 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/CommonParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/CommonParser.cs @@ -25,7 +25,8 @@ internal static readonly Parser LineEnds = EndOfLine.AtLeastOnceString(); internal static readonly Parser WhiteSpaces - = OneOf(Spaces, LineEnds); + = OneOf(Spaces, LineEnds, LineEnds) + .AtLeastOnceString(); internal static readonly Parser Identifier = Letter.Then(AnyString, (h, t) => h + t); @@ -33,6 +34,9 @@ internal static readonly Parser Identifier internal static readonly Parser Comma = Char(Constant.Comma); + internal static readonly Parser Colon + = Char(Constant.Colon); + internal static readonly Parser DoubleQuotes = Char(Constant.DoubleQuotes); diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/FindRulesParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/FindRulesParser.cs index 7d6b8af..bce825c 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/FindRulesParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/FindRulesParser.cs @@ -53,9 +53,7 @@ internal static readonly Parser> Not public static readonly Parser Expr = ExpressionParser.Build( rule => ( Parser.OneOf( - SubRuleParser.UnarySubRule, - SubRuleParser.IsSubRule, - SubRuleParser.InSubRule, + SubRuleParser.OneOfSubRule, CommonParser.Parenthesised(rule, x => x.TrimStart()) ), new[] @@ -71,14 +69,9 @@ internal static readonly Parser> Not ) ); - internal static readonly Parser Rule = - Parser.Map((parameter, rule) => new FindRule(parameter, rule), - ParametersParser.PlaceholderParameter, - Expr.TrimStart()); - - internal static FindRule ParseTemplate(string str) + internal static IRule ParseTemplate(string str) { - return Rule.ParseOrThrow(str); + return Expr.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 59f767c..d8f6bbb 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/FindTemplateParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/FindTemplateParser.cs @@ -32,7 +32,7 @@ static FindTemplateParser() .Try(); internal static readonly Parser> WhiteSpaces = - ParserToParser.ResultAsParser(CommonParser.WhiteSpaces) + ParserToParser.ParserAsParser(CommonParser.WhiteSpaces) .Try(); internal static readonly Parser> Placeholder = diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs index 2292245..1c8bf34 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/ReplaceRuleParser.cs @@ -13,14 +13,26 @@ public static class ReplaceRuleParser .As() .Try() .TrimStart(); + + internal static readonly Parser Then = + Parser.CIString(Constant.Then) + .Try() + .TrimStart(); - internal static readonly Parser ReplaceRule = - Parser.Map((rule, parameter) => new ReplaceRule(rule, parameter), - FindRuleParser.Rule.Before(CommonTemplateParser.Should.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())) .Try() .TrimStart(); + internal static readonly Parser ReplaceRule = + Parser.Map((rule, subRules) => new ReplaceRule(rule, subRules), + 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/StructuralSearch.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/StructuralSearch.cs index 3e2acd7..f2904e8 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/StructuralSearch.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/StructuralSearch.cs @@ -12,7 +12,7 @@ public static IFindParser ParseFindTemplate(string template) public static IReplaceBuilder ParseReplaceTemplate(string template) => ReplaceTemplateParser.ParseTemplate(template); - public static FindRule ParseFindRule(string template) + public static IRule ParseFindRule(string template) => FindRuleParser.ParseTemplate(template); public static ReplaceRule ParseReplaceRule(string template) diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubFindRuleParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubFindRuleParser.cs deleted file mode 100644 index 1d5b3b7..0000000 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubFindRuleParser.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Collections.Generic; -using Pidgin; -using SimpleStateMachine.StructuralSearch.Extensions; - -namespace SimpleStateMachine.StructuralSearch.Rules -{ - public static class SubRuleParser - { - public static readonly Parser SubRuleType = - Parsers.EnumExcept(true, Rules.SubRuleType.Is, Rules.SubRuleType.In) - .TrimStart(); - - public static readonly Parser UnarySubRule = - Parser.Map((type, param) => new UnarySubRule(type, param), - SubRuleType, ParametersParser.Parameter) - .As() - .Try(); - - public static readonly Parser PlaceholderType = - Parser.CIEnum() - .TrimStart(); - - public static readonly Parser IsSubRule = - Parser.Map((type, param) => new IsRule(type, param), - Parsers.EnumValue(Rules.SubRuleType.Is, true) - .TrimStart(), - PlaceholderType) - .As() - .Try(); - - public static readonly Parser InSubRule = - Parser.Map((type, param) => new InRule(type, param), - Parsers.EnumValue(Rules.SubRuleType.In, true) - .TrimStart(), Parser.OneOf(ParametersParser.Parameters, - CommonParser.Parenthesised(ParametersParser.Parameters, x=> x.Trim()))) - .As() - .Try(); - } -} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubRuleParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubRuleParser.cs new file mode 100644 index 0000000..1d24283 --- /dev/null +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearch/SubRuleParser.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using Pidgin; +using SimpleStateMachine.StructuralSearch.Extensions; + +namespace SimpleStateMachine.StructuralSearch.Rules +{ + 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() + .Try(); + + public static readonly Parser PlaceholderType = + Parser.CIEnum() + .TrimStart(); + + public static Parser IsSubRule(IRuleParameter left, SubRuleType ruleType) => + PlaceholderType.Select(arg => new IsSubRule(left, arg)) + .As() + .Try(); + + public static Parser InSubRule(IRuleParameter left, SubRuleType ruleType) => + Parser.OneOf(ParametersParser.Parameters, + CommonParser.Parenthesised(ParametersParser.Parameters, x => x.Trim())) + .Select(args => new InSubRule(left, args)) + .As() + .Try(); + + + public static readonly Parser OneOfSubRule = + Parser.Map((left, ruleType) => (left, ruleType), + ParametersParser.Parameter, SubRuleType) + .Then(x => x.ruleType switch + { + Rules.SubRuleType.In => InSubRule(x.left, x.ruleType), + Rules.SubRuleType.Is => IsSubRule(x.left, x.ruleType), + _ => SubRule(x.left, x.ruleType) + }); + } +} \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/StructuralSearchParser.cs b/src/SimpleStateMachine.StructuralSearch/StructuralSearchParser.cs index 6c21071..86b0f96 100644 --- a/src/SimpleStateMachine.StructuralSearch/StructuralSearchParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/StructuralSearchParser.cs @@ -1,5 +1,6 @@  using System.Collections.Generic; +using System.IO; using System.Linq; using SimpleStateMachine.StructuralSearch.Configurations; using SimpleStateMachine.StructuralSearch.Extensions; @@ -12,11 +13,11 @@ public class StructuralSearchParser { public IFindParser FindParser { get; set; } - public Dictionary FindRules { get; set; } + public IEnumerable FindRules { get; set; } public IReplaceBuilder ReplaceBuilder { get; set; } - public Dictionary ReplaceRules { get; set; } + public IEnumerable ReplaceRules { get; set; } public StructuralSearchParser(Configuration configuration) { @@ -24,26 +25,64 @@ public StructuralSearchParser(Configuration configuration) FindRules = configuration.FindRules .EmptyIfNull() - .Select(StructuralSearch.ParseFindRule) - .ToDictionary(x => x.Placeholder.Name, x => x); + .Select(StructuralSearch.ParseFindRule); ReplaceBuilder = StructuralSearch.ParseReplaceTemplate(configuration.ReplaceTemplate); ReplaceRules = configuration.ReplaceRules .EmptyIfNull() - .Select(StructuralSearch.ParseReplaceRule) - .ToDictionary(x => x.FindRule.Placeholder.Name, x => x); + .Select(StructuralSearch.ParseReplaceRule); } - public void Parse(ref IParsingContext context) + public IEnumerable Parse(ref IParsingContext context) { - FindParser.Parse(ref context, context.File.Data); + var matches = FindParser.Parse(ref context); + return matches; } - - public void Replace(ref IParsingContext context) + + public IEnumerable ApplyFindRule(ref IParsingContext context, IEnumerable matches) + { + var result = new List(); + foreach (var match in matches) + { + context.Set(match.Placeholders); + var all = FindRules.All(x => x.Execute()); + if (all) + { + result.Add(match); + } + } + + return result; + } + public void ApplyReplaceRule(ref IParsingContext context, IEnumerable matches) + { + // var result = new List(); + // foreach (var match in matches) + // { + // context.Set(match.Placeholders); + // + // var rules = ReplaceRules + // .Where(x => x.FindRule.Execute()) + // .SelectMany(x => x.Rules); + // + // var placeHolder = match.Placeholders + // .ToDictionary(x=> x.Key, x=> x.Value); + // + // foreach (var rule in rules) + // { + // placeHolder[rule.Placeholder.Name].Value + // } + // } + // + // return result; + } + public void Replace(FindParserMatch context) { - ReplaceBuilder.Build(context); + //ReplaceBuilder.Build(context); + // context. //FindParser.Parse(context, context.File.Data); } + } } \ No newline at end of file diff --git a/src/SimpleStateMachine.StructuralSearch/Templates/FindTemplate/ParserToParser.cs b/src/SimpleStateMachine.StructuralSearch/Templates/FindTemplate/ParserToParser.cs index f505059..fa80992 100644 --- a/src/SimpleStateMachine.StructuralSearch/Templates/FindTemplate/ParserToParser.cs +++ b/src/SimpleStateMachine.StructuralSearch/Templates/FindTemplate/ParserToParser.cs @@ -27,6 +27,11 @@ public static Parser> ResultAsParser(Parser Parsers.String(value, ignoreCase)); } + public static Parser> ParserAsParser(Parser parser) + { + return parser.Select(value => parser); + } + public static Parser> ResultAsMatch(Parser parser, bool ignoreCase = false) { return parser.Select(x=> Parsers.String(x, ignoreCase).AsMatch());