diff --git a/.idea/.idea.Calyx/.idea/.gitignore b/.idea/.idea.Calyx/.idea/.gitignore new file mode 100644 index 0000000..a4c0e03 --- /dev/null +++ b/.idea/.idea.Calyx/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/projectSettingsUpdater.xml +/modules.xml +/.idea.Calyx.iml +/contentModel.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.Calyx/.idea/.name b/.idea/.idea.Calyx/.idea/.name new file mode 100644 index 0000000..6ea682b --- /dev/null +++ b/.idea/.idea.Calyx/.idea/.name @@ -0,0 +1 @@ +Calyx \ No newline at end of file diff --git a/.idea/.idea.Calyx/.idea/encodings.xml b/.idea/.idea.Calyx/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.Calyx/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.Calyx/.idea/indexLayout.xml b/.idea/.idea.Calyx/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.Calyx/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.Calyx/.idea/misc.xml b/.idea/.idea.Calyx/.idea/misc.xml new file mode 100644 index 0000000..da6640e --- /dev/null +++ b/.idea/.idea.Calyx/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/.idea.Calyx/.idea/sonarlint/issuestore/index.pb b/.idea/.idea.Calyx/.idea/sonarlint/issuestore/index.pb new file mode 100644 index 0000000..e69de29 diff --git a/.idea/.idea.Calyx/.idea/sonarlint/securityhotspotstore/index.pb b/.idea/.idea.Calyx/.idea/sonarlint/securityhotspotstore/index.pb new file mode 100644 index 0000000..e69de29 diff --git a/.idea/.idea.Calyx/.idea/vcs.xml b/.idea/.idea.Calyx/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/.idea.Calyx/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Calyx.sln.DotSettings.user b/Calyx.sln.DotSettings.user new file mode 100644 index 0000000..3298afa --- /dev/null +++ b/Calyx.sln.DotSettings.user @@ -0,0 +1,6 @@ + + <SessionState ContinuousTestingMode="0" IsActive="True" Name="FiltersApplyToMemoizedRules" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <TestAncestor> + <TestId>NUnit3x::7A4CD3DB-F115-4731-B257-EFBC32D8D3C3::net6.0::Calyx.Test.FilterTest.FiltersApplyToMemoizedRules</TestId> + </TestAncestor> +</SessionState> \ No newline at end of file diff --git a/Calyx/Syntax/ExpressionChain.cs b/Calyx/Syntax/ExpressionChain.cs index 45b2ad9..cdc8272 100644 --- a/Calyx/Syntax/ExpressionChain.cs +++ b/Calyx/Syntax/ExpressionChain.cs @@ -7,23 +7,25 @@ namespace Calyx.Syntax { public class ExpressionChain : IProduction { + private string ruleName; private string[] components; private Registry registry; - public ExpressionChain(string[] components, Registry registry) + public ExpressionChain(string ruleName, string[] components, Registry registry) { + RemoveSigil(ref ruleName); + this.ruleName = ruleName; this.registry = registry; - this.components = components; + this.components = components.Skip(1).ToArray(); } public Expansion Evaluate(Options options) { - Expansion eval = registry.Expand(components[0]).Evaluate(options); + Expansion eval = registry.Expand(ruleName).Evaluate(options); string initial = new Expansion(Exp.Expression, eval.Tail).Flatten().ToString(); // Dynamic dispatch to string modifiers one after another string modified = components - .Skip(1) .Aggregate(initial, (accumulator, filterName) => { try { return registry.GetFilterComponent(filterName).Invoke(accumulator); @@ -40,5 +42,13 @@ public Expansion Evaluate(Options options) return new Expansion(Exp.Expression, new Expansion(Exp.Atom, modified)); } + + private static void RemoveSigil(ref string ruleName) + { + if (ExpressionNode.IsSigil(ruleName[0])) + { + ruleName = ruleName.Substring(1); + } + } } } diff --git a/Calyx/Syntax/ExpressionNode.cs b/Calyx/Syntax/ExpressionNode.cs index e0a994d..30c79cf 100644 --- a/Calyx/Syntax/ExpressionNode.cs +++ b/Calyx/Syntax/ExpressionNode.cs @@ -35,5 +35,10 @@ public Expansion Evaluate(Options options) Expansion eval = registry.Expand(reference).Evaluate(options); return new Expansion(Exp.Expression, eval.Tail); } + + public static bool IsSigil(char character) + { + return character == MEMO_SIGIL || character == UNIQUE_SIGIL; + } } } diff --git a/Calyx/Syntax/TemplateNode.cs b/Calyx/Syntax/TemplateNode.cs index 6dc72e2..0705814 100644 --- a/Calyx/Syntax/TemplateNode.cs +++ b/Calyx/Syntax/TemplateNode.cs @@ -33,7 +33,7 @@ public static TemplateNode Parse(string raw, Registry registry) // Check if we have a post-processing chain if (components.Length > 1) { // Generate a chained expression headed by a non-terminal - concatNodes.Add(new ExpressionChain(components, registry)); + concatNodes.Add(new ExpressionChain(components[0], components, registry)); } else { // Generate a standalone non-terminal expression concatNodes.Add(ExpressionNode.Parse(components[0], registry)); diff --git a/Tests/FilterTest.cs b/Tests/FilterTest.cs index 17694f7..7e40eea 100644 --- a/Tests/FilterTest.cs +++ b/Tests/FilterTest.cs @@ -99,6 +99,16 @@ public void IncorrectFilterParameterCountThrowsException() { Assert.Throws(() => registry.Evaluate("start")); } + [Test] + public void FiltersApplyToMemoizedRules() { + Registry registry = new Registry(new Options(seed: 1234)); + + registry.DefineRule("start", new [] { "{$names.uppercase}" }); + registry.DefineRule("names", new [] { "Jewels" } ); + + Assert.That(registry.Evaluate("start").Flatten().ToString(), Is.EqualTo("JEWELS")); + } + internal static class TestFilter { [FilterName("backwards")] public static string Backwards(string input, Options options) {