From f6ef155c4712c1c597134662e763a30132ff9fb9 Mon Sep 17 00:00:00 2001 From: Jan-Niklas Date: Sun, 1 Sep 2019 20:39:06 +0200 Subject: [PATCH 01/45] fixed unit test --- ThinkSharp.FormulaParser.Test/FormulaParserTest.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs b/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs index db1dd88..abeea7c 100644 --- a/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs +++ b/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs @@ -148,14 +148,6 @@ public void Test_FormulatText() { var parser = FormulaParser.Create(); - var parser2 = FormulaParser - .CreateBuilder() - .ConfigureFunctions(functions => functions.Add("max", (a, b) => Math.Max(a, b))) - .Build(); - - parser2.Evaluate("1 + max(2, 4)"); - - var result = parser.Parse("2 * pi").Value as FormulaNode; Assert.AreEqual("2 * pi", result.FormulaText); } From e895edaa2b89affe04c86090a8f6316568dae01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Sun, 1 Sep 2019 21:18:04 +0200 Subject: [PATCH 02/45] Create README.md --- README.md | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..a9c29cf --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +# ThinkSharp.FormulaParser + +[![Build status](https://ci.appveyor.com/api/projects/status/l3aagqmbfmgxwv3t?svg=true)](https://ci.appveyor.com/project/JanDotNet/thinksharp-licensing) +[![NuGet](https://img.shields.io/nuget/v/ThinkSharp.FormulaParser.svg)](https://www.nuget.org/packages/ThinkSharp.FormulaParser/) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.TXT) +[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MSBFDUU5UUQZL) +## Introduction + +**ThinkSharp.FormulaParser** is a simple library with fluent API for parsing and evaluating mathematical functions. + +Mathematical functions can be parsed to a parsing tree (hereinafter called "parsing") or directly evaluated to a numeric value (hereinafter called "evaluating"). + +The following features are supported +* Basic Mathematical Operations: +, -, /, *, ^, ( .. ), scientific notation (3e2 = 300) +* Variables: Detect variables on parsing or use a dictionary to provide variables for evaluation. +* Contants: Use build-in constats (pi, e) or define your own. Constants are available independent of the provided variables. +* Functions: User build-in functions (rnd, abs, log, sin, cos, min, max...) or define your owns. +* Error Handling: The parser provides an expressive error message in case of invalid formulas. +* Customizable: The parser may be configured to disable features and add custom functions / constants. + +## Installation + +ThinkSharp.FormulaParser can be installed via [Nuget](https://www.nuget.org/packages/ThinkSharp.FormulaParser) + + Install-Package ThinkSharp.FormulaParser + +## API Reference + +### Evaluation + + // The simples way to create a formula parser is the static method 'Create'. + var parser = FormulaParser.Create(); + + // Parsing a simple mathematical formula + var result1 = parser.Evaluat("1+1").Value; // result1 = 2.0 + + // Usage of variables + var variables = new Dictionary { ["x"] = 2.0 }; + var result2 = parser.Evaluat("1+x", variables).Value; // result2 = 3.0 + + // Usage of functions + var result3 = parser.Evaluat("1+min(3,4)").Value; // result2 = 4.0 + + // Handle errors + var parsingResult = parser.Evaluat("2*?"); + if (!parsingResult.Success) Console.WriteLine(parsingResult.Error); // "column 2: token recognition error at: '?'" + +#### Usage + +to be continued... + +## License + +ThinkSharp.FormulaParser is released under [The MIT license (MIT)](LICENSE.TXT) + +## Versioning + +We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/JanDotNet/ThinkSharp.FormulaParser/tags). + +## Donation +If you like ThinkSharp.FormulaParser and use it in your project(s), feel free to give me a cup of coffee :) + +[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MSBFDUU5UUQZL) From 2c0823d7437965440a9e2951a36a81ce418994b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Sun, 1 Sep 2019 21:23:20 +0200 Subject: [PATCH 03/45] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a9c29cf..6e4b2c2 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MSBFDUU5UUQZL) ## Introduction -**ThinkSharp.FormulaParser** is a simple library with fluent API for parsing and evaluating mathematical functions. +**ThinkSharp.FormulaParser** is a simple library with fluent API for parsing and evaluating mathematical formulas. Mathematical functions can be parsed to a parsing tree (hereinafter called "parsing") or directly evaluated to a numeric value (hereinafter called "evaluating"). @@ -14,7 +14,7 @@ The following features are supported * Basic Mathematical Operations: +, -, /, *, ^, ( .. ), scientific notation (3e2 = 300) * Variables: Detect variables on parsing or use a dictionary to provide variables for evaluation. * Contants: Use build-in constats (pi, e) or define your own. Constants are available independent of the provided variables. -* Functions: User build-in functions (rnd, abs, log, sin, cos, min, max...) or define your owns. +* Functions: Use build-in functions (rnd, abs, log, sin, cos, min, max...) or define your owns. * Error Handling: The parser provides an expressive error message in case of invalid formulas. * Customizable: The parser may be configured to disable features and add custom functions / constants. From 237324c7cf5a81355e46f6e6767fab4b991bfbdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 2 Sep 2019 15:15:47 +0200 Subject: [PATCH 04/45] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6e4b2c2..84af049 100644 --- a/README.md +++ b/README.md @@ -32,17 +32,17 @@ ThinkSharp.FormulaParser can be installed via [Nuget](https://www.nuget.org/pack var parser = FormulaParser.Create(); // Parsing a simple mathematical formula - var result1 = parser.Evaluat("1+1").Value; // result1 = 2.0 + var result1 = parser.Evaluate("1+1").Value; // result1 = 2.0 // Usage of variables var variables = new Dictionary { ["x"] = 2.0 }; - var result2 = parser.Evaluat("1+x", variables).Value; // result2 = 3.0 + var result2 = parser.Evaluate("1+x", variables).Value; // result2 = 3.0 // Usage of functions - var result3 = parser.Evaluat("1+min(3,4)").Value; // result2 = 4.0 + var result3 = parser.Evaluate("1+min(3,4)").Value; // result2 = 4.0 // Handle errors - var parsingResult = parser.Evaluat("2*?"); + var parsingResult = parser.Evaluate("2*?"); if (!parsingResult.Success) Console.WriteLine(parsingResult.Error); // "column 2: token recognition error at: '?'" #### Usage From 08db39fb590ccd50aae74cd2c5d9d7ce4e9affb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 2 Sep 2019 15:18:23 +0200 Subject: [PATCH 05/45] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 84af049..ac7044b 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build status](https://ci.appveyor.com/api/projects/status/l3aagqmbfmgxwv3t?svg=true)](https://ci.appveyor.com/project/JanDotNet/thinksharp-licensing) [![NuGet](https://img.shields.io/nuget/v/ThinkSharp.FormulaParser.svg)](https://www.nuget.org/packages/ThinkSharp.FormulaParser/) -[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.TXT) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.txt) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MSBFDUU5UUQZL) ## Introduction From 66b888af2f19d413004fde1d71f6231fac67a190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 2 Sep 2019 21:18:12 +0200 Subject: [PATCH 06/45] Update README.md --- README.md | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ac7044b..f0660aa 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![NuGet](https://img.shields.io/nuget/v/ThinkSharp.FormulaParser.svg)](https://www.nuget.org/packages/ThinkSharp.FormulaParser/) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.txt) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MSBFDUU5UUQZL) + ## Introduction **ThinkSharp.FormulaParser** is a simple library with fluent API for parsing and evaluating mathematical formulas. @@ -13,8 +14,8 @@ Mathematical functions can be parsed to a parsing tree (hereinafter called "pars The following features are supported * Basic Mathematical Operations: +, -, /, *, ^, ( .. ), scientific notation (3e2 = 300) * Variables: Detect variables on parsing or use a dictionary to provide variables for evaluation. -* Contants: Use build-in constats (pi, e) or define your own. Constants are available independent of the provided variables. -* Functions: Use build-in functions (rnd, abs, log, sin, cos, min, max...) or define your owns. +* Constants: Use build-in constants (pi, e) or define your own. Constants are available independent of the provided variables. +* Functions: Use build-in functions (sqrt, sum, rnd, abs, log, ln, sin, cos, tan, min, max) or define your own. * Error Handling: The parser provides an expressive error message in case of invalid formulas. * Customizable: The parser may be configured to disable features and add custom functions / constants. @@ -24,9 +25,9 @@ ThinkSharp.FormulaParser can be installed via [Nuget](https://www.nuget.org/pack Install-Package ThinkSharp.FormulaParser -## API Reference +## Examples -### Evaluation +### Evaluating formulas // The simples way to create a formula parser is the static method 'Create'. var parser = FormulaParser.Create(); @@ -45,9 +46,63 @@ ThinkSharp.FormulaParser can be installed via [Nuget](https://www.nuget.org/pack var parsingResult = parser.Evaluate("2*?"); if (!parsingResult.Success) Console.WriteLine(parsingResult.Error); // "column 2: token recognition error at: '?'" -#### Usage +#### Creating and evaluating a parsing tree + + // The simples way to create a formula parser is the static method 'Create'. + var parser = FormulaParser.Create(); + var variables = new Dictionary { ["x"] = 2.0 }; + + // Parsing a simple mathematical formula + var node1 = parser.Parse("1+x", variables).Value; + // |FormulaNode("1+x") + // |- Child: BinaryOperatorNode(+) + // |- LeftNode: NumericNode(1.0) + // |- RightNode: VariableNode("x") + var result1 = parser.Evaluate(node1, variables).Value; // result = 3.0 + + + var node2 = parser.Parse("pi * sqrt(3*x)", variables).Value; + // |FormulaNode("pi * sqrt(3*x)") + // |- Child: BinaryOperatorNode(*) + // |- LeftNode: ConstantNode("pi") + // |- RightNode: FunctionNode("sqrt") + // |- Parameters: [BinaryOperationNode(*)] + // |- LeftNode: Numeric(3.0) + // |- RightNode: VariableNode("x") + var result2 = parser.Evaluate(node2, variables).Value; // result = 7.695... + +#### Configure custom functions / constants + + var parser = FormulaParser + .CreateBuilder() + .ConfigureConstats(constants => + { + // constants.RemoveAll() for removing all default constants + // constants.Remove("pi") for removing constants by name + + constants.Add("h", 6.62607015e-34); + }) + .ConfigureFunctions(functions => + { + // functions.RemoveAll() for removing all default functions + // functions.Remove("sum") for removing function by name + + // define function with 2 to n number of parameters (typeof(nums) = double[]) + functions.Add("product", nums => nums.Aggregate((p1, p2) => p1 * p2)); + + // define functions with specified number of parameters (1-5 parameters are supported) + functions.Add("celsiusToFarenheit", celsius => celsius * 1.8 + 32); + functions.Add("fahrenheitToCelsius", farenheit => (farenheit - 32) * 5 / 9); + functions.Add("p1_plus_p2_plus_p3", (p1, p2, p3) => p1 + p2 + p3); + }).Build(); + + var poolTemperatureInCelsius = parser.Evaluate("celsiusToFarenheit(fahrenheitToCelsius(30))").Value; // poolTemperatureInCelsius = 30 + var result2 = parser.Evaluate("product(2, 2, 2, 2, 2, 2, 2)").Value; // result2 = 2^6 = 128 + var result3 = parser.Evaluate("p1_plus_p2_plus_p3(1, 2, 3)").Value; // result3 = 6 -to be continued... + string error1 = parser.Evaluate("celsiusToFarenheit(1, 2)").Error; // column 0: There is no function 'celsiusToFarenheit' that takes 2 argument(s). + string error2 = parser.Evaluate("product()").Error; // column 0: There is no function 'product' that takes 0 argument(s). + string error3 = parser.Evaluate("p1_plus_p2_plus_p3(1, 2)").Error; // column 0: There is no function 'p1_plus_p2_plus_p3' that takes 2 argument(s). ## License From 1100cf5e78ca49e1c425335f839c527a5f1d6403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 2 Sep 2019 21:30:09 +0200 Subject: [PATCH 07/45] added method "sqrt" improved error handling for known functions with invalid parameter count --- ThinkSharp.FormulaParser.Test/FormulaParserTest.cs | 10 ++++++++-- .../FormularParser.Configuration.Test.cs | 1 + .../ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs | 12 ++++++++++-- ThinkSharp.FormulaParser/Configuration.cs | 12 ++++++++++++ ThinkSharp.FormulaParser/IConfiguration.cs | 2 ++ ThinkSharp.FormulaParser/ParserConfiguration.cs | 2 ++ ThinkSharp.FormulaParser/ParsingException.cs | 2 ++ 7 files changed, 37 insertions(+), 4 deletions(-) diff --git a/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs b/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs index abeea7c..d533762 100644 --- a/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs +++ b/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs @@ -194,9 +194,15 @@ public void TestFunctionFunctionOneValue() } [TestMethod] - public void TestFunctionFunctionWithoutParameters() + public void TestRxistingFunctionWithoutParameters() { - AssertFailure("column 0: Unknown function 'min'.", "min()"); + AssertFailure("column 0: There is no function 'min' that takes 0 argument(s).", "min()"); + } + + [TestMethod] + public void TestNotExistingFunction() + { + AssertFailure("column 0: Unknown function 'moep'.", "moep()"); } [TestMethod] diff --git a/ThinkSharp.FormulaParser.Test/FormularParser.Configuration.Test.cs b/ThinkSharp.FormulaParser.Test/FormularParser.Configuration.Test.cs index 1302b2d..8511688 100644 --- a/ThinkSharp.FormulaParser.Test/FormularParser.Configuration.Test.cs +++ b/ThinkSharp.FormulaParser.Test/FormularParser.Configuration.Test.cs @@ -32,6 +32,7 @@ public void TestDefaultConfiguration() Assert.AreEqual(Math.Sin(3), parser.Evaluate("sin(3)").Value); Assert.AreEqual(Math.Cos(3), parser.Evaluate("cos(3)").Value); Assert.AreEqual(Math.Tan(3), parser.Evaluate("tan(3)").Value); + Assert.AreEqual(Math.Sqrt(3), parser.Evaluate("sqrt(3)").Value); } [TestMethod] diff --git a/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs b/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs index 5d82626..0a2de5d 100644 --- a/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs +++ b/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs @@ -166,9 +166,17 @@ public override Node VisitFunc([NotNull] FormulaGrammerParser.FuncContext contex parameters.Add(this.Visit(exp)); } - if (!this.configuration.IsFunctionNameValidationDisabled && !this.configuration.HasFunction(functionName, parameters.Count)) + if (!this.configuration.IsFunctionNameValidationDisabled) { - ParsingException.ThrowUnknownFunctionException(functionNameToken); + if (!this.configuration.HasFunction(functionName)) + { + ParsingException.ThrowUnknownFunctionException(functionNameToken); + } + + if (!this.configuration.HasFunction(functionName, parameters.Count)) + { + ParsingException.ThrowFunctionArgumentCountDoesNotExistException(functionNameToken, parameters.Count); + } } return new FunctionNode(functionName, parameters.ToArray()); diff --git a/ThinkSharp.FormulaParser/Configuration.cs b/ThinkSharp.FormulaParser/Configuration.cs index b4b9dea..a3626e7 100644 --- a/ThinkSharp.FormulaParser/Configuration.cs +++ b/ThinkSharp.FormulaParser/Configuration.cs @@ -38,6 +38,7 @@ public Configuration() (this as IConfigureFunctions).Add("sin", u => Math.Sin(u)); (this as IConfigureFunctions).Add("cos", u => Math.Cos(u)); (this as IConfigureFunctions).Add("tan", u => Math.Tan(u)); + (this as IConfigureFunctions).Add("sqrt", u => Math.Sqrt(u)); (this as IConfigureConstants).Add("pi", Math.PI); (this as IConfigureConstants).Add("e", Math.E); @@ -75,6 +76,17 @@ bool IConfiguration.HasFunction(string name, int argumentCount) return false; } + bool IConfiguration.HasFunction(string name) + { + return this.functionsArgs0.ContainsKey(name) + || this.functionsArgs1.ContainsKey(name) + || this.functionsArgs2.ContainsKey(name) + || this.functionsArgs3.ContainsKey(name) + || this.functionsArgs4.ContainsKey(name) + || this.functionsArgs5.ContainsKey(name) + || this.functionsArgsN.ContainsKey(name); + } + private bool MatchFunction0To5(string name, int argumentCount) { switch (argumentCount) diff --git a/ThinkSharp.FormulaParser/IConfiguration.cs b/ThinkSharp.FormulaParser/IConfiguration.cs index 9a18aeb..4e576a5 100644 --- a/ThinkSharp.FormulaParser/IConfiguration.cs +++ b/ThinkSharp.FormulaParser/IConfiguration.cs @@ -22,6 +22,8 @@ internal interface IConfiguration bool IsFunctionNameValidationDisabled { get; } + bool HasFunction(string name); + bool HasFunction(string name, int argumentCount); bool HasConstant(string name); diff --git a/ThinkSharp.FormulaParser/ParserConfiguration.cs b/ThinkSharp.FormulaParser/ParserConfiguration.cs index 070fc93..6931483 100644 --- a/ThinkSharp.FormulaParser/ParserConfiguration.cs +++ b/ThinkSharp.FormulaParser/ParserConfiguration.cs @@ -35,6 +35,8 @@ public ParserConfiguration(IConfiguration configuration, IDictionary this.configuration.HasFunction(name, argumentCount); + public bool HasFunction(string name) => this.configuration.HasFunction(name); + public bool HasVariable(string variable) => this.varialeNames.Contains(variable); } } diff --git a/ThinkSharp.FormulaParser/ParsingException.cs b/ThinkSharp.FormulaParser/ParsingException.cs index f8efa50..f91225c 100644 --- a/ThinkSharp.FormulaParser/ParsingException.cs +++ b/ThinkSharp.FormulaParser/ParsingException.cs @@ -29,6 +29,8 @@ private ParsingException(int line, int column, string invalidToken, string messa internal static void ThrowUnknownFunctionException(IToken token) => ThrowException(token.Line, token.Column, token.Text, $"Unknown function '{token.Text}'."); + internal static void ThrowFunctionArgumentCountDoesNotExistException(IToken token, int argumentCount) => ThrowException(token.Line, token.Column, token.Text, $"There is no function '{token.Text}' that takes {argumentCount} argument(s)."); + internal static void ThrowUnknownVariableException(IToken token) => ThrowException(token.Line, token.Column, token.Text, $"Unknown variable '{token.Text}'."); } } From 137e968f69fd45d88d4ae7c187562c906e6488a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Wed, 4 Sep 2019 20:47:51 +0200 Subject: [PATCH 08/45] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f0660aa..328ca7d 100644 --- a/README.md +++ b/README.md @@ -9,15 +9,15 @@ **ThinkSharp.FormulaParser** is a simple library with fluent API for parsing and evaluating mathematical formulas. -Mathematical functions can be parsed to a parsing tree (hereinafter called "parsing") or directly evaluated to a numeric value (hereinafter called "evaluating"). +Mathematical formulas can be parsed to a parsing tree (hereinafter called "parsing") or directly evaluated to a numeric value (hereinafter called "evaluating"). The following features are supported -* Basic Mathematical Operations: +, -, /, *, ^, ( .. ), scientific notation (3e2 = 300) +* Basic mathematical operations: +, -, /, *, ^, ( .. ), scientific notation (3e2 = 300) * Variables: Detect variables on parsing or use a dictionary to provide variables for evaluation. * Constants: Use build-in constants (pi, e) or define your own. Constants are available independent of the provided variables. * Functions: Use build-in functions (sqrt, sum, rnd, abs, log, ln, sin, cos, tan, min, max) or define your own. * Error Handling: The parser provides an expressive error message in case of invalid formulas. -* Customizable: The parser may be configured to disable features and add custom functions / constants. +* Customization: The parser may be configured to disable features and add custom functions / constants. ## Installation From 588a08622b1562f73ef4d5a2ddb156294078c3af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Wed, 4 Sep 2019 20:49:40 +0200 Subject: [PATCH 09/45] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 328ca7d..8c77524 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,6 @@ ThinkSharp.FormulaParser can be installed via [Nuget](https://www.nuget.org/pack #### Creating and evaluating a parsing tree - // The simples way to create a formula parser is the static method 'Create'. var parser = FormulaParser.Create(); var variables = new Dictionary { ["x"] = 2.0 }; From 02e2b56eca5c873cc6383b20530be7c7c7f2062e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Wed, 4 Sep 2019 20:51:51 +0200 Subject: [PATCH 10/45] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8c77524..11e32e6 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ ThinkSharp.FormulaParser can be installed via [Nuget](https://www.nuget.org/pack // define functions with specified number of parameters (1-5 parameters are supported) functions.Add("celsiusToFarenheit", celsius => celsius * 1.8 + 32); - functions.Add("fahrenheitToCelsius", farenheit => (farenheit - 32) * 5 / 9); + functions.Add("fahrenheitToCelsius", fahrenheit => (fahrenheit - 32) * 5 / 9); functions.Add("p1_plus_p2_plus_p3", (p1, p2, p3) => p1 + p2 + p3); }).Build(); From 5332362a71102cfcea6888f951eaecefc59a0465 Mon Sep 17 00:00:00 2001 From: Jan-Niklas Date: Wed, 4 Sep 2019 21:42:03 +0200 Subject: [PATCH 11/45] added comments --- .../FormulaParserTest.cs | 2 +- .../FormularParser.ParsingBehavior.Test.cs | 6 +- .../MainWindow.xaml.cs | 80 +- .../ThinkSharp.FormulaParser.Wpf.csproj | 9 +- ThinkSharp.FormulaParser.Wpf/packages.config | 1 - ThinkSharp.FormulaParser/Configuration.cs | 8 +- ThinkSharp.FormulaParser/FormulaParser.cs | 17 + .../FormulaParserBuilder.cs | 2 +- .../IConfigureConstants.cs | 18 + .../IConfigureFunctions.cs | 72 ++ .../IConfigureParsingBehavior.cs | 15 - .../IConfigureSupportedFeatures.cs | 15 + .../IConfigureValidationBehavior.cs | 21 + ThinkSharp.FormulaParser/IFormulaParser.cs | 111 +++ .../IFormulaParserBuilder.cs | 49 +- .../ThinkSharp.FormulaParser.csproj | 13 +- .../ThinkSharp.FormulaParser.xml | 848 ++++++++++++++++++ 17 files changed, 1253 insertions(+), 34 deletions(-) delete mode 100644 ThinkSharp.FormulaParser/IConfigureParsingBehavior.cs create mode 100644 ThinkSharp.FormulaParser/IConfigureValidationBehavior.cs create mode 100644 ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml diff --git a/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs b/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs index d533762..585a04a 100644 --- a/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs +++ b/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs @@ -100,7 +100,7 @@ public void Test_ScientificNumber() [TestMethod] public void Test_VariableNotExist() { - var parser = FormulaParser.CreateBuilder().ConfigureParsingBehavior(pb => pb.DisableVariableNameValidation()).Build(); + var parser = FormulaParser.CreateBuilder().ConfigureValidationBehavior(pb => pb.DisableVariableNameValidation()).Build(); var node = parser.Parse("2 * X").Value; diff --git a/ThinkSharp.FormulaParser.Test/FormularParser.ParsingBehavior.Test.cs b/ThinkSharp.FormulaParser.Test/FormularParser.ParsingBehavior.Test.cs index f71d6e5..a78ef95 100644 --- a/ThinkSharp.FormulaParser.Test/FormularParser.ParsingBehavior.Test.cs +++ b/ThinkSharp.FormulaParser.Test/FormularParser.ParsingBehavior.Test.cs @@ -10,7 +10,7 @@ namespace ThinkSharp.FormulaParsing.Test { [TestClass] - public class ConfigureParsingBehaviorTest + public class ConfigureValidationBehaviorTest { [TestMethod] public void TestNotConfigured_InvalidVariable() @@ -27,7 +27,7 @@ public void TestNotConfigured_InvalidVariableIgnoreVariableValidation() { var parser = FormulaParser .CreateBuilder() - .ConfigureParsingBehavior(parsingBehavior => + .ConfigureValidationBehavior(parsingBehavior => { parsingBehavior.DisableVariableNameValidation(); }) @@ -55,7 +55,7 @@ public void TestNotConfigured_InvalidFunctionIgnoreFunctionValidation() { var parser = FormulaParser .CreateBuilder() - .ConfigureParsingBehavior(parsingBehavior => + .ConfigureValidationBehavior(parsingBehavior => { parsingBehavior.DisableFunctionNameValidation(); }) diff --git a/ThinkSharp.FormulaParser.Wpf/MainWindow.xaml.cs b/ThinkSharp.FormulaParser.Wpf/MainWindow.xaml.cs index 526191a..b14df85 100644 --- a/ThinkSharp.FormulaParser.Wpf/MainWindow.xaml.cs +++ b/ThinkSharp.FormulaParser.Wpf/MainWindow.xaml.cs @@ -27,7 +27,7 @@ public partial class MainWindow : Window { private readonly IFormulaParser parser = FormulaParser .CreateBuilder() - .ConfigureParsingBehavior(parsingBehavior => + .ConfigureValidationBehavior(parsingBehavior => { parsingBehavior.DisableVariableNameValidation(); }) @@ -35,6 +35,84 @@ public partial class MainWindow : Window public MainWindow() { InitializeComponent(); + TestConfiguration(); + } + + private void TestEvaluation() + { + // The simples way to create a formula parser is the static method 'Create'. + var parser = FormulaParser.Create(); + + // Parsing a simple mathematical formula + var result1 = parser.Evaluate("1+3E2").Value; // result1 = 2.0 + + // Usage of variables + var variables = new Dictionary { ["x"] = 2.0 }; + var result2 = parser.Evaluate("1+x", variables).Value; // result2 = 3.0 + + // Usage of functions + var result3 = parser.Evaluate("1+min(3,4)").Value; // result2 = 4.0 + + // Handle errors + var parsingResult = parser.Evaluate("2*?"); + if (!parsingResult.Success) Console.WriteLine(parsingResult.Error); // "column 2: token recognition error at: '?'" + } + + private void TestParsing() + { + // The simples way to create a formula parser is the static method 'Create'. + var parser = FormulaParser.Create(); + var variables = new Dictionary { ["x"] = 2.0 }; + + // Parsing a simple mathematical formula + var node1 = parser.Parse("1+x", variables).Value; + // |FormulaNode("1+x") + // |- Child: BinaryOperatorNode(+) + // |- LeftNode: NumericNode(1.0) + // |- RightNode: VariableNode("x") + var result1 = parser.Evaluate(node1, variables).Value; // result = 3.0 + + + var node2 = parser.Parse("pi * sqrt(3*x)", variables).Value; + // |FormulaNode("pi * sqrt(3*x)") + // |- Child: BinaryOperatorNode(*) + // |- LeftNode: ConstantNode(3.14...) + // |- RightNode: FunctionNode("sqrt") + // |- Parameters: [BinaryOperationNode(*)] + // |- LeftNode: Numeric(3.0) + // |- RightNode: VariableNode("x") + var result2 = parser.Evaluate(node2, variables).Value; // result = 7.695... + } + + private void TestConfiguration() + { + var parser = FormulaParser + .CreateBuilder() + .ConfigureConstats(constants => + { + constants.Add("h", 6.62607015e-34); + }) + .ConfigureFunctions(functions => + { + // functions.RemoveAll() for removing all default functions + // functions.Remove("sum") for removing function by name + + // define function with 2 to n number of parameters (typeof(nums) = double[]) + functions.Add("product", nums => nums.Aggregate((p1, p2) => p1 * p2)); + + // define functions with specified number of parameters (1-5 parameters are supported) + functions.Add("celsiusToFarenheit", celsius => celsius * 1.8 + 32); + functions.Add("fahrenheitToCelsius", farenheit => (farenheit - 32) * 5 / 9); + functions.Add("p1_plus_p2_plus_p3", (p1, p2, p3) => p1 + p2 + p3); + }).Build(); + + var poolTemperatureInCelsius = parser.Evaluate("celsiusToFarenheit(fahrenheitToCelsius(30))").Value; // poolTemperatureInCelsius = 30 + var result2 = parser.Evaluate("product(2, 2, 2, 2, 2, 2, 2)").Value; // result2 = 2^6 = 128 + var result3 = parser.Evaluate("p1_plus_p2_plus_p3(1, 2, 3)").Value; // result3 = 6 + + string error1 = parser.Evaluate("celsiusToFarenheit(1, 2)").Error; // column 0: There is no function 'celsiusToFarenheit' that takes 2 argument(s). + string error2 = parser.Evaluate("product()").Error; // column 0: There is no function 'product' that takes 0 argument(s). + string error3 = parser.Evaluate("p1_plus_p2_plus_p3(1, 2)").Error; // column 0: There is no function 'p1_plus_p2_plus_p3' that takes 2 argument(s). } private void Input_TextChanged(object sender, TextChangedEventArgs e) diff --git a/ThinkSharp.FormulaParser.Wpf/ThinkSharp.FormulaParser.Wpf.csproj b/ThinkSharp.FormulaParser.Wpf/ThinkSharp.FormulaParser.Wpf.csproj index de3fffd..865cc4d 100644 --- a/ThinkSharp.FormulaParser.Wpf/ThinkSharp.FormulaParser.Wpf.csproj +++ b/ThinkSharp.FormulaParser.Wpf/ThinkSharp.FormulaParser.Wpf.csproj @@ -49,9 +49,6 @@ 4.0 - - ..\packages\ThinkSharp.FormulaParser.0.9.0\lib\netstandard2.0\ThinkSharp.FormulaParser.dll - @@ -101,5 +98,11 @@ + + + {c69728f7-cdc0-4fa2-b805-e0dd6f498e9f} + ThinkSharp.FormulaParser + + \ No newline at end of file diff --git a/ThinkSharp.FormulaParser.Wpf/packages.config b/ThinkSharp.FormulaParser.Wpf/packages.config index 04c82cc..ff6a875 100644 --- a/ThinkSharp.FormulaParser.Wpf/packages.config +++ b/ThinkSharp.FormulaParser.Wpf/packages.config @@ -1,5 +1,4 @@  - \ No newline at end of file diff --git a/ThinkSharp.FormulaParser/Configuration.cs b/ThinkSharp.FormulaParser/Configuration.cs index a3626e7..7d40446 100644 --- a/ThinkSharp.FormulaParser/Configuration.cs +++ b/ThinkSharp.FormulaParser/Configuration.cs @@ -6,7 +6,7 @@ namespace ThinkSharp.FormulaParsing { - internal class Configuration : IConfigureFunctions, IConfigureConstants, IConfigureSupportedFeatures, IConfigureParsingBehavior, IConfiguration, IConfigurationEvaluator + internal class Configuration : IConfigureFunctions, IConfigureConstants, IConfigureSupportedFeatures, IConfigureValidationBehavior, IConfiguration, IConfigurationEvaluator { private static readonly Random random = new Random(); @@ -273,11 +273,11 @@ IEnumerable> IConfigurationEvaluator.EnumerateConst void IConfigureSupportedFeatures.DisableVariables() => this.IsVariablesSupportDisabled = true; void IConfigureSupportedFeatures.DisableFunctions() => this.IsFunctionsSupportDisabled = true; - // IConfigureParsingBehavior + // IConfigureValidationBehavior // //////////////////////////////////////////////////////////////////// - void IConfigureParsingBehavior.DisableVariableNameValidation() => this.IsVariableNameValidationDisabled = true; - void IConfigureParsingBehavior.DisableFunctionNameValidation() => this.IsFunctionNameValidationDisabled = true; + void IConfigureValidationBehavior.DisableVariableNameValidation() => this.IsVariableNameValidationDisabled = true; + void IConfigureValidationBehavior.DisableFunctionNameValidation() => this.IsFunctionNameValidationDisabled = true; // Helper // //////////////////////////////////////////////////////////////////// diff --git a/ThinkSharp.FormulaParser/FormulaParser.cs b/ThinkSharp.FormulaParser/FormulaParser.cs index 8fc18de..4add740 100644 --- a/ThinkSharp.FormulaParser/FormulaParser.cs +++ b/ThinkSharp.FormulaParser/FormulaParser.cs @@ -8,6 +8,11 @@ namespace ThinkSharp.FormulaParsing { + /// + /// The class provides static methods for creating instances. + /// Use the method to create a with default configuration. + /// Use the method to create a that allows to configure the instance. + /// public class FormulaParser : IFormulaParser { private readonly Configuration configuration; @@ -20,8 +25,20 @@ internal FormulaParser(Configuration configuration) this.configuration = configuration; } + /// + /// Creates a new with its default configuration. + /// + /// + /// A new with its default configuration. + /// public static IFormulaParser Create() => new FormulaParser(); + /// + /// Creates a that allows to configure the . + /// + /// + /// a . + /// public static IFormulaParserBuilder CreateBuilder() => new FormulaParserBuilder(); public FormulaParserResult Evaluate(string formula) diff --git a/ThinkSharp.FormulaParser/FormulaParserBuilder.cs b/ThinkSharp.FormulaParser/FormulaParserBuilder.cs index 1f4b1d3..6510a9c 100644 --- a/ThinkSharp.FormulaParser/FormulaParserBuilder.cs +++ b/ThinkSharp.FormulaParser/FormulaParserBuilder.cs @@ -21,7 +21,7 @@ public IFormulaParser Build() public IFormulaParserBuilder ConfigureSupportedFeatures(Action supportedFeatures) => Configure(supportedFeatures); - public IFormulaParserBuilder ConfigureParsingBehavior(Action parsingBehavior) => Configure(parsingBehavior); + public IFormulaParserBuilder ConfigureValidationBehavior(Action parsingBehavior) => Configure(parsingBehavior); private IFormulaParserBuilder Configure(Action action) where TConfigure : class { diff --git a/ThinkSharp.FormulaParser/IConfigureConstants.cs b/ThinkSharp.FormulaParser/IConfigureConstants.cs index a4810c4..9abee93 100644 --- a/ThinkSharp.FormulaParser/IConfigureConstants.cs +++ b/ThinkSharp.FormulaParser/IConfigureConstants.cs @@ -8,10 +8,28 @@ namespace ThinkSharp.FormulaParsing { public interface IConfigureConstants { + /// + /// Adds a constant. + /// + /// + /// The name of the constant to add. + /// + /// + /// The value of the constant. + /// void Add(string name, double value); + /// + /// Removes all configured functions. + /// void RemoveAll(); + /// + /// Removed the function with the specified name. + /// + /// + /// The name of the function to remove. + /// void Remove(string name); } } diff --git a/ThinkSharp.FormulaParser/IConfigureFunctions.cs b/ThinkSharp.FormulaParser/IConfigureFunctions.cs index e9021cb..ab1a96a 100644 --- a/ThinkSharp.FormulaParser/IConfigureFunctions.cs +++ b/ThinkSharp.FormulaParser/IConfigureFunctions.cs @@ -8,22 +8,94 @@ namespace ThinkSharp.FormulaParsing { public interface IConfigureFunctions { + /// + /// Adds a function with zero paramteter. + /// + /// + /// The name of the function. + /// + /// + /// The function. + /// void Add(string name, Func function); + /// + /// Adds a function with one paramteter. + /// + /// + /// The name of the function. + /// + /// + /// The function. + /// void Add(string name, Func function); + /// + /// Adds a function with two paramteters. + /// + /// + /// The name of the function. + /// + /// + /// The function. + /// void Add(string name, Func function); + /// + /// Adds a function with three paramteters. + /// + /// + /// The name of the function. + /// + /// + /// The function. + /// void Add(string name, Func function); + /// + /// Adds a function with four paramteters. + /// + /// + /// The name of the function. + /// + /// + /// The function. + /// void Add(string name, Func function); + /// + /// Adds a function with five paramteters. + /// + /// + /// The name of the function. + /// + /// + /// The function. + /// void Add(string name, Func function); + /// + /// Adds a function with 2 to n paramteters. + /// + /// + /// The name of the function. + /// + /// + /// The function. + /// void Add(string name, Func function); + /// + /// Removes all configured functions. + /// void RemoveAll(); + /// + /// Removed the function with the specified name. + /// + /// + /// The name of the function to remove. + /// void Remove(string name); } } diff --git a/ThinkSharp.FormulaParser/IConfigureParsingBehavior.cs b/ThinkSharp.FormulaParser/IConfigureParsingBehavior.cs deleted file mode 100644 index 3168243..0000000 --- a/ThinkSharp.FormulaParser/IConfigureParsingBehavior.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ThinkSharp.FormulaParsing -{ - public interface IConfigureParsingBehavior - { - void DisableVariableNameValidation(); - - void DisableFunctionNameValidation(); - } -} diff --git a/ThinkSharp.FormulaParser/IConfigureSupportedFeatures.cs b/ThinkSharp.FormulaParser/IConfigureSupportedFeatures.cs index 32b1883..c3de0e4 100644 --- a/ThinkSharp.FormulaParser/IConfigureSupportedFeatures.cs +++ b/ThinkSharp.FormulaParser/IConfigureSupportedFeatures.cs @@ -2,14 +2,29 @@ { public interface IConfigureSupportedFeatures { + /// + /// Prevents the usage of scientific notation (e.g. 2e3 = 4000) + /// void DisableScientificNotation(); + /// + /// Prevents the usage of brackets. + /// void DisableBracket(); + /// + /// Prevents the usage of pow (e.g. 3^2 = 9) + /// void DisablePow(); + /// + /// Ptevents the usage of variables. + /// void DisableVariables(); + /// + /// Prevents the usage of functions. + /// void DisableFunctions(); } } diff --git a/ThinkSharp.FormulaParser/IConfigureValidationBehavior.cs b/ThinkSharp.FormulaParser/IConfigureValidationBehavior.cs new file mode 100644 index 0000000..41a6b8a --- /dev/null +++ b/ThinkSharp.FormulaParser/IConfigureValidationBehavior.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ThinkSharp.FormulaParsing +{ + public interface IConfigureValidationBehavior + { + /// + /// Diables the validation of variable names when creating a parsing tree. + /// + void DisableVariableNameValidation(); + + /// + /// Diables the validation of functions names when creating a parsing tree. + /// + void DisableFunctionNameValidation(); + } +} diff --git a/ThinkSharp.FormulaParser/IFormulaParser.cs b/ThinkSharp.FormulaParser/IFormulaParser.cs index 3b4c909..47e2f2f 100644 --- a/ThinkSharp.FormulaParser/IFormulaParser.cs +++ b/ThinkSharp.FormulaParser/IFormulaParser.cs @@ -10,22 +10,133 @@ namespace ThinkSharp.FormulaParsing { public interface IFormulaParser { + /// + /// Evaluates the provided formula to a numeric value. + /// + /// + /// The formula to evaluate. + /// + /// + /// The object that contains the evaluation result or an error. + /// FormulaParserResult Evaluate(string formula); + /// + /// Evaluates the provided formula to a numeric value. + /// + /// + /// The formula to evaluate. + /// + /// + /// A dictionary that provides variables to be used for evaluation. + /// + /// + /// The object that contains the evaluation result or an error. + /// FormulaParserResult Evaluate(string formula, IDictionary variables); + /// + /// Evaluates the provided . + /// + /// + /// The root node of the parsing tree to evaluate. + /// + /// + /// The object that contains the evaluation result or an error. + /// FormulaParserResult Evaluate(Node formulaNode); + /// + /// Evaluates the provided . + /// + /// + /// The root node of the parsing tree to evaluate. + /// + /// + /// A dictionary that provides variables to be used for evaluation. + /// + /// + /// The object that contains the evaluation result or an error. + /// FormulaParserResult Evaluate(Node formulaNode, IDictionary variables); + /// + /// Parses the provided formula to a parsing tree. + /// + /// + /// The formula to parse. + /// + /// + /// The object that contains the root node of the parsing tree or an error. + /// FormulaParserResult Parse(string formula); + /// + /// Parses the provided formula to a parsing tree. + /// + /// + /// The formula to parse. + /// + /// + /// A dictionary that provides variables to be used for evaluation. + /// + /// + /// The object that contains the root node of the parsing tree or an error. + /// FormulaParserResult Parse(string formula, IDictionary variables); + /// + /// Parses the formula and executes the visitor to the genereted parsing tree. + /// + /// + /// The type of the visitors result. + /// + /// + /// The formula to parse. + /// + /// + /// The visitor to run on the parsing tree. + /// + /// + /// The object that contains the result produced by the visitor or an error. + /// FormulaParserResult RunVisitor(string formula, INodeVisitor visitor); + /// + /// Parses the formula and executes the visitor to the genereted parsing tree. + /// + /// + /// The type of the visitors result. + /// + /// + /// The formula to parse. + /// + /// + /// The visitor to run on the parsing tree. + /// + /// + /// A dictionary that provides variables to be used for evaluation. + /// + /// + /// The object that contains the result produced by the visitor or an error. + /// FormulaParserResult RunVisitor(string formula, INodeVisitor visitor, IDictionary variables); + /// + /// Executes the visitor to the provided parsing tree. + /// + /// + /// The type of the visitors result. + /// + /// + /// The root node of the parsing tree to run the visitor on. + /// + /// + /// The visitor to run on the parsing tree. + /// + /// + /// The object that contains the result produced by the visitor or an error. + /// FormulaParserResult RunVisitor(Node node, INodeVisitor visitor); } } diff --git a/ThinkSharp.FormulaParser/IFormulaParserBuilder.cs b/ThinkSharp.FormulaParser/IFormulaParserBuilder.cs index ffa7d0d..4115863 100644 --- a/ThinkSharp.FormulaParser/IFormulaParserBuilder.cs +++ b/ThinkSharp.FormulaParser/IFormulaParserBuilder.cs @@ -8,14 +8,61 @@ namespace ThinkSharp.FormulaParsing { public interface IFormulaParserBuilder { + /// + /// Allows to configure functions of the . + /// + /// + /// The object that provides methods for configuring functions of the formula parser. + /// + /// + /// The . + /// IFormulaParserBuilder ConfigureFunctions(Action functions); + /// + /// Allows to configure constants of the . + /// + /// + /// The object that provides methods for configuring constants of the formula parser. + /// + /// + /// The . + /// IFormulaParserBuilder ConfigureConstats(Action constants); + /// + /// Allows to disable features of the . + /// + /// + /// The object that provides methods for disabling features of the formula parser. + /// + /// + /// The . + /// IFormulaParserBuilder ConfigureSupportedFeatures(Action supportedFeatures); - IFormulaParserBuilder ConfigureParsingBehavior(Action parsingBehavior); + /// + /// Allows to configure the validation behavior of the . + /// + /// + /// The default behavior is, that names of configured functions / provided variables are required. If the formula contains unknown + /// functions / variables, the parsing process fails with an appropriated error message. + /// This method allows to disable validation for variables / functions which may be useful for creating a parsing tree. + /// + /// + /// The object that provides methods for disabling features of the formula parser. + /// + /// + /// The . + /// + IFormulaParserBuilder ConfigureValidationBehavior(Action parsingBehavior); + /// + /// Build the configured . + /// + /// + /// The configured . + /// IFormulaParser Build(); } } diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj index 6e2806e..7f7efb1 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj @@ -9,16 +9,21 @@ ThinkSharp A formula parser with fluent API that allows parsing and evaluation of mathematically formulas. Features: functions, constants, variables, scientific numbers, focus on customization and flexibility. © 2019 Jan-Niklas Schäfer - 0.1.0.0 - 0.1.0.0 + 0.2.0.0 + 0.2.0.0 LICENSE.txt - 0.1 Initial Version + Added comments +Added function'sqrt' https://github.com/JanDotNet/ThinkSharp.FormulaParser true - 0.1.0 + 0.2.0 + + C:\Users\Tachy\Projects\ThinkSharp\ThinkSharp.FormulaParser\ThinkSharp.FormulaParser\ThinkSharp.FormulaParser.xml + + diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml new file mode 100644 index 0000000..c781fee --- /dev/null +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml @@ -0,0 +1,848 @@ + + + + ThinkSharp.FormulaParser + + + + + The class provides static methods for creating instances. + Use the method to create a with default configuration. + Use the method to create a that allows to configure the instance. + + + + + Creates a new with its default configuration. + + + A new with its default configuration. + + + + + Creates a that allows to configure the . + + + a . + + + + + Adds a constant. + + + The name of the constant to add. + + + The value of the constant. + + + + + Removes all configured functions. + + + + + Removed the function with the specified name. + + + The name of the function to remove. + + + + + Adds a function with zero paramteter. + + + The name of the function. + + + The function. + + + + + Adds a function with one paramteter. + + + The name of the function. + + + The function. + + + + + Adds a function with two paramteters. + + + The name of the function. + + + The function. + + + + + Adds a function with three paramteters. + + + The name of the function. + + + The function. + + + + + Adds a function with four paramteters. + + + The name of the function. + + + The function. + + + + + Adds a function with five paramteters. + + + The name of the function. + + + The function. + + + + + Adds a function with 2 to n paramteters. + + + The name of the function. + + + The function. + + + + + Removes all configured functions. + + + + + Removed the function with the specified name. + + + The name of the function to remove. + + + + + Prevents the usage of scientific notation (e.g. 2e3 = 4000) + + + + + Prevents the usage of brackets. + + + + + Prevents the usage of pow (e.g. 3^2 = 9) + + + + + Ptevents the usage of variables. + + + + + Prevents the usage of functions. + + + + + Diables the validation of variable names when creating a parsing tree. + + + + + Diables the validation of functions names when creating a parsing tree. + + + + + + + + + + + + + + Allows to configure functions of the . + + + The object that provides methods for configuring functions of the formula parser. + + + The . + + + + + Allows to configure constants of the . + + + The object that provides methods for configuring constants of the formula parser. + + + The . + + + + + Allows to disable features of the . + + + The object that provides methods for disabling features of the formula parser. + + + The . + + + + + Allows to configure the validation behavior of the . + + + The default behavior is, that names of configured functions / provided variables are required. If the formula contains unknown + functions / variables, the parsing process fails with an appropriated error message. + This method allows to disable validation for variables / functions which may be useful for creating a parsing tree. + + + The object that provides methods for disabling features of the formula parser. + + + The . + + + + + Build the configured . + + + The configured . + + + + + This class provides an empty implementation of , + which can be extended to create a listener which only needs to handle a subset + of the available methods. + + + + + Enter a parse tree produced by . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by the PlusAtom + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by the PlusAtom + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by the NegativeAtom + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by the NegativeAtom + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by the Function + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by the Function + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by the UnsignedAtom + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by the UnsignedAtom + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by the ScientificNumber + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by the ScientificNumber + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by . + The default implementation does nothing. + + The parse tree. + + + + The default implementation does nothing. + + + + The default implementation does nothing. + + + + The default implementation does nothing. + + + + The default implementation does nothing. + + + + This class provides an empty implementation of , + which can be extended to create a visitor which only needs to handle a subset + of the available methods. + + The return type of the visit operation. + + + + Visit a parse tree produced by . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the PlusAtom + labeled alternative in . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the NegativeAtom + labeled alternative in . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the Function + labeled alternative in . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the UnsignedAtom + labeled alternative in . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the ScientificNumber + labeled alternative in . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + This interface defines a complete listener for a parse tree produced by + . + + + + + Enter a parse tree produced by . + + The parse tree. + + + + Exit a parse tree produced by . + + The parse tree. + + + + Enter a parse tree produced by . + + The parse tree. + + + + Exit a parse tree produced by . + + The parse tree. + + + + Enter a parse tree produced by . + + The parse tree. + + + + Exit a parse tree produced by . + + The parse tree. + + + + Enter a parse tree produced by . + + The parse tree. + + + + Exit a parse tree produced by . + + The parse tree. + + + + Enter a parse tree produced by the PlusAtom + labeled alternative in . + + The parse tree. + + + + Exit a parse tree produced by the PlusAtom + labeled alternative in . + + The parse tree. + + + + Enter a parse tree produced by the NegativeAtom + labeled alternative in . + + The parse tree. + + + + Exit a parse tree produced by the NegativeAtom + labeled alternative in . + + The parse tree. + + + + Enter a parse tree produced by the Function + labeled alternative in . + + The parse tree. + + + + Exit a parse tree produced by the Function + labeled alternative in . + + The parse tree. + + + + Enter a parse tree produced by the UnsignedAtom + labeled alternative in . + + The parse tree. + + + + Exit a parse tree produced by the UnsignedAtom + labeled alternative in . + + The parse tree. + + + + Enter a parse tree produced by . + + The parse tree. + + + + Exit a parse tree produced by . + + The parse tree. + + + + Enter a parse tree produced by the ScientificNumber + labeled alternative in . + + The parse tree. + + + + Exit a parse tree produced by the ScientificNumber + labeled alternative in . + + The parse tree. + + + + Enter a parse tree produced by . + + The parse tree. + + + + Exit a parse tree produced by . + + The parse tree. + + + + Enter a parse tree produced by . + + The parse tree. + + + + Exit a parse tree produced by . + + The parse tree. + + + + This interface defines a complete generic visitor for a parse tree produced + by . + + The return type of the visit operation. + + + + Visit a parse tree produced by . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the PlusAtom + labeled alternative in . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the NegativeAtom + labeled alternative in . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the Function + labeled alternative in . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the UnsignedAtom + labeled alternative in . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the ScientificNumber + labeled alternative in . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by . + + The parse tree. + The visitor result. + + + From 3ffb18ded09255c1cef9f0c7b181a5330db5fe44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Wed, 11 Sep 2019 16:13:28 +0200 Subject: [PATCH 12/45] Update README.md --- README.md | 134 +++++++++++++++++++++++++++++------------------------- 1 file changed, 71 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index 11e32e6..19afe4d 100644 --- a/README.md +++ b/README.md @@ -29,80 +29,88 @@ ThinkSharp.FormulaParser can be installed via [Nuget](https://www.nuget.org/pack ### Evaluating formulas - // The simples way to create a formula parser is the static method 'Create'. - var parser = FormulaParser.Create(); +```csharp +// The simples way to create a formula parser is the static method 'Create'. +var parser = FormulaParser.Create(); - // Parsing a simple mathematical formula - var result1 = parser.Evaluate("1+1").Value; // result1 = 2.0 +// Parsing a simple mathematical formula +var result1 = parser.Evaluate("1+1").Value; // result1 = 2.0 - // Usage of variables - var variables = new Dictionary { ["x"] = 2.0 }; - var result2 = parser.Evaluate("1+x", variables).Value; // result2 = 3.0 +// Usage of variables +var variables = new Dictionary { ["x"] = 2.0 }; +var result2 = parser.Evaluate("1+x", variables).Value; // result2 = 3.0 - // Usage of functions - var result3 = parser.Evaluate("1+min(3,4)").Value; // result2 = 4.0 +// Usage of functions +var result3 = parser.Evaluate("1+min(3,4)").Value; // result2 = 4.0 - // Handle errors - var parsingResult = parser.Evaluate("2*?"); - if (!parsingResult.Success) Console.WriteLine(parsingResult.Error); // "column 2: token recognition error at: '?'" +// Handle errors +var parsingResult = parser.Evaluate("2*?"); +if (!parsingResult.Success) +{ + Console.WriteLine(parsingResult.Error); // "column 2: token recognition error at: '?'" +} +``` #### Creating and evaluating a parsing tree - var parser = FormulaParser.Create(); - var variables = new Dictionary { ["x"] = 2.0 }; - - // Parsing a simple mathematical formula - var node1 = parser.Parse("1+x", variables).Value; - // |FormulaNode("1+x") - // |- Child: BinaryOperatorNode(+) - // |- LeftNode: NumericNode(1.0) - // |- RightNode: VariableNode("x") - var result1 = parser.Evaluate(node1, variables).Value; // result = 3.0 - - - var node2 = parser.Parse("pi * sqrt(3*x)", variables).Value; - // |FormulaNode("pi * sqrt(3*x)") - // |- Child: BinaryOperatorNode(*) - // |- LeftNode: ConstantNode("pi") - // |- RightNode: FunctionNode("sqrt") - // |- Parameters: [BinaryOperationNode(*)] - // |- LeftNode: Numeric(3.0) - // |- RightNode: VariableNode("x") - var result2 = parser.Evaluate(node2, variables).Value; // result = 7.695... - +```csharp +var parser = FormulaParser.Create(); +var variables = new Dictionary { ["x"] = 2.0 }; + +// Parsing a simple mathematical formula +var node1 = parser.Parse("1+x", variables).Value; +// |FormulaNode("1+x") +// |- Child: BinaryOperatorNode(+) +// |- LeftNode: NumericNode(1.0) +// |- RightNode: VariableNode("x") +var result1 = parser.Evaluate(node1, variables).Value; // result = 3.0 + + +var node2 = parser.Parse("pi * sqrt(3*x)", variables).Value; +// |FormulaNode("pi * sqrt(3*x)") +// |- Child: BinaryOperatorNode(*) +// |- LeftNode: ConstantNode("pi") +// |- RightNode: FunctionNode("sqrt") +// |- Parameters: [BinaryOperationNode(*)] +// |- LeftNode: Numeric(3.0) +// |- RightNode: VariableNode("x") +var result2 = parser.Evaluate(node2, variables).Value; // result = 7.695... +``` + #### Configure custom functions / constants - var parser = FormulaParser - .CreateBuilder() - .ConfigureConstats(constants => - { - // constants.RemoveAll() for removing all default constants - // constants.Remove("pi") for removing constants by name +```csharp +var parser = FormulaParser + .CreateBuilder() + .ConfigureConstats(constants => + { + // constants.RemoveAll() for removing all default constants + // constants.Remove("pi") for removing constants by name - constants.Add("h", 6.62607015e-34); - }) - .ConfigureFunctions(functions => - { - // functions.RemoveAll() for removing all default functions - // functions.Remove("sum") for removing function by name - - // define function with 2 to n number of parameters (typeof(nums) = double[]) - functions.Add("product", nums => nums.Aggregate((p1, p2) => p1 * p2)); - - // define functions with specified number of parameters (1-5 parameters are supported) - functions.Add("celsiusToFarenheit", celsius => celsius * 1.8 + 32); - functions.Add("fahrenheitToCelsius", fahrenheit => (fahrenheit - 32) * 5 / 9); - functions.Add("p1_plus_p2_plus_p3", (p1, p2, p3) => p1 + p2 + p3); - }).Build(); - - var poolTemperatureInCelsius = parser.Evaluate("celsiusToFarenheit(fahrenheitToCelsius(30))").Value; // poolTemperatureInCelsius = 30 - var result2 = parser.Evaluate("product(2, 2, 2, 2, 2, 2, 2)").Value; // result2 = 2^6 = 128 - var result3 = parser.Evaluate("p1_plus_p2_plus_p3(1, 2, 3)").Value; // result3 = 6 - - string error1 = parser.Evaluate("celsiusToFarenheit(1, 2)").Error; // column 0: There is no function 'celsiusToFarenheit' that takes 2 argument(s). + constants.Add("h", 6.62607015e-34); + }) + .ConfigureFunctions(functions => + { + // functions.RemoveAll() for removing all default functions + // functions.Remove("sum") for removing function by name + // define function with 2 to n number of parameters (typeof(nums) = double[]) + functions.Add("product", nums => nums.Aggregate((p1, p2) => p1 * p2)); + + // define functions with specified number of parameters (1-5 parameters are supported) + functions.Add("celsiusToFarenheit", celsius => celsius * 1.8 + 32); + functions.Add("fahrenheitToCelsius", fahrenheit => (fahrenheit - 32) * 5 / 9); + functions.Add("p1_plus_p2_plus_p3", (p1, p2, p3) => p1 + p2 + p3); + }).Build(); + +var poolTemperatureInCelsius = parser.Evaluate("celsiusToFarenheit(fahrenheitToCelsius(30))").Value; // poolTemperatureInCelsius = 30 +var result2 = parser.Evaluate("product(2, 2, 2, 2, 2, 2, 2)").Value; // result2 = 2^6 = 128 +var result3 = parser.Evaluate("p1_plus_p2_plus_p3(1, 2, 3)").Value; // result3 = 6 + +string error1 = parser.Evaluate("celsiusToFarenheit(1, 2)").Error; // column 0: There is no function 'celsiusToFarenheit' that takes 2 argument(s). string error2 = parser.Evaluate("product()").Error; // column 0: There is no function 'product' that takes 0 argument(s). - string error3 = parser.Evaluate("p1_plus_p2_plus_p3(1, 2)").Error; // column 0: There is no function 'p1_plus_p2_plus_p3' that takes 2 argument(s). - +string error3 = parser.Evaluate("p1_plus_p2_plus_p3(1, 2)").Error; // column 0: There is no function 'p1_plus_p2_plus_p3' that takes 2 argument(s). +``` + ## License ThinkSharp.FormulaParser is released under [The MIT license (MIT)](LICENSE.TXT) From 5024a4f94370fbae26d45131e1eac16d6eb7e1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 16 Sep 2019 20:37:17 +0200 Subject: [PATCH 13/45] added support for binary (0x1001101) / hexadecimal (0x134A) number representations --- .../AntlrToAstNodesGrammerTreeVisitor.cs | 33 ++- .../ANTLR/FormulaGrammer.g4 | 53 +++- .../ANTLR/FormulaGrammer.interp | 10 +- .../ANTLR/FormulaGrammer.tokens | 7 +- .../ANTLR/FormulaGrammerBaseListener.cs | 46 +++- .../ANTLR/FormulaGrammerBaseVisitor.cs | 35 ++- .../ANTLR/FormulaGrammerLexer.cs | 228 +++++++++++------- .../ANTLR/FormulaGrammerLexer.interp | 19 +- .../ANTLR/FormulaGrammerLexer.tokens | 7 +- .../ANTLR/FormulaGrammerListener.cs | 40 ++- .../ANTLR/FormulaGrammerParser.cs | 202 +++++++++++----- .../ANTLR/FormulaGrammerVisitor.cs | 23 +- .../Ast/Nodes/NumericNode.cs | 5 +- ThinkSharp.FormulaParser/Configuration.cs | 6 + ThinkSharp.FormulaParser/IConfiguration.cs | 4 + .../IConfigureSupportedFeatures.cs | 13 + .../ParserConfiguration.cs | 4 + 17 files changed, 564 insertions(+), 171 deletions(-) diff --git a/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs b/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs index 0a2de5d..5a49e46 100644 --- a/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs +++ b/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs @@ -119,8 +119,37 @@ public override Node VisitScientificNumber([NotNull] FormulaGrammerParser.Scient ParsingException.ThrowInvalidTokenException(context.SCIENTIFIC_NUMBER().Symbol); } - var scientificNumber = context.SCIENTIFIC_NUMBER().Symbol.Text; - return new NumberNode(double.Parse(scientificNumber)); + var token = context.SCIENTIFIC_NUMBER().Symbol.Text; + return new NumberNode(token, double.Parse(token)); + } + + public override Node VisitBinaryNumber([NotNull] FormulaGrammerParser.BinaryNumberContext context) + { + if (this.configuration.IsBinaryNumberNotationSupportDisabled) + { + ParsingException.ThrowInvalidTokenException(context.BINARY_NUMBER().Symbol); + } + + var token = context.BINARY_NUMBER().Symbol.Text; + return new NumberNode(token, Convert.ToInt32(token.Substring(2), 2)); + } + + public override Node VisitDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context) + { + var token = context.DECIMAL_NUMBER().Symbol.Text; + var hasPrefix = token.StartsWith("0D", StringComparison.InvariantCultureIgnoreCase); + return new NumberNode(token, double.Parse(hasPrefix ? token.Substring(2) : token)); + } + + public override Node VisitHexadecimalNumber([NotNull] FormulaGrammerParser.HexadecimalNumberContext context) + { + if (this.configuration.IsHexadecimalNumberNotationSupportDisabled) + { + ParsingException.ThrowInvalidTokenException(context.HEXADECIMAL_NUMBER().Symbol); + } + + var token = context.HEXADECIMAL_NUMBER().Symbol.Text; + return new NumberNode(token, Convert.ToInt32(token.Substring(token[0] == '#' ? 1 : 2), 16)); } public override Node VisitVariable([NotNull] FormulaGrammerParser.VariableContext context) diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.g4 b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.g4 index b21d3ba..4d7555f 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.g4 +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.g4 @@ -24,13 +24,16 @@ signedAtom ; atom - : scientific + : number | variable | LPAREN expression RPAREN ; -scientific +number : SCIENTIFIC_NUMBER # ScientificNumber + | DECIMAL_NUMBER # DecimalNumber + | BINARY_NUMBER # BinaryNumber + | HEXADECIMAL_NUMBER # HexadecimalNumber ; func @@ -91,23 +94,58 @@ IDENTIFIER : VALID_ID_START VALID_ID_CHAR* ; +DECIMAL_NUMBER + : (PREFIX_DEC)? NUMBER_DEC + ; + +BINARY_NUMBER + : PREFIX_BIN NUMBER_BIN + ; + +HEXADECIMAL_NUMBER + : (PREFIX_HEX | NUMBER_HEX2) NUMBER_HEX + ; + SCIENTIFIC_NUMBER - : NUMBER ((E1 | E2) SIGN? NUMBER)? + : NUMBER_DEC (E1 | E2) SIGN? NUMBER_DEC ; fragment VALID_ID_START : ('a' .. 'z') | ('A' .. 'Z') | '_' ; - - + fragment VALID_ID_CHAR : VALID_ID_START | ('0' .. '9') ; -fragment NUMBER +fragment PREFIX_DEC + : '0' ('D' | 'd') + ; + +fragment NUMBER_DEC : ('0' .. '9') + ('.' ('0' .. '9') +)? ; +fragment PREFIX_BIN + : '0' ('B' | 'b') + ; + +fragment NUMBER_BIN + : ('0' | '1')+ + ; + +fragment PREFIX_HEX + : '0' ('X' | 'x') + ; + +fragment NUMBER_HEX2 + : '#' + ; + +fragment NUMBER_HEX + : (('0' .. '9') | ('A' .. 'F') | ('a' .. 'f')) + + ; + fragment E1 : 'E' @@ -122,8 +160,7 @@ fragment E2 fragment SIGN : ('+' | '-') ; - - + WS : [ \r\n\t] + -> skip ; \ No newline at end of file diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.interp b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.interp index cfc604b..3f82ae6 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.interp +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.interp @@ -12,6 +12,9 @@ null null null null +null +null +null token symbolic names: null @@ -25,6 +28,9 @@ COMMA POINT POW IDENTIFIER +DECIMAL_NUMBER +BINARY_NUMBER +HEXADECIMAL_NUMBER SCIENTIFIC_NUMBER WS @@ -35,10 +41,10 @@ multiplyingExpression powExpression signedAtom atom -scientific +number func variable atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 14, 82, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 7, 3, 27, 10, 3, 12, 3, 14, 3, 30, 11, 3, 3, 4, 3, 4, 3, 4, 7, 4, 35, 10, 4, 12, 4, 14, 4, 38, 11, 4, 3, 5, 3, 5, 3, 5, 7, 5, 43, 10, 5, 12, 5, 14, 5, 46, 11, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 54, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 5, 7, 62, 10, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 7, 9, 71, 10, 9, 12, 9, 14, 9, 74, 11, 9, 5, 9, 76, 10, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 2, 2, 11, 2, 4, 6, 8, 10, 12, 14, 16, 18, 2, 4, 3, 2, 5, 6, 3, 2, 7, 8, 2, 82, 2, 20, 3, 2, 2, 2, 4, 23, 3, 2, 2, 2, 6, 31, 3, 2, 2, 2, 8, 39, 3, 2, 2, 2, 10, 53, 3, 2, 2, 2, 12, 61, 3, 2, 2, 2, 14, 63, 3, 2, 2, 2, 16, 65, 3, 2, 2, 2, 18, 79, 3, 2, 2, 2, 20, 21, 5, 4, 3, 2, 21, 22, 7, 2, 2, 3, 22, 3, 3, 2, 2, 2, 23, 28, 5, 6, 4, 2, 24, 25, 9, 2, 2, 2, 25, 27, 5, 6, 4, 2, 26, 24, 3, 2, 2, 2, 27, 30, 3, 2, 2, 2, 28, 26, 3, 2, 2, 2, 28, 29, 3, 2, 2, 2, 29, 5, 3, 2, 2, 2, 30, 28, 3, 2, 2, 2, 31, 36, 5, 8, 5, 2, 32, 33, 9, 3, 2, 2, 33, 35, 5, 8, 5, 2, 34, 32, 3, 2, 2, 2, 35, 38, 3, 2, 2, 2, 36, 34, 3, 2, 2, 2, 36, 37, 3, 2, 2, 2, 37, 7, 3, 2, 2, 2, 38, 36, 3, 2, 2, 2, 39, 44, 5, 10, 6, 2, 40, 41, 7, 11, 2, 2, 41, 43, 5, 10, 6, 2, 42, 40, 3, 2, 2, 2, 43, 46, 3, 2, 2, 2, 44, 42, 3, 2, 2, 2, 44, 45, 3, 2, 2, 2, 45, 9, 3, 2, 2, 2, 46, 44, 3, 2, 2, 2, 47, 48, 7, 5, 2, 2, 48, 54, 5, 12, 7, 2, 49, 50, 7, 6, 2, 2, 50, 54, 5, 12, 7, 2, 51, 54, 5, 16, 9, 2, 52, 54, 5, 12, 7, 2, 53, 47, 3, 2, 2, 2, 53, 49, 3, 2, 2, 2, 53, 51, 3, 2, 2, 2, 53, 52, 3, 2, 2, 2, 54, 11, 3, 2, 2, 2, 55, 62, 5, 14, 8, 2, 56, 62, 5, 18, 10, 2, 57, 58, 7, 3, 2, 2, 58, 59, 5, 4, 3, 2, 59, 60, 7, 4, 2, 2, 60, 62, 3, 2, 2, 2, 61, 55, 3, 2, 2, 2, 61, 56, 3, 2, 2, 2, 61, 57, 3, 2, 2, 2, 62, 13, 3, 2, 2, 2, 63, 64, 7, 13, 2, 2, 64, 15, 3, 2, 2, 2, 65, 66, 7, 12, 2, 2, 66, 75, 7, 3, 2, 2, 67, 72, 5, 4, 3, 2, 68, 69, 7, 9, 2, 2, 69, 71, 5, 4, 3, 2, 70, 68, 3, 2, 2, 2, 71, 74, 3, 2, 2, 2, 72, 70, 3, 2, 2, 2, 72, 73, 3, 2, 2, 2, 73, 76, 3, 2, 2, 2, 74, 72, 3, 2, 2, 2, 75, 67, 3, 2, 2, 2, 75, 76, 3, 2, 2, 2, 76, 77, 3, 2, 2, 2, 77, 78, 7, 4, 2, 2, 78, 17, 3, 2, 2, 2, 79, 80, 7, 12, 2, 2, 80, 19, 3, 2, 2, 2, 9, 28, 36, 44, 53, 61, 72, 75] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 17, 86, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 7, 3, 27, 10, 3, 12, 3, 14, 3, 30, 11, 3, 3, 4, 3, 4, 3, 4, 7, 4, 35, 10, 4, 12, 4, 14, 4, 38, 11, 4, 3, 5, 3, 5, 3, 5, 7, 5, 43, 10, 5, 12, 5, 14, 5, 46, 11, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 54, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 5, 7, 62, 10, 7, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 68, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 7, 9, 75, 10, 9, 12, 9, 14, 9, 78, 11, 9, 5, 9, 80, 10, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 2, 2, 11, 2, 4, 6, 8, 10, 12, 14, 16, 18, 2, 4, 3, 2, 5, 6, 3, 2, 7, 8, 2, 89, 2, 20, 3, 2, 2, 2, 4, 23, 3, 2, 2, 2, 6, 31, 3, 2, 2, 2, 8, 39, 3, 2, 2, 2, 10, 53, 3, 2, 2, 2, 12, 61, 3, 2, 2, 2, 14, 67, 3, 2, 2, 2, 16, 69, 3, 2, 2, 2, 18, 83, 3, 2, 2, 2, 20, 21, 5, 4, 3, 2, 21, 22, 7, 2, 2, 3, 22, 3, 3, 2, 2, 2, 23, 28, 5, 6, 4, 2, 24, 25, 9, 2, 2, 2, 25, 27, 5, 6, 4, 2, 26, 24, 3, 2, 2, 2, 27, 30, 3, 2, 2, 2, 28, 26, 3, 2, 2, 2, 28, 29, 3, 2, 2, 2, 29, 5, 3, 2, 2, 2, 30, 28, 3, 2, 2, 2, 31, 36, 5, 8, 5, 2, 32, 33, 9, 3, 2, 2, 33, 35, 5, 8, 5, 2, 34, 32, 3, 2, 2, 2, 35, 38, 3, 2, 2, 2, 36, 34, 3, 2, 2, 2, 36, 37, 3, 2, 2, 2, 37, 7, 3, 2, 2, 2, 38, 36, 3, 2, 2, 2, 39, 44, 5, 10, 6, 2, 40, 41, 7, 11, 2, 2, 41, 43, 5, 10, 6, 2, 42, 40, 3, 2, 2, 2, 43, 46, 3, 2, 2, 2, 44, 42, 3, 2, 2, 2, 44, 45, 3, 2, 2, 2, 45, 9, 3, 2, 2, 2, 46, 44, 3, 2, 2, 2, 47, 48, 7, 5, 2, 2, 48, 54, 5, 12, 7, 2, 49, 50, 7, 6, 2, 2, 50, 54, 5, 12, 7, 2, 51, 54, 5, 16, 9, 2, 52, 54, 5, 12, 7, 2, 53, 47, 3, 2, 2, 2, 53, 49, 3, 2, 2, 2, 53, 51, 3, 2, 2, 2, 53, 52, 3, 2, 2, 2, 54, 11, 3, 2, 2, 2, 55, 62, 5, 14, 8, 2, 56, 62, 5, 18, 10, 2, 57, 58, 7, 3, 2, 2, 58, 59, 5, 4, 3, 2, 59, 60, 7, 4, 2, 2, 60, 62, 3, 2, 2, 2, 61, 55, 3, 2, 2, 2, 61, 56, 3, 2, 2, 2, 61, 57, 3, 2, 2, 2, 62, 13, 3, 2, 2, 2, 63, 68, 7, 16, 2, 2, 64, 68, 7, 13, 2, 2, 65, 68, 7, 14, 2, 2, 66, 68, 7, 15, 2, 2, 67, 63, 3, 2, 2, 2, 67, 64, 3, 2, 2, 2, 67, 65, 3, 2, 2, 2, 67, 66, 3, 2, 2, 2, 68, 15, 3, 2, 2, 2, 69, 70, 7, 12, 2, 2, 70, 79, 7, 3, 2, 2, 71, 76, 5, 4, 3, 2, 72, 73, 7, 9, 2, 2, 73, 75, 5, 4, 3, 2, 74, 72, 3, 2, 2, 2, 75, 78, 3, 2, 2, 2, 76, 74, 3, 2, 2, 2, 76, 77, 3, 2, 2, 2, 77, 80, 3, 2, 2, 2, 78, 76, 3, 2, 2, 2, 79, 71, 3, 2, 2, 2, 79, 80, 3, 2, 2, 2, 80, 81, 3, 2, 2, 2, 81, 82, 7, 4, 2, 2, 82, 17, 3, 2, 2, 2, 83, 84, 7, 12, 2, 2, 84, 19, 3, 2, 2, 2, 10, 28, 36, 44, 53, 61, 67, 76, 79] \ No newline at end of file diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.tokens b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.tokens index 83a628c..a954a79 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.tokens +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.tokens @@ -8,8 +8,11 @@ COMMA=7 POINT=8 POW=9 IDENTIFIER=10 -SCIENTIFIC_NUMBER=11 -WS=12 +DECIMAL_NUMBER=11 +BINARY_NUMBER=12 +HEXADECIMAL_NUMBER=13 +SCIENTIFIC_NUMBER=14 +WS=15 '('=1 ')'=2 '+'=3 diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerBaseListener.cs b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerBaseListener.cs index bce36d1..1f31424 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerBaseListener.cs +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerBaseListener.cs @@ -152,19 +152,61 @@ public virtual void EnterAtom([NotNull] FormulaGrammerParser.AtomContext context public virtual void ExitAtom([NotNull] FormulaGrammerParser.AtomContext context) { } /// /// Enter a parse tree produced by the ScientificNumber - /// labeled alternative in . + /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. public virtual void EnterScientificNumber([NotNull] FormulaGrammerParser.ScientificNumberContext context) { } /// /// Exit a parse tree produced by the ScientificNumber - /// labeled alternative in . + /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. public virtual void ExitScientificNumber([NotNull] FormulaGrammerParser.ScientificNumberContext context) { } /// + /// Enter a parse tree produced by the DecimalNumber + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void EnterDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context) { } + /// + /// Exit a parse tree produced by the DecimalNumber + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void ExitDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context) { } + /// + /// Enter a parse tree produced by the BinaryNumber + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void EnterBinaryNumber([NotNull] FormulaGrammerParser.BinaryNumberContext context) { } + /// + /// Exit a parse tree produced by the BinaryNumber + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void ExitBinaryNumber([NotNull] FormulaGrammerParser.BinaryNumberContext context) { } + /// + /// Enter a parse tree produced by the HexadecimalNumber + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void EnterHexadecimalNumber([NotNull] FormulaGrammerParser.HexadecimalNumberContext context) { } + /// + /// Exit a parse tree produced by the HexadecimalNumber + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void ExitHexadecimalNumber([NotNull] FormulaGrammerParser.HexadecimalNumberContext context) { } + /// /// Enter a parse tree produced by . /// The default implementation does nothing. /// diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerBaseVisitor.cs b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerBaseVisitor.cs index 70a9227..677ef4a 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerBaseVisitor.cs +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerBaseVisitor.cs @@ -129,7 +129,7 @@ public partial class FormulaGrammerBaseVisitor : AbstractParseTreeVisito public virtual Result VisitAtom([NotNull] FormulaGrammerParser.AtomContext context) { return VisitChildren(context); } /// /// Visit a parse tree produced by the ScientificNumber - /// labeled alternative in . + /// labeled alternative in . /// /// The default implementation returns the result of calling /// on . @@ -139,6 +139,39 @@ public partial class FormulaGrammerBaseVisitor : AbstractParseTreeVisito /// The visitor result. public virtual Result VisitScientificNumber([NotNull] FormulaGrammerParser.ScientificNumberContext context) { return VisitChildren(context); } /// + /// Visit a parse tree produced by the DecimalNumber + /// labeled alternative in . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by the BinaryNumber + /// labeled alternative in . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitBinaryNumber([NotNull] FormulaGrammerParser.BinaryNumberContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by the HexadecimalNumber + /// labeled alternative in . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitHexadecimalNumber([NotNull] FormulaGrammerParser.HexadecimalNumberContext context) { return VisitChildren(context); } + /// /// Visit a parse tree produced by . /// /// The default implementation returns the result of calling diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.cs b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.cs index 735a70b..e202fab 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.cs +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.cs @@ -34,7 +34,8 @@ public partial class FormulaGrammerLexer : Lexer { protected static PredictionContextCache sharedContextCache = new PredictionContextCache(); public const int LPAREN=1, RPAREN=2, PLUS=3, MINUS=4, TIMES=5, DIV=6, COMMA=7, POINT=8, - POW=9, IDENTIFIER=10, SCIENTIFIC_NUMBER=11, WS=12; + POW=9, IDENTIFIER=10, DECIMAL_NUMBER=11, BINARY_NUMBER=12, HEXADECIMAL_NUMBER=13, + SCIENTIFIC_NUMBER=14, WS=15; public static string[] channelNames = { "DEFAULT_TOKEN_CHANNEL", "HIDDEN" }; @@ -45,8 +46,10 @@ public const int public static readonly string[] ruleNames = { "LPAREN", "RPAREN", "PLUS", "MINUS", "TIMES", "DIV", "COMMA", "POINT", - "POW", "IDENTIFIER", "SCIENTIFIC_NUMBER", "VALID_ID_START", "VALID_ID_CHAR", - "NUMBER", "E1", "E2", "SIGN", "WS" + "POW", "IDENTIFIER", "DECIMAL_NUMBER", "BINARY_NUMBER", "HEXADECIMAL_NUMBER", + "SCIENTIFIC_NUMBER", "VALID_ID_START", "VALID_ID_CHAR", "PREFIX_DEC", + "NUMBER_DEC", "PREFIX_BIN", "NUMBER_BIN", "PREFIX_HEX", "NUMBER_HEX2", + "NUMBER_HEX", "E1", "E2", "SIGN", "WS" }; @@ -64,7 +67,8 @@ public FormulaGrammerLexer(ICharStream input, TextWriter output, TextWriter erro }; private static readonly string[] _SymbolicNames = { null, "LPAREN", "RPAREN", "PLUS", "MINUS", "TIMES", "DIV", "COMMA", "POINT", - "POW", "IDENTIFIER", "SCIENTIFIC_NUMBER", "WS" + "POW", "IDENTIFIER", "DECIMAL_NUMBER", "BINARY_NUMBER", "HEXADECIMAL_NUMBER", + "SCIENTIFIC_NUMBER", "WS" }; public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames); @@ -95,94 +99,138 @@ static FormulaGrammerLexer() { } private static char[] _serializedATN = { '\x3', '\x608B', '\xA72A', '\x8133', '\xB9ED', '\x417C', '\x3BE7', '\x7786', - '\x5964', '\x2', '\xE', 'm', '\b', '\x1', '\x4', '\x2', '\t', '\x2', '\x4', - '\x3', '\t', '\x3', '\x4', '\x4', '\t', '\x4', '\x4', '\x5', '\t', '\x5', - '\x4', '\x6', '\t', '\x6', '\x4', '\a', '\t', '\a', '\x4', '\b', '\t', - '\b', '\x4', '\t', '\t', '\t', '\x4', '\n', '\t', '\n', '\x4', '\v', '\t', - '\v', '\x4', '\f', '\t', '\f', '\x4', '\r', '\t', '\r', '\x4', '\xE', + '\x5964', '\x2', '\x11', '\xA0', '\b', '\x1', '\x4', '\x2', '\t', '\x2', + '\x4', '\x3', '\t', '\x3', '\x4', '\x4', '\t', '\x4', '\x4', '\x5', '\t', + '\x5', '\x4', '\x6', '\t', '\x6', '\x4', '\a', '\t', '\a', '\x4', '\b', + '\t', '\b', '\x4', '\t', '\t', '\t', '\x4', '\n', '\t', '\n', '\x4', '\v', + '\t', '\v', '\x4', '\f', '\t', '\f', '\x4', '\r', '\t', '\r', '\x4', '\xE', '\t', '\xE', '\x4', '\xF', '\t', '\xF', '\x4', '\x10', '\t', '\x10', '\x4', '\x11', '\t', '\x11', '\x4', '\x12', '\t', '\x12', '\x4', '\x13', '\t', - '\x13', '\x3', '\x2', '\x3', '\x2', '\x3', '\x3', '\x3', '\x3', '\x3', - '\x4', '\x3', '\x4', '\x3', '\x5', '\x3', '\x5', '\x3', '\x6', '\x3', - '\x6', '\x3', '\a', '\x3', '\a', '\x3', '\b', '\x3', '\b', '\x3', '\t', - '\x3', '\t', '\x3', '\n', '\x3', '\n', '\x3', '\v', '\x3', '\v', '\a', - '\v', '<', '\n', '\v', '\f', '\v', '\xE', '\v', '?', '\v', '\v', '\x3', - '\f', '\x3', '\f', '\x3', '\f', '\x5', '\f', '\x44', '\n', '\f', '\x3', - '\f', '\x5', '\f', 'G', '\n', '\f', '\x3', '\f', '\x3', '\f', '\x5', '\f', - 'K', '\n', '\f', '\x3', '\r', '\x5', '\r', 'N', '\n', '\r', '\x3', '\xE', - '\x3', '\xE', '\x5', '\xE', 'R', '\n', '\xE', '\x3', '\xF', '\x6', '\xF', - 'U', '\n', '\xF', '\r', '\xF', '\xE', '\xF', 'V', '\x3', '\xF', '\x3', - '\xF', '\x6', '\xF', '[', '\n', '\xF', '\r', '\xF', '\xE', '\xF', '\\', - '\x5', '\xF', '_', '\n', '\xF', '\x3', '\x10', '\x3', '\x10', '\x3', '\x11', - '\x3', '\x11', '\x3', '\x12', '\x3', '\x12', '\x3', '\x13', '\x6', '\x13', - 'h', '\n', '\x13', '\r', '\x13', '\xE', '\x13', 'i', '\x3', '\x13', '\x3', - '\x13', '\x2', '\x2', '\x14', '\x3', '\x3', '\x5', '\x4', '\a', '\x5', - '\t', '\x6', '\v', '\a', '\r', '\b', '\xF', '\t', '\x11', '\n', '\x13', - '\v', '\x15', '\f', '\x17', '\r', '\x19', '\x2', '\x1B', '\x2', '\x1D', - '\x2', '\x1F', '\x2', '!', '\x2', '#', '\x2', '%', '\xE', '\x3', '\x2', - '\x5', '\x5', '\x2', '\x43', '\\', '\x61', '\x61', '\x63', '|', '\x4', - '\x2', '-', '-', '/', '/', '\x5', '\x2', '\v', '\f', '\xF', '\xF', '\"', - '\"', '\x2', 'o', '\x2', '\x3', '\x3', '\x2', '\x2', '\x2', '\x2', '\x5', - '\x3', '\x2', '\x2', '\x2', '\x2', '\a', '\x3', '\x2', '\x2', '\x2', '\x2', - '\t', '\x3', '\x2', '\x2', '\x2', '\x2', '\v', '\x3', '\x2', '\x2', '\x2', - '\x2', '\r', '\x3', '\x2', '\x2', '\x2', '\x2', '\xF', '\x3', '\x2', '\x2', - '\x2', '\x2', '\x11', '\x3', '\x2', '\x2', '\x2', '\x2', '\x13', '\x3', - '\x2', '\x2', '\x2', '\x2', '\x15', '\x3', '\x2', '\x2', '\x2', '\x2', - '\x17', '\x3', '\x2', '\x2', '\x2', '\x2', '%', '\x3', '\x2', '\x2', '\x2', - '\x3', '\'', '\x3', '\x2', '\x2', '\x2', '\x5', ')', '\x3', '\x2', '\x2', - '\x2', '\a', '+', '\x3', '\x2', '\x2', '\x2', '\t', '-', '\x3', '\x2', - '\x2', '\x2', '\v', '/', '\x3', '\x2', '\x2', '\x2', '\r', '\x31', '\x3', - '\x2', '\x2', '\x2', '\xF', '\x33', '\x3', '\x2', '\x2', '\x2', '\x11', - '\x35', '\x3', '\x2', '\x2', '\x2', '\x13', '\x37', '\x3', '\x2', '\x2', - '\x2', '\x15', '\x39', '\x3', '\x2', '\x2', '\x2', '\x17', '@', '\x3', - '\x2', '\x2', '\x2', '\x19', 'M', '\x3', '\x2', '\x2', '\x2', '\x1B', - 'Q', '\x3', '\x2', '\x2', '\x2', '\x1D', 'T', '\x3', '\x2', '\x2', '\x2', - '\x1F', '`', '\x3', '\x2', '\x2', '\x2', '!', '\x62', '\x3', '\x2', '\x2', - '\x2', '#', '\x64', '\x3', '\x2', '\x2', '\x2', '%', 'g', '\x3', '\x2', - '\x2', '\x2', '\'', '(', '\a', '*', '\x2', '\x2', '(', '\x4', '\x3', '\x2', - '\x2', '\x2', ')', '*', '\a', '+', '\x2', '\x2', '*', '\x6', '\x3', '\x2', - '\x2', '\x2', '+', ',', '\a', '-', '\x2', '\x2', ',', '\b', '\x3', '\x2', - '\x2', '\x2', '-', '.', '\a', '/', '\x2', '\x2', '.', '\n', '\x3', '\x2', - '\x2', '\x2', '/', '\x30', '\a', ',', '\x2', '\x2', '\x30', '\f', '\x3', - '\x2', '\x2', '\x2', '\x31', '\x32', '\a', '\x31', '\x2', '\x2', '\x32', - '\xE', '\x3', '\x2', '\x2', '\x2', '\x33', '\x34', '\a', '.', '\x2', '\x2', - '\x34', '\x10', '\x3', '\x2', '\x2', '\x2', '\x35', '\x36', '\a', '\x30', - '\x2', '\x2', '\x36', '\x12', '\x3', '\x2', '\x2', '\x2', '\x37', '\x38', - '\a', '`', '\x2', '\x2', '\x38', '\x14', '\x3', '\x2', '\x2', '\x2', '\x39', - '=', '\x5', '\x19', '\r', '\x2', ':', '<', '\x5', '\x1B', '\xE', '\x2', - ';', ':', '\x3', '\x2', '\x2', '\x2', '<', '?', '\x3', '\x2', '\x2', '\x2', - '=', ';', '\x3', '\x2', '\x2', '\x2', '=', '>', '\x3', '\x2', '\x2', '\x2', - '>', '\x16', '\x3', '\x2', '\x2', '\x2', '?', '=', '\x3', '\x2', '\x2', - '\x2', '@', 'J', '\x5', '\x1D', '\xF', '\x2', '\x41', '\x44', '\x5', '\x1F', - '\x10', '\x2', '\x42', '\x44', '\x5', '!', '\x11', '\x2', '\x43', '\x41', - '\x3', '\x2', '\x2', '\x2', '\x43', '\x42', '\x3', '\x2', '\x2', '\x2', - '\x44', '\x46', '\x3', '\x2', '\x2', '\x2', '\x45', 'G', '\x5', '#', '\x12', - '\x2', '\x46', '\x45', '\x3', '\x2', '\x2', '\x2', '\x46', 'G', '\x3', - '\x2', '\x2', '\x2', 'G', 'H', '\x3', '\x2', '\x2', '\x2', 'H', 'I', '\x5', - '\x1D', '\xF', '\x2', 'I', 'K', '\x3', '\x2', '\x2', '\x2', 'J', '\x43', - '\x3', '\x2', '\x2', '\x2', 'J', 'K', '\x3', '\x2', '\x2', '\x2', 'K', - '\x18', '\x3', '\x2', '\x2', '\x2', 'L', 'N', '\t', '\x2', '\x2', '\x2', - 'M', 'L', '\x3', '\x2', '\x2', '\x2', 'N', '\x1A', '\x3', '\x2', '\x2', - '\x2', 'O', 'R', '\x5', '\x19', '\r', '\x2', 'P', 'R', '\x4', '\x32', - ';', '\x2', 'Q', 'O', '\x3', '\x2', '\x2', '\x2', 'Q', 'P', '\x3', '\x2', - '\x2', '\x2', 'R', '\x1C', '\x3', '\x2', '\x2', '\x2', 'S', 'U', '\x4', - '\x32', ';', '\x2', 'T', 'S', '\x3', '\x2', '\x2', '\x2', 'U', 'V', '\x3', - '\x2', '\x2', '\x2', 'V', 'T', '\x3', '\x2', '\x2', '\x2', 'V', 'W', '\x3', - '\x2', '\x2', '\x2', 'W', '^', '\x3', '\x2', '\x2', '\x2', 'X', 'Z', '\a', - '\x30', '\x2', '\x2', 'Y', '[', '\x4', '\x32', ';', '\x2', 'Z', 'Y', '\x3', - '\x2', '\x2', '\x2', '[', '\\', '\x3', '\x2', '\x2', '\x2', '\\', 'Z', - '\x3', '\x2', '\x2', '\x2', '\\', ']', '\x3', '\x2', '\x2', '\x2', ']', - '_', '\x3', '\x2', '\x2', '\x2', '^', 'X', '\x3', '\x2', '\x2', '\x2', - '^', '_', '\x3', '\x2', '\x2', '\x2', '_', '\x1E', '\x3', '\x2', '\x2', - '\x2', '`', '\x61', '\a', 'G', '\x2', '\x2', '\x61', ' ', '\x3', '\x2', - '\x2', '\x2', '\x62', '\x63', '\a', 'g', '\x2', '\x2', '\x63', '\"', '\x3', - '\x2', '\x2', '\x2', '\x64', '\x65', '\t', '\x3', '\x2', '\x2', '\x65', - '$', '\x3', '\x2', '\x2', '\x2', '\x66', 'h', '\t', '\x4', '\x2', '\x2', - 'g', '\x66', '\x3', '\x2', '\x2', '\x2', 'h', 'i', '\x3', '\x2', '\x2', - '\x2', 'i', 'g', '\x3', '\x2', '\x2', '\x2', 'i', 'j', '\x3', '\x2', '\x2', - '\x2', 'j', 'k', '\x3', '\x2', '\x2', '\x2', 'k', 'l', '\b', '\x13', '\x2', - '\x2', 'l', '&', '\x3', '\x2', '\x2', '\x2', '\r', '\x2', '=', '\x43', - '\x46', 'J', 'M', 'Q', 'V', '\\', '^', 'i', '\x3', '\b', '\x2', '\x2', + '\x13', '\x4', '\x14', '\t', '\x14', '\x4', '\x15', '\t', '\x15', '\x4', + '\x16', '\t', '\x16', '\x4', '\x17', '\t', '\x17', '\x4', '\x18', '\t', + '\x18', '\x4', '\x19', '\t', '\x19', '\x4', '\x1A', '\t', '\x1A', '\x4', + '\x1B', '\t', '\x1B', '\x4', '\x1C', '\t', '\x1C', '\x3', '\x2', '\x3', + '\x2', '\x3', '\x3', '\x3', '\x3', '\x3', '\x4', '\x3', '\x4', '\x3', + '\x5', '\x3', '\x5', '\x3', '\x6', '\x3', '\x6', '\x3', '\a', '\x3', '\a', + '\x3', '\b', '\x3', '\b', '\x3', '\t', '\x3', '\t', '\x3', '\n', '\x3', + '\n', '\x3', '\v', '\x3', '\v', '\a', '\v', 'N', '\n', '\v', '\f', '\v', + '\xE', '\v', 'Q', '\v', '\v', '\x3', '\f', '\x5', '\f', 'T', '\n', '\f', + '\x3', '\f', '\x3', '\f', '\x3', '\r', '\x3', '\r', '\x3', '\r', '\x3', + '\xE', '\x3', '\xE', '\x5', '\xE', ']', '\n', '\xE', '\x3', '\xE', '\x3', + '\xE', '\x3', '\xF', '\x3', '\xF', '\x3', '\xF', '\x5', '\xF', '\x64', + '\n', '\xF', '\x3', '\xF', '\x5', '\xF', 'g', '\n', '\xF', '\x3', '\xF', + '\x3', '\xF', '\x3', '\x10', '\x5', '\x10', 'l', '\n', '\x10', '\x3', + '\x11', '\x3', '\x11', '\x5', '\x11', 'p', '\n', '\x11', '\x3', '\x12', + '\x3', '\x12', '\x3', '\x12', '\x3', '\x13', '\x6', '\x13', 'v', '\n', + '\x13', '\r', '\x13', '\xE', '\x13', 'w', '\x3', '\x13', '\x3', '\x13', + '\x6', '\x13', '|', '\n', '\x13', '\r', '\x13', '\xE', '\x13', '}', '\x5', + '\x13', '\x80', '\n', '\x13', '\x3', '\x14', '\x3', '\x14', '\x3', '\x14', + '\x3', '\x15', '\x6', '\x15', '\x86', '\n', '\x15', '\r', '\x15', '\xE', + '\x15', '\x87', '\x3', '\x16', '\x3', '\x16', '\x3', '\x16', '\x3', '\x17', + '\x3', '\x17', '\x3', '\x18', '\x6', '\x18', '\x90', '\n', '\x18', '\r', + '\x18', '\xE', '\x18', '\x91', '\x3', '\x19', '\x3', '\x19', '\x3', '\x1A', + '\x3', '\x1A', '\x3', '\x1B', '\x3', '\x1B', '\x3', '\x1C', '\x6', '\x1C', + '\x9B', '\n', '\x1C', '\r', '\x1C', '\xE', '\x1C', '\x9C', '\x3', '\x1C', + '\x3', '\x1C', '\x2', '\x2', '\x1D', '\x3', '\x3', '\x5', '\x4', '\a', + '\x5', '\t', '\x6', '\v', '\a', '\r', '\b', '\xF', '\t', '\x11', '\n', + '\x13', '\v', '\x15', '\f', '\x17', '\r', '\x19', '\xE', '\x1B', '\xF', + '\x1D', '\x10', '\x1F', '\x2', '!', '\x2', '#', '\x2', '%', '\x2', '\'', + '\x2', ')', '\x2', '+', '\x2', '-', '\x2', '/', '\x2', '\x31', '\x2', + '\x33', '\x2', '\x35', '\x2', '\x37', '\x11', '\x3', '\x2', '\t', '\x5', + '\x2', '\x43', '\\', '\x61', '\x61', '\x63', '|', '\x4', '\x2', '\x46', + '\x46', '\x66', '\x66', '\x4', '\x2', '\x44', '\x44', '\x64', '\x64', + '\x4', '\x2', 'Z', 'Z', 'z', 'z', '\x5', '\x2', '\x32', ';', '\x43', 'H', + '\x63', 'h', '\x4', '\x2', '-', '-', '/', '/', '\x5', '\x2', '\v', '\f', + '\xF', '\xF', '\"', '\"', '\x2', '\x9F', '\x2', '\x3', '\x3', '\x2', '\x2', + '\x2', '\x2', '\x5', '\x3', '\x2', '\x2', '\x2', '\x2', '\a', '\x3', '\x2', + '\x2', '\x2', '\x2', '\t', '\x3', '\x2', '\x2', '\x2', '\x2', '\v', '\x3', + '\x2', '\x2', '\x2', '\x2', '\r', '\x3', '\x2', '\x2', '\x2', '\x2', '\xF', + '\x3', '\x2', '\x2', '\x2', '\x2', '\x11', '\x3', '\x2', '\x2', '\x2', + '\x2', '\x13', '\x3', '\x2', '\x2', '\x2', '\x2', '\x15', '\x3', '\x2', + '\x2', '\x2', '\x2', '\x17', '\x3', '\x2', '\x2', '\x2', '\x2', '\x19', + '\x3', '\x2', '\x2', '\x2', '\x2', '\x1B', '\x3', '\x2', '\x2', '\x2', + '\x2', '\x1D', '\x3', '\x2', '\x2', '\x2', '\x2', '\x37', '\x3', '\x2', + '\x2', '\x2', '\x3', '\x39', '\x3', '\x2', '\x2', '\x2', '\x5', ';', '\x3', + '\x2', '\x2', '\x2', '\a', '=', '\x3', '\x2', '\x2', '\x2', '\t', '?', + '\x3', '\x2', '\x2', '\x2', '\v', '\x41', '\x3', '\x2', '\x2', '\x2', + '\r', '\x43', '\x3', '\x2', '\x2', '\x2', '\xF', '\x45', '\x3', '\x2', + '\x2', '\x2', '\x11', 'G', '\x3', '\x2', '\x2', '\x2', '\x13', 'I', '\x3', + '\x2', '\x2', '\x2', '\x15', 'K', '\x3', '\x2', '\x2', '\x2', '\x17', + 'S', '\x3', '\x2', '\x2', '\x2', '\x19', 'W', '\x3', '\x2', '\x2', '\x2', + '\x1B', '\\', '\x3', '\x2', '\x2', '\x2', '\x1D', '`', '\x3', '\x2', '\x2', + '\x2', '\x1F', 'k', '\x3', '\x2', '\x2', '\x2', '!', 'o', '\x3', '\x2', + '\x2', '\x2', '#', 'q', '\x3', '\x2', '\x2', '\x2', '%', 'u', '\x3', '\x2', + '\x2', '\x2', '\'', '\x81', '\x3', '\x2', '\x2', '\x2', ')', '\x85', '\x3', + '\x2', '\x2', '\x2', '+', '\x89', '\x3', '\x2', '\x2', '\x2', '-', '\x8C', + '\x3', '\x2', '\x2', '\x2', '/', '\x8F', '\x3', '\x2', '\x2', '\x2', '\x31', + '\x93', '\x3', '\x2', '\x2', '\x2', '\x33', '\x95', '\x3', '\x2', '\x2', + '\x2', '\x35', '\x97', '\x3', '\x2', '\x2', '\x2', '\x37', '\x9A', '\x3', + '\x2', '\x2', '\x2', '\x39', ':', '\a', '*', '\x2', '\x2', ':', '\x4', + '\x3', '\x2', '\x2', '\x2', ';', '<', '\a', '+', '\x2', '\x2', '<', '\x6', + '\x3', '\x2', '\x2', '\x2', '=', '>', '\a', '-', '\x2', '\x2', '>', '\b', + '\x3', '\x2', '\x2', '\x2', '?', '@', '\a', '/', '\x2', '\x2', '@', '\n', + '\x3', '\x2', '\x2', '\x2', '\x41', '\x42', '\a', ',', '\x2', '\x2', '\x42', + '\f', '\x3', '\x2', '\x2', '\x2', '\x43', '\x44', '\a', '\x31', '\x2', + '\x2', '\x44', '\xE', '\x3', '\x2', '\x2', '\x2', '\x45', '\x46', '\a', + '.', '\x2', '\x2', '\x46', '\x10', '\x3', '\x2', '\x2', '\x2', 'G', 'H', + '\a', '\x30', '\x2', '\x2', 'H', '\x12', '\x3', '\x2', '\x2', '\x2', 'I', + 'J', '\a', '`', '\x2', '\x2', 'J', '\x14', '\x3', '\x2', '\x2', '\x2', + 'K', 'O', '\x5', '\x1F', '\x10', '\x2', 'L', 'N', '\x5', '!', '\x11', + '\x2', 'M', 'L', '\x3', '\x2', '\x2', '\x2', 'N', 'Q', '\x3', '\x2', '\x2', + '\x2', 'O', 'M', '\x3', '\x2', '\x2', '\x2', 'O', 'P', '\x3', '\x2', '\x2', + '\x2', 'P', '\x16', '\x3', '\x2', '\x2', '\x2', 'Q', 'O', '\x3', '\x2', + '\x2', '\x2', 'R', 'T', '\x5', '#', '\x12', '\x2', 'S', 'R', '\x3', '\x2', + '\x2', '\x2', 'S', 'T', '\x3', '\x2', '\x2', '\x2', 'T', 'U', '\x3', '\x2', + '\x2', '\x2', 'U', 'V', '\x5', '%', '\x13', '\x2', 'V', '\x18', '\x3', + '\x2', '\x2', '\x2', 'W', 'X', '\x5', '\'', '\x14', '\x2', 'X', 'Y', '\x5', + ')', '\x15', '\x2', 'Y', '\x1A', '\x3', '\x2', '\x2', '\x2', 'Z', ']', + '\x5', '+', '\x16', '\x2', '[', ']', '\x5', '-', '\x17', '\x2', '\\', + 'Z', '\x3', '\x2', '\x2', '\x2', '\\', '[', '\x3', '\x2', '\x2', '\x2', + ']', '^', '\x3', '\x2', '\x2', '\x2', '^', '_', '\x5', '/', '\x18', '\x2', + '_', '\x1C', '\x3', '\x2', '\x2', '\x2', '`', '\x63', '\x5', '%', '\x13', + '\x2', '\x61', '\x64', '\x5', '\x31', '\x19', '\x2', '\x62', '\x64', '\x5', + '\x33', '\x1A', '\x2', '\x63', '\x61', '\x3', '\x2', '\x2', '\x2', '\x63', + '\x62', '\x3', '\x2', '\x2', '\x2', '\x64', '\x66', '\x3', '\x2', '\x2', + '\x2', '\x65', 'g', '\x5', '\x35', '\x1B', '\x2', '\x66', '\x65', '\x3', + '\x2', '\x2', '\x2', '\x66', 'g', '\x3', '\x2', '\x2', '\x2', 'g', 'h', + '\x3', '\x2', '\x2', '\x2', 'h', 'i', '\x5', '%', '\x13', '\x2', 'i', + '\x1E', '\x3', '\x2', '\x2', '\x2', 'j', 'l', '\t', '\x2', '\x2', '\x2', + 'k', 'j', '\x3', '\x2', '\x2', '\x2', 'l', ' ', '\x3', '\x2', '\x2', '\x2', + 'm', 'p', '\x5', '\x1F', '\x10', '\x2', 'n', 'p', '\x4', '\x32', ';', + '\x2', 'o', 'm', '\x3', '\x2', '\x2', '\x2', 'o', 'n', '\x3', '\x2', '\x2', + '\x2', 'p', '\"', '\x3', '\x2', '\x2', '\x2', 'q', 'r', '\a', '\x32', + '\x2', '\x2', 'r', 's', '\t', '\x3', '\x2', '\x2', 's', '$', '\x3', '\x2', + '\x2', '\x2', 't', 'v', '\x4', '\x32', ';', '\x2', 'u', 't', '\x3', '\x2', + '\x2', '\x2', 'v', 'w', '\x3', '\x2', '\x2', '\x2', 'w', 'u', '\x3', '\x2', + '\x2', '\x2', 'w', 'x', '\x3', '\x2', '\x2', '\x2', 'x', '\x7F', '\x3', + '\x2', '\x2', '\x2', 'y', '{', '\a', '\x30', '\x2', '\x2', 'z', '|', '\x4', + '\x32', ';', '\x2', '{', 'z', '\x3', '\x2', '\x2', '\x2', '|', '}', '\x3', + '\x2', '\x2', '\x2', '}', '{', '\x3', '\x2', '\x2', '\x2', '}', '~', '\x3', + '\x2', '\x2', '\x2', '~', '\x80', '\x3', '\x2', '\x2', '\x2', '\x7F', + 'y', '\x3', '\x2', '\x2', '\x2', '\x7F', '\x80', '\x3', '\x2', '\x2', + '\x2', '\x80', '&', '\x3', '\x2', '\x2', '\x2', '\x81', '\x82', '\a', + '\x32', '\x2', '\x2', '\x82', '\x83', '\t', '\x4', '\x2', '\x2', '\x83', + '(', '\x3', '\x2', '\x2', '\x2', '\x84', '\x86', '\x4', '\x32', '\x33', + '\x2', '\x85', '\x84', '\x3', '\x2', '\x2', '\x2', '\x86', '\x87', '\x3', + '\x2', '\x2', '\x2', '\x87', '\x85', '\x3', '\x2', '\x2', '\x2', '\x87', + '\x88', '\x3', '\x2', '\x2', '\x2', '\x88', '*', '\x3', '\x2', '\x2', + '\x2', '\x89', '\x8A', '\a', '\x32', '\x2', '\x2', '\x8A', '\x8B', '\t', + '\x5', '\x2', '\x2', '\x8B', ',', '\x3', '\x2', '\x2', '\x2', '\x8C', + '\x8D', '\a', '%', '\x2', '\x2', '\x8D', '.', '\x3', '\x2', '\x2', '\x2', + '\x8E', '\x90', '\t', '\x6', '\x2', '\x2', '\x8F', '\x8E', '\x3', '\x2', + '\x2', '\x2', '\x90', '\x91', '\x3', '\x2', '\x2', '\x2', '\x91', '\x8F', + '\x3', '\x2', '\x2', '\x2', '\x91', '\x92', '\x3', '\x2', '\x2', '\x2', + '\x92', '\x30', '\x3', '\x2', '\x2', '\x2', '\x93', '\x94', '\a', 'G', + '\x2', '\x2', '\x94', '\x32', '\x3', '\x2', '\x2', '\x2', '\x95', '\x96', + '\a', 'g', '\x2', '\x2', '\x96', '\x34', '\x3', '\x2', '\x2', '\x2', '\x97', + '\x98', '\t', '\a', '\x2', '\x2', '\x98', '\x36', '\x3', '\x2', '\x2', + '\x2', '\x99', '\x9B', '\t', '\b', '\x2', '\x2', '\x9A', '\x99', '\x3', + '\x2', '\x2', '\x2', '\x9B', '\x9C', '\x3', '\x2', '\x2', '\x2', '\x9C', + '\x9A', '\x3', '\x2', '\x2', '\x2', '\x9C', '\x9D', '\x3', '\x2', '\x2', + '\x2', '\x9D', '\x9E', '\x3', '\x2', '\x2', '\x2', '\x9E', '\x9F', '\b', + '\x1C', '\x2', '\x2', '\x9F', '\x38', '\x3', '\x2', '\x2', '\x2', '\x11', + '\x2', 'O', 'S', '\\', '\x63', '\x66', 'k', 'o', 'w', '}', '\x7F', '\x87', + '\x8F', '\x91', '\x9C', '\x3', '\b', '\x2', '\x2', }; public static readonly ATN _ATN = diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.interp b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.interp index c636130..69e18b5 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.interp +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.interp @@ -12,6 +12,9 @@ null null null null +null +null +null token symbolic names: null @@ -25,6 +28,9 @@ COMMA POINT POW IDENTIFIER +DECIMAL_NUMBER +BINARY_NUMBER +HEXADECIMAL_NUMBER SCIENTIFIC_NUMBER WS @@ -39,10 +45,19 @@ COMMA POINT POW IDENTIFIER +DECIMAL_NUMBER +BINARY_NUMBER +HEXADECIMAL_NUMBER SCIENTIFIC_NUMBER VALID_ID_START VALID_ID_CHAR -NUMBER +PREFIX_DEC +NUMBER_DEC +PREFIX_BIN +NUMBER_BIN +PREFIX_HEX +NUMBER_HEX2 +NUMBER_HEX E1 E2 SIGN @@ -56,4 +71,4 @@ mode names: DEFAULT_MODE atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 14, 109, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 7, 11, 60, 10, 11, 12, 11, 14, 11, 63, 11, 11, 3, 12, 3, 12, 3, 12, 5, 12, 68, 10, 12, 3, 12, 5, 12, 71, 10, 12, 3, 12, 3, 12, 5, 12, 75, 10, 12, 3, 13, 5, 13, 78, 10, 13, 3, 14, 3, 14, 5, 14, 82, 10, 14, 3, 15, 6, 15, 85, 10, 15, 13, 15, 14, 15, 86, 3, 15, 3, 15, 6, 15, 91, 10, 15, 13, 15, 14, 15, 92, 5, 15, 95, 10, 15, 3, 16, 3, 16, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 6, 19, 104, 10, 19, 13, 19, 14, 19, 105, 3, 19, 3, 19, 2, 2, 20, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 2, 27, 2, 29, 2, 31, 2, 33, 2, 35, 2, 37, 14, 3, 2, 5, 5, 2, 67, 92, 97, 97, 99, 124, 4, 2, 45, 45, 47, 47, 5, 2, 11, 12, 15, 15, 34, 34, 2, 111, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 3, 39, 3, 2, 2, 2, 5, 41, 3, 2, 2, 2, 7, 43, 3, 2, 2, 2, 9, 45, 3, 2, 2, 2, 11, 47, 3, 2, 2, 2, 13, 49, 3, 2, 2, 2, 15, 51, 3, 2, 2, 2, 17, 53, 3, 2, 2, 2, 19, 55, 3, 2, 2, 2, 21, 57, 3, 2, 2, 2, 23, 64, 3, 2, 2, 2, 25, 77, 3, 2, 2, 2, 27, 81, 3, 2, 2, 2, 29, 84, 3, 2, 2, 2, 31, 96, 3, 2, 2, 2, 33, 98, 3, 2, 2, 2, 35, 100, 3, 2, 2, 2, 37, 103, 3, 2, 2, 2, 39, 40, 7, 42, 2, 2, 40, 4, 3, 2, 2, 2, 41, 42, 7, 43, 2, 2, 42, 6, 3, 2, 2, 2, 43, 44, 7, 45, 2, 2, 44, 8, 3, 2, 2, 2, 45, 46, 7, 47, 2, 2, 46, 10, 3, 2, 2, 2, 47, 48, 7, 44, 2, 2, 48, 12, 3, 2, 2, 2, 49, 50, 7, 49, 2, 2, 50, 14, 3, 2, 2, 2, 51, 52, 7, 46, 2, 2, 52, 16, 3, 2, 2, 2, 53, 54, 7, 48, 2, 2, 54, 18, 3, 2, 2, 2, 55, 56, 7, 96, 2, 2, 56, 20, 3, 2, 2, 2, 57, 61, 5, 25, 13, 2, 58, 60, 5, 27, 14, 2, 59, 58, 3, 2, 2, 2, 60, 63, 3, 2, 2, 2, 61, 59, 3, 2, 2, 2, 61, 62, 3, 2, 2, 2, 62, 22, 3, 2, 2, 2, 63, 61, 3, 2, 2, 2, 64, 74, 5, 29, 15, 2, 65, 68, 5, 31, 16, 2, 66, 68, 5, 33, 17, 2, 67, 65, 3, 2, 2, 2, 67, 66, 3, 2, 2, 2, 68, 70, 3, 2, 2, 2, 69, 71, 5, 35, 18, 2, 70, 69, 3, 2, 2, 2, 70, 71, 3, 2, 2, 2, 71, 72, 3, 2, 2, 2, 72, 73, 5, 29, 15, 2, 73, 75, 3, 2, 2, 2, 74, 67, 3, 2, 2, 2, 74, 75, 3, 2, 2, 2, 75, 24, 3, 2, 2, 2, 76, 78, 9, 2, 2, 2, 77, 76, 3, 2, 2, 2, 78, 26, 3, 2, 2, 2, 79, 82, 5, 25, 13, 2, 80, 82, 4, 50, 59, 2, 81, 79, 3, 2, 2, 2, 81, 80, 3, 2, 2, 2, 82, 28, 3, 2, 2, 2, 83, 85, 4, 50, 59, 2, 84, 83, 3, 2, 2, 2, 85, 86, 3, 2, 2, 2, 86, 84, 3, 2, 2, 2, 86, 87, 3, 2, 2, 2, 87, 94, 3, 2, 2, 2, 88, 90, 7, 48, 2, 2, 89, 91, 4, 50, 59, 2, 90, 89, 3, 2, 2, 2, 91, 92, 3, 2, 2, 2, 92, 90, 3, 2, 2, 2, 92, 93, 3, 2, 2, 2, 93, 95, 3, 2, 2, 2, 94, 88, 3, 2, 2, 2, 94, 95, 3, 2, 2, 2, 95, 30, 3, 2, 2, 2, 96, 97, 7, 71, 2, 2, 97, 32, 3, 2, 2, 2, 98, 99, 7, 103, 2, 2, 99, 34, 3, 2, 2, 2, 100, 101, 9, 3, 2, 2, 101, 36, 3, 2, 2, 2, 102, 104, 9, 4, 2, 2, 103, 102, 3, 2, 2, 2, 104, 105, 3, 2, 2, 2, 105, 103, 3, 2, 2, 2, 105, 106, 3, 2, 2, 2, 106, 107, 3, 2, 2, 2, 107, 108, 8, 19, 2, 2, 108, 38, 3, 2, 2, 2, 13, 2, 61, 67, 70, 74, 77, 81, 86, 92, 94, 105, 3, 8, 2, 2] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 17, 160, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 7, 11, 78, 10, 11, 12, 11, 14, 11, 81, 11, 11, 3, 12, 5, 12, 84, 10, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 5, 14, 93, 10, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 5, 15, 100, 10, 15, 3, 15, 5, 15, 103, 10, 15, 3, 15, 3, 15, 3, 16, 5, 16, 108, 10, 16, 3, 17, 3, 17, 5, 17, 112, 10, 17, 3, 18, 3, 18, 3, 18, 3, 19, 6, 19, 118, 10, 19, 13, 19, 14, 19, 119, 3, 19, 3, 19, 6, 19, 124, 10, 19, 13, 19, 14, 19, 125, 5, 19, 128, 10, 19, 3, 20, 3, 20, 3, 20, 3, 21, 6, 21, 134, 10, 21, 13, 21, 14, 21, 135, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 6, 24, 144, 10, 24, 13, 24, 14, 24, 145, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 28, 6, 28, 155, 10, 28, 13, 28, 14, 28, 156, 3, 28, 3, 28, 2, 2, 29, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 2, 33, 2, 35, 2, 37, 2, 39, 2, 41, 2, 43, 2, 45, 2, 47, 2, 49, 2, 51, 2, 53, 2, 55, 17, 3, 2, 9, 5, 2, 67, 92, 97, 97, 99, 124, 4, 2, 70, 70, 102, 102, 4, 2, 68, 68, 100, 100, 4, 2, 90, 90, 122, 122, 5, 2, 50, 59, 67, 72, 99, 104, 4, 2, 45, 45, 47, 47, 5, 2, 11, 12, 15, 15, 34, 34, 2, 159, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 3, 57, 3, 2, 2, 2, 5, 59, 3, 2, 2, 2, 7, 61, 3, 2, 2, 2, 9, 63, 3, 2, 2, 2, 11, 65, 3, 2, 2, 2, 13, 67, 3, 2, 2, 2, 15, 69, 3, 2, 2, 2, 17, 71, 3, 2, 2, 2, 19, 73, 3, 2, 2, 2, 21, 75, 3, 2, 2, 2, 23, 83, 3, 2, 2, 2, 25, 87, 3, 2, 2, 2, 27, 92, 3, 2, 2, 2, 29, 96, 3, 2, 2, 2, 31, 107, 3, 2, 2, 2, 33, 111, 3, 2, 2, 2, 35, 113, 3, 2, 2, 2, 37, 117, 3, 2, 2, 2, 39, 129, 3, 2, 2, 2, 41, 133, 3, 2, 2, 2, 43, 137, 3, 2, 2, 2, 45, 140, 3, 2, 2, 2, 47, 143, 3, 2, 2, 2, 49, 147, 3, 2, 2, 2, 51, 149, 3, 2, 2, 2, 53, 151, 3, 2, 2, 2, 55, 154, 3, 2, 2, 2, 57, 58, 7, 42, 2, 2, 58, 4, 3, 2, 2, 2, 59, 60, 7, 43, 2, 2, 60, 6, 3, 2, 2, 2, 61, 62, 7, 45, 2, 2, 62, 8, 3, 2, 2, 2, 63, 64, 7, 47, 2, 2, 64, 10, 3, 2, 2, 2, 65, 66, 7, 44, 2, 2, 66, 12, 3, 2, 2, 2, 67, 68, 7, 49, 2, 2, 68, 14, 3, 2, 2, 2, 69, 70, 7, 46, 2, 2, 70, 16, 3, 2, 2, 2, 71, 72, 7, 48, 2, 2, 72, 18, 3, 2, 2, 2, 73, 74, 7, 96, 2, 2, 74, 20, 3, 2, 2, 2, 75, 79, 5, 31, 16, 2, 76, 78, 5, 33, 17, 2, 77, 76, 3, 2, 2, 2, 78, 81, 3, 2, 2, 2, 79, 77, 3, 2, 2, 2, 79, 80, 3, 2, 2, 2, 80, 22, 3, 2, 2, 2, 81, 79, 3, 2, 2, 2, 82, 84, 5, 35, 18, 2, 83, 82, 3, 2, 2, 2, 83, 84, 3, 2, 2, 2, 84, 85, 3, 2, 2, 2, 85, 86, 5, 37, 19, 2, 86, 24, 3, 2, 2, 2, 87, 88, 5, 39, 20, 2, 88, 89, 5, 41, 21, 2, 89, 26, 3, 2, 2, 2, 90, 93, 5, 43, 22, 2, 91, 93, 5, 45, 23, 2, 92, 90, 3, 2, 2, 2, 92, 91, 3, 2, 2, 2, 93, 94, 3, 2, 2, 2, 94, 95, 5, 47, 24, 2, 95, 28, 3, 2, 2, 2, 96, 99, 5, 37, 19, 2, 97, 100, 5, 49, 25, 2, 98, 100, 5, 51, 26, 2, 99, 97, 3, 2, 2, 2, 99, 98, 3, 2, 2, 2, 100, 102, 3, 2, 2, 2, 101, 103, 5, 53, 27, 2, 102, 101, 3, 2, 2, 2, 102, 103, 3, 2, 2, 2, 103, 104, 3, 2, 2, 2, 104, 105, 5, 37, 19, 2, 105, 30, 3, 2, 2, 2, 106, 108, 9, 2, 2, 2, 107, 106, 3, 2, 2, 2, 108, 32, 3, 2, 2, 2, 109, 112, 5, 31, 16, 2, 110, 112, 4, 50, 59, 2, 111, 109, 3, 2, 2, 2, 111, 110, 3, 2, 2, 2, 112, 34, 3, 2, 2, 2, 113, 114, 7, 50, 2, 2, 114, 115, 9, 3, 2, 2, 115, 36, 3, 2, 2, 2, 116, 118, 4, 50, 59, 2, 117, 116, 3, 2, 2, 2, 118, 119, 3, 2, 2, 2, 119, 117, 3, 2, 2, 2, 119, 120, 3, 2, 2, 2, 120, 127, 3, 2, 2, 2, 121, 123, 7, 48, 2, 2, 122, 124, 4, 50, 59, 2, 123, 122, 3, 2, 2, 2, 124, 125, 3, 2, 2, 2, 125, 123, 3, 2, 2, 2, 125, 126, 3, 2, 2, 2, 126, 128, 3, 2, 2, 2, 127, 121, 3, 2, 2, 2, 127, 128, 3, 2, 2, 2, 128, 38, 3, 2, 2, 2, 129, 130, 7, 50, 2, 2, 130, 131, 9, 4, 2, 2, 131, 40, 3, 2, 2, 2, 132, 134, 4, 50, 51, 2, 133, 132, 3, 2, 2, 2, 134, 135, 3, 2, 2, 2, 135, 133, 3, 2, 2, 2, 135, 136, 3, 2, 2, 2, 136, 42, 3, 2, 2, 2, 137, 138, 7, 50, 2, 2, 138, 139, 9, 5, 2, 2, 139, 44, 3, 2, 2, 2, 140, 141, 7, 37, 2, 2, 141, 46, 3, 2, 2, 2, 142, 144, 9, 6, 2, 2, 143, 142, 3, 2, 2, 2, 144, 145, 3, 2, 2, 2, 145, 143, 3, 2, 2, 2, 145, 146, 3, 2, 2, 2, 146, 48, 3, 2, 2, 2, 147, 148, 7, 71, 2, 2, 148, 50, 3, 2, 2, 2, 149, 150, 7, 103, 2, 2, 150, 52, 3, 2, 2, 2, 151, 152, 9, 7, 2, 2, 152, 54, 3, 2, 2, 2, 153, 155, 9, 8, 2, 2, 154, 153, 3, 2, 2, 2, 155, 156, 3, 2, 2, 2, 156, 154, 3, 2, 2, 2, 156, 157, 3, 2, 2, 2, 157, 158, 3, 2, 2, 2, 158, 159, 8, 28, 2, 2, 159, 56, 3, 2, 2, 2, 17, 2, 79, 83, 92, 99, 102, 107, 111, 119, 125, 127, 135, 143, 145, 156, 3, 8, 2, 2] \ No newline at end of file diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.tokens b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.tokens index 83a628c..a954a79 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.tokens +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.tokens @@ -8,8 +8,11 @@ COMMA=7 POINT=8 POW=9 IDENTIFIER=10 -SCIENTIFIC_NUMBER=11 -WS=12 +DECIMAL_NUMBER=11 +BINARY_NUMBER=12 +HEXADECIMAL_NUMBER=13 +SCIENTIFIC_NUMBER=14 +WS=15 '('=1 ')'=2 '+'=3 diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerListener.cs b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerListener.cs index 0b0ceb3..2e377e4 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerListener.cs +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerListener.cs @@ -130,17 +130,53 @@ public interface IFormulaGrammerListener : IParseTreeListener { void ExitAtom([NotNull] FormulaGrammerParser.AtomContext context); /// /// Enter a parse tree produced by the ScientificNumber - /// labeled alternative in . + /// labeled alternative in . /// /// The parse tree. void EnterScientificNumber([NotNull] FormulaGrammerParser.ScientificNumberContext context); /// /// Exit a parse tree produced by the ScientificNumber - /// labeled alternative in . + /// labeled alternative in . /// /// The parse tree. void ExitScientificNumber([NotNull] FormulaGrammerParser.ScientificNumberContext context); /// + /// Enter a parse tree produced by the DecimalNumber + /// labeled alternative in . + /// + /// The parse tree. + void EnterDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context); + /// + /// Exit a parse tree produced by the DecimalNumber + /// labeled alternative in . + /// + /// The parse tree. + void ExitDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context); + /// + /// Enter a parse tree produced by the BinaryNumber + /// labeled alternative in . + /// + /// The parse tree. + void EnterBinaryNumber([NotNull] FormulaGrammerParser.BinaryNumberContext context); + /// + /// Exit a parse tree produced by the BinaryNumber + /// labeled alternative in . + /// + /// The parse tree. + void ExitBinaryNumber([NotNull] FormulaGrammerParser.BinaryNumberContext context); + /// + /// Enter a parse tree produced by the HexadecimalNumber + /// labeled alternative in . + /// + /// The parse tree. + void EnterHexadecimalNumber([NotNull] FormulaGrammerParser.HexadecimalNumberContext context); + /// + /// Exit a parse tree produced by the HexadecimalNumber + /// labeled alternative in . + /// + /// The parse tree. + void ExitHexadecimalNumber([NotNull] FormulaGrammerParser.HexadecimalNumberContext context); + /// /// Enter a parse tree produced by . /// /// The parse tree. diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerParser.cs b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerParser.cs index 05fe37c..579a20d 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerParser.cs +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerParser.cs @@ -37,14 +37,15 @@ public partial class FormulaGrammerParser : Parser { protected static PredictionContextCache sharedContextCache = new PredictionContextCache(); public const int LPAREN=1, RPAREN=2, PLUS=3, MINUS=4, TIMES=5, DIV=6, COMMA=7, POINT=8, - POW=9, IDENTIFIER=10, SCIENTIFIC_NUMBER=11, WS=12; + POW=9, IDENTIFIER=10, DECIMAL_NUMBER=11, BINARY_NUMBER=12, HEXADECIMAL_NUMBER=13, + SCIENTIFIC_NUMBER=14, WS=15; public const int RULE_formula = 0, RULE_expression = 1, RULE_multiplyingExpression = 2, - RULE_powExpression = 3, RULE_signedAtom = 4, RULE_atom = 5, RULE_scientific = 6, + RULE_powExpression = 3, RULE_signedAtom = 4, RULE_atom = 5, RULE_number = 6, RULE_func = 7, RULE_variable = 8; public static readonly string[] ruleNames = { "formula", "expression", "multiplyingExpression", "powExpression", "signedAtom", - "atom", "scientific", "func", "variable" + "atom", "number", "func", "variable" }; private static readonly string[] _LiteralNames = { @@ -52,7 +53,8 @@ public const int }; private static readonly string[] _SymbolicNames = { null, "LPAREN", "RPAREN", "PLUS", "MINUS", "TIMES", "DIV", "COMMA", "POINT", - "POW", "IDENTIFIER", "SCIENTIFIC_NUMBER", "WS" + "POW", "IDENTIFIER", "DECIMAL_NUMBER", "BINARY_NUMBER", "HEXADECIMAL_NUMBER", + "SCIENTIFIC_NUMBER", "WS" }; public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames); @@ -501,8 +503,8 @@ public SignedAtomContext signedAtom() { } public partial class AtomContext : ParserRuleContext { - public ScientificContext scientific() { - return GetRuleContext(0); + public NumberContext number() { + return GetRuleContext(0); } public VariableContext variable() { return GetRuleContext(0); @@ -540,10 +542,13 @@ public AtomContext atom() { State = 59; ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { + case DECIMAL_NUMBER: + case BINARY_NUMBER: + case HEXADECIMAL_NUMBER: case SCIENTIFIC_NUMBER: EnterOuterAlt(_localctx, 1); { - State = 53; scientific(); + State = 53; number(); } break; case IDENTIFIER: @@ -575,21 +580,55 @@ public AtomContext atom() { return _localctx; } - public partial class ScientificContext : ParserRuleContext { - public ScientificContext(ParserRuleContext parent, int invokingState) + public partial class NumberContext : ParserRuleContext { + public NumberContext(ParserRuleContext parent, int invokingState) : base(parent, invokingState) { } - public override int RuleIndex { get { return RULE_scientific; } } + public override int RuleIndex { get { return RULE_number; } } - public ScientificContext() { } - public virtual void CopyFrom(ScientificContext context) { + public NumberContext() { } + public virtual void CopyFrom(NumberContext context) { base.CopyFrom(context); } } - public partial class ScientificNumberContext : ScientificContext { + public partial class DecimalNumberContext : NumberContext { + public ITerminalNode DECIMAL_NUMBER() { return GetToken(FormulaGrammerParser.DECIMAL_NUMBER, 0); } + public DecimalNumberContext(NumberContext context) { CopyFrom(context); } + public override void EnterRule(IParseTreeListener listener) { + IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; + if (typedListener != null) typedListener.EnterDecimalNumber(this); + } + public override void ExitRule(IParseTreeListener listener) { + IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; + if (typedListener != null) typedListener.ExitDecimalNumber(this); + } + public override TResult Accept(IParseTreeVisitor visitor) { + IFormulaGrammerVisitor typedVisitor = visitor as IFormulaGrammerVisitor; + if (typedVisitor != null) return typedVisitor.VisitDecimalNumber(this); + else return visitor.VisitChildren(this); + } + } + public partial class BinaryNumberContext : NumberContext { + public ITerminalNode BINARY_NUMBER() { return GetToken(FormulaGrammerParser.BINARY_NUMBER, 0); } + public BinaryNumberContext(NumberContext context) { CopyFrom(context); } + public override void EnterRule(IParseTreeListener listener) { + IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; + if (typedListener != null) typedListener.EnterBinaryNumber(this); + } + public override void ExitRule(IParseTreeListener listener) { + IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; + if (typedListener != null) typedListener.ExitBinaryNumber(this); + } + public override TResult Accept(IParseTreeVisitor visitor) { + IFormulaGrammerVisitor typedVisitor = visitor as IFormulaGrammerVisitor; + if (typedVisitor != null) return typedVisitor.VisitBinaryNumber(this); + else return visitor.VisitChildren(this); + } + } + public partial class ScientificNumberContext : NumberContext { public ITerminalNode SCIENTIFIC_NUMBER() { return GetToken(FormulaGrammerParser.SCIENTIFIC_NUMBER, 0); } - public ScientificNumberContext(ScientificContext context) { CopyFrom(context); } + public ScientificNumberContext(NumberContext context) { CopyFrom(context); } public override void EnterRule(IParseTreeListener listener) { IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; if (typedListener != null) typedListener.EnterScientificNumber(this); @@ -604,16 +643,62 @@ public override TResult Accept(IParseTreeVisitor visitor) { else return visitor.VisitChildren(this); } } + public partial class HexadecimalNumberContext : NumberContext { + public ITerminalNode HEXADECIMAL_NUMBER() { return GetToken(FormulaGrammerParser.HEXADECIMAL_NUMBER, 0); } + public HexadecimalNumberContext(NumberContext context) { CopyFrom(context); } + public override void EnterRule(IParseTreeListener listener) { + IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; + if (typedListener != null) typedListener.EnterHexadecimalNumber(this); + } + public override void ExitRule(IParseTreeListener listener) { + IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; + if (typedListener != null) typedListener.ExitHexadecimalNumber(this); + } + public override TResult Accept(IParseTreeVisitor visitor) { + IFormulaGrammerVisitor typedVisitor = visitor as IFormulaGrammerVisitor; + if (typedVisitor != null) return typedVisitor.VisitHexadecimalNumber(this); + else return visitor.VisitChildren(this); + } + } [RuleVersion(0)] - public ScientificContext scientific() { - ScientificContext _localctx = new ScientificContext(Context, State); - EnterRule(_localctx, 12, RULE_scientific); + public NumberContext number() { + NumberContext _localctx = new NumberContext(Context, State); + EnterRule(_localctx, 12, RULE_number); try { - _localctx = new ScientificNumberContext(_localctx); - EnterOuterAlt(_localctx, 1); - { - State = 61; Match(SCIENTIFIC_NUMBER); + State = 65; + ErrorHandler.Sync(this); + switch (TokenStream.LA(1)) { + case SCIENTIFIC_NUMBER: + _localctx = new ScientificNumberContext(_localctx); + EnterOuterAlt(_localctx, 1); + { + State = 61; Match(SCIENTIFIC_NUMBER); + } + break; + case DECIMAL_NUMBER: + _localctx = new DecimalNumberContext(_localctx); + EnterOuterAlt(_localctx, 2); + { + State = 62; Match(DECIMAL_NUMBER); + } + break; + case BINARY_NUMBER: + _localctx = new BinaryNumberContext(_localctx); + EnterOuterAlt(_localctx, 3); + { + State = 63; Match(BINARY_NUMBER); + } + break; + case HEXADECIMAL_NUMBER: + _localctx = new HexadecimalNumberContext(_localctx); + EnterOuterAlt(_localctx, 4); + { + State = 64; Match(HEXADECIMAL_NUMBER); + } + break; + default: + throw new NoViableAltException(this); } } catch (RecognitionException re) { @@ -669,32 +754,32 @@ public FuncContext func() { try { EnterOuterAlt(_localctx, 1); { - State = 63; Match(IDENTIFIER); - State = 64; Match(LPAREN); - State = 73; + State = 67; Match(IDENTIFIER); + State = 68; Match(LPAREN); + State = 77; ErrorHandler.Sync(this); _la = TokenStream.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << LPAREN) | (1L << PLUS) | (1L << MINUS) | (1L << IDENTIFIER) | (1L << SCIENTIFIC_NUMBER))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << LPAREN) | (1L << PLUS) | (1L << MINUS) | (1L << IDENTIFIER) | (1L << DECIMAL_NUMBER) | (1L << BINARY_NUMBER) | (1L << HEXADECIMAL_NUMBER) | (1L << SCIENTIFIC_NUMBER))) != 0)) { { - State = 65; expression(); - State = 70; + State = 69; expression(); + State = 74; ErrorHandler.Sync(this); _la = TokenStream.LA(1); while (_la==COMMA) { { { - State = 66; Match(COMMA); - State = 67; expression(); + State = 70; Match(COMMA); + State = 71; expression(); } } - State = 72; + State = 76; ErrorHandler.Sync(this); _la = TokenStream.LA(1); } } } - State = 75; Match(RPAREN); + State = 79; Match(RPAREN); } } catch (RecognitionException re) { @@ -737,7 +822,7 @@ public VariableContext variable() { try { EnterOuterAlt(_localctx, 1); { - State = 77; Match(IDENTIFIER); + State = 81; Match(IDENTIFIER); } } catch (RecognitionException re) { @@ -753,7 +838,7 @@ public VariableContext variable() { private static char[] _serializedATN = { '\x3', '\x608B', '\xA72A', '\x8133', '\xB9ED', '\x417C', '\x3BE7', '\x7786', - '\x5964', '\x3', '\xE', 'R', '\x4', '\x2', '\t', '\x2', '\x4', '\x3', + '\x5964', '\x3', '\x11', 'V', '\x4', '\x2', '\t', '\x2', '\x4', '\x3', '\t', '\x3', '\x4', '\x4', '\t', '\x4', '\x4', '\x5', '\t', '\x5', '\x4', '\x6', '\t', '\x6', '\x4', '\a', '\t', '\a', '\x4', '\b', '\t', '\b', '\x4', '\t', '\t', '\t', '\x4', '\n', '\t', '\n', '\x3', '\x2', '\x3', @@ -765,17 +850,18 @@ public VariableContext variable() { '\v', '\x5', '\x3', '\x6', '\x3', '\x6', '\x3', '\x6', '\x3', '\x6', '\x3', '\x6', '\x3', '\x6', '\x5', '\x6', '\x36', '\n', '\x6', '\x3', '\a', '\x3', '\a', '\x3', '\a', '\x3', '\a', '\x3', '\a', '\x3', '\a', '\x5', '\a', - '>', '\n', '\a', '\x3', '\b', '\x3', '\b', '\x3', '\t', '\x3', '\t', '\x3', - '\t', '\x3', '\t', '\x3', '\t', '\a', '\t', 'G', '\n', '\t', '\f', '\t', - '\xE', '\t', 'J', '\v', '\t', '\x5', '\t', 'L', '\n', '\t', '\x3', '\t', - '\x3', '\t', '\x3', '\n', '\x3', '\n', '\x3', '\n', '\x2', '\x2', '\v', - '\x2', '\x4', '\x6', '\b', '\n', '\f', '\xE', '\x10', '\x12', '\x2', '\x4', - '\x3', '\x2', '\x5', '\x6', '\x3', '\x2', '\a', '\b', '\x2', 'R', '\x2', - '\x14', '\x3', '\x2', '\x2', '\x2', '\x4', '\x17', '\x3', '\x2', '\x2', - '\x2', '\x6', '\x1F', '\x3', '\x2', '\x2', '\x2', '\b', '\'', '\x3', '\x2', - '\x2', '\x2', '\n', '\x35', '\x3', '\x2', '\x2', '\x2', '\f', '=', '\x3', - '\x2', '\x2', '\x2', '\xE', '?', '\x3', '\x2', '\x2', '\x2', '\x10', '\x41', - '\x3', '\x2', '\x2', '\x2', '\x12', 'O', '\x3', '\x2', '\x2', '\x2', '\x14', + '>', '\n', '\a', '\x3', '\b', '\x3', '\b', '\x3', '\b', '\x3', '\b', '\x5', + '\b', '\x44', '\n', '\b', '\x3', '\t', '\x3', '\t', '\x3', '\t', '\x3', + '\t', '\x3', '\t', '\a', '\t', 'K', '\n', '\t', '\f', '\t', '\xE', '\t', + 'N', '\v', '\t', '\x5', '\t', 'P', '\n', '\t', '\x3', '\t', '\x3', '\t', + '\x3', '\n', '\x3', '\n', '\x3', '\n', '\x2', '\x2', '\v', '\x2', '\x4', + '\x6', '\b', '\n', '\f', '\xE', '\x10', '\x12', '\x2', '\x4', '\x3', '\x2', + '\x5', '\x6', '\x3', '\x2', '\a', '\b', '\x2', 'Y', '\x2', '\x14', '\x3', + '\x2', '\x2', '\x2', '\x4', '\x17', '\x3', '\x2', '\x2', '\x2', '\x6', + '\x1F', '\x3', '\x2', '\x2', '\x2', '\b', '\'', '\x3', '\x2', '\x2', '\x2', + '\n', '\x35', '\x3', '\x2', '\x2', '\x2', '\f', '=', '\x3', '\x2', '\x2', + '\x2', '\xE', '\x43', '\x3', '\x2', '\x2', '\x2', '\x10', '\x45', '\x3', + '\x2', '\x2', '\x2', '\x12', 'S', '\x3', '\x2', '\x2', '\x2', '\x14', '\x15', '\x5', '\x4', '\x3', '\x2', '\x15', '\x16', '\a', '\x2', '\x2', '\x3', '\x16', '\x3', '\x3', '\x2', '\x2', '\x2', '\x17', '\x1C', '\x5', '\x6', '\x4', '\x2', '\x18', '\x19', '\t', '\x2', '\x2', '\x2', '\x19', @@ -804,18 +890,22 @@ public VariableContext variable() { '\x4', '\x3', '\x2', ';', '<', '\a', '\x4', '\x2', '\x2', '<', '>', '\x3', '\x2', '\x2', '\x2', '=', '\x37', '\x3', '\x2', '\x2', '\x2', '=', '\x38', '\x3', '\x2', '\x2', '\x2', '=', '\x39', '\x3', '\x2', '\x2', '\x2', '>', - '\r', '\x3', '\x2', '\x2', '\x2', '?', '@', '\a', '\r', '\x2', '\x2', - '@', '\xF', '\x3', '\x2', '\x2', '\x2', '\x41', '\x42', '\a', '\f', '\x2', - '\x2', '\x42', 'K', '\a', '\x3', '\x2', '\x2', '\x43', 'H', '\x5', '\x4', - '\x3', '\x2', '\x44', '\x45', '\a', '\t', '\x2', '\x2', '\x45', 'G', '\x5', - '\x4', '\x3', '\x2', '\x46', '\x44', '\x3', '\x2', '\x2', '\x2', 'G', - 'J', '\x3', '\x2', '\x2', '\x2', 'H', '\x46', '\x3', '\x2', '\x2', '\x2', - 'H', 'I', '\x3', '\x2', '\x2', '\x2', 'I', 'L', '\x3', '\x2', '\x2', '\x2', - 'J', 'H', '\x3', '\x2', '\x2', '\x2', 'K', '\x43', '\x3', '\x2', '\x2', - '\x2', 'K', 'L', '\x3', '\x2', '\x2', '\x2', 'L', 'M', '\x3', '\x2', '\x2', - '\x2', 'M', 'N', '\a', '\x4', '\x2', '\x2', 'N', '\x11', '\x3', '\x2', - '\x2', '\x2', 'O', 'P', '\a', '\f', '\x2', '\x2', 'P', '\x13', '\x3', - '\x2', '\x2', '\x2', '\t', '\x1C', '$', ',', '\x35', '=', 'H', 'K', + '\r', '\x3', '\x2', '\x2', '\x2', '?', '\x44', '\a', '\x10', '\x2', '\x2', + '@', '\x44', '\a', '\r', '\x2', '\x2', '\x41', '\x44', '\a', '\xE', '\x2', + '\x2', '\x42', '\x44', '\a', '\xF', '\x2', '\x2', '\x43', '?', '\x3', + '\x2', '\x2', '\x2', '\x43', '@', '\x3', '\x2', '\x2', '\x2', '\x43', + '\x41', '\x3', '\x2', '\x2', '\x2', '\x43', '\x42', '\x3', '\x2', '\x2', + '\x2', '\x44', '\xF', '\x3', '\x2', '\x2', '\x2', '\x45', '\x46', '\a', + '\f', '\x2', '\x2', '\x46', 'O', '\a', '\x3', '\x2', '\x2', 'G', 'L', + '\x5', '\x4', '\x3', '\x2', 'H', 'I', '\a', '\t', '\x2', '\x2', 'I', 'K', + '\x5', '\x4', '\x3', '\x2', 'J', 'H', '\x3', '\x2', '\x2', '\x2', 'K', + 'N', '\x3', '\x2', '\x2', '\x2', 'L', 'J', '\x3', '\x2', '\x2', '\x2', + 'L', 'M', '\x3', '\x2', '\x2', '\x2', 'M', 'P', '\x3', '\x2', '\x2', '\x2', + 'N', 'L', '\x3', '\x2', '\x2', '\x2', 'O', 'G', '\x3', '\x2', '\x2', '\x2', + 'O', 'P', '\x3', '\x2', '\x2', '\x2', 'P', 'Q', '\x3', '\x2', '\x2', '\x2', + 'Q', 'R', '\a', '\x4', '\x2', '\x2', 'R', '\x11', '\x3', '\x2', '\x2', + '\x2', 'S', 'T', '\a', '\f', '\x2', '\x2', 'T', '\x13', '\x3', '\x2', + '\x2', '\x2', '\n', '\x1C', '$', ',', '\x35', '=', '\x43', 'L', 'O', }; public static readonly ATN _ATN = diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerVisitor.cs b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerVisitor.cs index 6269d38..3339c55 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerVisitor.cs +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerVisitor.cs @@ -91,12 +91,33 @@ public interface IFormulaGrammerVisitor : IParseTreeVisitor { Result VisitAtom([NotNull] FormulaGrammerParser.AtomContext context); /// /// Visit a parse tree produced by the ScientificNumber - /// labeled alternative in . + /// labeled alternative in . /// /// The parse tree. /// The visitor result. Result VisitScientificNumber([NotNull] FormulaGrammerParser.ScientificNumberContext context); /// + /// Visit a parse tree produced by the DecimalNumber + /// labeled alternative in . + /// + /// The parse tree. + /// The visitor result. + Result VisitDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context); + /// + /// Visit a parse tree produced by the BinaryNumber + /// labeled alternative in . + /// + /// The parse tree. + /// The visitor result. + Result VisitBinaryNumber([NotNull] FormulaGrammerParser.BinaryNumberContext context); + /// + /// Visit a parse tree produced by the HexadecimalNumber + /// labeled alternative in . + /// + /// The parse tree. + /// The visitor result. + Result VisitHexadecimalNumber([NotNull] FormulaGrammerParser.HexadecimalNumberContext context); + /// /// Visit a parse tree produced by . /// /// The parse tree. diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/NumericNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/NumericNode.cs index 8c14d7f..16665b4 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/NumericNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/NumericNode.cs @@ -9,11 +9,14 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { public class NumberNode : Node { - public NumberNode(double value) + public NumberNode(string token, double value) { + this.Token = token; this.Value = value; } + public string Token { get; } + public double Value { get; } public override TReturn Visit(INodeVisitor visitor) => visitor.Visit(this); diff --git a/ThinkSharp.FormulaParser/Configuration.cs b/ThinkSharp.FormulaParser/Configuration.cs index 7d40446..6e97bbb 100644 --- a/ThinkSharp.FormulaParser/Configuration.cs +++ b/ThinkSharp.FormulaParser/Configuration.cs @@ -61,6 +61,10 @@ public Configuration() public bool IsFunctionNameValidationDisabled { get; private set; } = false; + public bool IsBinaryNumberNotationSupportDisabled { get; private set; } = false; + + public bool IsHexadecimalNumberNotationSupportDisabled { get; private set; } = false; + bool IConfiguration.HasFunction(string name, int argumentCount) { if (this.MatchFunction0To5(name, argumentCount)) @@ -268,6 +272,8 @@ IEnumerable> IConfigurationEvaluator.EnumerateConst // //////////////////////////////////////////////////////////////////// void IConfigureSupportedFeatures.DisableScientificNotation() => this.IsScientificNotationSupportDisabled = true; + void IConfigureSupportedFeatures.DisableBinaryNumberNotation() => this.IsBinaryNumberNotationSupportDisabled = true; + void IConfigureSupportedFeatures.DisableHexadecimalNumberNotation() => this.IsHexadecimalNumberNotationSupportDisabled = true; void IConfigureSupportedFeatures.DisableBracket() => this.IsBracketSupportDisabled = true; void IConfigureSupportedFeatures.DisablePow() => this.IsPowSupportDisabled = true; void IConfigureSupportedFeatures.DisableVariables() => this.IsVariablesSupportDisabled = true; diff --git a/ThinkSharp.FormulaParser/IConfiguration.cs b/ThinkSharp.FormulaParser/IConfiguration.cs index 4e576a5..ec0871d 100644 --- a/ThinkSharp.FormulaParser/IConfiguration.cs +++ b/ThinkSharp.FormulaParser/IConfiguration.cs @@ -10,6 +10,10 @@ internal interface IConfiguration { bool IsScientificNotationSupportDisabled { get; } + bool IsBinaryNumberNotationSupportDisabled { get; } + + bool IsHexadecimalNumberNotationSupportDisabled { get; } + bool IsBracketSupportDisabled { get; } bool IsPowSupportDisabled { get; } diff --git a/ThinkSharp.FormulaParser/IConfigureSupportedFeatures.cs b/ThinkSharp.FormulaParser/IConfigureSupportedFeatures.cs index c3de0e4..01fcdac 100644 --- a/ThinkSharp.FormulaParser/IConfigureSupportedFeatures.cs +++ b/ThinkSharp.FormulaParser/IConfigureSupportedFeatures.cs @@ -1,5 +1,8 @@ namespace ThinkSharp.FormulaParsing { + /// + /// Interface encapsulating the API for configuring supported features. + /// public interface IConfigureSupportedFeatures { /// @@ -7,6 +10,16 @@ public interface IConfigureSupportedFeatures /// void DisableScientificNotation(); + /// + /// Prevents the usage of binary notation (e.g. 0b101 = 5) + /// + void DisableBinaryNumberNotation(); + + /// + /// Prevents the usage of hexadecimal notation (e.g. 0x20 = 32) + /// + void DisableHexadecimalNumberNotation(); + /// /// Prevents the usage of brackets. /// diff --git a/ThinkSharp.FormulaParser/ParserConfiguration.cs b/ThinkSharp.FormulaParser/ParserConfiguration.cs index 6931483..1caf788 100644 --- a/ThinkSharp.FormulaParser/ParserConfiguration.cs +++ b/ThinkSharp.FormulaParser/ParserConfiguration.cs @@ -31,6 +31,10 @@ public ParserConfiguration(IConfiguration configuration, IDictionary this.configuration.IsFunctionNameValidationDisabled; + public bool IsBinaryNumberNotationSupportDisabled => this.configuration.IsBinaryNumberNotationSupportDisabled; + + public bool IsHexadecimalNumberNotationSupportDisabled => this.configuration.IsHexadecimalNumberNotationSupportDisabled; + public bool HasConstant(string name) => this.configuration.HasConstant(name); public bool HasFunction(string name, int argumentCount) => this.configuration.HasFunction(name, argumentCount); From b2702ce5eb8eaebfd90dbf6b3a461bf6873a5813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 16 Sep 2019 20:37:56 +0200 Subject: [PATCH 14/45] added helper methods for handling parsing result --- .../FormulaParserResult.cs | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/ThinkSharp.FormulaParser/FormulaParserResult.cs b/ThinkSharp.FormulaParser/FormulaParserResult.cs index 55fdbc7..1bf6898 100644 --- a/ThinkSharp.FormulaParser/FormulaParserResult.cs +++ b/ThinkSharp.FormulaParser/FormulaParserResult.cs @@ -45,5 +45,38 @@ private void EnsureResultHasNoErrors() Environment.NewLine + this.Error); } } + + public bool Handle(Action onSuccess, Action onError) + { + if (onSuccess == null) throw new ArgumentNullException(nameof(onSuccess)); + if (onError == null) throw new ArgumentNullException(nameof(onError)); + + if (this.Success) + { + onSuccess(this.Value); + return true; + } + else + { + onError(this.Error); + return false; + } + } + + public bool Handle(Func onSuccess, Action onError) + { + if (onSuccess == null) throw new ArgumentNullException(nameof(onSuccess)); + if (onError == null) throw new ArgumentNullException(nameof(onError)); + + if (this.Success) + { + return onSuccess(this.Value); + } + else + { + onError(this.Error); + return false; + } + } } } From 496b45293d97906d87d1d380a41130a2ce30a821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 16 Sep 2019 20:39:15 +0200 Subject: [PATCH 15/45] added / improved comments --- .../IConfigureConstants.cs | 9 +- .../IConfigureFunctions.cs | 17 +- .../IConfigureValidationBehavior.cs | 3 + ThinkSharp.FormulaParser/IFormulaParser.cs | 18 +- .../ThinkSharp.FormulaParser.xml | 350 ++++++++++++++++-- 5 files changed, 353 insertions(+), 44 deletions(-) diff --git a/ThinkSharp.FormulaParser/IConfigureConstants.cs b/ThinkSharp.FormulaParser/IConfigureConstants.cs index 9abee93..b8cc88f 100644 --- a/ThinkSharp.FormulaParser/IConfigureConstants.cs +++ b/ThinkSharp.FormulaParser/IConfigureConstants.cs @@ -6,6 +6,9 @@ namespace ThinkSharp.FormulaParsing { + /// + /// Interface encapsulating the API for configuring constants. + /// public interface IConfigureConstants { /// @@ -20,15 +23,15 @@ public interface IConfigureConstants void Add(string name, double value); /// - /// Removes all configured functions. + /// Removes all configured contants. /// void RemoveAll(); /// - /// Removed the function with the specified name. + /// Removes the constant with the specified name. /// /// - /// The name of the function to remove. + /// The name of the constant to remove. /// void Remove(string name); } diff --git a/ThinkSharp.FormulaParser/IConfigureFunctions.cs b/ThinkSharp.FormulaParser/IConfigureFunctions.cs index ab1a96a..9f30103 100644 --- a/ThinkSharp.FormulaParser/IConfigureFunctions.cs +++ b/ThinkSharp.FormulaParser/IConfigureFunctions.cs @@ -6,10 +6,13 @@ namespace ThinkSharp.FormulaParsing { + /// + /// Interface encapsulating the API for configuring functions. + /// public interface IConfigureFunctions { /// - /// Adds a function with zero paramteter. + /// Adds a function with zero parameters. /// /// /// The name of the function. @@ -31,7 +34,7 @@ public interface IConfigureFunctions void Add(string name, Func function); /// - /// Adds a function with two paramteters. + /// Adds a function with two parameters. /// /// /// The name of the function. @@ -42,7 +45,7 @@ public interface IConfigureFunctions void Add(string name, Func function); /// - /// Adds a function with three paramteters. + /// Adds a function with three parameters. /// /// /// The name of the function. @@ -53,7 +56,7 @@ public interface IConfigureFunctions void Add(string name, Func function); /// - /// Adds a function with four paramteters. + /// Adds a function with four parameters. /// /// /// The name of the function. @@ -64,7 +67,7 @@ public interface IConfigureFunctions void Add(string name, Func function); /// - /// Adds a function with five paramteters. + /// Adds a function with five parameters. /// /// /// The name of the function. @@ -75,7 +78,7 @@ public interface IConfigureFunctions void Add(string name, Func function); /// - /// Adds a function with 2 to n paramteters. + /// Adds a function with 2 to n parameters. /// /// /// The name of the function. @@ -91,7 +94,7 @@ public interface IConfigureFunctions void RemoveAll(); /// - /// Removed the function with the specified name. + /// Removes the function with the specified name. /// /// /// The name of the function to remove. diff --git a/ThinkSharp.FormulaParser/IConfigureValidationBehavior.cs b/ThinkSharp.FormulaParser/IConfigureValidationBehavior.cs index 41a6b8a..7f25b45 100644 --- a/ThinkSharp.FormulaParser/IConfigureValidationBehavior.cs +++ b/ThinkSharp.FormulaParser/IConfigureValidationBehavior.cs @@ -6,6 +6,9 @@ namespace ThinkSharp.FormulaParsing { + /// + /// Interface encapsulating the API for configuring validation behavior. + /// public interface IConfigureValidationBehavior { /// diff --git a/ThinkSharp.FormulaParser/IFormulaParser.cs b/ThinkSharp.FormulaParser/IFormulaParser.cs index 47e2f2f..6f76ac0 100644 --- a/ThinkSharp.FormulaParser/IFormulaParser.cs +++ b/ThinkSharp.FormulaParser/IFormulaParser.cs @@ -17,7 +17,7 @@ public interface IFormulaParser /// The formula to evaluate. /// /// - /// The object that contains the evaluation result or an error. + /// The object that contains the evaluation result or an error. /// FormulaParserResult Evaluate(string formula); @@ -31,7 +31,7 @@ public interface IFormulaParser /// A dictionary that provides variables to be used for evaluation. /// /// - /// The object that contains the evaluation result or an error. + /// The object that contains the evaluation result or an error. /// FormulaParserResult Evaluate(string formula, IDictionary variables); @@ -42,7 +42,7 @@ public interface IFormulaParser /// The root node of the parsing tree to evaluate. /// /// - /// The object that contains the evaluation result or an error. + /// The object that contains the evaluation result or an error. /// FormulaParserResult Evaluate(Node formulaNode); @@ -56,7 +56,7 @@ public interface IFormulaParser /// A dictionary that provides variables to be used for evaluation. /// /// - /// The object that contains the evaluation result or an error. + /// The object that contains the evaluation result or an error. /// FormulaParserResult Evaluate(Node formulaNode, IDictionary variables); @@ -67,7 +67,7 @@ public interface IFormulaParser /// The formula to parse. /// /// - /// The object that contains the root node of the parsing tree or an error. + /// The object that contains the root node of the parsing tree or an error. /// FormulaParserResult Parse(string formula); @@ -81,7 +81,7 @@ public interface IFormulaParser /// A dictionary that provides variables to be used for evaluation. /// /// - /// The object that contains the root node of the parsing tree or an error. + /// The object that contains the root node of the parsing tree or an error. /// FormulaParserResult Parse(string formula, IDictionary variables); @@ -98,7 +98,7 @@ public interface IFormulaParser /// The visitor to run on the parsing tree. /// /// - /// The object that contains the result produced by the visitor or an error. + /// The object that contains the result produced by the visitor or an error. /// FormulaParserResult RunVisitor(string formula, INodeVisitor visitor); @@ -118,7 +118,7 @@ public interface IFormulaParser /// A dictionary that provides variables to be used for evaluation. /// /// - /// The object that contains the result produced by the visitor or an error. + /// The object that contains the result produced by the visitor or an error. /// FormulaParserResult RunVisitor(string formula, INodeVisitor visitor, IDictionary variables); @@ -135,7 +135,7 @@ public interface IFormulaParser /// The visitor to run on the parsing tree. /// /// - /// The object that contains the result produced by the visitor or an error. + /// The object that contains the result produced by the visitor or an error. /// FormulaParserResult RunVisitor(Node node, INodeVisitor visitor); } diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml index c781fee..bdb5b4f 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml @@ -27,6 +27,11 @@ a . + + + Interface encapsulating the API for configuring constants. + + Adds a constant. @@ -40,20 +45,25 @@ - Removes all configured functions. + Removes all configured contants. - Removed the function with the specified name. + Removes the constant with the specified name. - The name of the function to remove. + The name of the constant to remove. + + + Interface encapsulating the API for configuring functions. + + - Adds a function with zero paramteter. + Adds a function with zero parameters. The name of the function. @@ -75,7 +85,7 @@ - Adds a function with two paramteters. + Adds a function with two parameters. The name of the function. @@ -86,7 +96,7 @@ - Adds a function with three paramteters. + Adds a function with three parameters. The name of the function. @@ -97,7 +107,7 @@ - Adds a function with four paramteters. + Adds a function with four parameters. The name of the function. @@ -108,7 +118,7 @@ - Adds a function with five paramteters. + Adds a function with five parameters. The name of the function. @@ -119,7 +129,7 @@ - Adds a function with 2 to n paramteters. + Adds a function with 2 to n parameters. The name of the function. @@ -135,17 +145,32 @@ - Removed the function with the specified name. + Removes the function with the specified name. The name of the function to remove. + + + Interface encapsulating the API for configuring supported features. + + Prevents the usage of scientific notation (e.g. 2e3 = 4000) + + + Prevents the usage of binary notation (e.g. 0b101 = 5) + + + + + Prevents the usage of hexadecimal notation (e.g. 0x20 = 32) + + Prevents the usage of brackets. @@ -166,6 +191,11 @@ Prevents the usage of functions. + + + Interface encapsulating the API for configuring validation behavior. + + Diables the validation of variable names when creating a parsing tree. @@ -176,15 +206,135 @@ Diables the validation of functions names when creating a parsing tree. - - - - - - - - - + + + Evaluates the provided formula to a numeric value. + + + The formula to evaluate. + + + The object that contains the evaluation result or an error. + + + + + Evaluates the provided formula to a numeric value. + + + The formula to evaluate. + + + A dictionary that provides variables to be used for evaluation. + + + The object that contains the evaluation result or an error. + + + + + Evaluates the provided . + + + The root node of the parsing tree to evaluate. + + + The object that contains the evaluation result or an error. + + + + + Evaluates the provided . + + + The root node of the parsing tree to evaluate. + + + A dictionary that provides variables to be used for evaluation. + + + The object that contains the evaluation result or an error. + + + + + Parses the provided formula to a parsing tree. + + + The formula to parse. + + + The object that contains the root node of the parsing tree or an error. + + + + + Parses the provided formula to a parsing tree. + + + The formula to parse. + + + A dictionary that provides variables to be used for evaluation. + + + The object that contains the root node of the parsing tree or an error. + + + + + Parses the formula and executes the visitor to the genereted parsing tree. + + + The type of the visitors result. + + + The formula to parse. + + + The visitor to run on the parsing tree. + + + The object that contains the result produced by the visitor or an error. + + + + + Parses the formula and executes the visitor to the genereted parsing tree. + + + The type of the visitors result. + + + The formula to parse. + + + The visitor to run on the parsing tree. + + + A dictionary that provides variables to be used for evaluation. + + + The object that contains the result produced by the visitor or an error. + + + + + Executes the visitor to the provided parsing tree. + + + The type of the visitors result. + + + The root node of the parsing tree to run the visitor on. + + + The visitor to run on the parsing tree. + + + The object that contains the result produced by the visitor or an error. + + Allows to configure functions of the . @@ -386,7 +536,7 @@ Enter a parse tree produced by the ScientificNumber - labeled alternative in . + labeled alternative in . The default implementation does nothing. The parse tree. @@ -394,7 +544,55 @@ Exit a parse tree produced by the ScientificNumber - labeled alternative in . + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by the DecimalNumber + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by the DecimalNumber + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by the BinaryNumber + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by the BinaryNumber + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by the HexadecimalNumber + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by the HexadecimalNumber + labeled alternative in . The default implementation does nothing. The parse tree. @@ -557,7 +755,43 @@ Visit a parse tree produced by the ScientificNumber - labeled alternative in . + labeled alternative in . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the DecimalNumber + labeled alternative in . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the BinaryNumber + labeled alternative in . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the HexadecimalNumber + labeled alternative in . The default implementation returns the result of calling on . @@ -713,14 +947,56 @@ Enter a parse tree produced by the ScientificNumber - labeled alternative in . + labeled alternative in . The parse tree. Exit a parse tree produced by the ScientificNumber - labeled alternative in . + labeled alternative in . + + The parse tree. + + + + Enter a parse tree produced by the DecimalNumber + labeled alternative in . + + The parse tree. + + + + Exit a parse tree produced by the DecimalNumber + labeled alternative in . + + The parse tree. + + + + Enter a parse tree produced by the BinaryNumber + labeled alternative in . + + The parse tree. + + + + Exit a parse tree produced by the BinaryNumber + labeled alternative in . + + The parse tree. + + + + Enter a parse tree produced by the HexadecimalNumber + labeled alternative in . + + The parse tree. + + + + Exit a parse tree produced by the HexadecimalNumber + labeled alternative in . The parse tree. @@ -825,7 +1101,31 @@ Visit a parse tree produced by the ScientificNumber - labeled alternative in . + labeled alternative in . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the DecimalNumber + labeled alternative in . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the BinaryNumber + labeled alternative in . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the HexadecimalNumber + labeled alternative in . The parse tree. The visitor result. From a4c66df28f3c139438913a8fb7413be3cbb40cd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 16 Sep 2019 20:39:30 +0200 Subject: [PATCH 16/45] added testes --- .../FormularParser.CustomVisitor.Test.cs | 4 +- .../FormularParser.NumberFormats.Test.cs | 71 +++++++++++++++++++ .../FormularParser.SupportedFeatures.Test.cs | 30 ++++++++ ...nkSharp.FluentFormulaParser.Test.projitems | 1 + 4 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 ThinkSharp.FormulaParser.Test/FormularParser.NumberFormats.Test.cs diff --git a/ThinkSharp.FormulaParser.Test/FormularParser.CustomVisitor.Test.cs b/ThinkSharp.FormulaParser.Test/FormularParser.CustomVisitor.Test.cs index 05ae798..c44d2d5 100644 --- a/ThinkSharp.FormulaParser.Test/FormularParser.CustomVisitor.Test.cs +++ b/ThinkSharp.FormulaParser.Test/FormularParser.CustomVisitor.Test.cs @@ -60,7 +60,7 @@ public override Node Visit(VariableNode node) { if (node.Name == "x") { - return new NumberNode(2); + return new NumberNode("2", 2); } throw new InvalidOperationException("Unknown Variable."); @@ -71,7 +71,7 @@ public override Node Visit(FormulaNode node) return new FormulaNode(node.ChildNode.Visit(this), node.FormulaText); } - public override Node Visit(NumberNode node) => new NumberNode(node.Value); + public override Node Visit(NumberNode node) => node; } } } diff --git a/ThinkSharp.FormulaParser.Test/FormularParser.NumberFormats.Test.cs b/ThinkSharp.FormulaParser.Test/FormularParser.NumberFormats.Test.cs new file mode 100644 index 0000000..06f2073 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/FormularParser.NumberFormats.Test.cs @@ -0,0 +1,71 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.Ast.Visitors; + +namespace ThinkSharp.FormulaParsing.Test +{ + [TestClass] + public class FormularParserNumberFormatsTest + { + [TestMethod] + public void TestBinayNotation() + { + var parser = FormulaParser.Create(); + + Assert.AreEqual(1.0, parser.Evaluate("0b1").Value); + Assert.AreEqual(5.0, parser.Evaluate("0b101").Value); + + Assert.AreEqual(10.0, parser.Evaluate("0b101 + 0b101").Value); + } + + [TestMethod] + public void TestHexadecimalNotation() + { + var parser = FormulaParser.Create(); + + Assert.AreEqual(1.0, parser.Evaluate("0x1").Value); + Assert.AreEqual(10.0, parser.Evaluate("0xa").Value); + Assert.AreEqual(10.0, parser.Evaluate("0xA").Value); + + Assert.AreEqual(477580.0, parser.Evaluate("0x7498C").Value); + Assert.AreEqual(477580.0, parser.Evaluate("0X7498C").Value); + Assert.AreEqual(477580.0, parser.Evaluate("#7498C").Value); + + Assert.AreEqual(100.0, parser.Evaluate("0xA * 0Xa").Value); + } + + [TestMethod] + public void TestDecimalNotation() + { + var parser = FormulaParser.Create(); + + Assert.AreEqual(1.0, parser.Evaluate("0d1").Value); + Assert.AreEqual(101.0, parser.Evaluate("0D101").Value); + Assert.AreEqual(101.0, parser.Evaluate("101").Value); + + Assert.AreEqual(202.0, parser.Evaluate("0d101 + 101").Value); + } + + [TestMethod] + public void TestScientificNotation() + { + var parser = FormulaParser.Create(); + + Assert.AreEqual(1000.0, parser.Evaluate("1e3").Value); + Assert.AreEqual(1110.0, parser.Evaluate("1.11e3").Value); + } + + [TestMethod] + public void TestMixedNotation() + { + var parser = FormulaParser.Create(); + + Assert.AreEqual(0.04, parser.Evaluate("(0b11 + 0x20 + 5) * 1e-3").Value); + } + } +} diff --git a/ThinkSharp.FormulaParser.Test/FormularParser.SupportedFeatures.Test.cs b/ThinkSharp.FormulaParser.Test/FormularParser.SupportedFeatures.Test.cs index f4ff5cc..3449e42 100644 --- a/ThinkSharp.FormulaParser.Test/FormularParser.SupportedFeatures.Test.cs +++ b/ThinkSharp.FormulaParser.Test/FormularParser.SupportedFeatures.Test.cs @@ -91,5 +91,35 @@ public void TestDisableBracket() Assert.IsFalse(result.Success); Assert.AreEqual("column 4: Invalid token '('.", (string)result.Error); } + + [TestMethod] + public void TestDisableBinaryNumberNotation() + { + var parser = FormulaParser + .CreateBuilder() + .ConfigureSupportedFeatures(supportedFeatures => + { + supportedFeatures.DisableBinaryNumberNotation(); + }) + .Build(); + var result = parser.Evaluate("0b101"); + Assert.IsFalse(result.Success); + Assert.AreEqual("column 0: Invalid token '0b101'.", (string)result.Error); + } + + [TestMethod] + public void TestDisableHexadecimalNumberNotation() + { + var parser = FormulaParser + .CreateBuilder() + .ConfigureSupportedFeatures(supportedFeatures => + { + supportedFeatures.DisableHexadecimalNumberNotation(); + }) + .Build(); + var result = parser.Evaluate("0xABC"); + Assert.IsFalse(result.Success); + Assert.AreEqual("column 0: Invalid token '0xABC'.", (string)result.Error); + } } } diff --git a/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems b/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems index 8f80a56..ea1adde 100644 --- a/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems +++ b/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems @@ -11,6 +11,7 @@ + From bd1fd2185adb9495a97d14e65ea992e395c66ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 16 Sep 2019 20:44:13 +0200 Subject: [PATCH 17/45] incremented version --- .../ThinkSharp.FormulaParser.csproj | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj index 7f7efb1..4f841b5 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj @@ -9,14 +9,14 @@ ThinkSharp A formula parser with fluent API that allows parsing and evaluation of mathematically formulas. Features: functions, constants, variables, scientific numbers, focus on customization and flexibility. © 2019 Jan-Niklas Schäfer - 0.2.0.0 - 0.2.0.0 + 0.3.0.0 + 0.3.0.0 LICENSE.txt - Added comments -Added function'sqrt' + added support for binary (0x1001101) / hexadecimal (0x134A) number representations +added helper methods for handling parsing result https://github.com/JanDotNet/ThinkSharp.FormulaParser true - 0.2.0 + 0.3.0 From 3ef3a70f39817d2ccd86f48150f7278804f6db3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 23 Sep 2019 09:14:02 +0200 Subject: [PATCH 18/45] removed formula text from formula node --- .../ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs b/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs index 5a49e46..5ebbe4a 100644 --- a/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs +++ b/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs @@ -20,7 +20,7 @@ public override Node VisitFormula([NotNull] FormulaGrammerParser.FormulaContext { var node = base.Visit(context.expression()); - return new FormulaNode(node, formulaText); + return new FormulaNode(node); } public override Node VisitExpression([NotNull] FormulaGrammerParser.ExpressionContext context) From cd0743053d93c3ddf34cb54896b865f892b6b04e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 23 Sep 2019 09:14:48 +0200 Subject: [PATCH 19/45] changed .ctor access modifier from internal to public for node types --- ThinkSharp.FormulaParser/Ast/Nodes/BracketedNode.cs | 2 +- ThinkSharp.FormulaParser/Ast/Nodes/ConstantNode.cs | 2 +- ThinkSharp.FormulaParser/Ast/Nodes/FormulaNode.cs | 5 +---- ThinkSharp.FormulaParser/Ast/Nodes/FunctionNode.cs | 2 +- ThinkSharp.FormulaParser/Ast/Nodes/PowerNode.cs | 2 +- ThinkSharp.FormulaParser/Ast/Nodes/SignedNode.cs | 2 +- ThinkSharp.FormulaParser/Ast/Nodes/VariableNode.cs | 2 +- 7 files changed, 7 insertions(+), 10 deletions(-) diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/BracketedNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/BracketedNode.cs index 64500a2..1c5351b 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/BracketedNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/BracketedNode.cs @@ -9,7 +9,7 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { public class BracketedNode : Node { - internal BracketedNode(Node childNode) + public BracketedNode(Node childNode) { this.ChildNode = childNode ?? throw new ArgumentNullException(nameof(childNode)); } diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/ConstantNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/ConstantNode.cs index 23d4769..66e17b3 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/ConstantNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/ConstantNode.cs @@ -9,7 +9,7 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { public class ConstantNode : Node { - internal ConstantNode(string name) + public ConstantNode(string name) { this.Name = name; } diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/FormulaNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/FormulaNode.cs index 6139f5c..fa010a3 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/FormulaNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/FormulaNode.cs @@ -9,14 +9,11 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { public class FormulaNode : Node { - public FormulaNode(Node childNode, string formularText) + public FormulaNode(Node childNode) { this.ChildNode = childNode ?? throw new ArgumentNullException(nameof(childNode)); - this.FormulaText = formularText; } - public string FormulaText { get; } - public Node ChildNode { get; } public override TReturn Visit(INodeVisitor visitor) => visitor.Visit(this); diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/FunctionNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/FunctionNode.cs index 0edc35b..b406481 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/FunctionNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/FunctionNode.cs @@ -9,7 +9,7 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { public class FunctionNode : Node { - internal FunctionNode(string functionName, params Node[] parameters) + public FunctionNode(string functionName, params Node[] parameters) { this.FunctionName = functionName ?? throw new ArgumentNullException(nameof(functionName)); this.Parameters = parameters ?? new Node[0]; diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/PowerNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/PowerNode.cs index d397a0f..350df24 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/PowerNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/PowerNode.cs @@ -9,7 +9,7 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { public class PowerNode : Node { - internal PowerNode(Node baseNode, Node exponentNode) + public PowerNode(Node baseNode, Node exponentNode) { this.BaseNode = baseNode ?? throw new ArgumentNullException(nameof(baseNode)); this.ExponentNode = exponentNode ?? throw new ArgumentNullException(nameof(exponentNode)); diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/SignedNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/SignedNode.cs index 788b6ce..f7a0f7c 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/SignedNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/SignedNode.cs @@ -11,7 +11,7 @@ public enum Sign { Plus, Minus } public class SignedNode : Node { - internal SignedNode(Sign sign, Node node) + public SignedNode(Sign sign, Node node) { this.Sign = sign; this.Node = node ?? throw new ArgumentNullException(nameof(node)); diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/VariableNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/VariableNode.cs index 8c0a254..363b1f1 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/VariableNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/VariableNode.cs @@ -9,7 +9,7 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { public class VariableNode : Node { - internal VariableNode(string name) + public VariableNode(string name) { this.Name = name; } From 86f2618c48489233b5942cd442c766de37f98ba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 23 Sep 2019 09:15:15 +0200 Subject: [PATCH 20/45] added visitor for cloning a parsing tree --- .../Ast/Visitors/CloneTreeVisitor.cs | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 ThinkSharp.FormulaParser/Ast/Visitors/CloneTreeVisitor.cs diff --git a/ThinkSharp.FormulaParser/Ast/Visitors/CloneTreeVisitor.cs b/ThinkSharp.FormulaParser/Ast/Visitors/CloneTreeVisitor.cs new file mode 100644 index 0000000..b978c26 --- /dev/null +++ b/ThinkSharp.FormulaParser/Ast/Visitors/CloneTreeVisitor.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.Ast.Visitors +{ + public class CloneTreeVisitor : NodeVisitor + { + public override Node Visit(BinaryOperatorNode node) + { + return new BinaryOperatorNode( + node.BinaryOperator, + node.LeftNode.Visit(this), + node.RightNode.Visit(this)); + } + + public override Node Visit(BracketedNode node) + { + return new BracketedNode(node.ChildNode.Visit(this)); + } + + public override Node Visit(ConstantNode node) + { + return new ConstantNode(node.Name); + } + + public override Node Visit(FormulaNode node) + { + return new FormulaNode(node.ChildNode.Visit(this)); + } + + public override Node Visit(FunctionNode node) + { + return new FunctionNode(node.FunctionName, node.Parameters.Select(p => p.Visit(this)).ToArray()); + } + + public override Node Visit(NumberNode node) + { + return new NumberNode(node.Token, node.Value); + } + + public override Node Visit(PowerNode node) + { + return new PowerNode(node.BaseNode.Visit(this), node.ExponentNode.Visit(this)); + } + + public override Node Visit(SignedNode node) + { + return new SignedNode(node.Sign, node.Node.Visit(this)); + } + + public override Node Visit(VariableNode node) + { + return new VariableNode(node.Name); + } + } +} From 6306a32cf45082e9ebed8c6eb7393305d3f463db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 23 Sep 2019 09:15:39 +0200 Subject: [PATCH 21/45] added helper class for validating identifier names --- .../Validation/ValidationHelper.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 ThinkSharp.FormulaParser/Validation/ValidationHelper.cs diff --git a/ThinkSharp.FormulaParser/Validation/ValidationHelper.cs b/ThinkSharp.FormulaParser/Validation/ValidationHelper.cs new file mode 100644 index 0000000..0983032 --- /dev/null +++ b/ThinkSharp.FormulaParser/Validation/ValidationHelper.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; + +namespace ThinkSharp.FormulaParsing.Validation +{ + public static class ValidationHelper + { + private static Regex variableRegex = new Regex("[a-zA-Z$_][a-zA-Z0-9$_]*", RegexOptions.Compiled); + + public static bool IsValidIdentifier(string name) => variableRegex.IsMatch(name); + } +} From b15ac9ad6934314fc6dee8bedffb675c7b7c946c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 23 Sep 2019 09:16:21 +0200 Subject: [PATCH 22/45] added another handle method for simlifying the handling of parsing / evaluation results. --- ThinkSharp.FormulaParser/FormulaParserResult.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ThinkSharp.FormulaParser/FormulaParserResult.cs b/ThinkSharp.FormulaParser/FormulaParserResult.cs index 1bf6898..4449c6a 100644 --- a/ThinkSharp.FormulaParser/FormulaParserResult.cs +++ b/ThinkSharp.FormulaParser/FormulaParserResult.cs @@ -46,6 +46,20 @@ private void EnsureResultHasNoErrors() } } + public TResult HandleError(Func onError) + { + if (onError == null) throw new ArgumentNullException(nameof(onError)); + + if (this.Success) + { + return Value; + } + else + { + throw onError(this.Error); + } + } + public bool Handle(Action onSuccess, Action onError) { if (onSuccess == null) throw new ArgumentNullException(nameof(onSuccess)); From a3dbd6ac2b435fd9825aa19697289ca7c71e70b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 23 Sep 2019 09:16:42 +0200 Subject: [PATCH 23/45] unit tests --- ThinkSharp.FormulaParser.Test/FormulaParserTest.cs | 9 --------- .../FormularParser.CustomVisitor.Test.cs | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs b/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs index 585a04a..a5b87eb 100644 --- a/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs +++ b/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs @@ -143,15 +143,6 @@ public void Test_NameOfVariableConflictsWithNameOfConstant() Assert.AreEqual("Variable name 'pi' conflicts with the name of an existing constant.", (string)result.Error); } - [TestMethod] - public void Test_FormulatText() - { - var parser = FormulaParser.Create(); - - var result = parser.Parse("2 * pi").Value as FormulaNode; - Assert.AreEqual("2 * pi", result.FormulaText); - } - [TestMethod] public void TestComplexFormulas() { diff --git a/ThinkSharp.FormulaParser.Test/FormularParser.CustomVisitor.Test.cs b/ThinkSharp.FormulaParser.Test/FormularParser.CustomVisitor.Test.cs index c44d2d5..5b01138 100644 --- a/ThinkSharp.FormulaParser.Test/FormularParser.CustomVisitor.Test.cs +++ b/ThinkSharp.FormulaParser.Test/FormularParser.CustomVisitor.Test.cs @@ -68,7 +68,7 @@ public override Node Visit(VariableNode node) public override Node Visit(FormulaNode node) { - return new FormulaNode(node.ChildNode.Visit(this), node.FormulaText); + return new FormulaNode(node.ChildNode.Visit(this)); } public override Node Visit(NumberNode node) => node; From 2c31814e1eba0128938545c6a974b84bdfb8bd58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 23 Sep 2019 10:08:38 +0200 Subject: [PATCH 24/45] removed UI project --- ThinkSharp.FormulaParser.Wpf/App.config | 6 - ThinkSharp.FormulaParser.Wpf/App.xaml | 9 - ThinkSharp.FormulaParser.Wpf/App.xaml.cs | 17 -- ThinkSharp.FormulaParser.Wpf/MainWindow.xaml | 15 -- .../MainWindow.xaml.cs | 159 ------------------ .../Properties/AssemblyInfo.cs | 55 ------ .../Properties/Resources.Designer.cs | 63 ------- .../Properties/Resources.resx | 117 ------------- .../Properties/Settings.Designer.cs | 26 --- .../Properties/Settings.settings | 7 - .../ThinkSharp.FormulaParser.Wpf.csproj | 108 ------------ ThinkSharp.FormulaParser.Wpf/packages.config | 4 - ThinkSharp.FormulaParser.sln | 6 - 13 files changed, 592 deletions(-) delete mode 100644 ThinkSharp.FormulaParser.Wpf/App.config delete mode 100644 ThinkSharp.FormulaParser.Wpf/App.xaml delete mode 100644 ThinkSharp.FormulaParser.Wpf/App.xaml.cs delete mode 100644 ThinkSharp.FormulaParser.Wpf/MainWindow.xaml delete mode 100644 ThinkSharp.FormulaParser.Wpf/MainWindow.xaml.cs delete mode 100644 ThinkSharp.FormulaParser.Wpf/Properties/AssemblyInfo.cs delete mode 100644 ThinkSharp.FormulaParser.Wpf/Properties/Resources.Designer.cs delete mode 100644 ThinkSharp.FormulaParser.Wpf/Properties/Resources.resx delete mode 100644 ThinkSharp.FormulaParser.Wpf/Properties/Settings.Designer.cs delete mode 100644 ThinkSharp.FormulaParser.Wpf/Properties/Settings.settings delete mode 100644 ThinkSharp.FormulaParser.Wpf/ThinkSharp.FormulaParser.Wpf.csproj delete mode 100644 ThinkSharp.FormulaParser.Wpf/packages.config diff --git a/ThinkSharp.FormulaParser.Wpf/App.config b/ThinkSharp.FormulaParser.Wpf/App.config deleted file mode 100644 index 56efbc7..0000000 --- a/ThinkSharp.FormulaParser.Wpf/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/ThinkSharp.FormulaParser.Wpf/App.xaml b/ThinkSharp.FormulaParser.Wpf/App.xaml deleted file mode 100644 index 5c8a139..0000000 --- a/ThinkSharp.FormulaParser.Wpf/App.xaml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - diff --git a/ThinkSharp.FormulaParser.Wpf/App.xaml.cs b/ThinkSharp.FormulaParser.Wpf/App.xaml.cs deleted file mode 100644 index 849b896..0000000 --- a/ThinkSharp.FormulaParser.Wpf/App.xaml.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Data; -using System.Linq; -using System.Threading.Tasks; -using System.Windows; - -namespace FormulaParser.Wpf -{ - /// - /// Interaction logic for App.xaml - /// - public partial class App : Application - { - } -} diff --git a/ThinkSharp.FormulaParser.Wpf/MainWindow.xaml b/ThinkSharp.FormulaParser.Wpf/MainWindow.xaml deleted file mode 100644 index a936b92..0000000 --- a/ThinkSharp.FormulaParser.Wpf/MainWindow.xaml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - diff --git a/ThinkSharp.FormulaParser.Wpf/MainWindow.xaml.cs b/ThinkSharp.FormulaParser.Wpf/MainWindow.xaml.cs deleted file mode 100644 index b14df85..0000000 --- a/ThinkSharp.FormulaParser.Wpf/MainWindow.xaml.cs +++ /dev/null @@ -1,159 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Visitors; - -namespace FormulaParser.Wpf -{ - using ThinkSharp.FormulaParsing.Ast.Nodes; - using FormulaParser = ThinkSharp.FormulaParsing.FormulaParser; - - /// - /// Interaction logic for MainWindow.xaml - /// - public partial class MainWindow : Window - { - private readonly IFormulaParser parser = FormulaParser - .CreateBuilder() - .ConfigureValidationBehavior(parsingBehavior => - { - parsingBehavior.DisableVariableNameValidation(); - }) - .Build(); - public MainWindow() - { - InitializeComponent(); - TestConfiguration(); - } - - private void TestEvaluation() - { - // The simples way to create a formula parser is the static method 'Create'. - var parser = FormulaParser.Create(); - - // Parsing a simple mathematical formula - var result1 = parser.Evaluate("1+3E2").Value; // result1 = 2.0 - - // Usage of variables - var variables = new Dictionary { ["x"] = 2.0 }; - var result2 = parser.Evaluate("1+x", variables).Value; // result2 = 3.0 - - // Usage of functions - var result3 = parser.Evaluate("1+min(3,4)").Value; // result2 = 4.0 - - // Handle errors - var parsingResult = parser.Evaluate("2*?"); - if (!parsingResult.Success) Console.WriteLine(parsingResult.Error); // "column 2: token recognition error at: '?'" - } - - private void TestParsing() - { - // The simples way to create a formula parser is the static method 'Create'. - var parser = FormulaParser.Create(); - var variables = new Dictionary { ["x"] = 2.0 }; - - // Parsing a simple mathematical formula - var node1 = parser.Parse("1+x", variables).Value; - // |FormulaNode("1+x") - // |- Child: BinaryOperatorNode(+) - // |- LeftNode: NumericNode(1.0) - // |- RightNode: VariableNode("x") - var result1 = parser.Evaluate(node1, variables).Value; // result = 3.0 - - - var node2 = parser.Parse("pi * sqrt(3*x)", variables).Value; - // |FormulaNode("pi * sqrt(3*x)") - // |- Child: BinaryOperatorNode(*) - // |- LeftNode: ConstantNode(3.14...) - // |- RightNode: FunctionNode("sqrt") - // |- Parameters: [BinaryOperationNode(*)] - // |- LeftNode: Numeric(3.0) - // |- RightNode: VariableNode("x") - var result2 = parser.Evaluate(node2, variables).Value; // result = 7.695... - } - - private void TestConfiguration() - { - var parser = FormulaParser - .CreateBuilder() - .ConfigureConstats(constants => - { - constants.Add("h", 6.62607015e-34); - }) - .ConfigureFunctions(functions => - { - // functions.RemoveAll() for removing all default functions - // functions.Remove("sum") for removing function by name - - // define function with 2 to n number of parameters (typeof(nums) = double[]) - functions.Add("product", nums => nums.Aggregate((p1, p2) => p1 * p2)); - - // define functions with specified number of parameters (1-5 parameters are supported) - functions.Add("celsiusToFarenheit", celsius => celsius * 1.8 + 32); - functions.Add("fahrenheitToCelsius", farenheit => (farenheit - 32) * 5 / 9); - functions.Add("p1_plus_p2_plus_p3", (p1, p2, p3) => p1 + p2 + p3); - }).Build(); - - var poolTemperatureInCelsius = parser.Evaluate("celsiusToFarenheit(fahrenheitToCelsius(30))").Value; // poolTemperatureInCelsius = 30 - var result2 = parser.Evaluate("product(2, 2, 2, 2, 2, 2, 2)").Value; // result2 = 2^6 = 128 - var result3 = parser.Evaluate("p1_plus_p2_plus_p3(1, 2, 3)").Value; // result3 = 6 - - string error1 = parser.Evaluate("celsiusToFarenheit(1, 2)").Error; // column 0: There is no function 'celsiusToFarenheit' that takes 2 argument(s). - string error2 = parser.Evaluate("product()").Error; // column 0: There is no function 'product' that takes 0 argument(s). - string error3 = parser.Evaluate("p1_plus_p2_plus_p3(1, 2)").Error; // column 0: There is no function 'p1_plus_p2_plus_p3' that takes 2 argument(s). - } - - private void Input_TextChanged(object sender, TextChangedEventArgs e) - { - var result = parser.Parse(Input.Text); - - if (!result.Success) - { - this.Result.Text = string.Join(Environment.NewLine, result.Error); - this.Result.Foreground = Brushes.Red; - } - else - { - var variableNames = result.Value.Visit(new CollectVariableNamesVisitor()); - this.Result.Text = "Variables: " + string.Join("|", variableNames); - this.Result.Foreground = Brushes.Black; - var evalResult = parser.Evaluate(result.Value); - if (!evalResult.Success) - { - this.ResultValue.Text = string.Join(Environment.NewLine, evalResult.Error); - this.ResultValue.Foreground = Brushes.Red; - } - else - { - this.ResultValue.Text = evalResult.Value.ToString(); - this.ResultValue.Foreground = Brushes.Black; - } - } - } - - private class CollectVariableNamesVisitor : NodeVisitor> - { - private readonly List variableNames = new List(); - - public override List Visit(VariableNode node) - { - variableNames.Add(node.Name); - return variableNames; - } - - protected override List DefaultResult() => variableNames; - } - } -} diff --git a/ThinkSharp.FormulaParser.Wpf/Properties/AssemblyInfo.cs b/ThinkSharp.FormulaParser.Wpf/Properties/AssemblyInfo.cs deleted file mode 100644 index 3116d09..0000000 --- a/ThinkSharp.FormulaParser.Wpf/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Reflection; -using System.Resources; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Windows; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("FormulaParser.Wpf")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("FormulaParser.Wpf")] -[assembly: AssemblyCopyright("Copyright © 2019")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -//In order to begin building localizable applications, set -//CultureYouAreCodingWith in your .csproj file -//inside a . For example, if you are using US english -//in your source files, set the to en-US. Then uncomment -//the NeutralResourceLanguage attribute below. Update the "en-US" in -//the line below to match the UICulture setting in the project file. - -//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] - - -[assembly: ThemeInfo( - ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located - //(used if a resource is not found in the page, - // or application resource dictionaries) - ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located - //(used if a resource is not found in the page, - // app, or any theme specific resource dictionaries) -)] - - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ThinkSharp.FormulaParser.Wpf/Properties/Resources.Designer.cs b/ThinkSharp.FormulaParser.Wpf/Properties/Resources.Designer.cs deleted file mode 100644 index ba2b561..0000000 --- a/ThinkSharp.FormulaParser.Wpf/Properties/Resources.Designer.cs +++ /dev/null @@ -1,63 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace ThinkSharp.FormulaParsing.Wpf.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ThinkSharp.FormulaParsing.Wpf.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} diff --git a/ThinkSharp.FormulaParser.Wpf/Properties/Resources.resx b/ThinkSharp.FormulaParser.Wpf/Properties/Resources.resx deleted file mode 100644 index af7dbeb..0000000 --- a/ThinkSharp.FormulaParser.Wpf/Properties/Resources.resx +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/ThinkSharp.FormulaParser.Wpf/Properties/Settings.Designer.cs b/ThinkSharp.FormulaParser.Wpf/Properties/Settings.Designer.cs deleted file mode 100644 index b760d95..0000000 --- a/ThinkSharp.FormulaParser.Wpf/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace ThinkSharp.FormulaParsing.Wpf.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} diff --git a/ThinkSharp.FormulaParser.Wpf/Properties/Settings.settings b/ThinkSharp.FormulaParser.Wpf/Properties/Settings.settings deleted file mode 100644 index 033d7a5..0000000 --- a/ThinkSharp.FormulaParser.Wpf/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/ThinkSharp.FormulaParser.Wpf/ThinkSharp.FormulaParser.Wpf.csproj b/ThinkSharp.FormulaParser.Wpf/ThinkSharp.FormulaParser.Wpf.csproj deleted file mode 100644 index 865cc4d..0000000 --- a/ThinkSharp.FormulaParser.Wpf/ThinkSharp.FormulaParser.Wpf.csproj +++ /dev/null @@ -1,108 +0,0 @@ - - - - - Debug - AnyCPU - {18AF0B56-CE95-4740-A5F7-91420E12E7A3} - WinExe - ThinkSharp.FluentFormulaParser.Wpf - ThinkSharp.FluentFormulaParser.Wpf - v4.7.2 - 512 - {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 4 - true - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\packages\Antlr4.Runtime.Standard.4.7.2\lib\net35\Antlr4.Runtime.Standard.dll - - - - - - - - - - - 4.0 - - - - - - - - MSBuild:Compile - Designer - - - MSBuild:Compile - Designer - - - App.xaml - Code - - - MainWindow.xaml - Code - - - - - Code - - - True - True - Resources.resx - - - True - Settings.settings - True - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - - - - - - {c69728f7-cdc0-4fa2-b805-e0dd6f498e9f} - ThinkSharp.FormulaParser - - - - \ No newline at end of file diff --git a/ThinkSharp.FormulaParser.Wpf/packages.config b/ThinkSharp.FormulaParser.Wpf/packages.config deleted file mode 100644 index ff6a875..0000000 --- a/ThinkSharp.FormulaParser.Wpf/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/ThinkSharp.FormulaParser.sln b/ThinkSharp.FormulaParser.sln index 7982aa3..354eeef 100644 --- a/ThinkSharp.FormulaParser.sln +++ b/ThinkSharp.FormulaParser.sln @@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.28922.388 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThinkSharp.FormulaParser.Wpf", "ThinkSharp.FormulaParser.Wpf\ThinkSharp.FormulaParser.Wpf.csproj", "{18AF0B56-CE95-4740-A5F7-91420E12E7A3}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThinkSharp.FormulaParser", "ThinkSharp.FormulaParser\ThinkSharp.FormulaParser.csproj", "{C69728F7-CDC0-4FA2-B805-E0DD6F498E9F}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThinkSharp.FormulaParser.Test.Core", "ThinkSharp.FormulaParser.Test.Core\ThinkSharp.FormulaParser.Test.Core.csproj", "{1CAA5403-6EBB-4885-A51A-10533E673890}" @@ -23,10 +21,6 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {18AF0B56-CE95-4740-A5F7-91420E12E7A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {18AF0B56-CE95-4740-A5F7-91420E12E7A3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {18AF0B56-CE95-4740-A5F7-91420E12E7A3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {18AF0B56-CE95-4740-A5F7-91420E12E7A3}.Release|Any CPU.Build.0 = Release|Any CPU {C69728F7-CDC0-4FA2-B805-E0DD6F498E9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C69728F7-CDC0-4FA2-B805-E0DD6F498E9F}.Debug|Any CPU.Build.0 = Debug|Any CPU {C69728F7-CDC0-4FA2-B805-E0DD6F498E9F}.Release|Any CPU.ActiveCfg = Release|Any CPU From 0102e50496a74da5c416c629139d8225e6f2b0b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 23 Sep 2019 10:08:59 +0200 Subject: [PATCH 25/45] incremented version to 0.4 --- .../ThinkSharp.FormulaParser.csproj | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj index 4f841b5..0e0a092 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj @@ -9,14 +9,17 @@ ThinkSharp A formula parser with fluent API that allows parsing and evaluation of mathematically formulas. Features: functions, constants, variables, scientific numbers, focus on customization and flexibility. © 2019 Jan-Niklas Schäfer - 0.3.0.0 - 0.3.0.0 + 0.4.0.0 + 0.4.0.0 LICENSE.txt - added support for binary (0x1001101) / hexadecimal (0x134A) number representations -added helper methods for handling parsing result + added another handle method for simlifying the handling of parsing / evaluation results. +added helper class for validating identifier names +added visitor for cloning a parsing tree +changed .ctor access modifier from internal to public for node types +removed formula text from formula node https://github.com/JanDotNet/ThinkSharp.FormulaParser true - 0.3.0 + 0.4.0 From cba895618776e288f45ddbcc4e7fe8952c8f02dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Sun, 6 Oct 2019 10:35:25 +0200 Subject: [PATCH 26/45] changed variables API from IDictionary to IReadOnlyDictionary added '$' as valid character for variables removed support for alternative hex number notation: '#'. Note that the main notation '0x v.DisableVariableNameValidation()) + .Build(); + + Assert.AreEqual(true, parser.Parse("abc").Success); + Assert.AreEqual(true, parser.Parse("_abc").Success); + Assert.AreEqual(true, parser.Parse("_a_bc").Success); + Assert.AreEqual(true, parser.Parse("$abc").Success); + Assert.AreEqual(true, parser.Parse("$a$bc").Success); + Assert.AreEqual(true, parser.Parse("$3a3$b534c").Success); + + Assert.AreEqual(false, parser.Parse("1abc").Success); + } + } +} diff --git a/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems b/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems index ea1adde..71b12f7 100644 --- a/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems +++ b/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems @@ -11,6 +11,7 @@ + diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.g4 b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.g4 index 4d7555f..b096c82 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.g4 +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.g4 @@ -103,7 +103,7 @@ BINARY_NUMBER ; HEXADECIMAL_NUMBER - : (PREFIX_HEX | NUMBER_HEX2) NUMBER_HEX + : PREFIX_HEX NUMBER_HEX ; SCIENTIFIC_NUMBER @@ -111,7 +111,7 @@ SCIENTIFIC_NUMBER ; fragment VALID_ID_START - : ('a' .. 'z') | ('A' .. 'Z') | '_' + : ('a' .. 'z') | ('A' .. 'Z') | '_' | '$' ; fragment VALID_ID_CHAR @@ -138,9 +138,6 @@ fragment PREFIX_HEX : '0' ('X' | 'x') ; -fragment NUMBER_HEX2 - : '#' - ; fragment NUMBER_HEX : (('0' .. '9') | ('A' .. 'F') | ('a' .. 'f')) + diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.cs b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.cs index e202fab..0effe6b 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.cs +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.cs @@ -48,8 +48,8 @@ public const int "LPAREN", "RPAREN", "PLUS", "MINUS", "TIMES", "DIV", "COMMA", "POINT", "POW", "IDENTIFIER", "DECIMAL_NUMBER", "BINARY_NUMBER", "HEXADECIMAL_NUMBER", "SCIENTIFIC_NUMBER", "VALID_ID_START", "VALID_ID_CHAR", "PREFIX_DEC", - "NUMBER_DEC", "PREFIX_BIN", "NUMBER_BIN", "PREFIX_HEX", "NUMBER_HEX2", - "NUMBER_HEX", "E1", "E2", "SIGN", "WS" + "NUMBER_DEC", "PREFIX_BIN", "NUMBER_BIN", "PREFIX_HEX", "NUMBER_HEX", + "E1", "E2", "SIGN", "WS" }; @@ -99,7 +99,7 @@ static FormulaGrammerLexer() { } private static char[] _serializedATN = { '\x3', '\x608B', '\xA72A', '\x8133', '\xB9ED', '\x417C', '\x3BE7', '\x7786', - '\x5964', '\x2', '\x11', '\xA0', '\b', '\x1', '\x4', '\x2', '\t', '\x2', + '\x5964', '\x2', '\x11', '\x99', '\b', '\x1', '\x4', '\x2', '\t', '\x2', '\x4', '\x3', '\t', '\x3', '\x4', '\x4', '\t', '\x4', '\x4', '\x5', '\t', '\x5', '\x4', '\x6', '\t', '\x6', '\x4', '\a', '\t', '\a', '\x4', '\b', '\t', '\b', '\x4', '\t', '\t', '\t', '\x4', '\n', '\t', '\n', '\x4', '\v', @@ -109,128 +109,123 @@ static FormulaGrammerLexer() { '\x13', '\x4', '\x14', '\t', '\x14', '\x4', '\x15', '\t', '\x15', '\x4', '\x16', '\t', '\x16', '\x4', '\x17', '\t', '\x17', '\x4', '\x18', '\t', '\x18', '\x4', '\x19', '\t', '\x19', '\x4', '\x1A', '\t', '\x1A', '\x4', - '\x1B', '\t', '\x1B', '\x4', '\x1C', '\t', '\x1C', '\x3', '\x2', '\x3', - '\x2', '\x3', '\x3', '\x3', '\x3', '\x3', '\x4', '\x3', '\x4', '\x3', - '\x5', '\x3', '\x5', '\x3', '\x6', '\x3', '\x6', '\x3', '\a', '\x3', '\a', - '\x3', '\b', '\x3', '\b', '\x3', '\t', '\x3', '\t', '\x3', '\n', '\x3', - '\n', '\x3', '\v', '\x3', '\v', '\a', '\v', 'N', '\n', '\v', '\f', '\v', - '\xE', '\v', 'Q', '\v', '\v', '\x3', '\f', '\x5', '\f', 'T', '\n', '\f', - '\x3', '\f', '\x3', '\f', '\x3', '\r', '\x3', '\r', '\x3', '\r', '\x3', - '\xE', '\x3', '\xE', '\x5', '\xE', ']', '\n', '\xE', '\x3', '\xE', '\x3', - '\xE', '\x3', '\xF', '\x3', '\xF', '\x3', '\xF', '\x5', '\xF', '\x64', - '\n', '\xF', '\x3', '\xF', '\x5', '\xF', 'g', '\n', '\xF', '\x3', '\xF', - '\x3', '\xF', '\x3', '\x10', '\x5', '\x10', 'l', '\n', '\x10', '\x3', - '\x11', '\x3', '\x11', '\x5', '\x11', 'p', '\n', '\x11', '\x3', '\x12', - '\x3', '\x12', '\x3', '\x12', '\x3', '\x13', '\x6', '\x13', 'v', '\n', - '\x13', '\r', '\x13', '\xE', '\x13', 'w', '\x3', '\x13', '\x3', '\x13', - '\x6', '\x13', '|', '\n', '\x13', '\r', '\x13', '\xE', '\x13', '}', '\x5', - '\x13', '\x80', '\n', '\x13', '\x3', '\x14', '\x3', '\x14', '\x3', '\x14', - '\x3', '\x15', '\x6', '\x15', '\x86', '\n', '\x15', '\r', '\x15', '\xE', - '\x15', '\x87', '\x3', '\x16', '\x3', '\x16', '\x3', '\x16', '\x3', '\x17', - '\x3', '\x17', '\x3', '\x18', '\x6', '\x18', '\x90', '\n', '\x18', '\r', - '\x18', '\xE', '\x18', '\x91', '\x3', '\x19', '\x3', '\x19', '\x3', '\x1A', - '\x3', '\x1A', '\x3', '\x1B', '\x3', '\x1B', '\x3', '\x1C', '\x6', '\x1C', - '\x9B', '\n', '\x1C', '\r', '\x1C', '\xE', '\x1C', '\x9C', '\x3', '\x1C', - '\x3', '\x1C', '\x2', '\x2', '\x1D', '\x3', '\x3', '\x5', '\x4', '\a', - '\x5', '\t', '\x6', '\v', '\a', '\r', '\b', '\xF', '\t', '\x11', '\n', - '\x13', '\v', '\x15', '\f', '\x17', '\r', '\x19', '\xE', '\x1B', '\xF', - '\x1D', '\x10', '\x1F', '\x2', '!', '\x2', '#', '\x2', '%', '\x2', '\'', - '\x2', ')', '\x2', '+', '\x2', '-', '\x2', '/', '\x2', '\x31', '\x2', - '\x33', '\x2', '\x35', '\x2', '\x37', '\x11', '\x3', '\x2', '\t', '\x5', - '\x2', '\x43', '\\', '\x61', '\x61', '\x63', '|', '\x4', '\x2', '\x46', - '\x46', '\x66', '\x66', '\x4', '\x2', '\x44', '\x44', '\x64', '\x64', - '\x4', '\x2', 'Z', 'Z', 'z', 'z', '\x5', '\x2', '\x32', ';', '\x43', 'H', - '\x63', 'h', '\x4', '\x2', '-', '-', '/', '/', '\x5', '\x2', '\v', '\f', - '\xF', '\xF', '\"', '\"', '\x2', '\x9F', '\x2', '\x3', '\x3', '\x2', '\x2', - '\x2', '\x2', '\x5', '\x3', '\x2', '\x2', '\x2', '\x2', '\a', '\x3', '\x2', - '\x2', '\x2', '\x2', '\t', '\x3', '\x2', '\x2', '\x2', '\x2', '\v', '\x3', - '\x2', '\x2', '\x2', '\x2', '\r', '\x3', '\x2', '\x2', '\x2', '\x2', '\xF', - '\x3', '\x2', '\x2', '\x2', '\x2', '\x11', '\x3', '\x2', '\x2', '\x2', - '\x2', '\x13', '\x3', '\x2', '\x2', '\x2', '\x2', '\x15', '\x3', '\x2', - '\x2', '\x2', '\x2', '\x17', '\x3', '\x2', '\x2', '\x2', '\x2', '\x19', - '\x3', '\x2', '\x2', '\x2', '\x2', '\x1B', '\x3', '\x2', '\x2', '\x2', - '\x2', '\x1D', '\x3', '\x2', '\x2', '\x2', '\x2', '\x37', '\x3', '\x2', - '\x2', '\x2', '\x3', '\x39', '\x3', '\x2', '\x2', '\x2', '\x5', ';', '\x3', - '\x2', '\x2', '\x2', '\a', '=', '\x3', '\x2', '\x2', '\x2', '\t', '?', - '\x3', '\x2', '\x2', '\x2', '\v', '\x41', '\x3', '\x2', '\x2', '\x2', - '\r', '\x43', '\x3', '\x2', '\x2', '\x2', '\xF', '\x45', '\x3', '\x2', - '\x2', '\x2', '\x11', 'G', '\x3', '\x2', '\x2', '\x2', '\x13', 'I', '\x3', - '\x2', '\x2', '\x2', '\x15', 'K', '\x3', '\x2', '\x2', '\x2', '\x17', - 'S', '\x3', '\x2', '\x2', '\x2', '\x19', 'W', '\x3', '\x2', '\x2', '\x2', - '\x1B', '\\', '\x3', '\x2', '\x2', '\x2', '\x1D', '`', '\x3', '\x2', '\x2', - '\x2', '\x1F', 'k', '\x3', '\x2', '\x2', '\x2', '!', 'o', '\x3', '\x2', - '\x2', '\x2', '#', 'q', '\x3', '\x2', '\x2', '\x2', '%', 'u', '\x3', '\x2', - '\x2', '\x2', '\'', '\x81', '\x3', '\x2', '\x2', '\x2', ')', '\x85', '\x3', - '\x2', '\x2', '\x2', '+', '\x89', '\x3', '\x2', '\x2', '\x2', '-', '\x8C', - '\x3', '\x2', '\x2', '\x2', '/', '\x8F', '\x3', '\x2', '\x2', '\x2', '\x31', - '\x93', '\x3', '\x2', '\x2', '\x2', '\x33', '\x95', '\x3', '\x2', '\x2', - '\x2', '\x35', '\x97', '\x3', '\x2', '\x2', '\x2', '\x37', '\x9A', '\x3', - '\x2', '\x2', '\x2', '\x39', ':', '\a', '*', '\x2', '\x2', ':', '\x4', - '\x3', '\x2', '\x2', '\x2', ';', '<', '\a', '+', '\x2', '\x2', '<', '\x6', - '\x3', '\x2', '\x2', '\x2', '=', '>', '\a', '-', '\x2', '\x2', '>', '\b', - '\x3', '\x2', '\x2', '\x2', '?', '@', '\a', '/', '\x2', '\x2', '@', '\n', - '\x3', '\x2', '\x2', '\x2', '\x41', '\x42', '\a', ',', '\x2', '\x2', '\x42', - '\f', '\x3', '\x2', '\x2', '\x2', '\x43', '\x44', '\a', '\x31', '\x2', - '\x2', '\x44', '\xE', '\x3', '\x2', '\x2', '\x2', '\x45', '\x46', '\a', - '.', '\x2', '\x2', '\x46', '\x10', '\x3', '\x2', '\x2', '\x2', 'G', 'H', - '\a', '\x30', '\x2', '\x2', 'H', '\x12', '\x3', '\x2', '\x2', '\x2', 'I', - 'J', '\a', '`', '\x2', '\x2', 'J', '\x14', '\x3', '\x2', '\x2', '\x2', - 'K', 'O', '\x5', '\x1F', '\x10', '\x2', 'L', 'N', '\x5', '!', '\x11', - '\x2', 'M', 'L', '\x3', '\x2', '\x2', '\x2', 'N', 'Q', '\x3', '\x2', '\x2', - '\x2', 'O', 'M', '\x3', '\x2', '\x2', '\x2', 'O', 'P', '\x3', '\x2', '\x2', - '\x2', 'P', '\x16', '\x3', '\x2', '\x2', '\x2', 'Q', 'O', '\x3', '\x2', - '\x2', '\x2', 'R', 'T', '\x5', '#', '\x12', '\x2', 'S', 'R', '\x3', '\x2', - '\x2', '\x2', 'S', 'T', '\x3', '\x2', '\x2', '\x2', 'T', 'U', '\x3', '\x2', - '\x2', '\x2', 'U', 'V', '\x5', '%', '\x13', '\x2', 'V', '\x18', '\x3', - '\x2', '\x2', '\x2', 'W', 'X', '\x5', '\'', '\x14', '\x2', 'X', 'Y', '\x5', - ')', '\x15', '\x2', 'Y', '\x1A', '\x3', '\x2', '\x2', '\x2', 'Z', ']', - '\x5', '+', '\x16', '\x2', '[', ']', '\x5', '-', '\x17', '\x2', '\\', - 'Z', '\x3', '\x2', '\x2', '\x2', '\\', '[', '\x3', '\x2', '\x2', '\x2', - ']', '^', '\x3', '\x2', '\x2', '\x2', '^', '_', '\x5', '/', '\x18', '\x2', - '_', '\x1C', '\x3', '\x2', '\x2', '\x2', '`', '\x63', '\x5', '%', '\x13', - '\x2', '\x61', '\x64', '\x5', '\x31', '\x19', '\x2', '\x62', '\x64', '\x5', - '\x33', '\x1A', '\x2', '\x63', '\x61', '\x3', '\x2', '\x2', '\x2', '\x63', - '\x62', '\x3', '\x2', '\x2', '\x2', '\x64', '\x66', '\x3', '\x2', '\x2', - '\x2', '\x65', 'g', '\x5', '\x35', '\x1B', '\x2', '\x66', '\x65', '\x3', - '\x2', '\x2', '\x2', '\x66', 'g', '\x3', '\x2', '\x2', '\x2', 'g', 'h', - '\x3', '\x2', '\x2', '\x2', 'h', 'i', '\x5', '%', '\x13', '\x2', 'i', - '\x1E', '\x3', '\x2', '\x2', '\x2', 'j', 'l', '\t', '\x2', '\x2', '\x2', - 'k', 'j', '\x3', '\x2', '\x2', '\x2', 'l', ' ', '\x3', '\x2', '\x2', '\x2', - 'm', 'p', '\x5', '\x1F', '\x10', '\x2', 'n', 'p', '\x4', '\x32', ';', - '\x2', 'o', 'm', '\x3', '\x2', '\x2', '\x2', 'o', 'n', '\x3', '\x2', '\x2', - '\x2', 'p', '\"', '\x3', '\x2', '\x2', '\x2', 'q', 'r', '\a', '\x32', - '\x2', '\x2', 'r', 's', '\t', '\x3', '\x2', '\x2', 's', '$', '\x3', '\x2', - '\x2', '\x2', 't', 'v', '\x4', '\x32', ';', '\x2', 'u', 't', '\x3', '\x2', - '\x2', '\x2', 'v', 'w', '\x3', '\x2', '\x2', '\x2', 'w', 'u', '\x3', '\x2', - '\x2', '\x2', 'w', 'x', '\x3', '\x2', '\x2', '\x2', 'x', '\x7F', '\x3', - '\x2', '\x2', '\x2', 'y', '{', '\a', '\x30', '\x2', '\x2', 'z', '|', '\x4', - '\x32', ';', '\x2', '{', 'z', '\x3', '\x2', '\x2', '\x2', '|', '}', '\x3', - '\x2', '\x2', '\x2', '}', '{', '\x3', '\x2', '\x2', '\x2', '}', '~', '\x3', - '\x2', '\x2', '\x2', '~', '\x80', '\x3', '\x2', '\x2', '\x2', '\x7F', - 'y', '\x3', '\x2', '\x2', '\x2', '\x7F', '\x80', '\x3', '\x2', '\x2', - '\x2', '\x80', '&', '\x3', '\x2', '\x2', '\x2', '\x81', '\x82', '\a', - '\x32', '\x2', '\x2', '\x82', '\x83', '\t', '\x4', '\x2', '\x2', '\x83', - '(', '\x3', '\x2', '\x2', '\x2', '\x84', '\x86', '\x4', '\x32', '\x33', - '\x2', '\x85', '\x84', '\x3', '\x2', '\x2', '\x2', '\x86', '\x87', '\x3', - '\x2', '\x2', '\x2', '\x87', '\x85', '\x3', '\x2', '\x2', '\x2', '\x87', - '\x88', '\x3', '\x2', '\x2', '\x2', '\x88', '*', '\x3', '\x2', '\x2', - '\x2', '\x89', '\x8A', '\a', '\x32', '\x2', '\x2', '\x8A', '\x8B', '\t', - '\x5', '\x2', '\x2', '\x8B', ',', '\x3', '\x2', '\x2', '\x2', '\x8C', - '\x8D', '\a', '%', '\x2', '\x2', '\x8D', '.', '\x3', '\x2', '\x2', '\x2', - '\x8E', '\x90', '\t', '\x6', '\x2', '\x2', '\x8F', '\x8E', '\x3', '\x2', - '\x2', '\x2', '\x90', '\x91', '\x3', '\x2', '\x2', '\x2', '\x91', '\x8F', - '\x3', '\x2', '\x2', '\x2', '\x91', '\x92', '\x3', '\x2', '\x2', '\x2', - '\x92', '\x30', '\x3', '\x2', '\x2', '\x2', '\x93', '\x94', '\a', 'G', - '\x2', '\x2', '\x94', '\x32', '\x3', '\x2', '\x2', '\x2', '\x95', '\x96', - '\a', 'g', '\x2', '\x2', '\x96', '\x34', '\x3', '\x2', '\x2', '\x2', '\x97', - '\x98', '\t', '\a', '\x2', '\x2', '\x98', '\x36', '\x3', '\x2', '\x2', - '\x2', '\x99', '\x9B', '\t', '\b', '\x2', '\x2', '\x9A', '\x99', '\x3', - '\x2', '\x2', '\x2', '\x9B', '\x9C', '\x3', '\x2', '\x2', '\x2', '\x9C', - '\x9A', '\x3', '\x2', '\x2', '\x2', '\x9C', '\x9D', '\x3', '\x2', '\x2', - '\x2', '\x9D', '\x9E', '\x3', '\x2', '\x2', '\x2', '\x9E', '\x9F', '\b', - '\x1C', '\x2', '\x2', '\x9F', '\x38', '\x3', '\x2', '\x2', '\x2', '\x11', - '\x2', 'O', 'S', '\\', '\x63', '\x66', 'k', 'o', 'w', '}', '\x7F', '\x87', - '\x8F', '\x91', '\x9C', '\x3', '\b', '\x2', '\x2', + '\x1B', '\t', '\x1B', '\x3', '\x2', '\x3', '\x2', '\x3', '\x3', '\x3', + '\x3', '\x3', '\x4', '\x3', '\x4', '\x3', '\x5', '\x3', '\x5', '\x3', + '\x6', '\x3', '\x6', '\x3', '\a', '\x3', '\a', '\x3', '\b', '\x3', '\b', + '\x3', '\t', '\x3', '\t', '\x3', '\n', '\x3', '\n', '\x3', '\v', '\x3', + '\v', '\a', '\v', 'L', '\n', '\v', '\f', '\v', '\xE', '\v', 'O', '\v', + '\v', '\x3', '\f', '\x5', '\f', 'R', '\n', '\f', '\x3', '\f', '\x3', '\f', + '\x3', '\r', '\x3', '\r', '\x3', '\r', '\x3', '\xE', '\x3', '\xE', '\x3', + '\xE', '\x3', '\xF', '\x3', '\xF', '\x3', '\xF', '\x5', '\xF', '_', '\n', + '\xF', '\x3', '\xF', '\x5', '\xF', '\x62', '\n', '\xF', '\x3', '\xF', + '\x3', '\xF', '\x3', '\x10', '\x5', '\x10', 'g', '\n', '\x10', '\x3', + '\x11', '\x3', '\x11', '\x5', '\x11', 'k', '\n', '\x11', '\x3', '\x12', + '\x3', '\x12', '\x3', '\x12', '\x3', '\x13', '\x6', '\x13', 'q', '\n', + '\x13', '\r', '\x13', '\xE', '\x13', 'r', '\x3', '\x13', '\x3', '\x13', + '\x6', '\x13', 'w', '\n', '\x13', '\r', '\x13', '\xE', '\x13', 'x', '\x5', + '\x13', '{', '\n', '\x13', '\x3', '\x14', '\x3', '\x14', '\x3', '\x14', + '\x3', '\x15', '\x6', '\x15', '\x81', '\n', '\x15', '\r', '\x15', '\xE', + '\x15', '\x82', '\x3', '\x16', '\x3', '\x16', '\x3', '\x16', '\x3', '\x17', + '\x6', '\x17', '\x89', '\n', '\x17', '\r', '\x17', '\xE', '\x17', '\x8A', + '\x3', '\x18', '\x3', '\x18', '\x3', '\x19', '\x3', '\x19', '\x3', '\x1A', + '\x3', '\x1A', '\x3', '\x1B', '\x6', '\x1B', '\x94', '\n', '\x1B', '\r', + '\x1B', '\xE', '\x1B', '\x95', '\x3', '\x1B', '\x3', '\x1B', '\x2', '\x2', + '\x1C', '\x3', '\x3', '\x5', '\x4', '\a', '\x5', '\t', '\x6', '\v', '\a', + '\r', '\b', '\xF', '\t', '\x11', '\n', '\x13', '\v', '\x15', '\f', '\x17', + '\r', '\x19', '\xE', '\x1B', '\xF', '\x1D', '\x10', '\x1F', '\x2', '!', + '\x2', '#', '\x2', '%', '\x2', '\'', '\x2', ')', '\x2', '+', '\x2', '-', + '\x2', '/', '\x2', '\x31', '\x2', '\x33', '\x2', '\x35', '\x11', '\x3', + '\x2', '\t', '\x6', '\x2', '&', '&', '\x43', '\\', '\x61', '\x61', '\x63', + '|', '\x4', '\x2', '\x46', '\x46', '\x66', '\x66', '\x4', '\x2', '\x44', + '\x44', '\x64', '\x64', '\x4', '\x2', 'Z', 'Z', 'z', 'z', '\x5', '\x2', + '\x32', ';', '\x43', 'H', '\x63', 'h', '\x4', '\x2', '-', '-', '/', '/', + '\x5', '\x2', '\v', '\f', '\xF', '\xF', '\"', '\"', '\x2', '\x98', '\x2', + '\x3', '\x3', '\x2', '\x2', '\x2', '\x2', '\x5', '\x3', '\x2', '\x2', + '\x2', '\x2', '\a', '\x3', '\x2', '\x2', '\x2', '\x2', '\t', '\x3', '\x2', + '\x2', '\x2', '\x2', '\v', '\x3', '\x2', '\x2', '\x2', '\x2', '\r', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xF', '\x3', '\x2', '\x2', '\x2', '\x2', + '\x11', '\x3', '\x2', '\x2', '\x2', '\x2', '\x13', '\x3', '\x2', '\x2', + '\x2', '\x2', '\x15', '\x3', '\x2', '\x2', '\x2', '\x2', '\x17', '\x3', + '\x2', '\x2', '\x2', '\x2', '\x19', '\x3', '\x2', '\x2', '\x2', '\x2', + '\x1B', '\x3', '\x2', '\x2', '\x2', '\x2', '\x1D', '\x3', '\x2', '\x2', + '\x2', '\x2', '\x35', '\x3', '\x2', '\x2', '\x2', '\x3', '\x37', '\x3', + '\x2', '\x2', '\x2', '\x5', '\x39', '\x3', '\x2', '\x2', '\x2', '\a', + ';', '\x3', '\x2', '\x2', '\x2', '\t', '=', '\x3', '\x2', '\x2', '\x2', + '\v', '?', '\x3', '\x2', '\x2', '\x2', '\r', '\x41', '\x3', '\x2', '\x2', + '\x2', '\xF', '\x43', '\x3', '\x2', '\x2', '\x2', '\x11', '\x45', '\x3', + '\x2', '\x2', '\x2', '\x13', 'G', '\x3', '\x2', '\x2', '\x2', '\x15', + 'I', '\x3', '\x2', '\x2', '\x2', '\x17', 'Q', '\x3', '\x2', '\x2', '\x2', + '\x19', 'U', '\x3', '\x2', '\x2', '\x2', '\x1B', 'X', '\x3', '\x2', '\x2', + '\x2', '\x1D', '[', '\x3', '\x2', '\x2', '\x2', '\x1F', '\x66', '\x3', + '\x2', '\x2', '\x2', '!', 'j', '\x3', '\x2', '\x2', '\x2', '#', 'l', '\x3', + '\x2', '\x2', '\x2', '%', 'p', '\x3', '\x2', '\x2', '\x2', '\'', '|', + '\x3', '\x2', '\x2', '\x2', ')', '\x80', '\x3', '\x2', '\x2', '\x2', '+', + '\x84', '\x3', '\x2', '\x2', '\x2', '-', '\x88', '\x3', '\x2', '\x2', + '\x2', '/', '\x8C', '\x3', '\x2', '\x2', '\x2', '\x31', '\x8E', '\x3', + '\x2', '\x2', '\x2', '\x33', '\x90', '\x3', '\x2', '\x2', '\x2', '\x35', + '\x93', '\x3', '\x2', '\x2', '\x2', '\x37', '\x38', '\a', '*', '\x2', + '\x2', '\x38', '\x4', '\x3', '\x2', '\x2', '\x2', '\x39', ':', '\a', '+', + '\x2', '\x2', ':', '\x6', '\x3', '\x2', '\x2', '\x2', ';', '<', '\a', + '-', '\x2', '\x2', '<', '\b', '\x3', '\x2', '\x2', '\x2', '=', '>', '\a', + '/', '\x2', '\x2', '>', '\n', '\x3', '\x2', '\x2', '\x2', '?', '@', '\a', + ',', '\x2', '\x2', '@', '\f', '\x3', '\x2', '\x2', '\x2', '\x41', '\x42', + '\a', '\x31', '\x2', '\x2', '\x42', '\xE', '\x3', '\x2', '\x2', '\x2', + '\x43', '\x44', '\a', '.', '\x2', '\x2', '\x44', '\x10', '\x3', '\x2', + '\x2', '\x2', '\x45', '\x46', '\a', '\x30', '\x2', '\x2', '\x46', '\x12', + '\x3', '\x2', '\x2', '\x2', 'G', 'H', '\a', '`', '\x2', '\x2', 'H', '\x14', + '\x3', '\x2', '\x2', '\x2', 'I', 'M', '\x5', '\x1F', '\x10', '\x2', 'J', + 'L', '\x5', '!', '\x11', '\x2', 'K', 'J', '\x3', '\x2', '\x2', '\x2', + 'L', 'O', '\x3', '\x2', '\x2', '\x2', 'M', 'K', '\x3', '\x2', '\x2', '\x2', + 'M', 'N', '\x3', '\x2', '\x2', '\x2', 'N', '\x16', '\x3', '\x2', '\x2', + '\x2', 'O', 'M', '\x3', '\x2', '\x2', '\x2', 'P', 'R', '\x5', '#', '\x12', + '\x2', 'Q', 'P', '\x3', '\x2', '\x2', '\x2', 'Q', 'R', '\x3', '\x2', '\x2', + '\x2', 'R', 'S', '\x3', '\x2', '\x2', '\x2', 'S', 'T', '\x5', '%', '\x13', + '\x2', 'T', '\x18', '\x3', '\x2', '\x2', '\x2', 'U', 'V', '\x5', '\'', + '\x14', '\x2', 'V', 'W', '\x5', ')', '\x15', '\x2', 'W', '\x1A', '\x3', + '\x2', '\x2', '\x2', 'X', 'Y', '\x5', '+', '\x16', '\x2', 'Y', 'Z', '\x5', + '-', '\x17', '\x2', 'Z', '\x1C', '\x3', '\x2', '\x2', '\x2', '[', '^', + '\x5', '%', '\x13', '\x2', '\\', '_', '\x5', '/', '\x18', '\x2', ']', + '_', '\x5', '\x31', '\x19', '\x2', '^', '\\', '\x3', '\x2', '\x2', '\x2', + '^', ']', '\x3', '\x2', '\x2', '\x2', '_', '\x61', '\x3', '\x2', '\x2', + '\x2', '`', '\x62', '\x5', '\x33', '\x1A', '\x2', '\x61', '`', '\x3', + '\x2', '\x2', '\x2', '\x61', '\x62', '\x3', '\x2', '\x2', '\x2', '\x62', + '\x63', '\x3', '\x2', '\x2', '\x2', '\x63', '\x64', '\x5', '%', '\x13', + '\x2', '\x64', '\x1E', '\x3', '\x2', '\x2', '\x2', '\x65', 'g', '\t', + '\x2', '\x2', '\x2', '\x66', '\x65', '\x3', '\x2', '\x2', '\x2', 'g', + ' ', '\x3', '\x2', '\x2', '\x2', 'h', 'k', '\x5', '\x1F', '\x10', '\x2', + 'i', 'k', '\x4', '\x32', ';', '\x2', 'j', 'h', '\x3', '\x2', '\x2', '\x2', + 'j', 'i', '\x3', '\x2', '\x2', '\x2', 'k', '\"', '\x3', '\x2', '\x2', + '\x2', 'l', 'm', '\a', '\x32', '\x2', '\x2', 'm', 'n', '\t', '\x3', '\x2', + '\x2', 'n', '$', '\x3', '\x2', '\x2', '\x2', 'o', 'q', '\x4', '\x32', + ';', '\x2', 'p', 'o', '\x3', '\x2', '\x2', '\x2', 'q', 'r', '\x3', '\x2', + '\x2', '\x2', 'r', 'p', '\x3', '\x2', '\x2', '\x2', 'r', 's', '\x3', '\x2', + '\x2', '\x2', 's', 'z', '\x3', '\x2', '\x2', '\x2', 't', 'v', '\a', '\x30', + '\x2', '\x2', 'u', 'w', '\x4', '\x32', ';', '\x2', 'v', 'u', '\x3', '\x2', + '\x2', '\x2', 'w', 'x', '\x3', '\x2', '\x2', '\x2', 'x', 'v', '\x3', '\x2', + '\x2', '\x2', 'x', 'y', '\x3', '\x2', '\x2', '\x2', 'y', '{', '\x3', '\x2', + '\x2', '\x2', 'z', 't', '\x3', '\x2', '\x2', '\x2', 'z', '{', '\x3', '\x2', + '\x2', '\x2', '{', '&', '\x3', '\x2', '\x2', '\x2', '|', '}', '\a', '\x32', + '\x2', '\x2', '}', '~', '\t', '\x4', '\x2', '\x2', '~', '(', '\x3', '\x2', + '\x2', '\x2', '\x7F', '\x81', '\x4', '\x32', '\x33', '\x2', '\x80', '\x7F', + '\x3', '\x2', '\x2', '\x2', '\x81', '\x82', '\x3', '\x2', '\x2', '\x2', + '\x82', '\x80', '\x3', '\x2', '\x2', '\x2', '\x82', '\x83', '\x3', '\x2', + '\x2', '\x2', '\x83', '*', '\x3', '\x2', '\x2', '\x2', '\x84', '\x85', + '\a', '\x32', '\x2', '\x2', '\x85', '\x86', '\t', '\x5', '\x2', '\x2', + '\x86', ',', '\x3', '\x2', '\x2', '\x2', '\x87', '\x89', '\t', '\x6', + '\x2', '\x2', '\x88', '\x87', '\x3', '\x2', '\x2', '\x2', '\x89', '\x8A', + '\x3', '\x2', '\x2', '\x2', '\x8A', '\x88', '\x3', '\x2', '\x2', '\x2', + '\x8A', '\x8B', '\x3', '\x2', '\x2', '\x2', '\x8B', '.', '\x3', '\x2', + '\x2', '\x2', '\x8C', '\x8D', '\a', 'G', '\x2', '\x2', '\x8D', '\x30', + '\x3', '\x2', '\x2', '\x2', '\x8E', '\x8F', '\a', 'g', '\x2', '\x2', '\x8F', + '\x32', '\x3', '\x2', '\x2', '\x2', '\x90', '\x91', '\t', '\a', '\x2', + '\x2', '\x91', '\x34', '\x3', '\x2', '\x2', '\x2', '\x92', '\x94', '\t', + '\b', '\x2', '\x2', '\x93', '\x92', '\x3', '\x2', '\x2', '\x2', '\x94', + '\x95', '\x3', '\x2', '\x2', '\x2', '\x95', '\x93', '\x3', '\x2', '\x2', + '\x2', '\x95', '\x96', '\x3', '\x2', '\x2', '\x2', '\x96', '\x97', '\x3', + '\x2', '\x2', '\x2', '\x97', '\x98', '\b', '\x1B', '\x2', '\x2', '\x98', + '\x36', '\x3', '\x2', '\x2', '\x2', '\x10', '\x2', 'M', 'Q', '^', '\x61', + '\x66', 'j', 'r', 'x', 'z', '\x82', '\x88', '\x8A', '\x95', '\x3', '\b', + '\x2', '\x2', }; public static readonly ATN _ATN = diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.interp b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.interp index 69e18b5..ac1c6b0 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.interp +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.interp @@ -56,7 +56,6 @@ NUMBER_DEC PREFIX_BIN NUMBER_BIN PREFIX_HEX -NUMBER_HEX2 NUMBER_HEX E1 E2 @@ -71,4 +70,4 @@ mode names: DEFAULT_MODE atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 17, 160, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 7, 11, 78, 10, 11, 12, 11, 14, 11, 81, 11, 11, 3, 12, 5, 12, 84, 10, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 5, 14, 93, 10, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 5, 15, 100, 10, 15, 3, 15, 5, 15, 103, 10, 15, 3, 15, 3, 15, 3, 16, 5, 16, 108, 10, 16, 3, 17, 3, 17, 5, 17, 112, 10, 17, 3, 18, 3, 18, 3, 18, 3, 19, 6, 19, 118, 10, 19, 13, 19, 14, 19, 119, 3, 19, 3, 19, 6, 19, 124, 10, 19, 13, 19, 14, 19, 125, 5, 19, 128, 10, 19, 3, 20, 3, 20, 3, 20, 3, 21, 6, 21, 134, 10, 21, 13, 21, 14, 21, 135, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 6, 24, 144, 10, 24, 13, 24, 14, 24, 145, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 28, 6, 28, 155, 10, 28, 13, 28, 14, 28, 156, 3, 28, 3, 28, 2, 2, 29, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 2, 33, 2, 35, 2, 37, 2, 39, 2, 41, 2, 43, 2, 45, 2, 47, 2, 49, 2, 51, 2, 53, 2, 55, 17, 3, 2, 9, 5, 2, 67, 92, 97, 97, 99, 124, 4, 2, 70, 70, 102, 102, 4, 2, 68, 68, 100, 100, 4, 2, 90, 90, 122, 122, 5, 2, 50, 59, 67, 72, 99, 104, 4, 2, 45, 45, 47, 47, 5, 2, 11, 12, 15, 15, 34, 34, 2, 159, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 3, 57, 3, 2, 2, 2, 5, 59, 3, 2, 2, 2, 7, 61, 3, 2, 2, 2, 9, 63, 3, 2, 2, 2, 11, 65, 3, 2, 2, 2, 13, 67, 3, 2, 2, 2, 15, 69, 3, 2, 2, 2, 17, 71, 3, 2, 2, 2, 19, 73, 3, 2, 2, 2, 21, 75, 3, 2, 2, 2, 23, 83, 3, 2, 2, 2, 25, 87, 3, 2, 2, 2, 27, 92, 3, 2, 2, 2, 29, 96, 3, 2, 2, 2, 31, 107, 3, 2, 2, 2, 33, 111, 3, 2, 2, 2, 35, 113, 3, 2, 2, 2, 37, 117, 3, 2, 2, 2, 39, 129, 3, 2, 2, 2, 41, 133, 3, 2, 2, 2, 43, 137, 3, 2, 2, 2, 45, 140, 3, 2, 2, 2, 47, 143, 3, 2, 2, 2, 49, 147, 3, 2, 2, 2, 51, 149, 3, 2, 2, 2, 53, 151, 3, 2, 2, 2, 55, 154, 3, 2, 2, 2, 57, 58, 7, 42, 2, 2, 58, 4, 3, 2, 2, 2, 59, 60, 7, 43, 2, 2, 60, 6, 3, 2, 2, 2, 61, 62, 7, 45, 2, 2, 62, 8, 3, 2, 2, 2, 63, 64, 7, 47, 2, 2, 64, 10, 3, 2, 2, 2, 65, 66, 7, 44, 2, 2, 66, 12, 3, 2, 2, 2, 67, 68, 7, 49, 2, 2, 68, 14, 3, 2, 2, 2, 69, 70, 7, 46, 2, 2, 70, 16, 3, 2, 2, 2, 71, 72, 7, 48, 2, 2, 72, 18, 3, 2, 2, 2, 73, 74, 7, 96, 2, 2, 74, 20, 3, 2, 2, 2, 75, 79, 5, 31, 16, 2, 76, 78, 5, 33, 17, 2, 77, 76, 3, 2, 2, 2, 78, 81, 3, 2, 2, 2, 79, 77, 3, 2, 2, 2, 79, 80, 3, 2, 2, 2, 80, 22, 3, 2, 2, 2, 81, 79, 3, 2, 2, 2, 82, 84, 5, 35, 18, 2, 83, 82, 3, 2, 2, 2, 83, 84, 3, 2, 2, 2, 84, 85, 3, 2, 2, 2, 85, 86, 5, 37, 19, 2, 86, 24, 3, 2, 2, 2, 87, 88, 5, 39, 20, 2, 88, 89, 5, 41, 21, 2, 89, 26, 3, 2, 2, 2, 90, 93, 5, 43, 22, 2, 91, 93, 5, 45, 23, 2, 92, 90, 3, 2, 2, 2, 92, 91, 3, 2, 2, 2, 93, 94, 3, 2, 2, 2, 94, 95, 5, 47, 24, 2, 95, 28, 3, 2, 2, 2, 96, 99, 5, 37, 19, 2, 97, 100, 5, 49, 25, 2, 98, 100, 5, 51, 26, 2, 99, 97, 3, 2, 2, 2, 99, 98, 3, 2, 2, 2, 100, 102, 3, 2, 2, 2, 101, 103, 5, 53, 27, 2, 102, 101, 3, 2, 2, 2, 102, 103, 3, 2, 2, 2, 103, 104, 3, 2, 2, 2, 104, 105, 5, 37, 19, 2, 105, 30, 3, 2, 2, 2, 106, 108, 9, 2, 2, 2, 107, 106, 3, 2, 2, 2, 108, 32, 3, 2, 2, 2, 109, 112, 5, 31, 16, 2, 110, 112, 4, 50, 59, 2, 111, 109, 3, 2, 2, 2, 111, 110, 3, 2, 2, 2, 112, 34, 3, 2, 2, 2, 113, 114, 7, 50, 2, 2, 114, 115, 9, 3, 2, 2, 115, 36, 3, 2, 2, 2, 116, 118, 4, 50, 59, 2, 117, 116, 3, 2, 2, 2, 118, 119, 3, 2, 2, 2, 119, 117, 3, 2, 2, 2, 119, 120, 3, 2, 2, 2, 120, 127, 3, 2, 2, 2, 121, 123, 7, 48, 2, 2, 122, 124, 4, 50, 59, 2, 123, 122, 3, 2, 2, 2, 124, 125, 3, 2, 2, 2, 125, 123, 3, 2, 2, 2, 125, 126, 3, 2, 2, 2, 126, 128, 3, 2, 2, 2, 127, 121, 3, 2, 2, 2, 127, 128, 3, 2, 2, 2, 128, 38, 3, 2, 2, 2, 129, 130, 7, 50, 2, 2, 130, 131, 9, 4, 2, 2, 131, 40, 3, 2, 2, 2, 132, 134, 4, 50, 51, 2, 133, 132, 3, 2, 2, 2, 134, 135, 3, 2, 2, 2, 135, 133, 3, 2, 2, 2, 135, 136, 3, 2, 2, 2, 136, 42, 3, 2, 2, 2, 137, 138, 7, 50, 2, 2, 138, 139, 9, 5, 2, 2, 139, 44, 3, 2, 2, 2, 140, 141, 7, 37, 2, 2, 141, 46, 3, 2, 2, 2, 142, 144, 9, 6, 2, 2, 143, 142, 3, 2, 2, 2, 144, 145, 3, 2, 2, 2, 145, 143, 3, 2, 2, 2, 145, 146, 3, 2, 2, 2, 146, 48, 3, 2, 2, 2, 147, 148, 7, 71, 2, 2, 148, 50, 3, 2, 2, 2, 149, 150, 7, 103, 2, 2, 150, 52, 3, 2, 2, 2, 151, 152, 9, 7, 2, 2, 152, 54, 3, 2, 2, 2, 153, 155, 9, 8, 2, 2, 154, 153, 3, 2, 2, 2, 155, 156, 3, 2, 2, 2, 156, 154, 3, 2, 2, 2, 156, 157, 3, 2, 2, 2, 157, 158, 3, 2, 2, 2, 158, 159, 8, 28, 2, 2, 159, 56, 3, 2, 2, 2, 17, 2, 79, 83, 92, 99, 102, 107, 111, 119, 125, 127, 135, 143, 145, 156, 3, 8, 2, 2] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 17, 153, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 7, 11, 76, 10, 11, 12, 11, 14, 11, 79, 11, 11, 3, 12, 5, 12, 82, 10, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 5, 15, 95, 10, 15, 3, 15, 5, 15, 98, 10, 15, 3, 15, 3, 15, 3, 16, 5, 16, 103, 10, 16, 3, 17, 3, 17, 5, 17, 107, 10, 17, 3, 18, 3, 18, 3, 18, 3, 19, 6, 19, 113, 10, 19, 13, 19, 14, 19, 114, 3, 19, 3, 19, 6, 19, 119, 10, 19, 13, 19, 14, 19, 120, 5, 19, 123, 10, 19, 3, 20, 3, 20, 3, 20, 3, 21, 6, 21, 129, 10, 21, 13, 21, 14, 21, 130, 3, 22, 3, 22, 3, 22, 3, 23, 6, 23, 137, 10, 23, 13, 23, 14, 23, 138, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 6, 27, 148, 10, 27, 13, 27, 14, 27, 149, 3, 27, 3, 27, 2, 2, 28, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 2, 33, 2, 35, 2, 37, 2, 39, 2, 41, 2, 43, 2, 45, 2, 47, 2, 49, 2, 51, 2, 53, 17, 3, 2, 9, 6, 2, 38, 38, 67, 92, 97, 97, 99, 124, 4, 2, 70, 70, 102, 102, 4, 2, 68, 68, 100, 100, 4, 2, 90, 90, 122, 122, 5, 2, 50, 59, 67, 72, 99, 104, 4, 2, 45, 45, 47, 47, 5, 2, 11, 12, 15, 15, 34, 34, 2, 152, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 3, 55, 3, 2, 2, 2, 5, 57, 3, 2, 2, 2, 7, 59, 3, 2, 2, 2, 9, 61, 3, 2, 2, 2, 11, 63, 3, 2, 2, 2, 13, 65, 3, 2, 2, 2, 15, 67, 3, 2, 2, 2, 17, 69, 3, 2, 2, 2, 19, 71, 3, 2, 2, 2, 21, 73, 3, 2, 2, 2, 23, 81, 3, 2, 2, 2, 25, 85, 3, 2, 2, 2, 27, 88, 3, 2, 2, 2, 29, 91, 3, 2, 2, 2, 31, 102, 3, 2, 2, 2, 33, 106, 3, 2, 2, 2, 35, 108, 3, 2, 2, 2, 37, 112, 3, 2, 2, 2, 39, 124, 3, 2, 2, 2, 41, 128, 3, 2, 2, 2, 43, 132, 3, 2, 2, 2, 45, 136, 3, 2, 2, 2, 47, 140, 3, 2, 2, 2, 49, 142, 3, 2, 2, 2, 51, 144, 3, 2, 2, 2, 53, 147, 3, 2, 2, 2, 55, 56, 7, 42, 2, 2, 56, 4, 3, 2, 2, 2, 57, 58, 7, 43, 2, 2, 58, 6, 3, 2, 2, 2, 59, 60, 7, 45, 2, 2, 60, 8, 3, 2, 2, 2, 61, 62, 7, 47, 2, 2, 62, 10, 3, 2, 2, 2, 63, 64, 7, 44, 2, 2, 64, 12, 3, 2, 2, 2, 65, 66, 7, 49, 2, 2, 66, 14, 3, 2, 2, 2, 67, 68, 7, 46, 2, 2, 68, 16, 3, 2, 2, 2, 69, 70, 7, 48, 2, 2, 70, 18, 3, 2, 2, 2, 71, 72, 7, 96, 2, 2, 72, 20, 3, 2, 2, 2, 73, 77, 5, 31, 16, 2, 74, 76, 5, 33, 17, 2, 75, 74, 3, 2, 2, 2, 76, 79, 3, 2, 2, 2, 77, 75, 3, 2, 2, 2, 77, 78, 3, 2, 2, 2, 78, 22, 3, 2, 2, 2, 79, 77, 3, 2, 2, 2, 80, 82, 5, 35, 18, 2, 81, 80, 3, 2, 2, 2, 81, 82, 3, 2, 2, 2, 82, 83, 3, 2, 2, 2, 83, 84, 5, 37, 19, 2, 84, 24, 3, 2, 2, 2, 85, 86, 5, 39, 20, 2, 86, 87, 5, 41, 21, 2, 87, 26, 3, 2, 2, 2, 88, 89, 5, 43, 22, 2, 89, 90, 5, 45, 23, 2, 90, 28, 3, 2, 2, 2, 91, 94, 5, 37, 19, 2, 92, 95, 5, 47, 24, 2, 93, 95, 5, 49, 25, 2, 94, 92, 3, 2, 2, 2, 94, 93, 3, 2, 2, 2, 95, 97, 3, 2, 2, 2, 96, 98, 5, 51, 26, 2, 97, 96, 3, 2, 2, 2, 97, 98, 3, 2, 2, 2, 98, 99, 3, 2, 2, 2, 99, 100, 5, 37, 19, 2, 100, 30, 3, 2, 2, 2, 101, 103, 9, 2, 2, 2, 102, 101, 3, 2, 2, 2, 103, 32, 3, 2, 2, 2, 104, 107, 5, 31, 16, 2, 105, 107, 4, 50, 59, 2, 106, 104, 3, 2, 2, 2, 106, 105, 3, 2, 2, 2, 107, 34, 3, 2, 2, 2, 108, 109, 7, 50, 2, 2, 109, 110, 9, 3, 2, 2, 110, 36, 3, 2, 2, 2, 111, 113, 4, 50, 59, 2, 112, 111, 3, 2, 2, 2, 113, 114, 3, 2, 2, 2, 114, 112, 3, 2, 2, 2, 114, 115, 3, 2, 2, 2, 115, 122, 3, 2, 2, 2, 116, 118, 7, 48, 2, 2, 117, 119, 4, 50, 59, 2, 118, 117, 3, 2, 2, 2, 119, 120, 3, 2, 2, 2, 120, 118, 3, 2, 2, 2, 120, 121, 3, 2, 2, 2, 121, 123, 3, 2, 2, 2, 122, 116, 3, 2, 2, 2, 122, 123, 3, 2, 2, 2, 123, 38, 3, 2, 2, 2, 124, 125, 7, 50, 2, 2, 125, 126, 9, 4, 2, 2, 126, 40, 3, 2, 2, 2, 127, 129, 4, 50, 51, 2, 128, 127, 3, 2, 2, 2, 129, 130, 3, 2, 2, 2, 130, 128, 3, 2, 2, 2, 130, 131, 3, 2, 2, 2, 131, 42, 3, 2, 2, 2, 132, 133, 7, 50, 2, 2, 133, 134, 9, 5, 2, 2, 134, 44, 3, 2, 2, 2, 135, 137, 9, 6, 2, 2, 136, 135, 3, 2, 2, 2, 137, 138, 3, 2, 2, 2, 138, 136, 3, 2, 2, 2, 138, 139, 3, 2, 2, 2, 139, 46, 3, 2, 2, 2, 140, 141, 7, 71, 2, 2, 141, 48, 3, 2, 2, 2, 142, 143, 7, 103, 2, 2, 143, 50, 3, 2, 2, 2, 144, 145, 9, 7, 2, 2, 145, 52, 3, 2, 2, 2, 146, 148, 9, 8, 2, 2, 147, 146, 3, 2, 2, 2, 148, 149, 3, 2, 2, 2, 149, 147, 3, 2, 2, 2, 149, 150, 3, 2, 2, 2, 150, 151, 3, 2, 2, 2, 151, 152, 8, 27, 2, 2, 152, 54, 3, 2, 2, 2, 16, 2, 77, 81, 94, 97, 102, 106, 114, 120, 122, 130, 136, 138, 149, 3, 8, 2, 2] \ No newline at end of file diff --git a/ThinkSharp.FormulaParser/Ast/Visitors/EvaluateAstVisitor.cs b/ThinkSharp.FormulaParser/Ast/Visitors/EvaluateAstVisitor.cs index 9520cfa..ae34a44 100644 --- a/ThinkSharp.FormulaParser/Ast/Visitors/EvaluateAstVisitor.cs +++ b/ThinkSharp.FormulaParser/Ast/Visitors/EvaluateAstVisitor.cs @@ -10,9 +10,9 @@ internal class EvaluateAstVisitor : NodeVisitor private readonly IDictionary variables; private readonly IConfigurationEvaluator configuration; - public EvaluateAstVisitor(IConfigurationEvaluator configurationEvaluation, IDictionary variables = null) + public EvaluateAstVisitor(IConfigurationEvaluator configurationEvaluation, IReadOnlyDictionary variables = null) { - this.variables = new Dictionary(variables ?? new Dictionary()); + this.variables = variables?.ToDictionary(x => x.Key, x => x.Value) ?? new Dictionary(); this.configuration = configurationEvaluation ?? throw new ArgumentNullException(nameof(configurationEvaluation)); foreach (var constant in configurationEvaluation.EnumerateConstantes()) diff --git a/ThinkSharp.FormulaParser/FormulaParser.cs b/ThinkSharp.FormulaParser/FormulaParser.cs index 4add740..49ad08e 100644 --- a/ThinkSharp.FormulaParser/FormulaParser.cs +++ b/ThinkSharp.FormulaParser/FormulaParser.cs @@ -46,7 +46,7 @@ public FormulaParserResult Evaluate(string formula) return this.Evaluate(formula, null); } - public FormulaParserResult Evaluate(string formula, IDictionary variables) + public FormulaParserResult Evaluate(string formula, IReadOnlyDictionary variables) { return WrapWithExceptionHandling(() => { @@ -63,7 +63,7 @@ public FormulaParserResult Evaluate(Node formulaNode) return this.Evaluate(formulaNode, null); } - public FormulaParserResult Evaluate(Node formulaNode, IDictionary variables) + public FormulaParserResult Evaluate(Node formulaNode, IReadOnlyDictionary variables) { return WrapWithExceptionHandling(() => { @@ -76,7 +76,7 @@ public FormulaParserResult Evaluate(Node formulaNode, IDictionary Parse(string formula) => this.Parse(formula, null); - public FormulaParserResult Parse(string formula, IDictionary variables) + public FormulaParserResult Parse(string formula, IReadOnlyDictionary variables) { return WrapWithExceptionHandling(() => { @@ -87,7 +87,7 @@ public FormulaParserResult Parse(string formula, IDictionary RunVisitor(string formula, INodeVisitor visitor) => RunVisitor(formula, visitor, null); - public FormulaParserResult RunVisitor(string formula, INodeVisitor visitor, IDictionary variables) + public FormulaParserResult RunVisitor(string formula, INodeVisitor visitor, IReadOnlyDictionary variables) { return WrapWithExceptionHandling(() => { @@ -134,7 +134,7 @@ private static FormulaParserResult WrapWithExceptionHandling(F } - private Node ParseFormula(string formula, IDictionary variables) + private Node ParseFormula(string formula, IReadOnlyDictionary variables) { var inputStream = new AntlrInputStream(formula); var lexer = new FormulaGrammerLexer(inputStream); diff --git a/ThinkSharp.FormulaParser/IFormulaParser.cs b/ThinkSharp.FormulaParser/IFormulaParser.cs index 6f76ac0..7353628 100644 --- a/ThinkSharp.FormulaParser/IFormulaParser.cs +++ b/ThinkSharp.FormulaParser/IFormulaParser.cs @@ -33,7 +33,7 @@ public interface IFormulaParser /// /// The object that contains the evaluation result or an error. /// - FormulaParserResult Evaluate(string formula, IDictionary variables); + FormulaParserResult Evaluate(string formula, IReadOnlyDictionary variables); /// /// Evaluates the provided . @@ -58,7 +58,7 @@ public interface IFormulaParser /// /// The object that contains the evaluation result or an error. /// - FormulaParserResult Evaluate(Node formulaNode, IDictionary variables); + FormulaParserResult Evaluate(Node formulaNode, IReadOnlyDictionary variables); /// /// Parses the provided formula to a parsing tree. @@ -83,7 +83,7 @@ public interface IFormulaParser /// /// The object that contains the root node of the parsing tree or an error. /// - FormulaParserResult Parse(string formula, IDictionary variables); + FormulaParserResult Parse(string formula, IReadOnlyDictionary variables); /// /// Parses the formula and executes the visitor to the genereted parsing tree. @@ -120,7 +120,7 @@ public interface IFormulaParser /// /// The object that contains the result produced by the visitor or an error. /// - FormulaParserResult RunVisitor(string formula, INodeVisitor visitor, IDictionary variables); + FormulaParserResult RunVisitor(string formula, INodeVisitor visitor, IReadOnlyDictionary variables); /// /// Executes the visitor to the provided parsing tree. diff --git a/ThinkSharp.FormulaParser/ParserConfiguration.cs b/ThinkSharp.FormulaParser/ParserConfiguration.cs index 1caf788..88053ef 100644 --- a/ThinkSharp.FormulaParser/ParserConfiguration.cs +++ b/ThinkSharp.FormulaParser/ParserConfiguration.cs @@ -11,7 +11,7 @@ internal class ParserConfiguration : IParserConfiguration private readonly IConfiguration configuration; private readonly HashSet varialeNames; - public ParserConfiguration(IConfiguration configuration, IDictionary variables) + public ParserConfiguration(IConfiguration configuration, IReadOnlyDictionary variables) { this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); this.varialeNames = new HashSet(variables?.Keys ?? Enumerable.Empty()); diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj index 0e0a092..ecb491b 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj @@ -9,17 +9,16 @@ ThinkSharp A formula parser with fluent API that allows parsing and evaluation of mathematically formulas. Features: functions, constants, variables, scientific numbers, focus on customization and flexibility. © 2019 Jan-Niklas Schäfer - 0.4.0.0 - 0.4.0.0 + 0.5.0.0 + 0.5.0.0 LICENSE.txt - added another handle method for simlifying the handling of parsing / evaluation results. -added helper class for validating identifier names -added visitor for cloning a parsing tree -changed .ctor access modifier from internal to public for node types -removed formula text from formula node + changed variables API from IDictionary to IReadOnlyDictionary +added '$' as valid character for variables +removed support for alternative hex number notation: '#<hexnumber>'. Note that the main notation '0x<hexnumber' is still supported. + https://github.com/JanDotNet/ThinkSharp.FormulaParser true - 0.4.0 + 0.5.0 From 5bc5d633012355362859f1cf28385cf374acabf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Sun, 20 Oct 2019 08:05:07 +0200 Subject: [PATCH 27/45] WIP --- .../NodesToFormulaTextVisitor.cs | 33 ++++ .../TermPlusOrMinusZeroIsTermRuleTest.cs | 55 +++++++ ...sOrDividedByMinusOneIsMinusTermRuleTest.cs | 69 ++++++++ .../TermTimesOrDividedByOneIsTermRuleTest.cs | 55 +++++++ ...nkSharp.FluentFormulaParser.Test.projitems | 4 + .../TermRewriting/ITermRewritingSystem.cs | 12 ++ .../TermRewriting/ReplaceRuleTreeVisitor.cs | 103 ++++++++++++ .../Rules/MoveOuterSignedToInnerTerm.cs | 155 ++++++++++++++++++ .../TermRewriting/Rules/Rule.cs | 14 ++ .../Rules/TermDividesByTermIsOne.cs | 72 ++++++++ .../Rules/TermPlusOrMinusZeroIsTerm.cs | 72 ++++++++ ...TermTimesOrDividedByMinusOneIsMinusTerm.cs | 85 ++++++++++ .../Rules/TermTimesOrDividedByOneIsTerm.cs | 66 ++++++++ .../TermRewriting/TermRewritingSystem.cs | 47 ++++++ .../ThinkSharp.FormulaParser.csproj | 9 + .../ThinkSharp.FormulaParser.xml | 8 +- 16 files changed, 855 insertions(+), 4 deletions(-) create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/NodesToFormulaTextVisitor.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/TermPlusOrMinusZeroIsTermRuleTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByMinusOneIsMinusTermRuleTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByOneIsTermRuleTest.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/ITermRewritingSystem.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/ReplaceRuleTreeVisitor.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/MoveOuterSignedToInnerTerm.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/Rule.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/TermDividesByTermIsOne.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/TermPlusOrMinusZeroIsTerm.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTerm.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByOneIsTerm.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/NodesToFormulaTextVisitor.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/NodesToFormulaTextVisitor.cs new file mode 100644 index 0000000..01ab3e3 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/NodesToFormulaTextVisitor.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.Ast.Visitors; + +namespace ThinkSharp.FormulaParsing.Test.TermRewriting +{ + internal class NodesToFormulaTextVisitor : INodeVisitor + { + public string Visit(FormulaNode node) + { + return node.ChildNode.Visit(this); + } + + public string Visit(BracketedNode node) => $"({node.ChildNode.Visit(this)})"; + + public string Visit(NumberNode node) => node.Token; + + public string Visit(VariableNode node) => node.Name; + + public string Visit(ConstantNode node) => node.Name; + + public string Visit(BinaryOperatorNode node) => $"{node.LeftNode.Visit(this)}{node.BinaryOperator.Symbol}{node.RightNode.Visit(this)}"; + + public string Visit(PowerNode node) => $"{node.BaseNode.Visit(this)}^{node.ExponentNode.Visit(this)}"; + + public string Visit(SignedNode node) => (node.Sign == Sign.Minus ? "-" : "") + node.Node.Visit(this); + + public string Visit(FunctionNode node) => $"{node.FunctionName}({string.Join(", ", node.Parameters.Select(p => p.Visit(this)))})"; + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/TermPlusOrMinusZeroIsTermRuleTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/TermPlusOrMinusZeroIsTermRuleTest.cs new file mode 100644 index 0000000..7842ecc --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/TermPlusOrMinusZeroIsTermRuleTest.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; + +namespace ThinkSharp.FormulaParsing.Test.TermRewriting +{ + [TestClass] + public class TermPlusOrMinusZeroIsTermRuleTest + { + private static IFormulaParser parser = FormulaParser + .CreateBuilder() + .ConfigureValidationBehavior(v => v.DisableVariableNameValidation()) + .Build(); + private static ITermRewritingSystem[] rewritingSystems = new ITermRewritingSystem[] + { + TermRewritingSystem.ForTesting(new TermPlusOrMinusZeroIsTermRule()) + }; + + [TestMethod] + public void Test_OnePlusZeroIsOne() => AssertRewritten("1", "1+0"); + + [TestMethod] + public void Test_ZeroPlusOneIsOne() => AssertRewritten("1", "1+0"); + + [TestMethod] + public void Test_OneMinusZeroIsOne() => AssertRewritten("1", "1-0"); + + [TestMethod] + public void Test_ZeroMinusOneIsMinusOne() => AssertRewritten("-1", "0-1"); + + [TestMethod] + public void Test_OneTimesOnePlusZeroIsOneTimesOne() => AssertRewritten("1*1", "1*1+0"); + + [TestMethod] + public void Test_APlusMinusManyZerusPlusAIsAPlusA() => AssertRewritten("a+a", "a+0-0+0-0+0-0+0+0+0+a"); + + private void AssertRewritten(string expected, string forumla) + { + foreach (var system in rewritingSystems) + { + var tree = parser.Parse(forumla).Value; + + var simlifiedTree = system.Simplify(tree); + + var nodeToTExtVisitor = new NodesToFormulaTextVisitor(); + + Assert.AreEqual(expected, simlifiedTree.Visit(nodeToTExtVisitor)); + } + } + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByMinusOneIsMinusTermRuleTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByMinusOneIsMinusTermRuleTest.cs new file mode 100644 index 0000000..021a0e1 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByMinusOneIsMinusTermRuleTest.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; + +namespace ThinkSharp.FormulaParsing.Test.TermRewriting +{ + [TestClass] + public class TermTimesOrDividedByMinusOneIsMinusTermRuleTest + { + private static IFormulaParser parser = FormulaParser + .CreateBuilder() + .ConfigureValidationBehavior(v => v.DisableVariableNameValidation()) + .Build(); + private static ITermRewritingSystem[] rewritingSystems = new ITermRewritingSystem[] + { + TermRewritingSystem.ForTesting( + new MoveOuterSignedToInnerTerm(), + new TermTimesOrDividedByMinusOneIsMinusTerm()) + }; + + [TestMethod] + public void Test_OneTImesOne() => AssertRewritten("-1", "1*-1"); + + [TestMethod] + public void Test_ATimesOne() => AssertRewritten("-a", "a*-1"); + + [TestMethod] + public void Test_OneTimesA() => AssertRewritten("-a", "-1*a"); + + [TestMethod] + public void Test_ADividedByOne() => AssertRewritten("-a", "a/-1"); + + [TestMethod] + public void Test_OneDividedByA() => AssertRewritten("-1/a", "-1/a"); + + [TestMethod] + public void Test_MinsADividedByMinusOne() => AssertRewritten("a", "-a/-1"); + + [TestMethod] + public void Test_MinusOneTimesMinsADividedByMinusOne() => AssertRewritten("-a", "-1*-a/-1"); + + [TestMethod] + public void Test_MinusOneTimesMinsADividedByMinusOne2() => AssertRewritten("-a*-a", "a*-a/-1"); + + [TestMethod] + public void Test_MinusOneTimesMinsADividedByMinusOne3() => AssertRewritten("a*-a", "a*-1*-a/-1"); + + [TestMethod] + public void Test_AManyTimeOneTimeADividedByOne() => AssertRewritten("a*a", "a*-1*-1*-1*-1*-1*a/-1"); + + private void AssertRewritten(string expected, string forumla) + { + foreach (var system in rewritingSystems) + { + var tree = parser.Parse(forumla).Value; + + var simlifiedTree = system.Simplify(tree); + + var nodeToTExtVisitor = new NodesToFormulaTextVisitor(); + + Assert.AreEqual(expected, simlifiedTree.Visit(nodeToTExtVisitor)); + } + } + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByOneIsTermRuleTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByOneIsTermRuleTest.cs new file mode 100644 index 0000000..e7b1495 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByOneIsTermRuleTest.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; + +namespace ThinkSharp.FormulaParsing.Test.TermRewriting +{ + [TestClass] + public class TermTimesOrDividedByOneIsTermRuleTest + { + private static IFormulaParser parser = FormulaParser + .CreateBuilder() + .ConfigureValidationBehavior(v => v.DisableVariableNameValidation()) + .Build(); + private static ITermRewritingSystem[] rewritingSystems = new ITermRewritingSystem[] + { + TermRewritingSystem.ForTesting(new TermTimesOrDividedByOneIsTerm()) + }; + + [TestMethod] + public void Test_OneTImesOne() => AssertRewritten("1", "1*1"); + + [TestMethod] + public void Test_ATimesOne() => AssertRewritten("a", "a*1"); + + [TestMethod] + public void Test_OneTimesA() => AssertRewritten("a", "1*a"); + + [TestMethod] + public void Test_ADividedByOne() => AssertRewritten("a", "a/1"); + + [TestMethod] + public void Test_OneDividedByA() => AssertRewritten("1/a", "1/a"); + + [TestMethod] + public void Test_AManyTimeOneTimeADividedByOne() => AssertRewritten("a*a", "a*1*1*1*1*1*a/1"); + + private void AssertRewritten(string expected, string forumla) + { + foreach (var system in rewritingSystems) + { + var tree = parser.Parse(forumla).Value; + + var simlifiedTree = system.Simplify(tree); + + var nodeToTExtVisitor = new NodesToFormulaTextVisitor(); + + Assert.AreEqual(expected, simlifiedTree.Visit(nodeToTExtVisitor)); + } + } + } +} diff --git a/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems b/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems index 71b12f7..38acb31 100644 --- a/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems +++ b/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems @@ -17,5 +17,9 @@ + + + + \ No newline at end of file diff --git a/ThinkSharp.FormulaParser/TermRewriting/ITermRewritingSystem.cs b/ThinkSharp.FormulaParser/TermRewriting/ITermRewritingSystem.cs new file mode 100644 index 0000000..06910b8 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/ITermRewritingSystem.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting +{ + public interface ITermRewritingSystem + { + Node Simplify(Node node); + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/ReplaceRuleTreeVisitor.cs b/ThinkSharp.FormulaParser/TermRewriting/ReplaceRuleTreeVisitor.cs new file mode 100644 index 0000000..a7b2657 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/ReplaceRuleTreeVisitor.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.Ast.Visitors; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; + +namespace ThinkSharp.FormulaParsing.TermRewriting +{ + internal class ReplaceRuleTreeVisitor : INodeVisitor + { + private readonly Rule rule; + + public ReplaceRuleTreeVisitor(Rule rule) + { + this.rule = rule; + } + + public Node Visit(FormulaNode node) + => TryRewrite(node.ChildNode, out Node rewrittenNode) + ? new FormulaNode(rewrittenNode) + : node; + + public Node Visit(BracketedNode node) + => TryRewrite(node.ChildNode, out Node rewrittenNode) + ? new BracketedNode(rewrittenNode) + : node; + + public Node Visit(NumberNode node) + => node; + + public Node Visit(VariableNode node) + => node; + + public Node Visit(ConstantNode node) + => node; + + public Node Visit(BinaryOperatorNode node) + { + if (TryRewrite(node.LeftNode, out Node leftRewritten)) + { + return new BinaryOperatorNode(node.BinaryOperator, leftRewritten, node.RightNode); + } + if (TryRewrite(node.RightNode, out Node rightRewritten)) + { + return new BinaryOperatorNode(node.BinaryOperator, node.LeftNode, rightRewritten); + } + return node; + } + + public Node Visit(PowerNode node) + { + if (TryRewrite(node.BaseNode, out Node rewrittenBaseNode)) + { + return new PowerNode(rewrittenBaseNode, node.ExponentNode); + } + if (TryRewrite(node.BaseNode, out Node rewrittenExponentNode)) + { + return new PowerNode(node.BaseNode, rewrittenExponentNode); + } + return node; + } + + public Node Visit(SignedNode node) + => TryRewrite(node.Node, out Node rewrittenNode) + ? new SignedNode(node.Sign, rewrittenNode) + : node; + + public Node Visit(FunctionNode node) + { + var rewrittenParameters = new List(); + var hasRewrittenParameters = false; + foreach (var argumentNode in node.Parameters) + { + if (TryRewrite(argumentNode, out Node rewrittenNode)) + { + rewrittenParameters.Add(rewrittenNode); + hasRewrittenParameters = true; + } + else + { + rewrittenParameters.Add(argumentNode); + } + } + + return hasRewrittenParameters + ? new FunctionNode(node.FunctionName, rewrittenParameters.ToArray()) + : node; + } + + private bool TryRewrite(Node node, out Node rewrittenNode) + { + if (this.rule.Match(node)) + { + rewrittenNode = rule.Rewrite(node); + return true; + } + + rewrittenNode = node.Visit(this); + return rewrittenNode != node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/MoveOuterSignedToInnerTerm.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/MoveOuterSignedToInnerTerm.cs new file mode 100644 index 0000000..493ed47 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/MoveOuterSignedToInnerTerm.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.Ast.Visitors; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class MoveOuterSignedToInnerTerm : Rule + { + private class SwitchSignWithinBracketsVisitor : INodeVisitor + { + public Node Visit(FormulaNode node) => node.ChildNode.Visit(this); + + public Node Visit(BracketedNode node) => node; + + public Node Visit(NumberNode node) => node; + + public Node Visit(VariableNode node) => node; + + public Node Visit(ConstantNode node) => node; + + public Node Visit(BinaryOperatorNode node) + { + var newLeft = node.LeftNode.Visit(this); + var newRight = node.RightNode.Visit(this); + + var symbol = node.BinaryOperator.Symbol; + var op = symbol == "+" ? BinaryOperator.BySymbol("-") + : symbol == "-" ? BinaryOperator.BySymbol("+") + : node.BinaryOperator; + + return new BinaryOperatorNode(op, newLeft, newRight); + } + + public Node Visit(PowerNode node) => node; + + public Node Visit(SignedNode node) => node; + + public Node Visit(FunctionNode node) => node; + } + + public override bool Match(Node node) + { + if (node is SignedNode signNode) + { + if (signNode.Sign == Sign.Plus) + { + return true; + } + + var targetNode = signNode.Node; + while (targetNode is BinaryOperatorNode binaryOperationNode) + { + targetNode = binaryOperationNode.LeftNode; + } + + if (targetNode == signNode.Node) + { + return targetNode is BracketedNode || + targetNode is NumberNode; + } + + return targetNode is BracketedNode || + targetNode is SignedNode || + targetNode is ConstantNode || + targetNode is FunctionNode || + targetNode is NumberNode || + targetNode is PowerNode || + targetNode is VariableNode; + } + + return false; + } + + public override Node Rewrite(Node node) + { + if (node is SignedNode signNode) + { + if (signNode.Sign == Sign.Plus) + { + return signNode.Node; + } + + var targetNode = signNode.Node; + if (targetNode is BracketedNode targetBracketedNode) + { + var newBracketedContentNode = targetBracketedNode.Visit(new SwitchSignWithinBracketsVisitor()); + return new SignedNode(Sign.Minus, newBracketedContentNode); + } + + var binOpQueue = new Queue(); + while (targetNode is BinaryOperatorNode binaryOperationNode) + { + binOpQueue.Enqueue(binaryOperationNode); + targetNode = binaryOperationNode.LeftNode; + } + + var transformedNode = TransformedNode(targetNode); + + if (transformedNode != null) + { + Node leftNode = transformedNode; + while (binOpQueue.Count > 0) + { + var binOpFromQueue = binOpQueue.Dequeue(); + leftNode = new BinaryOperatorNode(binOpFromQueue.BinaryOperator, leftNode, binOpFromQueue.RightNode); + } + return leftNode; + } + } + + Debug.Fail("Should not happen"); + return node; + } + + private Node TransformedNode(Node targetNode) + { + if (targetNode is BracketedNode targetBracketedNode) + { + var newBracketedContentNode = targetBracketedNode.Visit(new SwitchSignWithinBracketsVisitor()); + var newSignedBracketedContentNode = new SignedNode(Sign.Minus, newBracketedContentNode); + return new BracketedNode(newSignedBracketedContentNode); + } + + if (targetNode is SignedNode targetSignedNode) + { + if (targetSignedNode.Sign == Sign.Minus) + { + return targetSignedNode.Node; + } + return new SignedNode(Sign.Minus, targetSignedNode.Node); + } + + if (targetNode is ConstantNode + || targetNode is FunctionNode + || targetNode is PowerNode + || targetNode is VariableNode) + { + return new SignedNode(Sign.Minus, targetNode); + } + + if (targetNode is NumberNode numberNode) + { + var token = numberNode.Token[0] == '-' + ? numberNode.Token.Substring(1) + : "-" + numberNode.Token; + return new NumberNode(token, numberNode.Value * -1); + } + + return null; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/Rule.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/Rule.cs new file mode 100644 index 0000000..6a06a0d --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/Rule.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public abstract class Rule + { + public abstract bool Match(Node node); + + public abstract Node Rewrite(Node node); + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermDividesByTermIsOne.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermDividesByTermIsOne.cs new file mode 100644 index 0000000..3dc0e31 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermDividesByTermIsOne.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class TermDividesByTermIsOne : Rule + { + public override bool Match(Node node) + { + if (node is BinaryOperatorNode opNode) + { + if (opNode.BinaryOperator.Symbol == "+" || + opNode.BinaryOperator.Symbol == "-") + { + if (opNode.LeftNode is NumberNode leftNumNode) + { + if (leftNumNode.Value == 0.0) + { + return true; + } + } + + if (opNode.RightNode is NumberNode rightNumNode) + { + if (rightNumNode.Value == 0.0) + { + return true; + } + } + } + } + + return false; + } + + public override Node Rewrite(Node node) + { + if (node is BinaryOperatorNode opNode) + { + var isAddOperation = opNode.BinaryOperator.Symbol == "+"; + var isSubOperation = opNode.BinaryOperator.Symbol == "-"; + + if (isAddOperation || isSubOperation) + { + if (opNode.LeftNode is NumberNode leftNumNode) + { + if (leftNumNode.Value == 0.0) + { + return isSubOperation + ? new SignedNode(Sign.Minus, opNode.RightNode) + : opNode.RightNode; + } + } + + if (opNode.RightNode is NumberNode rightNumNode) + { + if (rightNumNode.Value == 0.0) + { + return opNode.LeftNode; + } + } + } + } + + Debug.Fail("Should not happen"); + return node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermPlusOrMinusZeroIsTerm.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermPlusOrMinusZeroIsTerm.cs new file mode 100644 index 0000000..745398d --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermPlusOrMinusZeroIsTerm.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class TermPlusOrMinusZeroIsTermRule : Rule + { + public override bool Match(Node node) + { + if (node is BinaryOperatorNode opNode) + { + if (opNode.BinaryOperator.Symbol == "+" || + opNode.BinaryOperator.Symbol == "-") + { + if (opNode.LeftNode is NumberNode leftNumNode) + { + if (leftNumNode.Value == 0.0) + { + return true; + } + } + + if (opNode.RightNode is NumberNode rightNumNode) + { + if (rightNumNode.Value == 0.0) + { + return true; + } + } + } + } + + return false; + } + + public override Node Rewrite(Node node) + { + if (node is BinaryOperatorNode opNode) + { + var isAddOperation = opNode.BinaryOperator.Symbol == "+"; + var isSubOperation = opNode.BinaryOperator.Symbol == "-"; + + if (isAddOperation || isSubOperation) + { + if (opNode.LeftNode is NumberNode leftNumNode) + { + if (leftNumNode.Value == 0.0) + { + return isSubOperation + ? new SignedNode(Sign.Minus, opNode.RightNode) + : opNode.RightNode; + } + } + + if (opNode.RightNode is NumberNode rightNumNode) + { + if (rightNumNode.Value == 0.0) + { + return opNode.LeftNode; + } + } + } + } + + Debug.Fail("Should not happen"); + return node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTerm.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTerm.cs new file mode 100644 index 0000000..da4da89 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTerm.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class TermTimesOrDividedByMinusOneIsMinusTerm : Rule + { + public override bool Match(Node node) + { + if (node is BinaryOperatorNode opNode) + { + var isTimes = opNode.BinaryOperator.Symbol == "*"; + var isDividedBy = opNode.BinaryOperator.Symbol == "/"; + + if (isTimes && opNode.LeftNode is NumberNode leftNumNode) + { + if (leftNumNode.Value == -1.0) + { + return true; + } + } + + if ((isTimes || isDividedBy) && opNode.RightNode is NumberNode rightNumNode) + { + if (rightNumNode.Value == -1.0) + { + return true; + } + } + } + + return false; + } + + public override Node Rewrite(Node node) + { + if (node is BinaryOperatorNode opNode) + { + var isTimes = opNode.BinaryOperator.Symbol == "*"; + var isDividedBy = opNode.BinaryOperator.Symbol == "/"; + + if (isTimes && opNode.LeftNode is NumberNode leftNumNode) + { + if (leftNumNode.Value == -1.0) + { + if (opNode.RightNode is SignedNode rightSignedNode) + { + if (rightSignedNode.Sign == Sign.Minus) + { + return rightSignedNode.Node; + } + return new SignedNode(Sign.Minus, rightSignedNode.Node); + } + + return new SignedNode(Sign.Minus, opNode.RightNode); + } + } + + if ((isTimes || isDividedBy) && opNode.RightNode is NumberNode rightNumNode) + { + if (rightNumNode.Value == -1.0) + { + if (opNode.LeftNode is SignedNode leftSignedNode) + { + if (leftSignedNode.Sign == Sign.Minus) + { + return leftSignedNode.Node; + } + + return new SignedNode(Sign.Minus, leftSignedNode.Node); + } + + return new SignedNode(Sign.Minus, opNode.LeftNode); + } + } + } + + Debug.Fail("Should not happen"); + return node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByOneIsTerm.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByOneIsTerm.cs new file mode 100644 index 0000000..fb8da57 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByOneIsTerm.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class TermTimesOrDividedByOneIsTerm : Rule + { + public override bool Match(Node node) + { + if (node is BinaryOperatorNode opNode) + { + var isTimes = opNode.BinaryOperator.Symbol == "*"; + var isDividedBy = opNode.BinaryOperator.Symbol == "/"; + + if (isTimes && opNode.LeftNode is NumberNode leftNumNode) + { + if (leftNumNode.Value == 1.0) + { + return true; + } + } + + if ((isTimes || isDividedBy) && opNode.RightNode is NumberNode rightNumNode) + { + if (rightNumNode.Value == 1.0) + { + return true; + } + } + } + + return false; + } + + public override Node Rewrite(Node node) + { + if (node is BinaryOperatorNode opNode) + { + var isTimes = opNode.BinaryOperator.Symbol == "*"; + var isDividedBy = opNode.BinaryOperator.Symbol == "/"; + + if (isTimes && opNode.LeftNode is NumberNode leftNumNode) + { + if (leftNumNode.Value == 1.0) + { + return opNode.RightNode; + } + } + + if ((isTimes || isDividedBy) && opNode.RightNode is NumberNode rightNumNode) + { + if (rightNumNode.Value == 1.0) + { + return opNode.LeftNode; + } + } + } + + Debug.Fail("Should not happen"); + return node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs b/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs new file mode 100644 index 0000000..917d651 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; + +namespace ThinkSharp.FormulaParsing.TermRewriting +{ + public class TermRewritingSystem : ITermRewritingSystem + { + public static ITermRewritingSystem Create() + { + var system = new TermRewritingSystem(); + system.rules.Add(new TermPlusOrMinusZeroIsTermRule()); + return system; + } + + public static ITermRewritingSystem ForTesting(params Rule[] rulesToTest) + { + var system = new TermRewritingSystem(); + foreach (var rule in rulesToTest) + system.rules.Add(rule); + return system; + } + + private List rules = new List(); + public Node Simplify(Node node) => SimplyfyInternal(node); + + private Node SimplyfyInternal(Node node) + { + + var visitors = rules.Select(r => new ReplaceRuleTreeVisitor(r)).ToArray(); + + Node simlifiedNode = node; + Node previousSimlifiedNode = node; + do + { + previousSimlifiedNode = simlifiedNode; + foreach (var visitor in visitors) + simlifiedNode = simlifiedNode.Visit(visitor); + } while (simlifiedNode != previousSimlifiedNode); + + return simlifiedNode; + } + } +} diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj index ecb491b..bd40e7c 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj @@ -40,4 +40,13 @@ removed support for alternative hex number notation: '#<hexnumber>'. Note + + + <_Parameter1>$(MSBuildProjectName).Test.Core + + + <_Parameter1>$(MSBuildProjectName).Test.Net461 + + + diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml index bdb5b4f..c665a74 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml @@ -217,7 +217,7 @@ The object that contains the evaluation result or an error. - + Evaluates the provided formula to a numeric value. @@ -242,7 +242,7 @@ The object that contains the evaluation result or an error. - + Evaluates the provided . @@ -267,7 +267,7 @@ The object that contains the root node of the parsing tree or an error. - + Parses the provided formula to a parsing tree. @@ -298,7 +298,7 @@ The object that contains the result produced by the visitor or an error. - + Parses the formula and executes the visitor to the genereted parsing tree. From 97a0785c68c0e689006672bcb7c4ea6a7fc5f81e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Sun, 20 Oct 2019 08:47:40 +0200 Subject: [PATCH 28/45] added MoveOuterMinusToInnerTermRuleTest --- .../MoveOuterMinusToInnerTermRuleTest.cs | 59 +++++++++++++++++++ ...sOrDividedByMinusOneIsMinusTermRuleTest.cs | 2 +- ...nkSharp.FluentFormulaParser.Test.projitems | 1 + ...erTerm.cs => MoveOuterMinusToInnerTerm.cs} | 12 ++-- 4 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/MoveOuterMinusToInnerTermRuleTest.cs rename ThinkSharp.FormulaParser/TermRewriting/Rules/{MoveOuterSignedToInnerTerm.cs => MoveOuterMinusToInnerTerm.cs} (93%) diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/MoveOuterMinusToInnerTermRuleTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/MoveOuterMinusToInnerTermRuleTest.cs new file mode 100644 index 0000000..674e5bf --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/MoveOuterMinusToInnerTermRuleTest.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; + +namespace ThinkSharp.FormulaParsing.Test.TermRewriting +{ + [TestClass] + public class MoveOuterMinusToInnerTermRuleTest + { + private static IFormulaParser parser = FormulaParser + .CreateBuilder() + .ConfigureValidationBehavior(v => v.DisableVariableNameValidation()) + .Build(); + private static ITermRewritingSystem[] rewritingSystems = new ITermRewritingSystem[] + { + TermRewritingSystem.ForTesting(new MoveOuterMinusToInnerTerm()) + }; + + [TestMethod] + public void Test_MinusOneInBrackets() => AssertRewritten("-1", "-(1)"); + + [TestMethod] + public void Test_APlusBInBrackets() => AssertRewritten("-a-b", "-(a+b)"); + + [TestMethod] + public void Test_MinusAMinusBInBrackets() => AssertRewritten("a+b", "-(-a-b)"); + + [TestMethod] + public void Test_ATimeBTimeCInBrackets() => AssertRewritten("-a*b*c", "-(a*b*c)"); + + [TestMethod] + public void Test_ATimeBMinusCInBracketsPlus3Times4() => AssertRewritten("-a*b+c+3*4", "-(a*b-c)+3*4"); + + [TestMethod] + public void Test_MaxOneTwoInBackets() => AssertRewritten("-max(1, 2)", "-(max(1, 2))"); + + [TestMethod] + public void Test_Compley1InBackets() => AssertRewritten("-pi-3*abc+max(1, 2)*3e4-2e5/3", "-(pi + 3 * abc - max(1, 2) * 3e4 +2e5 / 3)"); + + + private void AssertRewritten(string expected, string forumla) + { + foreach (var system in rewritingSystems) + { + var tree = parser.Parse(forumla).Value; + + var simlifiedTree = system.Simplify(tree); + + var nodeToTExtVisitor = new NodesToFormulaTextVisitor(); + + Assert.AreEqual(expected, simlifiedTree.Visit(nodeToTExtVisitor)); + } + } + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByMinusOneIsMinusTermRuleTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByMinusOneIsMinusTermRuleTest.cs index 021a0e1..3c56998 100644 --- a/ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByMinusOneIsMinusTermRuleTest.cs +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByMinusOneIsMinusTermRuleTest.cs @@ -18,7 +18,7 @@ public class TermTimesOrDividedByMinusOneIsMinusTermRuleTest private static ITermRewritingSystem[] rewritingSystems = new ITermRewritingSystem[] { TermRewritingSystem.ForTesting( - new MoveOuterSignedToInnerTerm(), + new MoveOuterMinusToInnerTerm(), new TermTimesOrDividedByMinusOneIsMinusTerm()) }; diff --git a/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems b/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems index 38acb31..91b5c87 100644 --- a/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems +++ b/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems @@ -18,6 +18,7 @@ + diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/MoveOuterSignedToInnerTerm.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/MoveOuterMinusToInnerTerm.cs similarity index 93% rename from ThinkSharp.FormulaParser/TermRewriting/Rules/MoveOuterSignedToInnerTerm.cs rename to ThinkSharp.FormulaParser/TermRewriting/Rules/MoveOuterMinusToInnerTerm.cs index 493ed47..63dd5d6 100644 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/MoveOuterSignedToInnerTerm.cs +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/MoveOuterMinusToInnerTerm.cs @@ -7,7 +7,7 @@ namespace ThinkSharp.FormulaParsing.TermRewriting.Rules { - public class MoveOuterSignedToInnerTerm : Rule + public class MoveOuterMinusToInnerTerm : Rule { private class SwitchSignWithinBracketsVisitor : INodeVisitor { @@ -86,14 +86,14 @@ public override Node Rewrite(Node node) var targetNode = signNode.Node; if (targetNode is BracketedNode targetBracketedNode) { - var newBracketedContentNode = targetBracketedNode.Visit(new SwitchSignWithinBracketsVisitor()); + var newBracketedContentNode = targetBracketedNode.ChildNode.Visit(new SwitchSignWithinBracketsVisitor()); return new SignedNode(Sign.Minus, newBracketedContentNode); } - var binOpQueue = new Queue(); + var binOpStack = new Stack(); while (targetNode is BinaryOperatorNode binaryOperationNode) { - binOpQueue.Enqueue(binaryOperationNode); + binOpStack.Push(binaryOperationNode); targetNode = binaryOperationNode.LeftNode; } @@ -102,9 +102,9 @@ public override Node Rewrite(Node node) if (transformedNode != null) { Node leftNode = transformedNode; - while (binOpQueue.Count > 0) + while (binOpStack.Count > 0) { - var binOpFromQueue = binOpQueue.Dequeue(); + var binOpFromQueue = binOpStack.Pop(); leftNode = new BinaryOperatorNode(binOpFromQueue.BinaryOperator, leftNode, binOpFromQueue.RightNode); } return leftNode; From 444fe5a601567ed7f389304b4c69507e81a86ba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Fri, 1 Nov 2019 19:37:19 +0100 Subject: [PATCH 29/45] added some basic rewriting rules removed scientific notation from grammer --- .../AST/ParsingHelperTest.cs | 32 ++ .../FormulaParserTest.cs | 10 + .../FormularParser.CustomVisitor.Test.cs | 6 +- .../FormularParser.NumberFormats.Test.cs | 4 +- .../FormularParser.SupportedFeatures.Test.cs | 1 + .../NodesToFormulaTextVisitor.cs | 7 +- .../MoveOuterMinusToInnerTermRuleTest.cs | 59 --- ...nTermPlusMinusBracketsPlusMinusTermTest.cs | 35 ++ ...moveBracketsInTermPlusMinusBracketsTest.cs | 29 ++ .../Rules/RemoveNegativSignFromNumberTest.cs | 24 + ...RemoveNegativeSignInFrontOfBracketsTest.cs | 35 ++ .../RemoveNegativeSignInInSubtractTest.cs | 20 + .../Rules/RemoveNegativeSignInInSumTest.cs | 26 + .../RemoveNegativeSignTimesNegatieSignTest.cs | 48 ++ .../Rules/RemoveNestedBracketsTest.cs | 32 ++ .../Rules/RemovePositiveSignTest.cs | 39 ++ .../Rules/RemoveRootBracketsTest.cs | 29 ++ .../TermRewriting/Rules/RuleTest.cs | 73 +++ .../Rules/TermPlusOrMinusZeroIsTermTest.cs | 32 ++ ...TimesOrDividedByMinusOneIsMinusTermTest.cs | 60 +++ .../TermTimesOrDividedByOneIsTermTest.cs | 35 ++ .../TermPlusOrMinusZeroIsTermRuleTest.cs | 55 -- ...sOrDividedByMinusOneIsMinusTermRuleTest.cs | 69 --- .../TermTimesOrDividedByOneIsTermRuleTest.cs | 55 -- .../TermRewriting/TermWritingSystemTest.cs | 90 ++++ ...nkSharp.FluentFormulaParser.Test.projitems | 23 +- .../Utils/BinaryOperatorTest.cs | 66 +++ .../AntlrToAstNodesGrammerTreeVisitor.cs | 79 ++- .../ANTLR/FormulaGrammer.g4 | 82 ++- .../ANTLR/FormulaGrammer.interp | 15 +- .../ANTLR/FormulaGrammer.tokens | 11 +- .../ANTLR/FormulaGrammerBaseListener.cs | 96 ++-- .../ANTLR/FormulaGrammerBaseVisitor.cs | 58 ++- .../ANTLR/FormulaGrammerLexer.cs | 273 +++++----- .../ANTLR/FormulaGrammerLexer.interp | 36 +- .../ANTLR/FormulaGrammerLexer.tokens | 11 +- .../ANTLR/FormulaGrammerListener.cs | 88 ++-- .../ANTLR/FormulaGrammerParser.cs | 490 +++++++++++------- .../ANTLR/FormulaGrammerVisitor.cs | 48 +- .../Ast/Nodes/BinaryOperator.cs | 27 +- .../Nodes/{NumericNode.cs => DecimalNode.cs} | 7 +- .../Ast/Nodes/IntegerNode.cs | 25 + .../Ast/Nodes/NumberFormat.cs | 14 + .../Ast/Visitors/CloneTreeVisitor.cs | 9 +- .../Ast/Visitors/EvaluateAstVisitor.cs | 7 +- .../Ast/Visitors/INodeVisitor.cs | 4 +- .../Ast/Visitors/NodeVisitor.cs | 4 +- .../Ast/Visitors/NodesToTextDebugVisitor.cs | 35 ++ ThinkSharp.FormulaParser/Configuration.cs | 3 + ThinkSharp.FormulaParser/IConfiguration.cs | 2 + .../IConfigureSupportedFeatures.cs | 5 + .../ParserConfiguration.cs | 2 + ThinkSharp.FormulaParser/ParsingException.cs | 2 + .../TermRewriting/ReplaceRuleTreeVisitor.cs | 125 +++-- .../Rules/ConvertDecimalToLong.cs | 36 ++ .../Rules/MoveOuterMinusToInnerTerm.cs | 155 ------ .../TermRewriting/Rules/NodeExtensions.cs | 98 ++++ .../RemoveBracketsInTermPlusMinusBrackets.cs | 63 +++ ...etsInTermPlusMinusBracketsPlusMinusTerm.cs | 65 +++ .../Rules/RemoveNegativeSignFromNumber.cs | 36 ++ .../RemoveNegativeSignInFrontOfBrackets.cs | 52 ++ .../Rules/RemoveNegativeSignInInSubtract.cs | 36 ++ .../Rules/RemoveNegativeSignInInSum.cs | 36 ++ .../RemoveNegativeSignTimesNegatieSign.cs | 78 +++ .../Rules/RemoveNestedBrackets.cs | 29 ++ .../TermRewriting/Rules/RemovePositiveSign.cs | 27 + .../TermRewriting/Rules/RemoveRootBrackets.cs | 27 + .../TermRewriting/Rules/Rule.cs | 22 +- .../Rules/TermDividesByTermIsOne.cs | 12 +- .../Rules/TermPlusOrMinusZeroIsTerm.cs | 42 +- ...TermTimesOrDividedByMinusOneIsMinusTerm.cs | 60 +-- .../Rules/TermTimesOrDividedByOneIsTerm.cs | 32 +- .../TermRewriting/TermRewritingSystem.cs | 13 + .../ThinkSharp.FormulaParser.csproj | 4 + .../ThinkSharp.FormulaParser.xml | 317 +++++++---- .../Utils/EnumerableExtensions.cs | 19 + .../Utils/NodeComparer.cs | 166 ++++++ .../Utils/NodeHashCodeVisitor.cs | 40 ++ 78 files changed, 2848 insertions(+), 1169 deletions(-) create mode 100644 ThinkSharp.FormulaParser.Test/AST/ParsingHelperTest.cs rename ThinkSharp.FormulaParser.Test/{TermRewriting => }/NodesToFormulaTextVisitor.cs (81%) delete mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/MoveOuterMinusToInnerTermRuleTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTermTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativSignFromNumberTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInFrontOfBracketsTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInInSubtractTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInInSumTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNestedBracketsTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemovePositiveSignTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveRootBracketsTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RuleTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermPlusOrMinusZeroIsTermTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTermTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermTimesOrDividedByOneIsTermTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/TermPlusOrMinusZeroIsTermRuleTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByMinusOneIsMinusTermRuleTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByOneIsTermRuleTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/TermWritingSystemTest.cs create mode 100644 ThinkSharp.FormulaParser.Test/Utils/BinaryOperatorTest.cs rename ThinkSharp.FormulaParser/Ast/Nodes/{NumericNode.cs => DecimalNode.cs} (72%) create mode 100644 ThinkSharp.FormulaParser/Ast/Nodes/IntegerNode.cs create mode 100644 ThinkSharp.FormulaParser/Ast/Nodes/NumberFormat.cs create mode 100644 ThinkSharp.FormulaParser/Ast/Visitors/NodesToTextDebugVisitor.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/ConvertDecimalToLong.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/MoveOuterMinusToInnerTerm.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/NodeExtensions.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBrackets.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTerm.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignFromNumber.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInFrontOfBrackets.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInInSubtract.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInInSum.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSign.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNestedBrackets.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemovePositiveSign.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveRootBrackets.cs create mode 100644 ThinkSharp.FormulaParser/Utils/EnumerableExtensions.cs create mode 100644 ThinkSharp.FormulaParser/Utils/NodeComparer.cs create mode 100644 ThinkSharp.FormulaParser/Utils/NodeHashCodeVisitor.cs diff --git a/ThinkSharp.FormulaParser.Test/AST/ParsingHelperTest.cs b/ThinkSharp.FormulaParser.Test/AST/ParsingHelperTest.cs new file mode 100644 index 0000000..f3c3133 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/AST/ParsingHelperTest.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.Test +{ + [TestClass] + public class ParsingHelperTest + { + [TestMethod] + public void TestGetBySymbol() + { + var o = BinaryOperator.BySymbol("+"); + Assert.AreEqual("+", o.Symbol); + Assert.AreEqual(2.0, o.Evaluate(1, 1)); + } + + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void TestGetBySymbol_NotExisting() + { + var o = BinaryOperator.BySymbol("abv"); + } + + private static void Test(string expected, string actual) + { + //var node = ParsingHelper. + } + } +} diff --git a/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs b/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs index a5b87eb..7e0eba2 100644 --- a/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs +++ b/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs @@ -36,6 +36,7 @@ public void TestMulDivFirst() { AsserEval(6.0, "1+1*5"); AsserEval(6.0, "1*1+5"); + AsserEval(11.0, "1+2*3+4"); AsserEval(3.0, "1+10/5"); AsserEval(5.1, "1/10+5"); @@ -88,6 +89,7 @@ public void Test_Pow() } [TestMethod] + [Ignore] public void Test_ScientificNumber() { AsserEval(2000, "2e3"); @@ -202,6 +204,13 @@ public void TestFunctionMax() AsserEval(12, "max(12, 11, 3, 4, 5, 2, 11 ,4)"); } + [TestMethod] + public void TestSignedFunctionMax() + { + AsserEval(-12, "-max(12, 11, 3, 4, 5, 2, 11 ,4)"); + AsserEval(12, "+max(12, 11, 3, 4, 5, 2, 11 ,4)"); + } + [TestMethod] public void TestConfigureRegistry() { @@ -260,6 +269,7 @@ public void TestDisablePow() } [TestMethod] + [Ignore] public void TestDisableScientificNotation() { var parser = FormulaParser diff --git a/ThinkSharp.FormulaParser.Test/FormularParser.CustomVisitor.Test.cs b/ThinkSharp.FormulaParser.Test/FormularParser.CustomVisitor.Test.cs index 5b01138..d011d2b 100644 --- a/ThinkSharp.FormulaParser.Test/FormularParser.CustomVisitor.Test.cs +++ b/ThinkSharp.FormulaParser.Test/FormularParser.CustomVisitor.Test.cs @@ -60,7 +60,7 @@ public override Node Visit(VariableNode node) { if (node.Name == "x") { - return new NumberNode("2", 2); + return new DecimalNode( 2); } throw new InvalidOperationException("Unknown Variable."); @@ -71,7 +71,9 @@ public override Node Visit(FormulaNode node) return new FormulaNode(node.ChildNode.Visit(this)); } - public override Node Visit(NumberNode node) => node; + public override Node Visit(DecimalNode node) => node; + + public override Node Visit(IntegerNode node) => node; } } } diff --git a/ThinkSharp.FormulaParser.Test/FormularParser.NumberFormats.Test.cs b/ThinkSharp.FormulaParser.Test/FormularParser.NumberFormats.Test.cs index 5d46a9b..66996e5 100644 --- a/ThinkSharp.FormulaParser.Test/FormularParser.NumberFormats.Test.cs +++ b/ThinkSharp.FormulaParser.Test/FormularParser.NumberFormats.Test.cs @@ -51,6 +51,7 @@ public void TestDecimalNotation() } [TestMethod] + [Ignore] public void TestScientificNotation() { var parser = FormulaParser.Create(); @@ -64,7 +65,8 @@ public void TestMixedNotation() { var parser = FormulaParser.Create(); - Assert.AreEqual(0.04, parser.Evaluate("(0b11 + 0x20 + 5) * 1e-3").Value); + //Assert.AreEqual(0.04, parser.Evaluate("(0b11 + 0x20 + 5) * 1e3").Value); + Assert.AreEqual(0.04, parser.Evaluate("(0b11 + 0x20 + 5) * 1*10^-3").Value); } } } diff --git a/ThinkSharp.FormulaParser.Test/FormularParser.SupportedFeatures.Test.cs b/ThinkSharp.FormulaParser.Test/FormularParser.SupportedFeatures.Test.cs index 3449e42..6d33404 100644 --- a/ThinkSharp.FormulaParser.Test/FormularParser.SupportedFeatures.Test.cs +++ b/ThinkSharp.FormulaParser.Test/FormularParser.SupportedFeatures.Test.cs @@ -27,6 +27,7 @@ public void TestDisablePow() } [TestMethod] + [Ignore] public void TestDisableScientificNotation() { var parser = FormulaParser diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/NodesToFormulaTextVisitor.cs b/ThinkSharp.FormulaParser.Test/NodesToFormulaTextVisitor.cs similarity index 81% rename from ThinkSharp.FormulaParser.Test/TermRewriting/NodesToFormulaTextVisitor.cs rename to ThinkSharp.FormulaParser.Test/NodesToFormulaTextVisitor.cs index 01ab3e3..6f01050 100644 --- a/ThinkSharp.FormulaParser.Test/TermRewriting/NodesToFormulaTextVisitor.cs +++ b/ThinkSharp.FormulaParser.Test/NodesToFormulaTextVisitor.cs @@ -1,11 +1,12 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text; using ThinkSharp.FormulaParsing.Ast.Nodes; using ThinkSharp.FormulaParsing.Ast.Visitors; -namespace ThinkSharp.FormulaParsing.Test.TermRewriting +namespace ThinkSharp.FormulaParsing.Test { internal class NodesToFormulaTextVisitor : INodeVisitor { @@ -16,7 +17,7 @@ public string Visit(FormulaNode node) public string Visit(BracketedNode node) => $"({node.ChildNode.Visit(this)})"; - public string Visit(NumberNode node) => node.Token; + public string Visit(DecimalNode node) => node.Value.ToString("0.00", CultureInfo.InvariantCulture); public string Visit(VariableNode node) => node.Name; @@ -29,5 +30,7 @@ public string Visit(FormulaNode node) public string Visit(SignedNode node) => (node.Sign == Sign.Minus ? "-" : "") + node.Node.Visit(this); public string Visit(FunctionNode node) => $"{node.FunctionName}({string.Join(", ", node.Parameters.Select(p => p.Visit(this)))})"; + + public string Visit(IntegerNode node) => node.Value.ToString(); } } diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/MoveOuterMinusToInnerTermRuleTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/MoveOuterMinusToInnerTermRuleTest.cs deleted file mode 100644 index 674e5bf..0000000 --- a/ThinkSharp.FormulaParser.Test/TermRewriting/MoveOuterMinusToInnerTermRuleTest.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; - -namespace ThinkSharp.FormulaParsing.Test.TermRewriting -{ - [TestClass] - public class MoveOuterMinusToInnerTermRuleTest - { - private static IFormulaParser parser = FormulaParser - .CreateBuilder() - .ConfigureValidationBehavior(v => v.DisableVariableNameValidation()) - .Build(); - private static ITermRewritingSystem[] rewritingSystems = new ITermRewritingSystem[] - { - TermRewritingSystem.ForTesting(new MoveOuterMinusToInnerTerm()) - }; - - [TestMethod] - public void Test_MinusOneInBrackets() => AssertRewritten("-1", "-(1)"); - - [TestMethod] - public void Test_APlusBInBrackets() => AssertRewritten("-a-b", "-(a+b)"); - - [TestMethod] - public void Test_MinusAMinusBInBrackets() => AssertRewritten("a+b", "-(-a-b)"); - - [TestMethod] - public void Test_ATimeBTimeCInBrackets() => AssertRewritten("-a*b*c", "-(a*b*c)"); - - [TestMethod] - public void Test_ATimeBMinusCInBracketsPlus3Times4() => AssertRewritten("-a*b+c+3*4", "-(a*b-c)+3*4"); - - [TestMethod] - public void Test_MaxOneTwoInBackets() => AssertRewritten("-max(1, 2)", "-(max(1, 2))"); - - [TestMethod] - public void Test_Compley1InBackets() => AssertRewritten("-pi-3*abc+max(1, 2)*3e4-2e5/3", "-(pi + 3 * abc - max(1, 2) * 3e4 +2e5 / 3)"); - - - private void AssertRewritten(string expected, string forumla) - { - foreach (var system in rewritingSystems) - { - var tree = parser.Parse(forumla).Value; - - var simlifiedTree = system.Simplify(tree); - - var nodeToTExtVisitor = new NodesToFormulaTextVisitor(); - - Assert.AreEqual(expected, simlifiedTree.Visit(nodeToTExtVisitor)); - } - } - } -} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTermTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTermTest.cs new file mode 100644 index 0000000..0986df5 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTermTest.cs @@ -0,0 +1,35 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; +using ThinkSharp.FormulaParsing.Test; + +namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules +{ + [TestClass] + public class RemoveBracketsInTermPlusMinusBracketsPlusMinusTermTest : RuleTest + { + protected override Rule CreateRule() => new RemoveBracketsInTermPlusMinusBracketsPlusMinusTerm(); + + [TestMethod] + public void Test_APlusAPlusAInBracketsPlusC() => AssertRewritten("a+a+a+c", "a+(a+a)+c"); + + [TestMethod] + public void Test_APlusAMinusAInBracketsPlusC() => AssertRewritten("a+a-a+c", "a+(a-a)+c"); + + [TestMethod] + public void Test_AMinusAMinusAInBracketsMinusC() => AssertRewritten("a-a+a-c", "a-(a-a)-c"); + + [TestMethod] + public void Test_AMinusAPlusAInBracketsPlusC() => AssertRewritten("a-a-a+c", "a-(a+a)+c"); + + [TestMethod] + public void Test_APlusAPlusAInBracketsMinusC() => AssertRewritten("a+a+a-c", "a+(a+a)-c"); + + [TestMethod] + public void Test_APlusAMinusAInBracketsMinusC() => AssertRewritten("a+a-a-c", "a+(a-a)-c"); + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsTest.cs new file mode 100644 index 0000000..3f173f3 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsTest.cs @@ -0,0 +1,29 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; +using ThinkSharp.FormulaParsing.Test; + +namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules +{ + [TestClass] + public class RemoveBracketsInTermPlusMinusBracketsTest : RuleTest + { + protected override Rule CreateRule() => new RemoveBracketsInTermPlusMinusBrackets(); + + [TestMethod] + public void Test_APlusAInBracketsPlusA() => AssertRewritten("a+a+a", "(a+a)+a"); + + [TestMethod] + public void Test_APlusAPlusAInBrackets() => AssertRewritten("a+a+a", "a+(a+a)"); + + [TestMethod] + public void Test_APlusAInBracketsMinusA() => AssertRewritten("a+a-a", "(a+a)-a"); + + [TestMethod] + public void Test_AMinusAPlusAInBrackets() => AssertRewritten("a-a-a", "a-(a+a)"); + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativSignFromNumberTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativSignFromNumberTest.cs new file mode 100644 index 0000000..0724892 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativSignFromNumberTest.cs @@ -0,0 +1,24 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; +using ThinkSharp.FormulaParsing.Test; + +namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules +{ + [TestClass] + public class RemoveNegativSignFromNumberTest : RuleTest + { + protected override Rule CreateRule() => new RemoveNegativeSignFromNumber(); + + [TestMethod] + public void Test_MinusOne() => AssertRewritten(new IntegerNode(-1), new SignedNode(Sign.Minus, new IntegerNode(1))); + [TestMethod] + public void Test_MinusDecimal() => AssertRewritten(new DecimalNode(-1), new SignedNode(Sign.Minus, new DecimalNode(1))); + [TestMethod] + public void Test_MinusVariable() => AssertNotMatching(new SignedNode(Sign.Minus, new VariableNode("TEST"))); + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInFrontOfBracketsTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInFrontOfBracketsTest.cs new file mode 100644 index 0000000..803fecd --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInFrontOfBracketsTest.cs @@ -0,0 +1,35 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; +using ThinkSharp.FormulaParsing.Test; + +namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules +{ + [TestClass] + public class RemoveNegativeSignInFrontOfBracketsTest : RuleTest + { + protected override Rule CreateRule() => new RemoveNegativeSignInFrontOfBrackets(); + + [TestMethod] + public void Test_MinusA() => AssertRewritten("(-a)", "-(a)"); + + [TestMethod] + public void Test_MinusAPlusB() => AssertRewritten("(-a-b)", "-(a+b)"); + + [TestMethod] + public void Test_MinusMinusB() => AssertRewritten("(--a+b)", "-(-a-b)"); + + [TestMethod] + public void Test_MinusAPlusBTimesBracket() => AssertRewritten("(-a-b*(a-b))", "-(a+b*(a-b))"); + + [TestMethod] + public void Test_MinusMinusA() => AssertRewritten("(--a)", "-(-a)"); + + [TestMethod] + public void Test_MinusProduct() => AssertRewritten("(--a*b*c*d)", "-(-a*b*c*d)"); + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInInSubtractTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInInSubtractTest.cs new file mode 100644 index 0000000..2936067 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInInSubtractTest.cs @@ -0,0 +1,20 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; +using ThinkSharp.FormulaParsing.Test; + +namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules +{ + [TestClass] + public class RemoveNegativeSignInInSubtractTest : RuleTest + { + protected override Rule CreateRule() => new RemoveNegativeSignInInSubtract(); + + [TestMethod] + public void Test_AMinusMinusB() => AssertRewritten("a+b", "a--b"); + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInInSumTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInInSumTest.cs new file mode 100644 index 0000000..6980f91 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInInSumTest.cs @@ -0,0 +1,26 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; +using ThinkSharp.FormulaParsing.Test; + +namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules +{ + [TestClass] + public class RemoveNegativeSignInInSumTest : RuleTest + { + protected override Rule CreateRule() => new RemoveNegativeSignInInSum(); + + [TestMethod] + public void Test_MinusAPlusB() => AssertRewritten("b-a", "-a+b"); + + [TestMethod] + public void Test_AMinusB() => AssertNotMatching("a-b"); + + [TestMethod] + public void Test_AMinusMinusB() => AssertNotMatching("a--b"); + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs new file mode 100644 index 0000000..7f61f6d --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs @@ -0,0 +1,48 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; +using ThinkSharp.FormulaParsing.Test; + +namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules +{ + [TestClass] + public class RemoveNegativeSignTimesNegatieSignTest : RuleTest + { + protected override Rule CreateRule() => new RemoveNegativeSignTimesNegatieSign(); + + [TestMethod] + public void Test_MinusMinusA () => AssertRewritten( + new VariableNode("a"), + new SignedNode(Sign.Minus, + new SignedNode(Sign.Minus, + new VariableNode("a")))); + + [TestMethod] + public void Test_MinusMinusAPlusB() => AssertRewritten( + new BinaryOperatorNode( + BinaryOperator.Plus, + new VariableNode("a"), + new VariableNode("b")), + new SignedNode(Sign.Minus, + new BinaryOperatorNode( + BinaryOperator.Plus, + new SignedNode(Sign.Minus, new VariableNode("a")), + new VariableNode("b")))); + + [TestMethod] + public void Test_MinusMinusATimesB() => AssertRewritten( + new BinaryOperatorNode( + BinaryOperator.Times, + new VariableNode("a"), + new VariableNode("b")), + new SignedNode(Sign.Minus, + new BinaryOperatorNode( + BinaryOperator.Times, + new SignedNode(Sign.Minus, new VariableNode("a")), + new VariableNode("b")))); + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNestedBracketsTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNestedBracketsTest.cs new file mode 100644 index 0000000..169d727 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNestedBracketsTest.cs @@ -0,0 +1,32 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; +using ThinkSharp.FormulaParsing.Test; + +namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules +{ + [TestClass] + public class RemoveNestedBracketsTest : RuleTest + { + protected override Rule CreateRule() => new RemoveNestedBrackets(); + + [TestMethod] + public void Test_APlusAInBrackets() => AssertRewritten("(a+a)", "((a+a))"); + + [TestMethod] + public void Test_APlusAInBracketsPlusA() => AssertNotMatching("((a+a)+a)"); + + [TestMethod] + public void Test_APlusAPlusAInBrackets() => AssertNotMatching("(a+(a+a))"); + + [TestMethod] + public void Test_APlusAPlusAInBracketsPlusC() => AssertNotMatching("(a+(a+a)+c)"); + + [TestMethod] + public void Test_APlusA() => AssertRewritten("(a+a)", "(((a+a)))"); + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemovePositiveSignTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemovePositiveSignTest.cs new file mode 100644 index 0000000..2208743 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemovePositiveSignTest.cs @@ -0,0 +1,39 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; +using ThinkSharp.FormulaParsing.Test; + +namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules +{ + [TestClass] + public class RemovePositiveSignTest : RuleTest + { + protected override Rule CreateRule() => new RemovePositiveSign(); + [TestMethod] + public void Test_PlusPointFourOne() => AssertRewritten("1.40", "+1.4"); + [TestMethod] + public void Test_PlusOne() => AssertRewritten("1", "+1"); + [TestMethod] + public void Test_MinusOne() => AssertNotMatching("-1"); + [TestMethod] + public void Test_PlusOneMinusOneInBrackets() => AssertRewritten("(1-1)", "+(1-1)"); + [TestMethod] + public void Test_MinusOneMinusOneInBrackets() => AssertNotMatching("-(1-1)"); + [TestMethod] + public void Test_PlusOnePlusOneInBrackets() => AssertRewritten("(1+1)", "+(1+1)"); + [TestMethod] + public void Test_MinusOnePlusOneInBrackets() => AssertNotMatching("-(1+1)"); + [TestMethod] + public void Test_PlusVariable() => AssertRewritten("a", "+a"); + [TestMethod] + public void Test_MinusVariable() => AssertNotMatching("-a"); + [TestMethod] + public void Test_PlusFunction() => AssertRewritten("max(3, 2)", "+max(3,2)"); + [TestMethod] + public void Test_MinusFunction() => AssertNotMatching("-max(3,2)"); + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveRootBracketsTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveRootBracketsTest.cs new file mode 100644 index 0000000..ac666b7 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveRootBracketsTest.cs @@ -0,0 +1,29 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; +using ThinkSharp.FormulaParsing.Test; + +namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules +{ + [TestClass] + public class RemoveRootBracketsTest : RuleTest + { + protected override Rule CreateRule() => new RemoveRootBrackets(); + + [TestMethod] + public void Test_APlusAInBrackets() => AssertRewritten("a+a", "(a+a)"); + + [TestMethod] + public void Test_APlusAInBracketsPlusAInBrackets() => AssertRewritten("(a+a)+a", "((a+a)+a)"); + + [TestMethod] + public void Test_APlusAPlusAInBracketsInBrackets() => AssertRewritten("a+(a+a)", "(a+(a+a))"); + + [TestMethod] + public void Test_APlusAPlusAInBracketsPlusCInBrackets() => AssertRewritten("a+(a+a)+c", "(a+(a+a)+c)"); + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RuleTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RuleTest.cs new file mode 100644 index 0000000..33e03f8 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RuleTest.cs @@ -0,0 +1,73 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; +using ThinkSharp.FormulaParsing.Test; +using ThinkSharp.FormulaParsing.Utils; + +namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules +{ + public abstract class RuleTest + { + private static IFormulaParser parser = FormulaParser + .CreateBuilder() + .ConfigureValidationBehavior(v => v.DisableVariableNameValidation()) + .Build(); + + protected abstract Rule CreateRule(); + + protected void AssertNotMatching(string formula) + { + var node = parser.Parse(formula).Value; + node = node is FormulaNode formulaNode + ? formulaNode.ChildNode + : node; + + AssertNotMatching(node); + } + + protected void AssertNotMatching(Node node) + { + var rule = CreateRule(); + + Assert.IsFalse(rule.Match(node)); + } + + protected void AssertRewritten(string expected, string formula) + { + var node = parser.Parse(formula).Value; + var rule = CreateRule(); + + var visitor = new ReplaceRuleTreeVisitor(rule); + + var simplifiedNode = node.Visit(visitor); + + Assert.IsTrue(simplifiedNode != node, "Rule matching fails."); + + var nodeToTExtVisitor = new NodesToFormulaTextVisitor(); + + var actual = simplifiedNode.Visit(nodeToTExtVisitor); + + Assert.AreEqual(expected, actual, "Simplified formula is not equal to actual."); + } + + protected void AssertRewritten(Node expected, Node input) + { + var rule = CreateRule(); + + var visitor = new ReplaceRuleTreeVisitor(rule); + + var simplifiedNode = input.Visit(visitor); + + Assert.IsTrue(simplifiedNode != input, "Rule matching fails."); + + var comparer = new NodeComparer(); + + Assert.IsTrue(comparer.Equals(expected, simplifiedNode), "Expected and actual trees are not equal."); + } + } +} \ No newline at end of file diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermPlusOrMinusZeroIsTermTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermPlusOrMinusZeroIsTermTest.cs new file mode 100644 index 0000000..272fd70 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermPlusOrMinusZeroIsTermTest.cs @@ -0,0 +1,32 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; +using ThinkSharp.FormulaParsing.Test; + +namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules +{ + [TestClass] + public class TermPlusOrMinusZeroIsTermTest : RuleTest + { + protected override Rule CreateRule() => new TermPlusOrMinusZeroIsTermRule(); + + [TestMethod] + public void Test_OnePlusZeroIsOne() => AssertRewritten("1", "1+0"); + + [TestMethod] + public void Test_ZeroPlusOneIsOne() => AssertRewritten("1", "1+0"); + + [TestMethod] + public void Test_OneMinusZeroIsOne() => AssertRewritten("1", "1-0"); + + [TestMethod] + public void Test_ZeroMinusOneIsMinusOne() => AssertRewritten("-1", "0-1"); + + [TestMethod] + public void Test_OneTimesOnePlusZeroIsOneTimesOne() => AssertRewritten("1*1", "1*1+0"); + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTermTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTermTest.cs new file mode 100644 index 0000000..71228a5 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTermTest.cs @@ -0,0 +1,60 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; +using ThinkSharp.FormulaParsing.Test; + +namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules +{ + [TestClass] + public class TermTimesOrDividedByMinusOneIsMinusTermTest : RuleTest + { + protected override Rule CreateRule() => new TermTimesOrDividedByMinusOneIsMinusTerm(); + + [TestMethod] + public void Test_OneTImesOne() => AssertRewritten( + new IntegerNode(-1), + new BinaryOperatorNode( + BinaryOperator.BySymbol("*"), + new IntegerNode(1), + new IntegerNode(-1))); + + [TestMethod] + public void Test_ATimesOne() => AssertRewritten( + new SignedNode(Sign.Minus, new VariableNode("a")), + new BinaryOperatorNode( + BinaryOperator.BySymbol("*"), + new VariableNode("a"), + new IntegerNode(-1))); + + [TestMethod] + public void Test_OneTimesA() => AssertRewritten( + new SignedNode(Sign.Minus, new VariableNode("a")), + new BinaryOperatorNode( + BinaryOperator.BySymbol("*"), + new IntegerNode(-1), + new VariableNode("a"))); + + [TestMethod] + public void Test_ADividedByOne() => AssertRewritten( + new BinaryOperatorNode( + BinaryOperator.BySymbol("/"), + new IntegerNode(1), + new SignedNode(Sign.Minus, new VariableNode("a"))), + new BinaryOperatorNode( + BinaryOperator.BySymbol("/"), + new IntegerNode(-1), + new VariableNode("a"))); + + [TestMethod] + public void Test_MinsADividedByMinusOne() => AssertRewritten( + new VariableNode("a"), + new BinaryOperatorNode( + BinaryOperator.BySymbol("/"), + new SignedNode(Sign.Minus, new VariableNode("a")), + new IntegerNode(-1))); + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermTimesOrDividedByOneIsTermTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermTimesOrDividedByOneIsTermTest.cs new file mode 100644 index 0000000..d9faf87 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermTimesOrDividedByOneIsTermTest.cs @@ -0,0 +1,35 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; +using ThinkSharp.FormulaParsing.Test; + +namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules +{ + [TestClass] + public class TermTimesOrDividedByOneIsTermTest : RuleTest + { + protected override Rule CreateRule() => new TermTimesOrDividedByOneIsTerm(); + + [TestMethod] + public void Test_OneTImesOne() => AssertRewritten("1", "1*1"); + + [TestMethod] + public void Test_ATimesOne() => AssertRewritten("a", "a*1"); + + [TestMethod] + public void Test_OneTimesA() => AssertRewritten("a", "1*a"); + + [TestMethod] + public void Test_ADividedByOne() => AssertRewritten("a", "a/1"); + + [TestMethod] + public void Test_TermInBracketsDividedByOne() => AssertRewritten("(1+2+4)", "(1+2+4)/1"); + + [TestMethod] + public void Test_OneDividedByA() => AssertNotMatching("1/a"); + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/TermPlusOrMinusZeroIsTermRuleTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/TermPlusOrMinusZeroIsTermRuleTest.cs deleted file mode 100644 index 7842ecc..0000000 --- a/ThinkSharp.FormulaParser.Test/TermRewriting/TermPlusOrMinusZeroIsTermRuleTest.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; - -namespace ThinkSharp.FormulaParsing.Test.TermRewriting -{ - [TestClass] - public class TermPlusOrMinusZeroIsTermRuleTest - { - private static IFormulaParser parser = FormulaParser - .CreateBuilder() - .ConfigureValidationBehavior(v => v.DisableVariableNameValidation()) - .Build(); - private static ITermRewritingSystem[] rewritingSystems = new ITermRewritingSystem[] - { - TermRewritingSystem.ForTesting(new TermPlusOrMinusZeroIsTermRule()) - }; - - [TestMethod] - public void Test_OnePlusZeroIsOne() => AssertRewritten("1", "1+0"); - - [TestMethod] - public void Test_ZeroPlusOneIsOne() => AssertRewritten("1", "1+0"); - - [TestMethod] - public void Test_OneMinusZeroIsOne() => AssertRewritten("1", "1-0"); - - [TestMethod] - public void Test_ZeroMinusOneIsMinusOne() => AssertRewritten("-1", "0-1"); - - [TestMethod] - public void Test_OneTimesOnePlusZeroIsOneTimesOne() => AssertRewritten("1*1", "1*1+0"); - - [TestMethod] - public void Test_APlusMinusManyZerusPlusAIsAPlusA() => AssertRewritten("a+a", "a+0-0+0-0+0-0+0+0+0+a"); - - private void AssertRewritten(string expected, string forumla) - { - foreach (var system in rewritingSystems) - { - var tree = parser.Parse(forumla).Value; - - var simlifiedTree = system.Simplify(tree); - - var nodeToTExtVisitor = new NodesToFormulaTextVisitor(); - - Assert.AreEqual(expected, simlifiedTree.Visit(nodeToTExtVisitor)); - } - } - } -} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByMinusOneIsMinusTermRuleTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByMinusOneIsMinusTermRuleTest.cs deleted file mode 100644 index 3c56998..0000000 --- a/ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByMinusOneIsMinusTermRuleTest.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; - -namespace ThinkSharp.FormulaParsing.Test.TermRewriting -{ - [TestClass] - public class TermTimesOrDividedByMinusOneIsMinusTermRuleTest - { - private static IFormulaParser parser = FormulaParser - .CreateBuilder() - .ConfigureValidationBehavior(v => v.DisableVariableNameValidation()) - .Build(); - private static ITermRewritingSystem[] rewritingSystems = new ITermRewritingSystem[] - { - TermRewritingSystem.ForTesting( - new MoveOuterMinusToInnerTerm(), - new TermTimesOrDividedByMinusOneIsMinusTerm()) - }; - - [TestMethod] - public void Test_OneTImesOne() => AssertRewritten("-1", "1*-1"); - - [TestMethod] - public void Test_ATimesOne() => AssertRewritten("-a", "a*-1"); - - [TestMethod] - public void Test_OneTimesA() => AssertRewritten("-a", "-1*a"); - - [TestMethod] - public void Test_ADividedByOne() => AssertRewritten("-a", "a/-1"); - - [TestMethod] - public void Test_OneDividedByA() => AssertRewritten("-1/a", "-1/a"); - - [TestMethod] - public void Test_MinsADividedByMinusOne() => AssertRewritten("a", "-a/-1"); - - [TestMethod] - public void Test_MinusOneTimesMinsADividedByMinusOne() => AssertRewritten("-a", "-1*-a/-1"); - - [TestMethod] - public void Test_MinusOneTimesMinsADividedByMinusOne2() => AssertRewritten("-a*-a", "a*-a/-1"); - - [TestMethod] - public void Test_MinusOneTimesMinsADividedByMinusOne3() => AssertRewritten("a*-a", "a*-1*-a/-1"); - - [TestMethod] - public void Test_AManyTimeOneTimeADividedByOne() => AssertRewritten("a*a", "a*-1*-1*-1*-1*-1*a/-1"); - - private void AssertRewritten(string expected, string forumla) - { - foreach (var system in rewritingSystems) - { - var tree = parser.Parse(forumla).Value; - - var simlifiedTree = system.Simplify(tree); - - var nodeToTExtVisitor = new NodesToFormulaTextVisitor(); - - Assert.AreEqual(expected, simlifiedTree.Visit(nodeToTExtVisitor)); - } - } - } -} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByOneIsTermRuleTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByOneIsTermRuleTest.cs deleted file mode 100644 index e7b1495..0000000 --- a/ThinkSharp.FormulaParser.Test/TermRewriting/TermTimesOrDividedByOneIsTermRuleTest.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; - -namespace ThinkSharp.FormulaParsing.Test.TermRewriting -{ - [TestClass] - public class TermTimesOrDividedByOneIsTermRuleTest - { - private static IFormulaParser parser = FormulaParser - .CreateBuilder() - .ConfigureValidationBehavior(v => v.DisableVariableNameValidation()) - .Build(); - private static ITermRewritingSystem[] rewritingSystems = new ITermRewritingSystem[] - { - TermRewritingSystem.ForTesting(new TermTimesOrDividedByOneIsTerm()) - }; - - [TestMethod] - public void Test_OneTImesOne() => AssertRewritten("1", "1*1"); - - [TestMethod] - public void Test_ATimesOne() => AssertRewritten("a", "a*1"); - - [TestMethod] - public void Test_OneTimesA() => AssertRewritten("a", "1*a"); - - [TestMethod] - public void Test_ADividedByOne() => AssertRewritten("a", "a/1"); - - [TestMethod] - public void Test_OneDividedByA() => AssertRewritten("1/a", "1/a"); - - [TestMethod] - public void Test_AManyTimeOneTimeADividedByOne() => AssertRewritten("a*a", "a*1*1*1*1*1*a/1"); - - private void AssertRewritten(string expected, string forumla) - { - foreach (var system in rewritingSystems) - { - var tree = parser.Parse(forumla).Value; - - var simlifiedTree = system.Simplify(tree); - - var nodeToTExtVisitor = new NodesToFormulaTextVisitor(); - - Assert.AreEqual(expected, simlifiedTree.Visit(nodeToTExtVisitor)); - } - } - } -} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/TermWritingSystemTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/TermWritingSystemTest.cs new file mode 100644 index 0000000..6c8775c --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/TermWritingSystemTest.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; + +namespace ThinkSharp.FormulaParsing.Test.TermRewriting +{ + [TestClass] + public class TermWritingSystemTest + { + private static IFormulaParser parser = FormulaParser + .CreateBuilder() + .ConfigureValidationBehavior(v => v.DisableVariableNameValidation()) + .Build(); + + private static ITermRewritingSystem rewritingSystem = TermRewritingSystem.Create(); + + [TestMethod] + public void Test_APlusMinusManyZerosPlusAIsAPlusA() => AssertRewritten("a+a", "a+0-0+0-0+0-0+0+0+0+a"); + + [TestMethod] + public void Test_MinusOneInBrackets() => AssertRewritten("-1", "-(1)"); + + [TestMethod] + public void Test_APlusBInBrackets() => AssertRewritten("-a-b", "-(a+b)"); + + [TestMethod] + public void Test_MinusAMinusBInBrackets() => AssertRewritten("b+a", "-(-a-b)"); + + [TestMethod] + public void Test_ATimeBTimeCInBrackets() => AssertRewritten("-a*b*c", "-(a*b*c)"); + + [TestMethod] + public void Test_ATimeBMinusCInBracketsPlus3Times4() => AssertRewritten("-a*b+c+3*4", "-(a*b-c)+3*4"); + + [TestMethod] + public void Test_MaxOneTwoInBackets() => AssertRewritten("-max(1, 2)", "-(max(1, 2))"); + + [TestMethod] + public void Test_Compley1InBackets() => AssertRewritten("-pi-3*abc+max(1, 2)*3*10^4-2*10^5/3", "-(pi + 3 * abc - max(1, 2) * 3*10^4 +2*10^5 / 3)"); + + [TestMethod] + public void Test_OneTimesMinusOne() => AssertRewritten("-1", "1*-1"); + + [TestMethod] + public void Test_ATimesMinusOne() => AssertRewritten("-a", "a*-1"); + + [TestMethod] + public void Test_MinusOneTimesA() => AssertRewritten("-a", "-1*a"); + + [TestMethod] + public void Test_ADividedByMinusOne() => AssertRewritten("-a", "a/-1"); + + [TestMethod] + public void Test_MinusOneDividedByA() => AssertRewritten("1/-a", "-1/a"); + + [TestMethod] + public void Test_MinsADividedByMinusOne() => AssertRewritten("a", "-a/-1"); + + [TestMethod] + public void Test_MinusOneTimesMinsADividedByMinusOne() => AssertRewritten("-a", "-1*-a/-1"); + + [TestMethod] + public void Test_MinusOneTimesMinsADividedByMinusOne2() => AssertRewritten("-a*-a", "a*-a/-1"); + + [TestMethod] + public void Test_MinusOneTimesMinsADividedByMinusOne3() => AssertRewritten("a*-a", "a*-1*-a/-1"); + + [TestMethod] + public void Test_AManyTimeMinusOneTimeADividedByMinusOne() => AssertRewritten("a*a", "a*-1*-1*-1*-1*-1*a/-1"); + + [TestMethod] + public void Test_AManyTimeOneTimeADividedByOne() => AssertRewritten("a*a", "a*1*1*1*1*1*a/1"); + + + private void AssertRewritten(string expected, string forumla) + { + var tree = parser.Parse(forumla).Value; + + var simlifiedTree = rewritingSystem.Simplify(tree); + + var nodeToTExtVisitor = new NodesToFormulaTextVisitor(); + + Assert.AreEqual(expected, simlifiedTree.Visit(nodeToTExtVisitor)); + } + } +} diff --git a/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems b/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems index 91b5c87..86241f1 100644 --- a/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems +++ b/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems @@ -9,6 +9,7 @@ ThinkSharp.FluentFormulaParser.Test + @@ -17,10 +18,22 @@ - - - - - + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ThinkSharp.FormulaParser.Test/Utils/BinaryOperatorTest.cs b/ThinkSharp.FormulaParser.Test/Utils/BinaryOperatorTest.cs new file mode 100644 index 0000000..cdf0aad --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/Utils/BinaryOperatorTest.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.Utils; + +namespace ThinkSharp.FormulaParsing.Test +{ + [TestClass] + public class NodeComparerTest + { + private static IEqualityComparer comparer = new NodeComparer(); + private static IFormulaParser parser = FormulaParser + .CreateBuilder() + .ConfigureValidationBehavior(b => + { + b.DisableVariableNameValidation(); + b.DisableFunctionNameValidation(); + }) + .Build(); + + [TestMethod] + public void TestComparePlusEquals() + { + AssertAreEqual("1+2", "2+1"); + AssertAreEqual("1*2", "2*1"); + AssertAreEqual("1+a*c+3", "3+c*a+1"); + AssertAreEqual("1+a*c+3", "1+3+c*a"); + AssertAreEqual("a+c*(1+3*3+4)+2+3+4", "2+3+(3*3+4+1)*c+a+4"); + } + + [TestMethod] + public void TestComparePowEquals() + => AssertAreEqual("(a+b)^(1+2*b+3)", "(b+a)^(3+b*2+1)"); + + [TestMethod] + public void TestCompareFunctionEquals() + => AssertAreEqual("3*test(a+1,1+b,d*c)", "test(1+a,b+1,c*d)*3"); + + [TestMethod] + public void TestCompareDividedByEquals() + => AssertAreEqual("3*(a+b+c)/2*(f*d*s)", "(c+a+b)*3/2*(d*f*s)"); + + //[TestMethod] + public void TestCompareMinusEquals() + { + AssertAreEqual("1-3", "-3+1"); + } + + private void AssertAreEqual(params string[] formulas) + { + if (formulas.Length < 2) + Assert.Fail("Need at least 2 formulas!"); + + var nodes = formulas.Select(f => parser.Parse(f).Value).ToArray(); + for (int i = 0; i < nodes.Length; i++) + { + for (int j = i; j < nodes.Length; j++) + { + Assert.IsTrue(comparer.Equals(nodes[i], nodes[j])); + } + } + } + } +} diff --git a/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs b/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs index 5ebbe4a..6f0a097 100644 --- a/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs +++ b/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs @@ -112,44 +112,83 @@ public override Node VisitAtom([NotNull] FormulaGrammerParser.AtomContext contex return base.VisitAtom(context); } - public override Node VisitScientificNumber([NotNull] FormulaGrammerParser.ScientificNumberContext context) + //public override Node VisitScientificNumber([NotNull] FormulaGrammerParser.ScientificNumberContext context) + //{ + // //if (this.configuration.IsScientificNotationSupportDisabled) + // //{ + // // ParsingException.ThrowInvalidTokenException(context.E().Symbol); + // //} + + // var scientificNumber = context.SCIENTIFIC_NUMBER().Symbol.Text; + // //var baseNumber = this.Visit(); + // //var exponentNumber = this.Visit(context.number(1)); + // //var isNegativ = context.MINUS() != null; + + // //if (isNegativ) + // //{ + // // exponentNumber = new SignedNode(Sign.Minus, exponentNumber); + // //} + + // //var pow = new PowerNode(new IntegerNode("10", 10), exponentNumber); + // //return new BinaryOperatorNode(BinaryOperator.BySymbol("*"), baseNumber, exponentNumber); + // return new DecimalNode(scientificNumber, double.Parse(scientificNumber)); + //} + + public override Node VisitPrefixedIntNumber([NotNull] FormulaGrammerParser.PrefixedIntNumberContext context) { - if (this.configuration.IsScientificNotationSupportDisabled) - { - ParsingException.ThrowInvalidTokenException(context.SCIENTIFIC_NUMBER().Symbol); - } - - var token = context.SCIENTIFIC_NUMBER().Symbol.Text; - return new NumberNode(token, double.Parse(token)); + var token = context.PREFIX_INT_NUMBER().Symbol.Text; + return new IntegerNode(NumberFormat.Dec, long.Parse(token.Substring(2))); } - public override Node VisitBinaryNumber([NotNull] FormulaGrammerParser.BinaryNumberContext context) + public override Node VisitPrefixedBinNumber([NotNull] FormulaGrammerParser.PrefixedBinNumberContext context) { if (this.configuration.IsBinaryNumberNotationSupportDisabled) { - ParsingException.ThrowInvalidTokenException(context.BINARY_NUMBER().Symbol); + ParsingException.ThrowInvalidTokenException(context.PREFIX_BIN_NUMBER().Symbol); } - var token = context.BINARY_NUMBER().Symbol.Text; - return new NumberNode(token, Convert.ToInt32(token.Substring(2), 2)); + var token = context.PREFIX_BIN_NUMBER().Symbol.Text; + return new IntegerNode(NumberFormat.Bin, Convert.ToInt64(token.Substring(2), 2)); } - public override Node VisitDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context) + public override Node VisitPrefixedDecNumber([NotNull] FormulaGrammerParser.PrefixedDecNumberContext context) { - var token = context.DECIMAL_NUMBER().Symbol.Text; - var hasPrefix = token.StartsWith("0D", StringComparison.InvariantCultureIgnoreCase); - return new NumberNode(token, double.Parse(hasPrefix ? token.Substring(2) : token)); + var token = context.PREFIX_DEC_NUMBER().Symbol.Text; + return new DecimalNode(double.Parse(token.Substring(2))); } - public override Node VisitHexadecimalNumber([NotNull] FormulaGrammerParser.HexadecimalNumberContext context) + public override Node VisitPrefixedHexNumber([NotNull] FormulaGrammerParser.PrefixedHexNumberContext context) { if (this.configuration.IsHexadecimalNumberNotationSupportDisabled) { - ParsingException.ThrowInvalidTokenException(context.HEXADECIMAL_NUMBER().Symbol); + ParsingException.ThrowInvalidTokenException(context.PREFIX_HEX_NUMBER().Symbol); } - var token = context.HEXADECIMAL_NUMBER().Symbol.Text; - return new NumberNode(token, Convert.ToInt32(token.Substring(token[0] == '#' ? 1 : 2), 16)); + var token = context.PREFIX_HEX_NUMBER().Symbol.Text; + return new IntegerNode(NumberFormat.Hex, Convert.ToInt64(token.Substring(2), 16)); + } + + public override Node VisitPrefixedOctNumber([NotNull] FormulaGrammerParser.PrefixedOctNumberContext context) + { + if (this.configuration.IsOctalNumberNotationSupportDisabled) + { + ParsingException.ThrowInvalidTokenException(context.PREFIX_OCT_NUMBER().Symbol); + } + + var token = context.PREFIX_OCT_NUMBER().Symbol.Text; + return new IntegerNode(NumberFormat.Oct, Convert.ToInt64(token.Substring(2), 8)); + } + + public override Node VisitDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context) + { + var token = context.DECIMAL_NUMBER().Symbol.Text; + return new DecimalNode(double.Parse(token)); + } + + public override Node VisitIntgerNumber([NotNull] FormulaGrammerParser.IntgerNumberContext context) + { + var token = context.INTEGER_NUMBER().Symbol.Text; + return new IntegerNode(NumberFormat.Dec, long.Parse(token)); } public override Node VisitVariable([NotNull] FormulaGrammerParser.VariableContext context) diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.g4 b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.g4 index b096c82..7c59ad2 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.g4 +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.g4 @@ -19,21 +19,28 @@ powExpression signedAtom : PLUS atom # PlusAtom | MINUS atom # NegativeAtom - | func # Function | atom # UnsignedAtom ; atom : number + | prefixedNumber | variable | LPAREN expression RPAREN + | func ; -number - : SCIENTIFIC_NUMBER # ScientificNumber - | DECIMAL_NUMBER # DecimalNumber - | BINARY_NUMBER # BinaryNumber - | HEXADECIMAL_NUMBER # HexadecimalNumber +number + : DECIMAL_NUMBER # DecimalNumber + | INTEGER_NUMBER # IntgerNumber + ; + +prefixedNumber + : PREFIX_DEC_NUMBER # PrefixedDecNumber + | PREFIX_INT_NUMBER # PrefixedIntNumber + | PREFIX_BIN_NUMBER # PrefixedBinNumber + | PREFIX_OCT_NUMBER # PrefixedOctNumber + | PREFIX_HEX_NUMBER # PrefixedHexNumber ; func @@ -89,25 +96,36 @@ POW : '^' ; - IDENTIFIER : VALID_ID_START VALID_ID_CHAR* ; DECIMAL_NUMBER - : (PREFIX_DEC)? NUMBER_DEC + : NUMBER_DEC + ; + +INTEGER_NUMBER + : NUMBER_INT ; -BINARY_NUMBER +PREFIX_BIN_NUMBER : PREFIX_BIN NUMBER_BIN ; -HEXADECIMAL_NUMBER +PREFIX_HEX_NUMBER : PREFIX_HEX NUMBER_HEX ; -SCIENTIFIC_NUMBER - : NUMBER_DEC (E1 | E2) SIGN? NUMBER_DEC +PREFIX_INT_NUMBER + : PREFIX_INT NUMBER_INT + ; + +PREFIX_OCT_NUMBER + : PREFIX_OCT NUMBER_OCT + ; + +PREFIX_DEC_NUMBER + : PREFIX_DEC (NUMBER_DEC | NUMBER_INT) ; fragment VALID_ID_START @@ -118,41 +136,49 @@ fragment VALID_ID_CHAR : VALID_ID_START | ('0' .. '9') ; -fragment PREFIX_DEC - : '0' ('D' | 'd') +fragment NUMBER_INT + : ('0' .. '9') + ; - -fragment NUMBER_DEC - : ('0' .. '9') + ('.' ('0' .. '9') +)? + +fragment NUMBER_OCT + : ('0' .. '7') + ; -fragment PREFIX_BIN - : '0' ('B' | 'b') +fragment NUMBER_DEC + : ('0' .. '9') * ('.' ('0' .. '9') +) ; fragment NUMBER_BIN : ('0' | '1')+ ; -fragment PREFIX_HEX - : '0' ('X' | 'x') - ; - - fragment NUMBER_HEX : (('0' .. '9') | ('A' .. 'F') | ('a' .. 'f')) + ; +fragment PREFIX_DEC + : '0' ('D' | 'd') + ; + +fragment PREFIX_INT + : '0' ('I' | 'i') + ; -fragment E1 - : 'E' +fragment PREFIX_OCT + : '0' ('o' | 'O') ; +fragment PREFIX_BIN + : '0' ('B' | 'b') + ; -fragment E2 - : 'e' +fragment PREFIX_HEX + : '0' ('X' | 'x') ; +fragment E + : ('E' | 'e') + ; fragment SIGN : ('+' | '-') diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.interp b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.interp index 3f82ae6..4c6776b 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.interp +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.interp @@ -15,6 +15,9 @@ null null null null +null +null +null token symbolic names: null @@ -29,9 +32,12 @@ POINT POW IDENTIFIER DECIMAL_NUMBER -BINARY_NUMBER -HEXADECIMAL_NUMBER -SCIENTIFIC_NUMBER +INTEGER_NUMBER +PREFIX_BIN_NUMBER +PREFIX_HEX_NUMBER +PREFIX_INT_NUMBER +PREFIX_OCT_NUMBER +PREFIX_DEC_NUMBER WS rule names: @@ -42,9 +48,10 @@ powExpression signedAtom atom number +prefixedNumber func variable atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 17, 86, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 7, 3, 27, 10, 3, 12, 3, 14, 3, 30, 11, 3, 3, 4, 3, 4, 3, 4, 7, 4, 35, 10, 4, 12, 4, 14, 4, 38, 11, 4, 3, 5, 3, 5, 3, 5, 7, 5, 43, 10, 5, 12, 5, 14, 5, 46, 11, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 54, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 5, 7, 62, 10, 7, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 68, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 7, 9, 75, 10, 9, 12, 9, 14, 9, 78, 11, 9, 5, 9, 80, 10, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 2, 2, 11, 2, 4, 6, 8, 10, 12, 14, 16, 18, 2, 4, 3, 2, 5, 6, 3, 2, 7, 8, 2, 89, 2, 20, 3, 2, 2, 2, 4, 23, 3, 2, 2, 2, 6, 31, 3, 2, 2, 2, 8, 39, 3, 2, 2, 2, 10, 53, 3, 2, 2, 2, 12, 61, 3, 2, 2, 2, 14, 67, 3, 2, 2, 2, 16, 69, 3, 2, 2, 2, 18, 83, 3, 2, 2, 2, 20, 21, 5, 4, 3, 2, 21, 22, 7, 2, 2, 3, 22, 3, 3, 2, 2, 2, 23, 28, 5, 6, 4, 2, 24, 25, 9, 2, 2, 2, 25, 27, 5, 6, 4, 2, 26, 24, 3, 2, 2, 2, 27, 30, 3, 2, 2, 2, 28, 26, 3, 2, 2, 2, 28, 29, 3, 2, 2, 2, 29, 5, 3, 2, 2, 2, 30, 28, 3, 2, 2, 2, 31, 36, 5, 8, 5, 2, 32, 33, 9, 3, 2, 2, 33, 35, 5, 8, 5, 2, 34, 32, 3, 2, 2, 2, 35, 38, 3, 2, 2, 2, 36, 34, 3, 2, 2, 2, 36, 37, 3, 2, 2, 2, 37, 7, 3, 2, 2, 2, 38, 36, 3, 2, 2, 2, 39, 44, 5, 10, 6, 2, 40, 41, 7, 11, 2, 2, 41, 43, 5, 10, 6, 2, 42, 40, 3, 2, 2, 2, 43, 46, 3, 2, 2, 2, 44, 42, 3, 2, 2, 2, 44, 45, 3, 2, 2, 2, 45, 9, 3, 2, 2, 2, 46, 44, 3, 2, 2, 2, 47, 48, 7, 5, 2, 2, 48, 54, 5, 12, 7, 2, 49, 50, 7, 6, 2, 2, 50, 54, 5, 12, 7, 2, 51, 54, 5, 16, 9, 2, 52, 54, 5, 12, 7, 2, 53, 47, 3, 2, 2, 2, 53, 49, 3, 2, 2, 2, 53, 51, 3, 2, 2, 2, 53, 52, 3, 2, 2, 2, 54, 11, 3, 2, 2, 2, 55, 62, 5, 14, 8, 2, 56, 62, 5, 18, 10, 2, 57, 58, 7, 3, 2, 2, 58, 59, 5, 4, 3, 2, 59, 60, 7, 4, 2, 2, 60, 62, 3, 2, 2, 2, 61, 55, 3, 2, 2, 2, 61, 56, 3, 2, 2, 2, 61, 57, 3, 2, 2, 2, 62, 13, 3, 2, 2, 2, 63, 68, 7, 16, 2, 2, 64, 68, 7, 13, 2, 2, 65, 68, 7, 14, 2, 2, 66, 68, 7, 15, 2, 2, 67, 63, 3, 2, 2, 2, 67, 64, 3, 2, 2, 2, 67, 65, 3, 2, 2, 2, 67, 66, 3, 2, 2, 2, 68, 15, 3, 2, 2, 2, 69, 70, 7, 12, 2, 2, 70, 79, 7, 3, 2, 2, 71, 76, 5, 4, 3, 2, 72, 73, 7, 9, 2, 2, 73, 75, 5, 4, 3, 2, 74, 72, 3, 2, 2, 2, 75, 78, 3, 2, 2, 2, 76, 74, 3, 2, 2, 2, 76, 77, 3, 2, 2, 2, 77, 80, 3, 2, 2, 2, 78, 76, 3, 2, 2, 2, 79, 71, 3, 2, 2, 2, 79, 80, 3, 2, 2, 2, 80, 81, 3, 2, 2, 2, 81, 82, 7, 4, 2, 2, 82, 17, 3, 2, 2, 2, 83, 84, 7, 12, 2, 2, 84, 19, 3, 2, 2, 2, 10, 28, 36, 44, 53, 61, 67, 76, 79] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 20, 94, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 7, 3, 29, 10, 3, 12, 3, 14, 3, 32, 11, 3, 3, 4, 3, 4, 3, 4, 7, 4, 37, 10, 4, 12, 4, 14, 4, 40, 11, 4, 3, 5, 3, 5, 3, 5, 7, 5, 45, 10, 5, 12, 5, 14, 5, 48, 11, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 55, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 5, 7, 65, 10, 7, 3, 8, 3, 8, 5, 8, 69, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 5, 9, 76, 10, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 7, 10, 83, 10, 10, 12, 10, 14, 10, 86, 11, 10, 5, 10, 88, 10, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 2, 2, 12, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 2, 4, 3, 2, 5, 6, 3, 2, 7, 8, 2, 99, 2, 22, 3, 2, 2, 2, 4, 25, 3, 2, 2, 2, 6, 33, 3, 2, 2, 2, 8, 41, 3, 2, 2, 2, 10, 54, 3, 2, 2, 2, 12, 64, 3, 2, 2, 2, 14, 68, 3, 2, 2, 2, 16, 75, 3, 2, 2, 2, 18, 77, 3, 2, 2, 2, 20, 91, 3, 2, 2, 2, 22, 23, 5, 4, 3, 2, 23, 24, 7, 2, 2, 3, 24, 3, 3, 2, 2, 2, 25, 30, 5, 6, 4, 2, 26, 27, 9, 2, 2, 2, 27, 29, 5, 6, 4, 2, 28, 26, 3, 2, 2, 2, 29, 32, 3, 2, 2, 2, 30, 28, 3, 2, 2, 2, 30, 31, 3, 2, 2, 2, 31, 5, 3, 2, 2, 2, 32, 30, 3, 2, 2, 2, 33, 38, 5, 8, 5, 2, 34, 35, 9, 3, 2, 2, 35, 37, 5, 8, 5, 2, 36, 34, 3, 2, 2, 2, 37, 40, 3, 2, 2, 2, 38, 36, 3, 2, 2, 2, 38, 39, 3, 2, 2, 2, 39, 7, 3, 2, 2, 2, 40, 38, 3, 2, 2, 2, 41, 46, 5, 10, 6, 2, 42, 43, 7, 11, 2, 2, 43, 45, 5, 10, 6, 2, 44, 42, 3, 2, 2, 2, 45, 48, 3, 2, 2, 2, 46, 44, 3, 2, 2, 2, 46, 47, 3, 2, 2, 2, 47, 9, 3, 2, 2, 2, 48, 46, 3, 2, 2, 2, 49, 50, 7, 5, 2, 2, 50, 55, 5, 12, 7, 2, 51, 52, 7, 6, 2, 2, 52, 55, 5, 12, 7, 2, 53, 55, 5, 12, 7, 2, 54, 49, 3, 2, 2, 2, 54, 51, 3, 2, 2, 2, 54, 53, 3, 2, 2, 2, 55, 11, 3, 2, 2, 2, 56, 65, 5, 14, 8, 2, 57, 65, 5, 16, 9, 2, 58, 65, 5, 20, 11, 2, 59, 60, 7, 3, 2, 2, 60, 61, 5, 4, 3, 2, 61, 62, 7, 4, 2, 2, 62, 65, 3, 2, 2, 2, 63, 65, 5, 18, 10, 2, 64, 56, 3, 2, 2, 2, 64, 57, 3, 2, 2, 2, 64, 58, 3, 2, 2, 2, 64, 59, 3, 2, 2, 2, 64, 63, 3, 2, 2, 2, 65, 13, 3, 2, 2, 2, 66, 69, 7, 13, 2, 2, 67, 69, 7, 14, 2, 2, 68, 66, 3, 2, 2, 2, 68, 67, 3, 2, 2, 2, 69, 15, 3, 2, 2, 2, 70, 76, 7, 19, 2, 2, 71, 76, 7, 17, 2, 2, 72, 76, 7, 15, 2, 2, 73, 76, 7, 18, 2, 2, 74, 76, 7, 16, 2, 2, 75, 70, 3, 2, 2, 2, 75, 71, 3, 2, 2, 2, 75, 72, 3, 2, 2, 2, 75, 73, 3, 2, 2, 2, 75, 74, 3, 2, 2, 2, 76, 17, 3, 2, 2, 2, 77, 78, 7, 12, 2, 2, 78, 87, 7, 3, 2, 2, 79, 84, 5, 4, 3, 2, 80, 81, 7, 9, 2, 2, 81, 83, 5, 4, 3, 2, 82, 80, 3, 2, 2, 2, 83, 86, 3, 2, 2, 2, 84, 82, 3, 2, 2, 2, 84, 85, 3, 2, 2, 2, 85, 88, 3, 2, 2, 2, 86, 84, 3, 2, 2, 2, 87, 79, 3, 2, 2, 2, 87, 88, 3, 2, 2, 2, 88, 89, 3, 2, 2, 2, 89, 90, 7, 4, 2, 2, 90, 19, 3, 2, 2, 2, 91, 92, 7, 12, 2, 2, 92, 21, 3, 2, 2, 2, 11, 30, 38, 46, 54, 64, 68, 75, 84, 87] \ No newline at end of file diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.tokens b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.tokens index a954a79..a254e9e 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.tokens +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammer.tokens @@ -9,10 +9,13 @@ POINT=8 POW=9 IDENTIFIER=10 DECIMAL_NUMBER=11 -BINARY_NUMBER=12 -HEXADECIMAL_NUMBER=13 -SCIENTIFIC_NUMBER=14 -WS=15 +INTEGER_NUMBER=12 +PREFIX_BIN_NUMBER=13 +PREFIX_HEX_NUMBER=14 +PREFIX_INT_NUMBER=15 +PREFIX_OCT_NUMBER=16 +PREFIX_DEC_NUMBER=17 +WS=18 '('=1 ')'=2 '+'=3 diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerBaseListener.cs b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerBaseListener.cs index 1f31424..9791f70 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerBaseListener.cs +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerBaseListener.cs @@ -111,20 +111,6 @@ public virtual void EnterNegativeAtom([NotNull] FormulaGrammerParser.NegativeAto /// The parse tree. public virtual void ExitNegativeAtom([NotNull] FormulaGrammerParser.NegativeAtomContext context) { } /// - /// Enter a parse tree produced by the Function - /// labeled alternative in . - /// The default implementation does nothing. - /// - /// The parse tree. - public virtual void EnterFunction([NotNull] FormulaGrammerParser.FunctionContext context) { } - /// - /// Exit a parse tree produced by the Function - /// labeled alternative in . - /// The default implementation does nothing. - /// - /// The parse tree. - public virtual void ExitFunction([NotNull] FormulaGrammerParser.FunctionContext context) { } - /// /// Enter a parse tree produced by the UnsignedAtom /// labeled alternative in . /// The default implementation does nothing. @@ -151,61 +137,103 @@ public virtual void EnterAtom([NotNull] FormulaGrammerParser.AtomContext context /// The parse tree. public virtual void ExitAtom([NotNull] FormulaGrammerParser.AtomContext context) { } /// - /// Enter a parse tree produced by the ScientificNumber + /// Enter a parse tree produced by the DecimalNumber /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void EnterScientificNumber([NotNull] FormulaGrammerParser.ScientificNumberContext context) { } + public virtual void EnterDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context) { } /// - /// Exit a parse tree produced by the ScientificNumber + /// Exit a parse tree produced by the DecimalNumber /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void ExitScientificNumber([NotNull] FormulaGrammerParser.ScientificNumberContext context) { } + public virtual void ExitDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context) { } /// - /// Enter a parse tree produced by the DecimalNumber + /// Enter a parse tree produced by the IntgerNumber /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void EnterDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context) { } + public virtual void EnterIntgerNumber([NotNull] FormulaGrammerParser.IntgerNumberContext context) { } /// - /// Exit a parse tree produced by the DecimalNumber + /// Exit a parse tree produced by the IntgerNumber /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void ExitDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context) { } + public virtual void ExitIntgerNumber([NotNull] FormulaGrammerParser.IntgerNumberContext context) { } /// - /// Enter a parse tree produced by the BinaryNumber - /// labeled alternative in . + /// Enter a parse tree produced by the PrefixedDecNumber + /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void EnterBinaryNumber([NotNull] FormulaGrammerParser.BinaryNumberContext context) { } + public virtual void EnterPrefixedDecNumber([NotNull] FormulaGrammerParser.PrefixedDecNumberContext context) { } /// - /// Exit a parse tree produced by the BinaryNumber - /// labeled alternative in . + /// Exit a parse tree produced by the PrefixedDecNumber + /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void ExitBinaryNumber([NotNull] FormulaGrammerParser.BinaryNumberContext context) { } + public virtual void ExitPrefixedDecNumber([NotNull] FormulaGrammerParser.PrefixedDecNumberContext context) { } /// - /// Enter a parse tree produced by the HexadecimalNumber - /// labeled alternative in . + /// Enter a parse tree produced by the PrefixedIntNumber + /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void EnterHexadecimalNumber([NotNull] FormulaGrammerParser.HexadecimalNumberContext context) { } + public virtual void EnterPrefixedIntNumber([NotNull] FormulaGrammerParser.PrefixedIntNumberContext context) { } /// - /// Exit a parse tree produced by the HexadecimalNumber - /// labeled alternative in . + /// Exit a parse tree produced by the PrefixedIntNumber + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void ExitPrefixedIntNumber([NotNull] FormulaGrammerParser.PrefixedIntNumberContext context) { } + /// + /// Enter a parse tree produced by the PrefixedBinNumber + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void EnterPrefixedBinNumber([NotNull] FormulaGrammerParser.PrefixedBinNumberContext context) { } + /// + /// Exit a parse tree produced by the PrefixedBinNumber + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void ExitPrefixedBinNumber([NotNull] FormulaGrammerParser.PrefixedBinNumberContext context) { } + /// + /// Enter a parse tree produced by the PrefixedOctNumber + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void EnterPrefixedOctNumber([NotNull] FormulaGrammerParser.PrefixedOctNumberContext context) { } + /// + /// Exit a parse tree produced by the PrefixedOctNumber + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void ExitPrefixedOctNumber([NotNull] FormulaGrammerParser.PrefixedOctNumberContext context) { } + /// + /// Enter a parse tree produced by the PrefixedHexNumber + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void EnterPrefixedHexNumber([NotNull] FormulaGrammerParser.PrefixedHexNumberContext context) { } + /// + /// Exit a parse tree produced by the PrefixedHexNumber + /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void ExitHexadecimalNumber([NotNull] FormulaGrammerParser.HexadecimalNumberContext context) { } + public virtual void ExitPrefixedHexNumber([NotNull] FormulaGrammerParser.PrefixedHexNumberContext context) { } /// /// Enter a parse tree produced by . /// The default implementation does nothing. diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerBaseVisitor.cs b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerBaseVisitor.cs index 677ef4a..afff3da 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerBaseVisitor.cs +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerBaseVisitor.cs @@ -96,7 +96,7 @@ public partial class FormulaGrammerBaseVisitor : AbstractParseTreeVisito /// The visitor result. public virtual Result VisitNegativeAtom([NotNull] FormulaGrammerParser.NegativeAtomContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by the Function + /// Visit a parse tree produced by the UnsignedAtom /// labeled alternative in . /// /// The default implementation returns the result of calling @@ -105,10 +105,9 @@ public partial class FormulaGrammerBaseVisitor : AbstractParseTreeVisito /// /// The parse tree. /// The visitor result. - public virtual Result VisitFunction([NotNull] FormulaGrammerParser.FunctionContext context) { return VisitChildren(context); } + public virtual Result VisitUnsignedAtom([NotNull] FormulaGrammerParser.UnsignedAtomContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by the UnsignedAtom - /// labeled alternative in . + /// Visit a parse tree produced by . /// /// The default implementation returns the result of calling /// on . @@ -116,9 +115,10 @@ public partial class FormulaGrammerBaseVisitor : AbstractParseTreeVisito /// /// The parse tree. /// The visitor result. - public virtual Result VisitUnsignedAtom([NotNull] FormulaGrammerParser.UnsignedAtomContext context) { return VisitChildren(context); } + public virtual Result VisitAtom([NotNull] FormulaGrammerParser.AtomContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by . + /// Visit a parse tree produced by the DecimalNumber + /// labeled alternative in . /// /// The default implementation returns the result of calling /// on . @@ -126,9 +126,9 @@ public partial class FormulaGrammerBaseVisitor : AbstractParseTreeVisito /// /// The parse tree. /// The visitor result. - public virtual Result VisitAtom([NotNull] FormulaGrammerParser.AtomContext context) { return VisitChildren(context); } + public virtual Result VisitDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by the ScientificNumber + /// Visit a parse tree produced by the IntgerNumber /// labeled alternative in . /// /// The default implementation returns the result of calling @@ -137,10 +137,10 @@ public partial class FormulaGrammerBaseVisitor : AbstractParseTreeVisito /// /// The parse tree. /// The visitor result. - public virtual Result VisitScientificNumber([NotNull] FormulaGrammerParser.ScientificNumberContext context) { return VisitChildren(context); } + public virtual Result VisitIntgerNumber([NotNull] FormulaGrammerParser.IntgerNumberContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by the DecimalNumber - /// labeled alternative in . + /// Visit a parse tree produced by the PrefixedDecNumber + /// labeled alternative in . /// /// The default implementation returns the result of calling /// on . @@ -148,10 +148,10 @@ public partial class FormulaGrammerBaseVisitor : AbstractParseTreeVisito /// /// The parse tree. /// The visitor result. - public virtual Result VisitDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context) { return VisitChildren(context); } + public virtual Result VisitPrefixedDecNumber([NotNull] FormulaGrammerParser.PrefixedDecNumberContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by the BinaryNumber - /// labeled alternative in . + /// Visit a parse tree produced by the PrefixedIntNumber + /// labeled alternative in . /// /// The default implementation returns the result of calling /// on . @@ -159,10 +159,32 @@ public partial class FormulaGrammerBaseVisitor : AbstractParseTreeVisito /// /// The parse tree. /// The visitor result. - public virtual Result VisitBinaryNumber([NotNull] FormulaGrammerParser.BinaryNumberContext context) { return VisitChildren(context); } + public virtual Result VisitPrefixedIntNumber([NotNull] FormulaGrammerParser.PrefixedIntNumberContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by the HexadecimalNumber - /// labeled alternative in . + /// Visit a parse tree produced by the PrefixedBinNumber + /// labeled alternative in . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitPrefixedBinNumber([NotNull] FormulaGrammerParser.PrefixedBinNumberContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by the PrefixedOctNumber + /// labeled alternative in . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitPrefixedOctNumber([NotNull] FormulaGrammerParser.PrefixedOctNumberContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by the PrefixedHexNumber + /// labeled alternative in . /// /// The default implementation returns the result of calling /// on . @@ -170,7 +192,7 @@ public partial class FormulaGrammerBaseVisitor : AbstractParseTreeVisito /// /// The parse tree. /// The visitor result. - public virtual Result VisitHexadecimalNumber([NotNull] FormulaGrammerParser.HexadecimalNumberContext context) { return VisitChildren(context); } + public virtual Result VisitPrefixedHexNumber([NotNull] FormulaGrammerParser.PrefixedHexNumberContext context) { return VisitChildren(context); } /// /// Visit a parse tree produced by . /// diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.cs b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.cs index 0effe6b..eef63e6 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.cs +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.cs @@ -34,8 +34,9 @@ public partial class FormulaGrammerLexer : Lexer { protected static PredictionContextCache sharedContextCache = new PredictionContextCache(); public const int LPAREN=1, RPAREN=2, PLUS=3, MINUS=4, TIMES=5, DIV=6, COMMA=7, POINT=8, - POW=9, IDENTIFIER=10, DECIMAL_NUMBER=11, BINARY_NUMBER=12, HEXADECIMAL_NUMBER=13, - SCIENTIFIC_NUMBER=14, WS=15; + POW=9, IDENTIFIER=10, DECIMAL_NUMBER=11, INTEGER_NUMBER=12, PREFIX_BIN_NUMBER=13, + PREFIX_HEX_NUMBER=14, PREFIX_INT_NUMBER=15, PREFIX_OCT_NUMBER=16, PREFIX_DEC_NUMBER=17, + WS=18; public static string[] channelNames = { "DEFAULT_TOKEN_CHANNEL", "HIDDEN" }; @@ -46,10 +47,11 @@ public const int public static readonly string[] ruleNames = { "LPAREN", "RPAREN", "PLUS", "MINUS", "TIMES", "DIV", "COMMA", "POINT", - "POW", "IDENTIFIER", "DECIMAL_NUMBER", "BINARY_NUMBER", "HEXADECIMAL_NUMBER", - "SCIENTIFIC_NUMBER", "VALID_ID_START", "VALID_ID_CHAR", "PREFIX_DEC", - "NUMBER_DEC", "PREFIX_BIN", "NUMBER_BIN", "PREFIX_HEX", "NUMBER_HEX", - "E1", "E2", "SIGN", "WS" + "POW", "IDENTIFIER", "DECIMAL_NUMBER", "INTEGER_NUMBER", "PREFIX_BIN_NUMBER", + "PREFIX_HEX_NUMBER", "PREFIX_INT_NUMBER", "PREFIX_OCT_NUMBER", "PREFIX_DEC_NUMBER", + "VALID_ID_START", "VALID_ID_CHAR", "NUMBER_INT", "NUMBER_OCT", "NUMBER_DEC", + "NUMBER_BIN", "NUMBER_HEX", "PREFIX_DEC", "PREFIX_INT", "PREFIX_OCT", + "PREFIX_BIN", "PREFIX_HEX", "E", "SIGN", "WS" }; @@ -67,8 +69,9 @@ public FormulaGrammerLexer(ICharStream input, TextWriter output, TextWriter erro }; private static readonly string[] _SymbolicNames = { null, "LPAREN", "RPAREN", "PLUS", "MINUS", "TIMES", "DIV", "COMMA", "POINT", - "POW", "IDENTIFIER", "DECIMAL_NUMBER", "BINARY_NUMBER", "HEXADECIMAL_NUMBER", - "SCIENTIFIC_NUMBER", "WS" + "POW", "IDENTIFIER", "DECIMAL_NUMBER", "INTEGER_NUMBER", "PREFIX_BIN_NUMBER", + "PREFIX_HEX_NUMBER", "PREFIX_INT_NUMBER", "PREFIX_OCT_NUMBER", "PREFIX_DEC_NUMBER", + "WS" }; public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames); @@ -99,7 +102,7 @@ static FormulaGrammerLexer() { } private static char[] _serializedATN = { '\x3', '\x608B', '\xA72A', '\x8133', '\xB9ED', '\x417C', '\x3BE7', '\x7786', - '\x5964', '\x2', '\x11', '\x99', '\b', '\x1', '\x4', '\x2', '\t', '\x2', + '\x5964', '\x2', '\x14', '\xB2', '\b', '\x1', '\x4', '\x2', '\t', '\x2', '\x4', '\x3', '\t', '\x3', '\x4', '\x4', '\t', '\x4', '\x4', '\x5', '\t', '\x5', '\x4', '\x6', '\t', '\x6', '\x4', '\a', '\t', '\a', '\x4', '\b', '\t', '\b', '\x4', '\t', '\t', '\t', '\x4', '\n', '\t', '\n', '\x4', '\v', @@ -109,122 +112,142 @@ static FormulaGrammerLexer() { '\x13', '\x4', '\x14', '\t', '\x14', '\x4', '\x15', '\t', '\x15', '\x4', '\x16', '\t', '\x16', '\x4', '\x17', '\t', '\x17', '\x4', '\x18', '\t', '\x18', '\x4', '\x19', '\t', '\x19', '\x4', '\x1A', '\t', '\x1A', '\x4', - '\x1B', '\t', '\x1B', '\x3', '\x2', '\x3', '\x2', '\x3', '\x3', '\x3', - '\x3', '\x3', '\x4', '\x3', '\x4', '\x3', '\x5', '\x3', '\x5', '\x3', - '\x6', '\x3', '\x6', '\x3', '\a', '\x3', '\a', '\x3', '\b', '\x3', '\b', - '\x3', '\t', '\x3', '\t', '\x3', '\n', '\x3', '\n', '\x3', '\v', '\x3', - '\v', '\a', '\v', 'L', '\n', '\v', '\f', '\v', '\xE', '\v', 'O', '\v', - '\v', '\x3', '\f', '\x5', '\f', 'R', '\n', '\f', '\x3', '\f', '\x3', '\f', - '\x3', '\r', '\x3', '\r', '\x3', '\r', '\x3', '\xE', '\x3', '\xE', '\x3', - '\xE', '\x3', '\xF', '\x3', '\xF', '\x3', '\xF', '\x5', '\xF', '_', '\n', - '\xF', '\x3', '\xF', '\x5', '\xF', '\x62', '\n', '\xF', '\x3', '\xF', - '\x3', '\xF', '\x3', '\x10', '\x5', '\x10', 'g', '\n', '\x10', '\x3', - '\x11', '\x3', '\x11', '\x5', '\x11', 'k', '\n', '\x11', '\x3', '\x12', - '\x3', '\x12', '\x3', '\x12', '\x3', '\x13', '\x6', '\x13', 'q', '\n', - '\x13', '\r', '\x13', '\xE', '\x13', 'r', '\x3', '\x13', '\x3', '\x13', - '\x6', '\x13', 'w', '\n', '\x13', '\r', '\x13', '\xE', '\x13', 'x', '\x5', - '\x13', '{', '\n', '\x13', '\x3', '\x14', '\x3', '\x14', '\x3', '\x14', - '\x3', '\x15', '\x6', '\x15', '\x81', '\n', '\x15', '\r', '\x15', '\xE', - '\x15', '\x82', '\x3', '\x16', '\x3', '\x16', '\x3', '\x16', '\x3', '\x17', - '\x6', '\x17', '\x89', '\n', '\x17', '\r', '\x17', '\xE', '\x17', '\x8A', - '\x3', '\x18', '\x3', '\x18', '\x3', '\x19', '\x3', '\x19', '\x3', '\x1A', - '\x3', '\x1A', '\x3', '\x1B', '\x6', '\x1B', '\x94', '\n', '\x1B', '\r', - '\x1B', '\xE', '\x1B', '\x95', '\x3', '\x1B', '\x3', '\x1B', '\x2', '\x2', - '\x1C', '\x3', '\x3', '\x5', '\x4', '\a', '\x5', '\t', '\x6', '\v', '\a', - '\r', '\b', '\xF', '\t', '\x11', '\n', '\x13', '\v', '\x15', '\f', '\x17', - '\r', '\x19', '\xE', '\x1B', '\xF', '\x1D', '\x10', '\x1F', '\x2', '!', - '\x2', '#', '\x2', '%', '\x2', '\'', '\x2', ')', '\x2', '+', '\x2', '-', - '\x2', '/', '\x2', '\x31', '\x2', '\x33', '\x2', '\x35', '\x11', '\x3', - '\x2', '\t', '\x6', '\x2', '&', '&', '\x43', '\\', '\x61', '\x61', '\x63', - '|', '\x4', '\x2', '\x46', '\x46', '\x66', '\x66', '\x4', '\x2', '\x44', - '\x44', '\x64', '\x64', '\x4', '\x2', 'Z', 'Z', 'z', 'z', '\x5', '\x2', - '\x32', ';', '\x43', 'H', '\x63', 'h', '\x4', '\x2', '-', '-', '/', '/', - '\x5', '\x2', '\v', '\f', '\xF', '\xF', '\"', '\"', '\x2', '\x98', '\x2', - '\x3', '\x3', '\x2', '\x2', '\x2', '\x2', '\x5', '\x3', '\x2', '\x2', - '\x2', '\x2', '\a', '\x3', '\x2', '\x2', '\x2', '\x2', '\t', '\x3', '\x2', - '\x2', '\x2', '\x2', '\v', '\x3', '\x2', '\x2', '\x2', '\x2', '\r', '\x3', - '\x2', '\x2', '\x2', '\x2', '\xF', '\x3', '\x2', '\x2', '\x2', '\x2', - '\x11', '\x3', '\x2', '\x2', '\x2', '\x2', '\x13', '\x3', '\x2', '\x2', - '\x2', '\x2', '\x15', '\x3', '\x2', '\x2', '\x2', '\x2', '\x17', '\x3', - '\x2', '\x2', '\x2', '\x2', '\x19', '\x3', '\x2', '\x2', '\x2', '\x2', - '\x1B', '\x3', '\x2', '\x2', '\x2', '\x2', '\x1D', '\x3', '\x2', '\x2', - '\x2', '\x2', '\x35', '\x3', '\x2', '\x2', '\x2', '\x3', '\x37', '\x3', - '\x2', '\x2', '\x2', '\x5', '\x39', '\x3', '\x2', '\x2', '\x2', '\a', - ';', '\x3', '\x2', '\x2', '\x2', '\t', '=', '\x3', '\x2', '\x2', '\x2', - '\v', '?', '\x3', '\x2', '\x2', '\x2', '\r', '\x41', '\x3', '\x2', '\x2', - '\x2', '\xF', '\x43', '\x3', '\x2', '\x2', '\x2', '\x11', '\x45', '\x3', - '\x2', '\x2', '\x2', '\x13', 'G', '\x3', '\x2', '\x2', '\x2', '\x15', - 'I', '\x3', '\x2', '\x2', '\x2', '\x17', 'Q', '\x3', '\x2', '\x2', '\x2', - '\x19', 'U', '\x3', '\x2', '\x2', '\x2', '\x1B', 'X', '\x3', '\x2', '\x2', - '\x2', '\x1D', '[', '\x3', '\x2', '\x2', '\x2', '\x1F', '\x66', '\x3', - '\x2', '\x2', '\x2', '!', 'j', '\x3', '\x2', '\x2', '\x2', '#', 'l', '\x3', - '\x2', '\x2', '\x2', '%', 'p', '\x3', '\x2', '\x2', '\x2', '\'', '|', - '\x3', '\x2', '\x2', '\x2', ')', '\x80', '\x3', '\x2', '\x2', '\x2', '+', - '\x84', '\x3', '\x2', '\x2', '\x2', '-', '\x88', '\x3', '\x2', '\x2', - '\x2', '/', '\x8C', '\x3', '\x2', '\x2', '\x2', '\x31', '\x8E', '\x3', - '\x2', '\x2', '\x2', '\x33', '\x90', '\x3', '\x2', '\x2', '\x2', '\x35', - '\x93', '\x3', '\x2', '\x2', '\x2', '\x37', '\x38', '\a', '*', '\x2', - '\x2', '\x38', '\x4', '\x3', '\x2', '\x2', '\x2', '\x39', ':', '\a', '+', - '\x2', '\x2', ':', '\x6', '\x3', '\x2', '\x2', '\x2', ';', '<', '\a', - '-', '\x2', '\x2', '<', '\b', '\x3', '\x2', '\x2', '\x2', '=', '>', '\a', - '/', '\x2', '\x2', '>', '\n', '\x3', '\x2', '\x2', '\x2', '?', '@', '\a', - ',', '\x2', '\x2', '@', '\f', '\x3', '\x2', '\x2', '\x2', '\x41', '\x42', - '\a', '\x31', '\x2', '\x2', '\x42', '\xE', '\x3', '\x2', '\x2', '\x2', - '\x43', '\x44', '\a', '.', '\x2', '\x2', '\x44', '\x10', '\x3', '\x2', - '\x2', '\x2', '\x45', '\x46', '\a', '\x30', '\x2', '\x2', '\x46', '\x12', - '\x3', '\x2', '\x2', '\x2', 'G', 'H', '\a', '`', '\x2', '\x2', 'H', '\x14', - '\x3', '\x2', '\x2', '\x2', 'I', 'M', '\x5', '\x1F', '\x10', '\x2', 'J', - 'L', '\x5', '!', '\x11', '\x2', 'K', 'J', '\x3', '\x2', '\x2', '\x2', - 'L', 'O', '\x3', '\x2', '\x2', '\x2', 'M', 'K', '\x3', '\x2', '\x2', '\x2', - 'M', 'N', '\x3', '\x2', '\x2', '\x2', 'N', '\x16', '\x3', '\x2', '\x2', - '\x2', 'O', 'M', '\x3', '\x2', '\x2', '\x2', 'P', 'R', '\x5', '#', '\x12', - '\x2', 'Q', 'P', '\x3', '\x2', '\x2', '\x2', 'Q', 'R', '\x3', '\x2', '\x2', - '\x2', 'R', 'S', '\x3', '\x2', '\x2', '\x2', 'S', 'T', '\x5', '%', '\x13', - '\x2', 'T', '\x18', '\x3', '\x2', '\x2', '\x2', 'U', 'V', '\x5', '\'', - '\x14', '\x2', 'V', 'W', '\x5', ')', '\x15', '\x2', 'W', '\x1A', '\x3', - '\x2', '\x2', '\x2', 'X', 'Y', '\x5', '+', '\x16', '\x2', 'Y', 'Z', '\x5', - '-', '\x17', '\x2', 'Z', '\x1C', '\x3', '\x2', '\x2', '\x2', '[', '^', - '\x5', '%', '\x13', '\x2', '\\', '_', '\x5', '/', '\x18', '\x2', ']', - '_', '\x5', '\x31', '\x19', '\x2', '^', '\\', '\x3', '\x2', '\x2', '\x2', - '^', ']', '\x3', '\x2', '\x2', '\x2', '_', '\x61', '\x3', '\x2', '\x2', - '\x2', '`', '\x62', '\x5', '\x33', '\x1A', '\x2', '\x61', '`', '\x3', - '\x2', '\x2', '\x2', '\x61', '\x62', '\x3', '\x2', '\x2', '\x2', '\x62', - '\x63', '\x3', '\x2', '\x2', '\x2', '\x63', '\x64', '\x5', '%', '\x13', - '\x2', '\x64', '\x1E', '\x3', '\x2', '\x2', '\x2', '\x65', 'g', '\t', - '\x2', '\x2', '\x2', '\x66', '\x65', '\x3', '\x2', '\x2', '\x2', 'g', - ' ', '\x3', '\x2', '\x2', '\x2', 'h', 'k', '\x5', '\x1F', '\x10', '\x2', - 'i', 'k', '\x4', '\x32', ';', '\x2', 'j', 'h', '\x3', '\x2', '\x2', '\x2', - 'j', 'i', '\x3', '\x2', '\x2', '\x2', 'k', '\"', '\x3', '\x2', '\x2', - '\x2', 'l', 'm', '\a', '\x32', '\x2', '\x2', 'm', 'n', '\t', '\x3', '\x2', - '\x2', 'n', '$', '\x3', '\x2', '\x2', '\x2', 'o', 'q', '\x4', '\x32', - ';', '\x2', 'p', 'o', '\x3', '\x2', '\x2', '\x2', 'q', 'r', '\x3', '\x2', - '\x2', '\x2', 'r', 'p', '\x3', '\x2', '\x2', '\x2', 'r', 's', '\x3', '\x2', - '\x2', '\x2', 's', 'z', '\x3', '\x2', '\x2', '\x2', 't', 'v', '\a', '\x30', - '\x2', '\x2', 'u', 'w', '\x4', '\x32', ';', '\x2', 'v', 'u', '\x3', '\x2', - '\x2', '\x2', 'w', 'x', '\x3', '\x2', '\x2', '\x2', 'x', 'v', '\x3', '\x2', - '\x2', '\x2', 'x', 'y', '\x3', '\x2', '\x2', '\x2', 'y', '{', '\x3', '\x2', - '\x2', '\x2', 'z', 't', '\x3', '\x2', '\x2', '\x2', 'z', '{', '\x3', '\x2', - '\x2', '\x2', '{', '&', '\x3', '\x2', '\x2', '\x2', '|', '}', '\a', '\x32', - '\x2', '\x2', '}', '~', '\t', '\x4', '\x2', '\x2', '~', '(', '\x3', '\x2', - '\x2', '\x2', '\x7F', '\x81', '\x4', '\x32', '\x33', '\x2', '\x80', '\x7F', - '\x3', '\x2', '\x2', '\x2', '\x81', '\x82', '\x3', '\x2', '\x2', '\x2', - '\x82', '\x80', '\x3', '\x2', '\x2', '\x2', '\x82', '\x83', '\x3', '\x2', - '\x2', '\x2', '\x83', '*', '\x3', '\x2', '\x2', '\x2', '\x84', '\x85', - '\a', '\x32', '\x2', '\x2', '\x85', '\x86', '\t', '\x5', '\x2', '\x2', - '\x86', ',', '\x3', '\x2', '\x2', '\x2', '\x87', '\x89', '\t', '\x6', - '\x2', '\x2', '\x88', '\x87', '\x3', '\x2', '\x2', '\x2', '\x89', '\x8A', - '\x3', '\x2', '\x2', '\x2', '\x8A', '\x88', '\x3', '\x2', '\x2', '\x2', - '\x8A', '\x8B', '\x3', '\x2', '\x2', '\x2', '\x8B', '.', '\x3', '\x2', - '\x2', '\x2', '\x8C', '\x8D', '\a', 'G', '\x2', '\x2', '\x8D', '\x30', - '\x3', '\x2', '\x2', '\x2', '\x8E', '\x8F', '\a', 'g', '\x2', '\x2', '\x8F', - '\x32', '\x3', '\x2', '\x2', '\x2', '\x90', '\x91', '\t', '\a', '\x2', - '\x2', '\x91', '\x34', '\x3', '\x2', '\x2', '\x2', '\x92', '\x94', '\t', - '\b', '\x2', '\x2', '\x93', '\x92', '\x3', '\x2', '\x2', '\x2', '\x94', - '\x95', '\x3', '\x2', '\x2', '\x2', '\x95', '\x93', '\x3', '\x2', '\x2', - '\x2', '\x95', '\x96', '\x3', '\x2', '\x2', '\x2', '\x96', '\x97', '\x3', - '\x2', '\x2', '\x2', '\x97', '\x98', '\b', '\x1B', '\x2', '\x2', '\x98', - '\x36', '\x3', '\x2', '\x2', '\x2', '\x10', '\x2', 'M', 'Q', '^', '\x61', - '\x66', 'j', 'r', 'x', 'z', '\x82', '\x88', '\x8A', '\x95', '\x3', '\b', + '\x1B', '\t', '\x1B', '\x4', '\x1C', '\t', '\x1C', '\x4', '\x1D', '\t', + '\x1D', '\x4', '\x1E', '\t', '\x1E', '\x4', '\x1F', '\t', '\x1F', '\x4', + ' ', '\t', ' ', '\x4', '!', '\t', '!', '\x3', '\x2', '\x3', '\x2', '\x3', + '\x3', '\x3', '\x3', '\x3', '\x4', '\x3', '\x4', '\x3', '\x5', '\x3', + '\x5', '\x3', '\x6', '\x3', '\x6', '\x3', '\a', '\x3', '\a', '\x3', '\b', + '\x3', '\b', '\x3', '\t', '\x3', '\t', '\x3', '\n', '\x3', '\n', '\x3', + '\v', '\x3', '\v', '\a', '\v', 'X', '\n', '\v', '\f', '\v', '\xE', '\v', + '[', '\v', '\v', '\x3', '\f', '\x3', '\f', '\x3', '\r', '\x3', '\r', '\x3', + '\xE', '\x3', '\xE', '\x3', '\xE', '\x3', '\xF', '\x3', '\xF', '\x3', + '\xF', '\x3', '\x10', '\x3', '\x10', '\x3', '\x10', '\x3', '\x11', '\x3', + '\x11', '\x3', '\x11', '\x3', '\x12', '\x3', '\x12', '\x3', '\x12', '\x5', + '\x12', 'p', '\n', '\x12', '\x3', '\x13', '\x5', '\x13', 's', '\n', '\x13', + '\x3', '\x14', '\x3', '\x14', '\x5', '\x14', 'w', '\n', '\x14', '\x3', + '\x15', '\x6', '\x15', 'z', '\n', '\x15', '\r', '\x15', '\xE', '\x15', + '{', '\x3', '\x16', '\x6', '\x16', '\x7F', '\n', '\x16', '\r', '\x16', + '\xE', '\x16', '\x80', '\x3', '\x17', '\a', '\x17', '\x84', '\n', '\x17', + '\f', '\x17', '\xE', '\x17', '\x87', '\v', '\x17', '\x3', '\x17', '\x3', + '\x17', '\x6', '\x17', '\x8B', '\n', '\x17', '\r', '\x17', '\xE', '\x17', + '\x8C', '\x3', '\x18', '\x6', '\x18', '\x90', '\n', '\x18', '\r', '\x18', + '\xE', '\x18', '\x91', '\x3', '\x19', '\x6', '\x19', '\x95', '\n', '\x19', + '\r', '\x19', '\xE', '\x19', '\x96', '\x3', '\x1A', '\x3', '\x1A', '\x3', + '\x1A', '\x3', '\x1B', '\x3', '\x1B', '\x3', '\x1B', '\x3', '\x1C', '\x3', + '\x1C', '\x3', '\x1C', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', + '\x1E', '\x3', '\x1E', '\x3', '\x1E', '\x3', '\x1F', '\x3', '\x1F', '\x3', + ' ', '\x3', ' ', '\x3', '!', '\x6', '!', '\xAD', '\n', '!', '\r', '!', + '\xE', '!', '\xAE', '\x3', '!', '\x3', '!', '\x2', '\x2', '\"', '\x3', + '\x3', '\x5', '\x4', '\a', '\x5', '\t', '\x6', '\v', '\a', '\r', '\b', + '\xF', '\t', '\x11', '\n', '\x13', '\v', '\x15', '\f', '\x17', '\r', '\x19', + '\xE', '\x1B', '\xF', '\x1D', '\x10', '\x1F', '\x11', '!', '\x12', '#', + '\x13', '%', '\x2', '\'', '\x2', ')', '\x2', '+', '\x2', '-', '\x2', '/', + '\x2', '\x31', '\x2', '\x33', '\x2', '\x35', '\x2', '\x37', '\x2', '\x39', + '\x2', ';', '\x2', '=', '\x2', '?', '\x2', '\x41', '\x14', '\x3', '\x2', + '\f', '\x6', '\x2', '&', '&', '\x43', '\\', '\x61', '\x61', '\x63', '|', + '\x5', '\x2', '\x32', ';', '\x43', 'H', '\x63', 'h', '\x4', '\x2', '\x46', + '\x46', '\x66', '\x66', '\x4', '\x2', 'K', 'K', 'k', 'k', '\x4', '\x2', + 'Q', 'Q', 'q', 'q', '\x4', '\x2', '\x44', '\x44', '\x64', '\x64', '\x4', + '\x2', 'Z', 'Z', 'z', 'z', '\x4', '\x2', 'G', 'G', 'g', 'g', '\x4', '\x2', + '-', '-', '/', '/', '\x5', '\x2', '\v', '\f', '\xF', '\xF', '\"', '\"', + '\x2', '\xAD', '\x2', '\x3', '\x3', '\x2', '\x2', '\x2', '\x2', '\x5', + '\x3', '\x2', '\x2', '\x2', '\x2', '\a', '\x3', '\x2', '\x2', '\x2', '\x2', + '\t', '\x3', '\x2', '\x2', '\x2', '\x2', '\v', '\x3', '\x2', '\x2', '\x2', + '\x2', '\r', '\x3', '\x2', '\x2', '\x2', '\x2', '\xF', '\x3', '\x2', '\x2', + '\x2', '\x2', '\x11', '\x3', '\x2', '\x2', '\x2', '\x2', '\x13', '\x3', + '\x2', '\x2', '\x2', '\x2', '\x15', '\x3', '\x2', '\x2', '\x2', '\x2', + '\x17', '\x3', '\x2', '\x2', '\x2', '\x2', '\x19', '\x3', '\x2', '\x2', + '\x2', '\x2', '\x1B', '\x3', '\x2', '\x2', '\x2', '\x2', '\x1D', '\x3', + '\x2', '\x2', '\x2', '\x2', '\x1F', '\x3', '\x2', '\x2', '\x2', '\x2', + '!', '\x3', '\x2', '\x2', '\x2', '\x2', '#', '\x3', '\x2', '\x2', '\x2', + '\x2', '\x41', '\x3', '\x2', '\x2', '\x2', '\x3', '\x43', '\x3', '\x2', + '\x2', '\x2', '\x5', '\x45', '\x3', '\x2', '\x2', '\x2', '\a', 'G', '\x3', + '\x2', '\x2', '\x2', '\t', 'I', '\x3', '\x2', '\x2', '\x2', '\v', 'K', + '\x3', '\x2', '\x2', '\x2', '\r', 'M', '\x3', '\x2', '\x2', '\x2', '\xF', + 'O', '\x3', '\x2', '\x2', '\x2', '\x11', 'Q', '\x3', '\x2', '\x2', '\x2', + '\x13', 'S', '\x3', '\x2', '\x2', '\x2', '\x15', 'U', '\x3', '\x2', '\x2', + '\x2', '\x17', '\\', '\x3', '\x2', '\x2', '\x2', '\x19', '^', '\x3', '\x2', + '\x2', '\x2', '\x1B', '`', '\x3', '\x2', '\x2', '\x2', '\x1D', '\x63', + '\x3', '\x2', '\x2', '\x2', '\x1F', '\x66', '\x3', '\x2', '\x2', '\x2', + '!', 'i', '\x3', '\x2', '\x2', '\x2', '#', 'l', '\x3', '\x2', '\x2', '\x2', + '%', 'r', '\x3', '\x2', '\x2', '\x2', '\'', 'v', '\x3', '\x2', '\x2', + '\x2', ')', 'y', '\x3', '\x2', '\x2', '\x2', '+', '~', '\x3', '\x2', '\x2', + '\x2', '-', '\x85', '\x3', '\x2', '\x2', '\x2', '/', '\x8F', '\x3', '\x2', + '\x2', '\x2', '\x31', '\x94', '\x3', '\x2', '\x2', '\x2', '\x33', '\x98', + '\x3', '\x2', '\x2', '\x2', '\x35', '\x9B', '\x3', '\x2', '\x2', '\x2', + '\x37', '\x9E', '\x3', '\x2', '\x2', '\x2', '\x39', '\xA1', '\x3', '\x2', + '\x2', '\x2', ';', '\xA4', '\x3', '\x2', '\x2', '\x2', '=', '\xA7', '\x3', + '\x2', '\x2', '\x2', '?', '\xA9', '\x3', '\x2', '\x2', '\x2', '\x41', + '\xAC', '\x3', '\x2', '\x2', '\x2', '\x43', '\x44', '\a', '*', '\x2', + '\x2', '\x44', '\x4', '\x3', '\x2', '\x2', '\x2', '\x45', '\x46', '\a', + '+', '\x2', '\x2', '\x46', '\x6', '\x3', '\x2', '\x2', '\x2', 'G', 'H', + '\a', '-', '\x2', '\x2', 'H', '\b', '\x3', '\x2', '\x2', '\x2', 'I', 'J', + '\a', '/', '\x2', '\x2', 'J', '\n', '\x3', '\x2', '\x2', '\x2', 'K', 'L', + '\a', ',', '\x2', '\x2', 'L', '\f', '\x3', '\x2', '\x2', '\x2', 'M', 'N', + '\a', '\x31', '\x2', '\x2', 'N', '\xE', '\x3', '\x2', '\x2', '\x2', 'O', + 'P', '\a', '.', '\x2', '\x2', 'P', '\x10', '\x3', '\x2', '\x2', '\x2', + 'Q', 'R', '\a', '\x30', '\x2', '\x2', 'R', '\x12', '\x3', '\x2', '\x2', + '\x2', 'S', 'T', '\a', '`', '\x2', '\x2', 'T', '\x14', '\x3', '\x2', '\x2', + '\x2', 'U', 'Y', '\x5', '%', '\x13', '\x2', 'V', 'X', '\x5', '\'', '\x14', + '\x2', 'W', 'V', '\x3', '\x2', '\x2', '\x2', 'X', '[', '\x3', '\x2', '\x2', + '\x2', 'Y', 'W', '\x3', '\x2', '\x2', '\x2', 'Y', 'Z', '\x3', '\x2', '\x2', + '\x2', 'Z', '\x16', '\x3', '\x2', '\x2', '\x2', '[', 'Y', '\x3', '\x2', + '\x2', '\x2', '\\', ']', '\x5', '-', '\x17', '\x2', ']', '\x18', '\x3', + '\x2', '\x2', '\x2', '^', '_', '\x5', ')', '\x15', '\x2', '_', '\x1A', + '\x3', '\x2', '\x2', '\x2', '`', '\x61', '\x5', '\x39', '\x1D', '\x2', + '\x61', '\x62', '\x5', '/', '\x18', '\x2', '\x62', '\x1C', '\x3', '\x2', + '\x2', '\x2', '\x63', '\x64', '\x5', ';', '\x1E', '\x2', '\x64', '\x65', + '\x5', '\x31', '\x19', '\x2', '\x65', '\x1E', '\x3', '\x2', '\x2', '\x2', + '\x66', 'g', '\x5', '\x35', '\x1B', '\x2', 'g', 'h', '\x5', ')', '\x15', + '\x2', 'h', ' ', '\x3', '\x2', '\x2', '\x2', 'i', 'j', '\x5', '\x37', + '\x1C', '\x2', 'j', 'k', '\x5', '+', '\x16', '\x2', 'k', '\"', '\x3', + '\x2', '\x2', '\x2', 'l', 'o', '\x5', '\x33', '\x1A', '\x2', 'm', 'p', + '\x5', '-', '\x17', '\x2', 'n', 'p', '\x5', ')', '\x15', '\x2', 'o', 'm', + '\x3', '\x2', '\x2', '\x2', 'o', 'n', '\x3', '\x2', '\x2', '\x2', 'p', + '$', '\x3', '\x2', '\x2', '\x2', 'q', 's', '\t', '\x2', '\x2', '\x2', + 'r', 'q', '\x3', '\x2', '\x2', '\x2', 's', '&', '\x3', '\x2', '\x2', '\x2', + 't', 'w', '\x5', '%', '\x13', '\x2', 'u', 'w', '\x4', '\x32', ';', '\x2', + 'v', 't', '\x3', '\x2', '\x2', '\x2', 'v', 'u', '\x3', '\x2', '\x2', '\x2', + 'w', '(', '\x3', '\x2', '\x2', '\x2', 'x', 'z', '\x4', '\x32', ';', '\x2', + 'y', 'x', '\x3', '\x2', '\x2', '\x2', 'z', '{', '\x3', '\x2', '\x2', '\x2', + '{', 'y', '\x3', '\x2', '\x2', '\x2', '{', '|', '\x3', '\x2', '\x2', '\x2', + '|', '*', '\x3', '\x2', '\x2', '\x2', '}', '\x7F', '\x4', '\x32', '\x39', + '\x2', '~', '}', '\x3', '\x2', '\x2', '\x2', '\x7F', '\x80', '\x3', '\x2', + '\x2', '\x2', '\x80', '~', '\x3', '\x2', '\x2', '\x2', '\x80', '\x81', + '\x3', '\x2', '\x2', '\x2', '\x81', ',', '\x3', '\x2', '\x2', '\x2', '\x82', + '\x84', '\x4', '\x32', ';', '\x2', '\x83', '\x82', '\x3', '\x2', '\x2', + '\x2', '\x84', '\x87', '\x3', '\x2', '\x2', '\x2', '\x85', '\x83', '\x3', + '\x2', '\x2', '\x2', '\x85', '\x86', '\x3', '\x2', '\x2', '\x2', '\x86', + '\x88', '\x3', '\x2', '\x2', '\x2', '\x87', '\x85', '\x3', '\x2', '\x2', + '\x2', '\x88', '\x8A', '\a', '\x30', '\x2', '\x2', '\x89', '\x8B', '\x4', + '\x32', ';', '\x2', '\x8A', '\x89', '\x3', '\x2', '\x2', '\x2', '\x8B', + '\x8C', '\x3', '\x2', '\x2', '\x2', '\x8C', '\x8A', '\x3', '\x2', '\x2', + '\x2', '\x8C', '\x8D', '\x3', '\x2', '\x2', '\x2', '\x8D', '.', '\x3', + '\x2', '\x2', '\x2', '\x8E', '\x90', '\x4', '\x32', '\x33', '\x2', '\x8F', + '\x8E', '\x3', '\x2', '\x2', '\x2', '\x90', '\x91', '\x3', '\x2', '\x2', + '\x2', '\x91', '\x8F', '\x3', '\x2', '\x2', '\x2', '\x91', '\x92', '\x3', + '\x2', '\x2', '\x2', '\x92', '\x30', '\x3', '\x2', '\x2', '\x2', '\x93', + '\x95', '\t', '\x3', '\x2', '\x2', '\x94', '\x93', '\x3', '\x2', '\x2', + '\x2', '\x95', '\x96', '\x3', '\x2', '\x2', '\x2', '\x96', '\x94', '\x3', + '\x2', '\x2', '\x2', '\x96', '\x97', '\x3', '\x2', '\x2', '\x2', '\x97', + '\x32', '\x3', '\x2', '\x2', '\x2', '\x98', '\x99', '\a', '\x32', '\x2', + '\x2', '\x99', '\x9A', '\t', '\x4', '\x2', '\x2', '\x9A', '\x34', '\x3', + '\x2', '\x2', '\x2', '\x9B', '\x9C', '\a', '\x32', '\x2', '\x2', '\x9C', + '\x9D', '\t', '\x5', '\x2', '\x2', '\x9D', '\x36', '\x3', '\x2', '\x2', + '\x2', '\x9E', '\x9F', '\a', '\x32', '\x2', '\x2', '\x9F', '\xA0', '\t', + '\x6', '\x2', '\x2', '\xA0', '\x38', '\x3', '\x2', '\x2', '\x2', '\xA1', + '\xA2', '\a', '\x32', '\x2', '\x2', '\xA2', '\xA3', '\t', '\a', '\x2', + '\x2', '\xA3', ':', '\x3', '\x2', '\x2', '\x2', '\xA4', '\xA5', '\a', + '\x32', '\x2', '\x2', '\xA5', '\xA6', '\t', '\b', '\x2', '\x2', '\xA6', + '<', '\x3', '\x2', '\x2', '\x2', '\xA7', '\xA8', '\t', '\t', '\x2', '\x2', + '\xA8', '>', '\x3', '\x2', '\x2', '\x2', '\xA9', '\xAA', '\t', '\n', '\x2', + '\x2', '\xAA', '@', '\x3', '\x2', '\x2', '\x2', '\xAB', '\xAD', '\t', + '\v', '\x2', '\x2', '\xAC', '\xAB', '\x3', '\x2', '\x2', '\x2', '\xAD', + '\xAE', '\x3', '\x2', '\x2', '\x2', '\xAE', '\xAC', '\x3', '\x2', '\x2', + '\x2', '\xAE', '\xAF', '\x3', '\x2', '\x2', '\x2', '\xAF', '\xB0', '\x3', + '\x2', '\x2', '\x2', '\xB0', '\xB1', '\b', '!', '\x2', '\x2', '\xB1', + '\x42', '\x3', '\x2', '\x2', '\x2', '\xF', '\x2', 'Y', 'o', 'r', 'v', + '{', '\x80', '\x85', '\x8C', '\x91', '\x94', '\x96', '\xAE', '\x3', '\b', '\x2', '\x2', }; diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.interp b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.interp index ac1c6b0..f372ee7 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.interp +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.interp @@ -15,6 +15,9 @@ null null null null +null +null +null token symbolic names: null @@ -29,9 +32,12 @@ POINT POW IDENTIFIER DECIMAL_NUMBER -BINARY_NUMBER -HEXADECIMAL_NUMBER -SCIENTIFIC_NUMBER +INTEGER_NUMBER +PREFIX_BIN_NUMBER +PREFIX_HEX_NUMBER +PREFIX_INT_NUMBER +PREFIX_OCT_NUMBER +PREFIX_DEC_NUMBER WS rule names: @@ -46,19 +52,25 @@ POINT POW IDENTIFIER DECIMAL_NUMBER -BINARY_NUMBER -HEXADECIMAL_NUMBER -SCIENTIFIC_NUMBER +INTEGER_NUMBER +PREFIX_BIN_NUMBER +PREFIX_HEX_NUMBER +PREFIX_INT_NUMBER +PREFIX_OCT_NUMBER +PREFIX_DEC_NUMBER VALID_ID_START VALID_ID_CHAR -PREFIX_DEC +NUMBER_INT +NUMBER_OCT NUMBER_DEC -PREFIX_BIN NUMBER_BIN -PREFIX_HEX NUMBER_HEX -E1 -E2 +PREFIX_DEC +PREFIX_INT +PREFIX_OCT +PREFIX_BIN +PREFIX_HEX +E SIGN WS @@ -70,4 +82,4 @@ mode names: DEFAULT_MODE atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 17, 153, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 7, 11, 76, 10, 11, 12, 11, 14, 11, 79, 11, 11, 3, 12, 5, 12, 82, 10, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 5, 15, 95, 10, 15, 3, 15, 5, 15, 98, 10, 15, 3, 15, 3, 15, 3, 16, 5, 16, 103, 10, 16, 3, 17, 3, 17, 5, 17, 107, 10, 17, 3, 18, 3, 18, 3, 18, 3, 19, 6, 19, 113, 10, 19, 13, 19, 14, 19, 114, 3, 19, 3, 19, 6, 19, 119, 10, 19, 13, 19, 14, 19, 120, 5, 19, 123, 10, 19, 3, 20, 3, 20, 3, 20, 3, 21, 6, 21, 129, 10, 21, 13, 21, 14, 21, 130, 3, 22, 3, 22, 3, 22, 3, 23, 6, 23, 137, 10, 23, 13, 23, 14, 23, 138, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 6, 27, 148, 10, 27, 13, 27, 14, 27, 149, 3, 27, 3, 27, 2, 2, 28, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 2, 33, 2, 35, 2, 37, 2, 39, 2, 41, 2, 43, 2, 45, 2, 47, 2, 49, 2, 51, 2, 53, 17, 3, 2, 9, 6, 2, 38, 38, 67, 92, 97, 97, 99, 124, 4, 2, 70, 70, 102, 102, 4, 2, 68, 68, 100, 100, 4, 2, 90, 90, 122, 122, 5, 2, 50, 59, 67, 72, 99, 104, 4, 2, 45, 45, 47, 47, 5, 2, 11, 12, 15, 15, 34, 34, 2, 152, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 3, 55, 3, 2, 2, 2, 5, 57, 3, 2, 2, 2, 7, 59, 3, 2, 2, 2, 9, 61, 3, 2, 2, 2, 11, 63, 3, 2, 2, 2, 13, 65, 3, 2, 2, 2, 15, 67, 3, 2, 2, 2, 17, 69, 3, 2, 2, 2, 19, 71, 3, 2, 2, 2, 21, 73, 3, 2, 2, 2, 23, 81, 3, 2, 2, 2, 25, 85, 3, 2, 2, 2, 27, 88, 3, 2, 2, 2, 29, 91, 3, 2, 2, 2, 31, 102, 3, 2, 2, 2, 33, 106, 3, 2, 2, 2, 35, 108, 3, 2, 2, 2, 37, 112, 3, 2, 2, 2, 39, 124, 3, 2, 2, 2, 41, 128, 3, 2, 2, 2, 43, 132, 3, 2, 2, 2, 45, 136, 3, 2, 2, 2, 47, 140, 3, 2, 2, 2, 49, 142, 3, 2, 2, 2, 51, 144, 3, 2, 2, 2, 53, 147, 3, 2, 2, 2, 55, 56, 7, 42, 2, 2, 56, 4, 3, 2, 2, 2, 57, 58, 7, 43, 2, 2, 58, 6, 3, 2, 2, 2, 59, 60, 7, 45, 2, 2, 60, 8, 3, 2, 2, 2, 61, 62, 7, 47, 2, 2, 62, 10, 3, 2, 2, 2, 63, 64, 7, 44, 2, 2, 64, 12, 3, 2, 2, 2, 65, 66, 7, 49, 2, 2, 66, 14, 3, 2, 2, 2, 67, 68, 7, 46, 2, 2, 68, 16, 3, 2, 2, 2, 69, 70, 7, 48, 2, 2, 70, 18, 3, 2, 2, 2, 71, 72, 7, 96, 2, 2, 72, 20, 3, 2, 2, 2, 73, 77, 5, 31, 16, 2, 74, 76, 5, 33, 17, 2, 75, 74, 3, 2, 2, 2, 76, 79, 3, 2, 2, 2, 77, 75, 3, 2, 2, 2, 77, 78, 3, 2, 2, 2, 78, 22, 3, 2, 2, 2, 79, 77, 3, 2, 2, 2, 80, 82, 5, 35, 18, 2, 81, 80, 3, 2, 2, 2, 81, 82, 3, 2, 2, 2, 82, 83, 3, 2, 2, 2, 83, 84, 5, 37, 19, 2, 84, 24, 3, 2, 2, 2, 85, 86, 5, 39, 20, 2, 86, 87, 5, 41, 21, 2, 87, 26, 3, 2, 2, 2, 88, 89, 5, 43, 22, 2, 89, 90, 5, 45, 23, 2, 90, 28, 3, 2, 2, 2, 91, 94, 5, 37, 19, 2, 92, 95, 5, 47, 24, 2, 93, 95, 5, 49, 25, 2, 94, 92, 3, 2, 2, 2, 94, 93, 3, 2, 2, 2, 95, 97, 3, 2, 2, 2, 96, 98, 5, 51, 26, 2, 97, 96, 3, 2, 2, 2, 97, 98, 3, 2, 2, 2, 98, 99, 3, 2, 2, 2, 99, 100, 5, 37, 19, 2, 100, 30, 3, 2, 2, 2, 101, 103, 9, 2, 2, 2, 102, 101, 3, 2, 2, 2, 103, 32, 3, 2, 2, 2, 104, 107, 5, 31, 16, 2, 105, 107, 4, 50, 59, 2, 106, 104, 3, 2, 2, 2, 106, 105, 3, 2, 2, 2, 107, 34, 3, 2, 2, 2, 108, 109, 7, 50, 2, 2, 109, 110, 9, 3, 2, 2, 110, 36, 3, 2, 2, 2, 111, 113, 4, 50, 59, 2, 112, 111, 3, 2, 2, 2, 113, 114, 3, 2, 2, 2, 114, 112, 3, 2, 2, 2, 114, 115, 3, 2, 2, 2, 115, 122, 3, 2, 2, 2, 116, 118, 7, 48, 2, 2, 117, 119, 4, 50, 59, 2, 118, 117, 3, 2, 2, 2, 119, 120, 3, 2, 2, 2, 120, 118, 3, 2, 2, 2, 120, 121, 3, 2, 2, 2, 121, 123, 3, 2, 2, 2, 122, 116, 3, 2, 2, 2, 122, 123, 3, 2, 2, 2, 123, 38, 3, 2, 2, 2, 124, 125, 7, 50, 2, 2, 125, 126, 9, 4, 2, 2, 126, 40, 3, 2, 2, 2, 127, 129, 4, 50, 51, 2, 128, 127, 3, 2, 2, 2, 129, 130, 3, 2, 2, 2, 130, 128, 3, 2, 2, 2, 130, 131, 3, 2, 2, 2, 131, 42, 3, 2, 2, 2, 132, 133, 7, 50, 2, 2, 133, 134, 9, 5, 2, 2, 134, 44, 3, 2, 2, 2, 135, 137, 9, 6, 2, 2, 136, 135, 3, 2, 2, 2, 137, 138, 3, 2, 2, 2, 138, 136, 3, 2, 2, 2, 138, 139, 3, 2, 2, 2, 139, 46, 3, 2, 2, 2, 140, 141, 7, 71, 2, 2, 141, 48, 3, 2, 2, 2, 142, 143, 7, 103, 2, 2, 143, 50, 3, 2, 2, 2, 144, 145, 9, 7, 2, 2, 145, 52, 3, 2, 2, 2, 146, 148, 9, 8, 2, 2, 147, 146, 3, 2, 2, 2, 148, 149, 3, 2, 2, 2, 149, 147, 3, 2, 2, 2, 149, 150, 3, 2, 2, 2, 150, 151, 3, 2, 2, 2, 151, 152, 8, 27, 2, 2, 152, 54, 3, 2, 2, 2, 16, 2, 77, 81, 94, 97, 102, 106, 114, 120, 122, 130, 136, 138, 149, 3, 8, 2, 2] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 20, 178, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 7, 11, 88, 10, 11, 12, 11, 14, 11, 91, 11, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 5, 18, 112, 10, 18, 3, 19, 5, 19, 115, 10, 19, 3, 20, 3, 20, 5, 20, 119, 10, 20, 3, 21, 6, 21, 122, 10, 21, 13, 21, 14, 21, 123, 3, 22, 6, 22, 127, 10, 22, 13, 22, 14, 22, 128, 3, 23, 7, 23, 132, 10, 23, 12, 23, 14, 23, 135, 11, 23, 3, 23, 3, 23, 6, 23, 139, 10, 23, 13, 23, 14, 23, 140, 3, 24, 6, 24, 144, 10, 24, 13, 24, 14, 24, 145, 3, 25, 6, 25, 149, 10, 25, 13, 25, 14, 25, 150, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 32, 3, 32, 3, 33, 6, 33, 173, 10, 33, 13, 33, 14, 33, 174, 3, 33, 3, 33, 2, 2, 34, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 2, 39, 2, 41, 2, 43, 2, 45, 2, 47, 2, 49, 2, 51, 2, 53, 2, 55, 2, 57, 2, 59, 2, 61, 2, 63, 2, 65, 20, 3, 2, 12, 6, 2, 38, 38, 67, 92, 97, 97, 99, 124, 5, 2, 50, 59, 67, 72, 99, 104, 4, 2, 70, 70, 102, 102, 4, 2, 75, 75, 107, 107, 4, 2, 81, 81, 113, 113, 4, 2, 68, 68, 100, 100, 4, 2, 90, 90, 122, 122, 4, 2, 71, 71, 103, 103, 4, 2, 45, 45, 47, 47, 5, 2, 11, 12, 15, 15, 34, 34, 2, 173, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 3, 67, 3, 2, 2, 2, 5, 69, 3, 2, 2, 2, 7, 71, 3, 2, 2, 2, 9, 73, 3, 2, 2, 2, 11, 75, 3, 2, 2, 2, 13, 77, 3, 2, 2, 2, 15, 79, 3, 2, 2, 2, 17, 81, 3, 2, 2, 2, 19, 83, 3, 2, 2, 2, 21, 85, 3, 2, 2, 2, 23, 92, 3, 2, 2, 2, 25, 94, 3, 2, 2, 2, 27, 96, 3, 2, 2, 2, 29, 99, 3, 2, 2, 2, 31, 102, 3, 2, 2, 2, 33, 105, 3, 2, 2, 2, 35, 108, 3, 2, 2, 2, 37, 114, 3, 2, 2, 2, 39, 118, 3, 2, 2, 2, 41, 121, 3, 2, 2, 2, 43, 126, 3, 2, 2, 2, 45, 133, 3, 2, 2, 2, 47, 143, 3, 2, 2, 2, 49, 148, 3, 2, 2, 2, 51, 152, 3, 2, 2, 2, 53, 155, 3, 2, 2, 2, 55, 158, 3, 2, 2, 2, 57, 161, 3, 2, 2, 2, 59, 164, 3, 2, 2, 2, 61, 167, 3, 2, 2, 2, 63, 169, 3, 2, 2, 2, 65, 172, 3, 2, 2, 2, 67, 68, 7, 42, 2, 2, 68, 4, 3, 2, 2, 2, 69, 70, 7, 43, 2, 2, 70, 6, 3, 2, 2, 2, 71, 72, 7, 45, 2, 2, 72, 8, 3, 2, 2, 2, 73, 74, 7, 47, 2, 2, 74, 10, 3, 2, 2, 2, 75, 76, 7, 44, 2, 2, 76, 12, 3, 2, 2, 2, 77, 78, 7, 49, 2, 2, 78, 14, 3, 2, 2, 2, 79, 80, 7, 46, 2, 2, 80, 16, 3, 2, 2, 2, 81, 82, 7, 48, 2, 2, 82, 18, 3, 2, 2, 2, 83, 84, 7, 96, 2, 2, 84, 20, 3, 2, 2, 2, 85, 89, 5, 37, 19, 2, 86, 88, 5, 39, 20, 2, 87, 86, 3, 2, 2, 2, 88, 91, 3, 2, 2, 2, 89, 87, 3, 2, 2, 2, 89, 90, 3, 2, 2, 2, 90, 22, 3, 2, 2, 2, 91, 89, 3, 2, 2, 2, 92, 93, 5, 45, 23, 2, 93, 24, 3, 2, 2, 2, 94, 95, 5, 41, 21, 2, 95, 26, 3, 2, 2, 2, 96, 97, 5, 57, 29, 2, 97, 98, 5, 47, 24, 2, 98, 28, 3, 2, 2, 2, 99, 100, 5, 59, 30, 2, 100, 101, 5, 49, 25, 2, 101, 30, 3, 2, 2, 2, 102, 103, 5, 53, 27, 2, 103, 104, 5, 41, 21, 2, 104, 32, 3, 2, 2, 2, 105, 106, 5, 55, 28, 2, 106, 107, 5, 43, 22, 2, 107, 34, 3, 2, 2, 2, 108, 111, 5, 51, 26, 2, 109, 112, 5, 45, 23, 2, 110, 112, 5, 41, 21, 2, 111, 109, 3, 2, 2, 2, 111, 110, 3, 2, 2, 2, 112, 36, 3, 2, 2, 2, 113, 115, 9, 2, 2, 2, 114, 113, 3, 2, 2, 2, 115, 38, 3, 2, 2, 2, 116, 119, 5, 37, 19, 2, 117, 119, 4, 50, 59, 2, 118, 116, 3, 2, 2, 2, 118, 117, 3, 2, 2, 2, 119, 40, 3, 2, 2, 2, 120, 122, 4, 50, 59, 2, 121, 120, 3, 2, 2, 2, 122, 123, 3, 2, 2, 2, 123, 121, 3, 2, 2, 2, 123, 124, 3, 2, 2, 2, 124, 42, 3, 2, 2, 2, 125, 127, 4, 50, 57, 2, 126, 125, 3, 2, 2, 2, 127, 128, 3, 2, 2, 2, 128, 126, 3, 2, 2, 2, 128, 129, 3, 2, 2, 2, 129, 44, 3, 2, 2, 2, 130, 132, 4, 50, 59, 2, 131, 130, 3, 2, 2, 2, 132, 135, 3, 2, 2, 2, 133, 131, 3, 2, 2, 2, 133, 134, 3, 2, 2, 2, 134, 136, 3, 2, 2, 2, 135, 133, 3, 2, 2, 2, 136, 138, 7, 48, 2, 2, 137, 139, 4, 50, 59, 2, 138, 137, 3, 2, 2, 2, 139, 140, 3, 2, 2, 2, 140, 138, 3, 2, 2, 2, 140, 141, 3, 2, 2, 2, 141, 46, 3, 2, 2, 2, 142, 144, 4, 50, 51, 2, 143, 142, 3, 2, 2, 2, 144, 145, 3, 2, 2, 2, 145, 143, 3, 2, 2, 2, 145, 146, 3, 2, 2, 2, 146, 48, 3, 2, 2, 2, 147, 149, 9, 3, 2, 2, 148, 147, 3, 2, 2, 2, 149, 150, 3, 2, 2, 2, 150, 148, 3, 2, 2, 2, 150, 151, 3, 2, 2, 2, 151, 50, 3, 2, 2, 2, 152, 153, 7, 50, 2, 2, 153, 154, 9, 4, 2, 2, 154, 52, 3, 2, 2, 2, 155, 156, 7, 50, 2, 2, 156, 157, 9, 5, 2, 2, 157, 54, 3, 2, 2, 2, 158, 159, 7, 50, 2, 2, 159, 160, 9, 6, 2, 2, 160, 56, 3, 2, 2, 2, 161, 162, 7, 50, 2, 2, 162, 163, 9, 7, 2, 2, 163, 58, 3, 2, 2, 2, 164, 165, 7, 50, 2, 2, 165, 166, 9, 8, 2, 2, 166, 60, 3, 2, 2, 2, 167, 168, 9, 9, 2, 2, 168, 62, 3, 2, 2, 2, 169, 170, 9, 10, 2, 2, 170, 64, 3, 2, 2, 2, 171, 173, 9, 11, 2, 2, 172, 171, 3, 2, 2, 2, 173, 174, 3, 2, 2, 2, 174, 172, 3, 2, 2, 2, 174, 175, 3, 2, 2, 2, 175, 176, 3, 2, 2, 2, 176, 177, 8, 33, 2, 2, 177, 66, 3, 2, 2, 2, 15, 2, 89, 111, 114, 118, 123, 128, 133, 140, 145, 148, 150, 174, 3, 8, 2, 2] \ No newline at end of file diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.tokens b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.tokens index a954a79..a254e9e 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.tokens +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerLexer.tokens @@ -9,10 +9,13 @@ POINT=8 POW=9 IDENTIFIER=10 DECIMAL_NUMBER=11 -BINARY_NUMBER=12 -HEXADECIMAL_NUMBER=13 -SCIENTIFIC_NUMBER=14 -WS=15 +INTEGER_NUMBER=12 +PREFIX_BIN_NUMBER=13 +PREFIX_HEX_NUMBER=14 +PREFIX_INT_NUMBER=15 +PREFIX_OCT_NUMBER=16 +PREFIX_DEC_NUMBER=17 +WS=18 '('=1 ')'=2 '+'=3 diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerListener.cs b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerListener.cs index 2e377e4..f53f669 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerListener.cs +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerListener.cs @@ -95,18 +95,6 @@ public interface IFormulaGrammerListener : IParseTreeListener { /// The parse tree. void ExitNegativeAtom([NotNull] FormulaGrammerParser.NegativeAtomContext context); /// - /// Enter a parse tree produced by the Function - /// labeled alternative in . - /// - /// The parse tree. - void EnterFunction([NotNull] FormulaGrammerParser.FunctionContext context); - /// - /// Exit a parse tree produced by the Function - /// labeled alternative in . - /// - /// The parse tree. - void ExitFunction([NotNull] FormulaGrammerParser.FunctionContext context); - /// /// Enter a parse tree produced by the UnsignedAtom /// labeled alternative in . /// @@ -129,53 +117,89 @@ public interface IFormulaGrammerListener : IParseTreeListener { /// The parse tree. void ExitAtom([NotNull] FormulaGrammerParser.AtomContext context); /// - /// Enter a parse tree produced by the ScientificNumber + /// Enter a parse tree produced by the DecimalNumber /// labeled alternative in . /// /// The parse tree. - void EnterScientificNumber([NotNull] FormulaGrammerParser.ScientificNumberContext context); + void EnterDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context); /// - /// Exit a parse tree produced by the ScientificNumber + /// Exit a parse tree produced by the DecimalNumber /// labeled alternative in . /// /// The parse tree. - void ExitScientificNumber([NotNull] FormulaGrammerParser.ScientificNumberContext context); + void ExitDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context); /// - /// Enter a parse tree produced by the DecimalNumber + /// Enter a parse tree produced by the IntgerNumber /// labeled alternative in . /// /// The parse tree. - void EnterDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context); + void EnterIntgerNumber([NotNull] FormulaGrammerParser.IntgerNumberContext context); /// - /// Exit a parse tree produced by the DecimalNumber + /// Exit a parse tree produced by the IntgerNumber /// labeled alternative in . /// /// The parse tree. - void ExitDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context); + void ExitIntgerNumber([NotNull] FormulaGrammerParser.IntgerNumberContext context); /// - /// Enter a parse tree produced by the BinaryNumber - /// labeled alternative in . + /// Enter a parse tree produced by the PrefixedDecNumber + /// labeled alternative in . /// /// The parse tree. - void EnterBinaryNumber([NotNull] FormulaGrammerParser.BinaryNumberContext context); + void EnterPrefixedDecNumber([NotNull] FormulaGrammerParser.PrefixedDecNumberContext context); /// - /// Exit a parse tree produced by the BinaryNumber - /// labeled alternative in . + /// Exit a parse tree produced by the PrefixedDecNumber + /// labeled alternative in . /// /// The parse tree. - void ExitBinaryNumber([NotNull] FormulaGrammerParser.BinaryNumberContext context); + void ExitPrefixedDecNumber([NotNull] FormulaGrammerParser.PrefixedDecNumberContext context); /// - /// Enter a parse tree produced by the HexadecimalNumber - /// labeled alternative in . + /// Enter a parse tree produced by the PrefixedIntNumber + /// labeled alternative in . /// /// The parse tree. - void EnterHexadecimalNumber([NotNull] FormulaGrammerParser.HexadecimalNumberContext context); + void EnterPrefixedIntNumber([NotNull] FormulaGrammerParser.PrefixedIntNumberContext context); /// - /// Exit a parse tree produced by the HexadecimalNumber - /// labeled alternative in . + /// Exit a parse tree produced by the PrefixedIntNumber + /// labeled alternative in . + /// + /// The parse tree. + void ExitPrefixedIntNumber([NotNull] FormulaGrammerParser.PrefixedIntNumberContext context); + /// + /// Enter a parse tree produced by the PrefixedBinNumber + /// labeled alternative in . + /// + /// The parse tree. + void EnterPrefixedBinNumber([NotNull] FormulaGrammerParser.PrefixedBinNumberContext context); + /// + /// Exit a parse tree produced by the PrefixedBinNumber + /// labeled alternative in . + /// + /// The parse tree. + void ExitPrefixedBinNumber([NotNull] FormulaGrammerParser.PrefixedBinNumberContext context); + /// + /// Enter a parse tree produced by the PrefixedOctNumber + /// labeled alternative in . + /// + /// The parse tree. + void EnterPrefixedOctNumber([NotNull] FormulaGrammerParser.PrefixedOctNumberContext context); + /// + /// Exit a parse tree produced by the PrefixedOctNumber + /// labeled alternative in . + /// + /// The parse tree. + void ExitPrefixedOctNumber([NotNull] FormulaGrammerParser.PrefixedOctNumberContext context); + /// + /// Enter a parse tree produced by the PrefixedHexNumber + /// labeled alternative in . + /// + /// The parse tree. + void EnterPrefixedHexNumber([NotNull] FormulaGrammerParser.PrefixedHexNumberContext context); + /// + /// Exit a parse tree produced by the PrefixedHexNumber + /// labeled alternative in . /// /// The parse tree. - void ExitHexadecimalNumber([NotNull] FormulaGrammerParser.HexadecimalNumberContext context); + void ExitPrefixedHexNumber([NotNull] FormulaGrammerParser.PrefixedHexNumberContext context); /// /// Enter a parse tree produced by . /// diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerParser.cs b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerParser.cs index 579a20d..3dd8c31 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerParser.cs +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerParser.cs @@ -37,15 +37,16 @@ public partial class FormulaGrammerParser : Parser { protected static PredictionContextCache sharedContextCache = new PredictionContextCache(); public const int LPAREN=1, RPAREN=2, PLUS=3, MINUS=4, TIMES=5, DIV=6, COMMA=7, POINT=8, - POW=9, IDENTIFIER=10, DECIMAL_NUMBER=11, BINARY_NUMBER=12, HEXADECIMAL_NUMBER=13, - SCIENTIFIC_NUMBER=14, WS=15; + POW=9, IDENTIFIER=10, DECIMAL_NUMBER=11, INTEGER_NUMBER=12, PREFIX_BIN_NUMBER=13, + PREFIX_HEX_NUMBER=14, PREFIX_INT_NUMBER=15, PREFIX_OCT_NUMBER=16, PREFIX_DEC_NUMBER=17, + WS=18; public const int RULE_formula = 0, RULE_expression = 1, RULE_multiplyingExpression = 2, RULE_powExpression = 3, RULE_signedAtom = 4, RULE_atom = 5, RULE_number = 6, - RULE_func = 7, RULE_variable = 8; + RULE_prefixedNumber = 7, RULE_func = 8, RULE_variable = 9; public static readonly string[] ruleNames = { "formula", "expression", "multiplyingExpression", "powExpression", "signedAtom", - "atom", "number", "func", "variable" + "atom", "number", "prefixedNumber", "func", "variable" }; private static readonly string[] _LiteralNames = { @@ -53,8 +54,9 @@ public const int }; private static readonly string[] _SymbolicNames = { null, "LPAREN", "RPAREN", "PLUS", "MINUS", "TIMES", "DIV", "COMMA", "POINT", - "POW", "IDENTIFIER", "DECIMAL_NUMBER", "BINARY_NUMBER", "HEXADECIMAL_NUMBER", - "SCIENTIFIC_NUMBER", "WS" + "POW", "IDENTIFIER", "DECIMAL_NUMBER", "INTEGER_NUMBER", "PREFIX_BIN_NUMBER", + "PREFIX_HEX_NUMBER", "PREFIX_INT_NUMBER", "PREFIX_OCT_NUMBER", "PREFIX_DEC_NUMBER", + "WS" }; public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames); @@ -120,8 +122,8 @@ public FormulaContext formula() { try { EnterOuterAlt(_localctx, 1); { - State = 18; expression(); - State = 19; Match(Eof); + State = 20; expression(); + State = 21; Match(Eof); } } catch (RecognitionException re) { @@ -178,14 +180,14 @@ public ExpressionContext expression() { try { EnterOuterAlt(_localctx, 1); { - State = 21; multiplyingExpression(); - State = 26; + State = 23; multiplyingExpression(); + State = 28; ErrorHandler.Sync(this); _la = TokenStream.LA(1); while (_la==PLUS || _la==MINUS) { { { - State = 22; + State = 24; _la = TokenStream.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { ErrorHandler.RecoverInline(this); @@ -194,10 +196,10 @@ public ExpressionContext expression() { ErrorHandler.ReportMatch(this); Consume(); } - State = 23; multiplyingExpression(); + State = 25; multiplyingExpression(); } } - State = 28; + State = 30; ErrorHandler.Sync(this); _la = TokenStream.LA(1); } @@ -257,14 +259,14 @@ public MultiplyingExpressionContext multiplyingExpression() { try { EnterOuterAlt(_localctx, 1); { - State = 29; powExpression(); - State = 34; + State = 31; powExpression(); + State = 36; ErrorHandler.Sync(this); _la = TokenStream.LA(1); while (_la==TIMES || _la==DIV) { { { - State = 30; + State = 32; _la = TokenStream.LA(1); if ( !(_la==TIMES || _la==DIV) ) { ErrorHandler.RecoverInline(this); @@ -273,10 +275,10 @@ public MultiplyingExpressionContext multiplyingExpression() { ErrorHandler.ReportMatch(this); Consume(); } - State = 31; powExpression(); + State = 33; powExpression(); } } - State = 36; + State = 38; ErrorHandler.Sync(this); _la = TokenStream.LA(1); } @@ -332,18 +334,18 @@ public PowExpressionContext powExpression() { try { EnterOuterAlt(_localctx, 1); { - State = 37; signedAtom(); - State = 42; + State = 39; signedAtom(); + State = 44; ErrorHandler.Sync(this); _la = TokenStream.LA(1); while (_la==POW) { { { - State = 38; Match(POW); - State = 39; signedAtom(); + State = 40; Match(POW); + State = 41; signedAtom(); } } - State = 44; + State = 46; ErrorHandler.Sync(this); _la = TokenStream.LA(1); } @@ -392,25 +394,6 @@ public override TResult Accept(IParseTreeVisitor visitor) { else return visitor.VisitChildren(this); } } - public partial class FunctionContext : SignedAtomContext { - public FuncContext func() { - return GetRuleContext(0); - } - public FunctionContext(SignedAtomContext context) { CopyFrom(context); } - public override void EnterRule(IParseTreeListener listener) { - IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; - if (typedListener != null) typedListener.EnterFunction(this); - } - public override void ExitRule(IParseTreeListener listener) { - IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; - if (typedListener != null) typedListener.ExitFunction(this); - } - public override TResult Accept(IParseTreeVisitor visitor) { - IFormulaGrammerVisitor typedVisitor = visitor as IFormulaGrammerVisitor; - if (typedVisitor != null) return typedVisitor.VisitFunction(this); - else return visitor.VisitChildren(this); - } - } public partial class PlusAtomContext : SignedAtomContext { public ITerminalNode PLUS() { return GetToken(FormulaGrammerParser.PLUS, 0); } public AtomContext atom() { @@ -456,39 +439,42 @@ public SignedAtomContext signedAtom() { SignedAtomContext _localctx = new SignedAtomContext(Context, State); EnterRule(_localctx, 8, RULE_signedAtom); try { - State = 51; + State = 52; ErrorHandler.Sync(this); - switch ( Interpreter.AdaptivePredict(TokenStream,3,Context) ) { - case 1: + switch (TokenStream.LA(1)) { + case PLUS: _localctx = new PlusAtomContext(_localctx); EnterOuterAlt(_localctx, 1); { - State = 45; Match(PLUS); - State = 46; atom(); + State = 47; Match(PLUS); + State = 48; atom(); } break; - case 2: + case MINUS: _localctx = new NegativeAtomContext(_localctx); EnterOuterAlt(_localctx, 2); { - State = 47; Match(MINUS); - State = 48; atom(); - } - break; - case 3: - _localctx = new FunctionContext(_localctx); - EnterOuterAlt(_localctx, 3); - { - State = 49; func(); + State = 49; Match(MINUS); + State = 50; atom(); } break; - case 4: + case LPAREN: + case IDENTIFIER: + case DECIMAL_NUMBER: + case INTEGER_NUMBER: + case PREFIX_BIN_NUMBER: + case PREFIX_HEX_NUMBER: + case PREFIX_INT_NUMBER: + case PREFIX_OCT_NUMBER: + case PREFIX_DEC_NUMBER: _localctx = new UnsignedAtomContext(_localctx); - EnterOuterAlt(_localctx, 4); + EnterOuterAlt(_localctx, 3); { - State = 50; atom(); + State = 51; atom(); } break; + default: + throw new NoViableAltException(this); } } catch (RecognitionException re) { @@ -506,6 +492,9 @@ public partial class AtomContext : ParserRuleContext { public NumberContext number() { return GetRuleContext(0); } + public PrefixedNumberContext prefixedNumber() { + return GetRuleContext(0); + } public VariableContext variable() { return GetRuleContext(0); } @@ -514,6 +503,9 @@ public ExpressionContext expression() { return GetRuleContext(0); } public ITerminalNode RPAREN() { return GetToken(FormulaGrammerParser.RPAREN, 0); } + public FuncContext func() { + return GetRuleContext(0); + } public AtomContext(ParserRuleContext parent, int invokingState) : base(parent, invokingState) { @@ -539,34 +531,41 @@ public AtomContext atom() { AtomContext _localctx = new AtomContext(Context, State); EnterRule(_localctx, 10, RULE_atom); try { - State = 59; + State = 62; ErrorHandler.Sync(this); - switch (TokenStream.LA(1)) { - case DECIMAL_NUMBER: - case BINARY_NUMBER: - case HEXADECIMAL_NUMBER: - case SCIENTIFIC_NUMBER: + switch ( Interpreter.AdaptivePredict(TokenStream,4,Context) ) { + case 1: EnterOuterAlt(_localctx, 1); { - State = 53; number(); + State = 54; number(); } break; - case IDENTIFIER: + case 2: EnterOuterAlt(_localctx, 2); { - State = 54; variable(); + State = 55; prefixedNumber(); } break; - case LPAREN: + case 3: EnterOuterAlt(_localctx, 3); { - State = 55; Match(LPAREN); - State = 56; expression(); - State = 57; Match(RPAREN); + State = 56; variable(); + } + break; + case 4: + EnterOuterAlt(_localctx, 4); + { + State = 57; Match(LPAREN); + State = 58; expression(); + State = 59; Match(RPAREN); + } + break; + case 5: + EnterOuterAlt(_localctx, 5); + { + State = 61; func(); } break; - default: - throw new NoViableAltException(this); } } catch (RecognitionException re) { @@ -609,92 +608,200 @@ public override TResult Accept(IParseTreeVisitor visitor) { else return visitor.VisitChildren(this); } } - public partial class BinaryNumberContext : NumberContext { - public ITerminalNode BINARY_NUMBER() { return GetToken(FormulaGrammerParser.BINARY_NUMBER, 0); } - public BinaryNumberContext(NumberContext context) { CopyFrom(context); } + public partial class IntgerNumberContext : NumberContext { + public ITerminalNode INTEGER_NUMBER() { return GetToken(FormulaGrammerParser.INTEGER_NUMBER, 0); } + public IntgerNumberContext(NumberContext context) { CopyFrom(context); } + public override void EnterRule(IParseTreeListener listener) { + IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; + if (typedListener != null) typedListener.EnterIntgerNumber(this); + } + public override void ExitRule(IParseTreeListener listener) { + IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; + if (typedListener != null) typedListener.ExitIntgerNumber(this); + } + public override TResult Accept(IParseTreeVisitor visitor) { + IFormulaGrammerVisitor typedVisitor = visitor as IFormulaGrammerVisitor; + if (typedVisitor != null) return typedVisitor.VisitIntgerNumber(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public NumberContext number() { + NumberContext _localctx = new NumberContext(Context, State); + EnterRule(_localctx, 12, RULE_number); + try { + State = 66; + ErrorHandler.Sync(this); + switch (TokenStream.LA(1)) { + case DECIMAL_NUMBER: + _localctx = new DecimalNumberContext(_localctx); + EnterOuterAlt(_localctx, 1); + { + State = 64; Match(DECIMAL_NUMBER); + } + break; + case INTEGER_NUMBER: + _localctx = new IntgerNumberContext(_localctx); + EnterOuterAlt(_localctx, 2); + { + State = 65; Match(INTEGER_NUMBER); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class PrefixedNumberContext : ParserRuleContext { + public PrefixedNumberContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_prefixedNumber; } } + + public PrefixedNumberContext() { } + public virtual void CopyFrom(PrefixedNumberContext context) { + base.CopyFrom(context); + } + } + public partial class PrefixedOctNumberContext : PrefixedNumberContext { + public ITerminalNode PREFIX_OCT_NUMBER() { return GetToken(FormulaGrammerParser.PREFIX_OCT_NUMBER, 0); } + public PrefixedOctNumberContext(PrefixedNumberContext context) { CopyFrom(context); } + public override void EnterRule(IParseTreeListener listener) { + IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; + if (typedListener != null) typedListener.EnterPrefixedOctNumber(this); + } + public override void ExitRule(IParseTreeListener listener) { + IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; + if (typedListener != null) typedListener.ExitPrefixedOctNumber(this); + } + public override TResult Accept(IParseTreeVisitor visitor) { + IFormulaGrammerVisitor typedVisitor = visitor as IFormulaGrammerVisitor; + if (typedVisitor != null) return typedVisitor.VisitPrefixedOctNumber(this); + else return visitor.VisitChildren(this); + } + } + public partial class PrefixedHexNumberContext : PrefixedNumberContext { + public ITerminalNode PREFIX_HEX_NUMBER() { return GetToken(FormulaGrammerParser.PREFIX_HEX_NUMBER, 0); } + public PrefixedHexNumberContext(PrefixedNumberContext context) { CopyFrom(context); } + public override void EnterRule(IParseTreeListener listener) { + IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; + if (typedListener != null) typedListener.EnterPrefixedHexNumber(this); + } + public override void ExitRule(IParseTreeListener listener) { + IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; + if (typedListener != null) typedListener.ExitPrefixedHexNumber(this); + } + public override TResult Accept(IParseTreeVisitor visitor) { + IFormulaGrammerVisitor typedVisitor = visitor as IFormulaGrammerVisitor; + if (typedVisitor != null) return typedVisitor.VisitPrefixedHexNumber(this); + else return visitor.VisitChildren(this); + } + } + public partial class PrefixedDecNumberContext : PrefixedNumberContext { + public ITerminalNode PREFIX_DEC_NUMBER() { return GetToken(FormulaGrammerParser.PREFIX_DEC_NUMBER, 0); } + public PrefixedDecNumberContext(PrefixedNumberContext context) { CopyFrom(context); } public override void EnterRule(IParseTreeListener listener) { IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; - if (typedListener != null) typedListener.EnterBinaryNumber(this); + if (typedListener != null) typedListener.EnterPrefixedDecNumber(this); } public override void ExitRule(IParseTreeListener listener) { IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; - if (typedListener != null) typedListener.ExitBinaryNumber(this); + if (typedListener != null) typedListener.ExitPrefixedDecNumber(this); } public override TResult Accept(IParseTreeVisitor visitor) { IFormulaGrammerVisitor typedVisitor = visitor as IFormulaGrammerVisitor; - if (typedVisitor != null) return typedVisitor.VisitBinaryNumber(this); + if (typedVisitor != null) return typedVisitor.VisitPrefixedDecNumber(this); else return visitor.VisitChildren(this); } } - public partial class ScientificNumberContext : NumberContext { - public ITerminalNode SCIENTIFIC_NUMBER() { return GetToken(FormulaGrammerParser.SCIENTIFIC_NUMBER, 0); } - public ScientificNumberContext(NumberContext context) { CopyFrom(context); } + public partial class PrefixedIntNumberContext : PrefixedNumberContext { + public ITerminalNode PREFIX_INT_NUMBER() { return GetToken(FormulaGrammerParser.PREFIX_INT_NUMBER, 0); } + public PrefixedIntNumberContext(PrefixedNumberContext context) { CopyFrom(context); } public override void EnterRule(IParseTreeListener listener) { IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; - if (typedListener != null) typedListener.EnterScientificNumber(this); + if (typedListener != null) typedListener.EnterPrefixedIntNumber(this); } public override void ExitRule(IParseTreeListener listener) { IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; - if (typedListener != null) typedListener.ExitScientificNumber(this); + if (typedListener != null) typedListener.ExitPrefixedIntNumber(this); } public override TResult Accept(IParseTreeVisitor visitor) { IFormulaGrammerVisitor typedVisitor = visitor as IFormulaGrammerVisitor; - if (typedVisitor != null) return typedVisitor.VisitScientificNumber(this); + if (typedVisitor != null) return typedVisitor.VisitPrefixedIntNumber(this); else return visitor.VisitChildren(this); } } - public partial class HexadecimalNumberContext : NumberContext { - public ITerminalNode HEXADECIMAL_NUMBER() { return GetToken(FormulaGrammerParser.HEXADECIMAL_NUMBER, 0); } - public HexadecimalNumberContext(NumberContext context) { CopyFrom(context); } + public partial class PrefixedBinNumberContext : PrefixedNumberContext { + public ITerminalNode PREFIX_BIN_NUMBER() { return GetToken(FormulaGrammerParser.PREFIX_BIN_NUMBER, 0); } + public PrefixedBinNumberContext(PrefixedNumberContext context) { CopyFrom(context); } public override void EnterRule(IParseTreeListener listener) { IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; - if (typedListener != null) typedListener.EnterHexadecimalNumber(this); + if (typedListener != null) typedListener.EnterPrefixedBinNumber(this); } public override void ExitRule(IParseTreeListener listener) { IFormulaGrammerListener typedListener = listener as IFormulaGrammerListener; - if (typedListener != null) typedListener.ExitHexadecimalNumber(this); + if (typedListener != null) typedListener.ExitPrefixedBinNumber(this); } public override TResult Accept(IParseTreeVisitor visitor) { IFormulaGrammerVisitor typedVisitor = visitor as IFormulaGrammerVisitor; - if (typedVisitor != null) return typedVisitor.VisitHexadecimalNumber(this); + if (typedVisitor != null) return typedVisitor.VisitPrefixedBinNumber(this); else return visitor.VisitChildren(this); } } [RuleVersion(0)] - public NumberContext number() { - NumberContext _localctx = new NumberContext(Context, State); - EnterRule(_localctx, 12, RULE_number); + public PrefixedNumberContext prefixedNumber() { + PrefixedNumberContext _localctx = new PrefixedNumberContext(Context, State); + EnterRule(_localctx, 14, RULE_prefixedNumber); try { - State = 65; + State = 73; ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { - case SCIENTIFIC_NUMBER: - _localctx = new ScientificNumberContext(_localctx); + case PREFIX_DEC_NUMBER: + _localctx = new PrefixedDecNumberContext(_localctx); EnterOuterAlt(_localctx, 1); { - State = 61; Match(SCIENTIFIC_NUMBER); + State = 68; Match(PREFIX_DEC_NUMBER); } break; - case DECIMAL_NUMBER: - _localctx = new DecimalNumberContext(_localctx); + case PREFIX_INT_NUMBER: + _localctx = new PrefixedIntNumberContext(_localctx); EnterOuterAlt(_localctx, 2); { - State = 62; Match(DECIMAL_NUMBER); + State = 69; Match(PREFIX_INT_NUMBER); } break; - case BINARY_NUMBER: - _localctx = new BinaryNumberContext(_localctx); + case PREFIX_BIN_NUMBER: + _localctx = new PrefixedBinNumberContext(_localctx); EnterOuterAlt(_localctx, 3); { - State = 63; Match(BINARY_NUMBER); + State = 70; Match(PREFIX_BIN_NUMBER); } break; - case HEXADECIMAL_NUMBER: - _localctx = new HexadecimalNumberContext(_localctx); + case PREFIX_OCT_NUMBER: + _localctx = new PrefixedOctNumberContext(_localctx); EnterOuterAlt(_localctx, 4); { - State = 64; Match(HEXADECIMAL_NUMBER); + State = 71; Match(PREFIX_OCT_NUMBER); + } + break; + case PREFIX_HEX_NUMBER: + _localctx = new PrefixedHexNumberContext(_localctx); + EnterOuterAlt(_localctx, 5); + { + State = 72; Match(PREFIX_HEX_NUMBER); } break; default: @@ -749,37 +856,37 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public FuncContext func() { FuncContext _localctx = new FuncContext(Context, State); - EnterRule(_localctx, 14, RULE_func); + EnterRule(_localctx, 16, RULE_func); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 67; Match(IDENTIFIER); - State = 68; Match(LPAREN); - State = 77; + State = 75; Match(IDENTIFIER); + State = 76; Match(LPAREN); + State = 85; ErrorHandler.Sync(this); _la = TokenStream.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << LPAREN) | (1L << PLUS) | (1L << MINUS) | (1L << IDENTIFIER) | (1L << DECIMAL_NUMBER) | (1L << BINARY_NUMBER) | (1L << HEXADECIMAL_NUMBER) | (1L << SCIENTIFIC_NUMBER))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << LPAREN) | (1L << PLUS) | (1L << MINUS) | (1L << IDENTIFIER) | (1L << DECIMAL_NUMBER) | (1L << INTEGER_NUMBER) | (1L << PREFIX_BIN_NUMBER) | (1L << PREFIX_HEX_NUMBER) | (1L << PREFIX_INT_NUMBER) | (1L << PREFIX_OCT_NUMBER) | (1L << PREFIX_DEC_NUMBER))) != 0)) { { - State = 69; expression(); - State = 74; + State = 77; expression(); + State = 82; ErrorHandler.Sync(this); _la = TokenStream.LA(1); while (_la==COMMA) { { { - State = 70; Match(COMMA); - State = 71; expression(); + State = 78; Match(COMMA); + State = 79; expression(); } } - State = 76; + State = 84; ErrorHandler.Sync(this); _la = TokenStream.LA(1); } } } - State = 79; Match(RPAREN); + State = 87; Match(RPAREN); } } catch (RecognitionException re) { @@ -818,11 +925,11 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public VariableContext variable() { VariableContext _localctx = new VariableContext(Context, State); - EnterRule(_localctx, 16, RULE_variable); + EnterRule(_localctx, 18, RULE_variable); try { EnterOuterAlt(_localctx, 1); { - State = 81; Match(IDENTIFIER); + State = 89; Match(IDENTIFIER); } } catch (RecognitionException re) { @@ -838,74 +945,81 @@ public VariableContext variable() { private static char[] _serializedATN = { '\x3', '\x608B', '\xA72A', '\x8133', '\xB9ED', '\x417C', '\x3BE7', '\x7786', - '\x5964', '\x3', '\x11', 'V', '\x4', '\x2', '\t', '\x2', '\x4', '\x3', + '\x5964', '\x3', '\x14', '^', '\x4', '\x2', '\t', '\x2', '\x4', '\x3', '\t', '\x3', '\x4', '\x4', '\t', '\x4', '\x4', '\x5', '\t', '\x5', '\x4', '\x6', '\t', '\x6', '\x4', '\a', '\t', '\a', '\x4', '\b', '\t', '\b', - '\x4', '\t', '\t', '\t', '\x4', '\n', '\t', '\n', '\x3', '\x2', '\x3', - '\x2', '\x3', '\x2', '\x3', '\x3', '\x3', '\x3', '\x3', '\x3', '\a', '\x3', - '\x1B', '\n', '\x3', '\f', '\x3', '\xE', '\x3', '\x1E', '\v', '\x3', '\x3', - '\x4', '\x3', '\x4', '\x3', '\x4', '\a', '\x4', '#', '\n', '\x4', '\f', - '\x4', '\xE', '\x4', '&', '\v', '\x4', '\x3', '\x5', '\x3', '\x5', '\x3', - '\x5', '\a', '\x5', '+', '\n', '\x5', '\f', '\x5', '\xE', '\x5', '.', - '\v', '\x5', '\x3', '\x6', '\x3', '\x6', '\x3', '\x6', '\x3', '\x6', '\x3', - '\x6', '\x3', '\x6', '\x5', '\x6', '\x36', '\n', '\x6', '\x3', '\a', '\x3', - '\a', '\x3', '\a', '\x3', '\a', '\x3', '\a', '\x3', '\a', '\x5', '\a', - '>', '\n', '\a', '\x3', '\b', '\x3', '\b', '\x3', '\b', '\x3', '\b', '\x5', - '\b', '\x44', '\n', '\b', '\x3', '\t', '\x3', '\t', '\x3', '\t', '\x3', - '\t', '\x3', '\t', '\a', '\t', 'K', '\n', '\t', '\f', '\t', '\xE', '\t', - 'N', '\v', '\t', '\x5', '\t', 'P', '\n', '\t', '\x3', '\t', '\x3', '\t', - '\x3', '\n', '\x3', '\n', '\x3', '\n', '\x2', '\x2', '\v', '\x2', '\x4', - '\x6', '\b', '\n', '\f', '\xE', '\x10', '\x12', '\x2', '\x4', '\x3', '\x2', - '\x5', '\x6', '\x3', '\x2', '\a', '\b', '\x2', 'Y', '\x2', '\x14', '\x3', - '\x2', '\x2', '\x2', '\x4', '\x17', '\x3', '\x2', '\x2', '\x2', '\x6', - '\x1F', '\x3', '\x2', '\x2', '\x2', '\b', '\'', '\x3', '\x2', '\x2', '\x2', - '\n', '\x35', '\x3', '\x2', '\x2', '\x2', '\f', '=', '\x3', '\x2', '\x2', - '\x2', '\xE', '\x43', '\x3', '\x2', '\x2', '\x2', '\x10', '\x45', '\x3', - '\x2', '\x2', '\x2', '\x12', 'S', '\x3', '\x2', '\x2', '\x2', '\x14', - '\x15', '\x5', '\x4', '\x3', '\x2', '\x15', '\x16', '\a', '\x2', '\x2', - '\x3', '\x16', '\x3', '\x3', '\x2', '\x2', '\x2', '\x17', '\x1C', '\x5', - '\x6', '\x4', '\x2', '\x18', '\x19', '\t', '\x2', '\x2', '\x2', '\x19', - '\x1B', '\x5', '\x6', '\x4', '\x2', '\x1A', '\x18', '\x3', '\x2', '\x2', - '\x2', '\x1B', '\x1E', '\x3', '\x2', '\x2', '\x2', '\x1C', '\x1A', '\x3', - '\x2', '\x2', '\x2', '\x1C', '\x1D', '\x3', '\x2', '\x2', '\x2', '\x1D', - '\x5', '\x3', '\x2', '\x2', '\x2', '\x1E', '\x1C', '\x3', '\x2', '\x2', - '\x2', '\x1F', '$', '\x5', '\b', '\x5', '\x2', ' ', '!', '\t', '\x3', - '\x2', '\x2', '!', '#', '\x5', '\b', '\x5', '\x2', '\"', ' ', '\x3', '\x2', - '\x2', '\x2', '#', '&', '\x3', '\x2', '\x2', '\x2', '$', '\"', '\x3', - '\x2', '\x2', '\x2', '$', '%', '\x3', '\x2', '\x2', '\x2', '%', '\a', - '\x3', '\x2', '\x2', '\x2', '&', '$', '\x3', '\x2', '\x2', '\x2', '\'', - ',', '\x5', '\n', '\x6', '\x2', '(', ')', '\a', '\v', '\x2', '\x2', ')', - '+', '\x5', '\n', '\x6', '\x2', '*', '(', '\x3', '\x2', '\x2', '\x2', - '+', '.', '\x3', '\x2', '\x2', '\x2', ',', '*', '\x3', '\x2', '\x2', '\x2', - ',', '-', '\x3', '\x2', '\x2', '\x2', '-', '\t', '\x3', '\x2', '\x2', - '\x2', '.', ',', '\x3', '\x2', '\x2', '\x2', '/', '\x30', '\a', '\x5', - '\x2', '\x2', '\x30', '\x36', '\x5', '\f', '\a', '\x2', '\x31', '\x32', - '\a', '\x6', '\x2', '\x2', '\x32', '\x36', '\x5', '\f', '\a', '\x2', '\x33', - '\x36', '\x5', '\x10', '\t', '\x2', '\x34', '\x36', '\x5', '\f', '\a', - '\x2', '\x35', '/', '\x3', '\x2', '\x2', '\x2', '\x35', '\x31', '\x3', - '\x2', '\x2', '\x2', '\x35', '\x33', '\x3', '\x2', '\x2', '\x2', '\x35', - '\x34', '\x3', '\x2', '\x2', '\x2', '\x36', '\v', '\x3', '\x2', '\x2', - '\x2', '\x37', '>', '\x5', '\xE', '\b', '\x2', '\x38', '>', '\x5', '\x12', - '\n', '\x2', '\x39', ':', '\a', '\x3', '\x2', '\x2', ':', ';', '\x5', - '\x4', '\x3', '\x2', ';', '<', '\a', '\x4', '\x2', '\x2', '<', '>', '\x3', - '\x2', '\x2', '\x2', '=', '\x37', '\x3', '\x2', '\x2', '\x2', '=', '\x38', - '\x3', '\x2', '\x2', '\x2', '=', '\x39', '\x3', '\x2', '\x2', '\x2', '>', - '\r', '\x3', '\x2', '\x2', '\x2', '?', '\x44', '\a', '\x10', '\x2', '\x2', - '@', '\x44', '\a', '\r', '\x2', '\x2', '\x41', '\x44', '\a', '\xE', '\x2', - '\x2', '\x42', '\x44', '\a', '\xF', '\x2', '\x2', '\x43', '?', '\x3', - '\x2', '\x2', '\x2', '\x43', '@', '\x3', '\x2', '\x2', '\x2', '\x43', - '\x41', '\x3', '\x2', '\x2', '\x2', '\x43', '\x42', '\x3', '\x2', '\x2', - '\x2', '\x44', '\xF', '\x3', '\x2', '\x2', '\x2', '\x45', '\x46', '\a', - '\f', '\x2', '\x2', '\x46', 'O', '\a', '\x3', '\x2', '\x2', 'G', 'L', - '\x5', '\x4', '\x3', '\x2', 'H', 'I', '\a', '\t', '\x2', '\x2', 'I', 'K', - '\x5', '\x4', '\x3', '\x2', 'J', 'H', '\x3', '\x2', '\x2', '\x2', 'K', - 'N', '\x3', '\x2', '\x2', '\x2', 'L', 'J', '\x3', '\x2', '\x2', '\x2', - 'L', 'M', '\x3', '\x2', '\x2', '\x2', 'M', 'P', '\x3', '\x2', '\x2', '\x2', - 'N', 'L', '\x3', '\x2', '\x2', '\x2', 'O', 'G', '\x3', '\x2', '\x2', '\x2', - 'O', 'P', '\x3', '\x2', '\x2', '\x2', 'P', 'Q', '\x3', '\x2', '\x2', '\x2', - 'Q', 'R', '\a', '\x4', '\x2', '\x2', 'R', '\x11', '\x3', '\x2', '\x2', - '\x2', 'S', 'T', '\a', '\f', '\x2', '\x2', 'T', '\x13', '\x3', '\x2', - '\x2', '\x2', '\n', '\x1C', '$', ',', '\x35', '=', '\x43', 'L', 'O', + '\x4', '\t', '\t', '\t', '\x4', '\n', '\t', '\n', '\x4', '\v', '\t', '\v', + '\x3', '\x2', '\x3', '\x2', '\x3', '\x2', '\x3', '\x3', '\x3', '\x3', + '\x3', '\x3', '\a', '\x3', '\x1D', '\n', '\x3', '\f', '\x3', '\xE', '\x3', + ' ', '\v', '\x3', '\x3', '\x4', '\x3', '\x4', '\x3', '\x4', '\a', '\x4', + '%', '\n', '\x4', '\f', '\x4', '\xE', '\x4', '(', '\v', '\x4', '\x3', + '\x5', '\x3', '\x5', '\x3', '\x5', '\a', '\x5', '-', '\n', '\x5', '\f', + '\x5', '\xE', '\x5', '\x30', '\v', '\x5', '\x3', '\x6', '\x3', '\x6', + '\x3', '\x6', '\x3', '\x6', '\x3', '\x6', '\x5', '\x6', '\x37', '\n', + '\x6', '\x3', '\a', '\x3', '\a', '\x3', '\a', '\x3', '\a', '\x3', '\a', + '\x3', '\a', '\x3', '\a', '\x3', '\a', '\x5', '\a', '\x41', '\n', '\a', + '\x3', '\b', '\x3', '\b', '\x5', '\b', '\x45', '\n', '\b', '\x3', '\t', + '\x3', '\t', '\x3', '\t', '\x3', '\t', '\x3', '\t', '\x5', '\t', 'L', + '\n', '\t', '\x3', '\n', '\x3', '\n', '\x3', '\n', '\x3', '\n', '\x3', + '\n', '\a', '\n', 'S', '\n', '\n', '\f', '\n', '\xE', '\n', 'V', '\v', + '\n', '\x5', '\n', 'X', '\n', '\n', '\x3', '\n', '\x3', '\n', '\x3', '\v', + '\x3', '\v', '\x3', '\v', '\x2', '\x2', '\f', '\x2', '\x4', '\x6', '\b', + '\n', '\f', '\xE', '\x10', '\x12', '\x14', '\x2', '\x4', '\x3', '\x2', + '\x5', '\x6', '\x3', '\x2', '\a', '\b', '\x2', '\x63', '\x2', '\x16', + '\x3', '\x2', '\x2', '\x2', '\x4', '\x19', '\x3', '\x2', '\x2', '\x2', + '\x6', '!', '\x3', '\x2', '\x2', '\x2', '\b', ')', '\x3', '\x2', '\x2', + '\x2', '\n', '\x36', '\x3', '\x2', '\x2', '\x2', '\f', '@', '\x3', '\x2', + '\x2', '\x2', '\xE', '\x44', '\x3', '\x2', '\x2', '\x2', '\x10', 'K', + '\x3', '\x2', '\x2', '\x2', '\x12', 'M', '\x3', '\x2', '\x2', '\x2', '\x14', + '[', '\x3', '\x2', '\x2', '\x2', '\x16', '\x17', '\x5', '\x4', '\x3', + '\x2', '\x17', '\x18', '\a', '\x2', '\x2', '\x3', '\x18', '\x3', '\x3', + '\x2', '\x2', '\x2', '\x19', '\x1E', '\x5', '\x6', '\x4', '\x2', '\x1A', + '\x1B', '\t', '\x2', '\x2', '\x2', '\x1B', '\x1D', '\x5', '\x6', '\x4', + '\x2', '\x1C', '\x1A', '\x3', '\x2', '\x2', '\x2', '\x1D', ' ', '\x3', + '\x2', '\x2', '\x2', '\x1E', '\x1C', '\x3', '\x2', '\x2', '\x2', '\x1E', + '\x1F', '\x3', '\x2', '\x2', '\x2', '\x1F', '\x5', '\x3', '\x2', '\x2', + '\x2', ' ', '\x1E', '\x3', '\x2', '\x2', '\x2', '!', '&', '\x5', '\b', + '\x5', '\x2', '\"', '#', '\t', '\x3', '\x2', '\x2', '#', '%', '\x5', '\b', + '\x5', '\x2', '$', '\"', '\x3', '\x2', '\x2', '\x2', '%', '(', '\x3', + '\x2', '\x2', '\x2', '&', '$', '\x3', '\x2', '\x2', '\x2', '&', '\'', + '\x3', '\x2', '\x2', '\x2', '\'', '\a', '\x3', '\x2', '\x2', '\x2', '(', + '&', '\x3', '\x2', '\x2', '\x2', ')', '.', '\x5', '\n', '\x6', '\x2', + '*', '+', '\a', '\v', '\x2', '\x2', '+', '-', '\x5', '\n', '\x6', '\x2', + ',', '*', '\x3', '\x2', '\x2', '\x2', '-', '\x30', '\x3', '\x2', '\x2', + '\x2', '.', ',', '\x3', '\x2', '\x2', '\x2', '.', '/', '\x3', '\x2', '\x2', + '\x2', '/', '\t', '\x3', '\x2', '\x2', '\x2', '\x30', '.', '\x3', '\x2', + '\x2', '\x2', '\x31', '\x32', '\a', '\x5', '\x2', '\x2', '\x32', '\x37', + '\x5', '\f', '\a', '\x2', '\x33', '\x34', '\a', '\x6', '\x2', '\x2', '\x34', + '\x37', '\x5', '\f', '\a', '\x2', '\x35', '\x37', '\x5', '\f', '\a', '\x2', + '\x36', '\x31', '\x3', '\x2', '\x2', '\x2', '\x36', '\x33', '\x3', '\x2', + '\x2', '\x2', '\x36', '\x35', '\x3', '\x2', '\x2', '\x2', '\x37', '\v', + '\x3', '\x2', '\x2', '\x2', '\x38', '\x41', '\x5', '\xE', '\b', '\x2', + '\x39', '\x41', '\x5', '\x10', '\t', '\x2', ':', '\x41', '\x5', '\x14', + '\v', '\x2', ';', '<', '\a', '\x3', '\x2', '\x2', '<', '=', '\x5', '\x4', + '\x3', '\x2', '=', '>', '\a', '\x4', '\x2', '\x2', '>', '\x41', '\x3', + '\x2', '\x2', '\x2', '?', '\x41', '\x5', '\x12', '\n', '\x2', '@', '\x38', + '\x3', '\x2', '\x2', '\x2', '@', '\x39', '\x3', '\x2', '\x2', '\x2', '@', + ':', '\x3', '\x2', '\x2', '\x2', '@', ';', '\x3', '\x2', '\x2', '\x2', + '@', '?', '\x3', '\x2', '\x2', '\x2', '\x41', '\r', '\x3', '\x2', '\x2', + '\x2', '\x42', '\x45', '\a', '\r', '\x2', '\x2', '\x43', '\x45', '\a', + '\xE', '\x2', '\x2', '\x44', '\x42', '\x3', '\x2', '\x2', '\x2', '\x44', + '\x43', '\x3', '\x2', '\x2', '\x2', '\x45', '\xF', '\x3', '\x2', '\x2', + '\x2', '\x46', 'L', '\a', '\x13', '\x2', '\x2', 'G', 'L', '\a', '\x11', + '\x2', '\x2', 'H', 'L', '\a', '\xF', '\x2', '\x2', 'I', 'L', '\a', '\x12', + '\x2', '\x2', 'J', 'L', '\a', '\x10', '\x2', '\x2', 'K', '\x46', '\x3', + '\x2', '\x2', '\x2', 'K', 'G', '\x3', '\x2', '\x2', '\x2', 'K', 'H', '\x3', + '\x2', '\x2', '\x2', 'K', 'I', '\x3', '\x2', '\x2', '\x2', 'K', 'J', '\x3', + '\x2', '\x2', '\x2', 'L', '\x11', '\x3', '\x2', '\x2', '\x2', 'M', 'N', + '\a', '\f', '\x2', '\x2', 'N', 'W', '\a', '\x3', '\x2', '\x2', 'O', 'T', + '\x5', '\x4', '\x3', '\x2', 'P', 'Q', '\a', '\t', '\x2', '\x2', 'Q', 'S', + '\x5', '\x4', '\x3', '\x2', 'R', 'P', '\x3', '\x2', '\x2', '\x2', 'S', + 'V', '\x3', '\x2', '\x2', '\x2', 'T', 'R', '\x3', '\x2', '\x2', '\x2', + 'T', 'U', '\x3', '\x2', '\x2', '\x2', 'U', 'X', '\x3', '\x2', '\x2', '\x2', + 'V', 'T', '\x3', '\x2', '\x2', '\x2', 'W', 'O', '\x3', '\x2', '\x2', '\x2', + 'W', 'X', '\x3', '\x2', '\x2', '\x2', 'X', 'Y', '\x3', '\x2', '\x2', '\x2', + 'Y', 'Z', '\a', '\x4', '\x2', '\x2', 'Z', '\x13', '\x3', '\x2', '\x2', + '\x2', '[', '\\', '\a', '\f', '\x2', '\x2', '\\', '\x15', '\x3', '\x2', + '\x2', '\x2', '\v', '\x1E', '&', '.', '\x36', '@', '\x44', 'K', 'T', 'W', }; public static readonly ATN _ATN = diff --git a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerVisitor.cs b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerVisitor.cs index 3339c55..b519a00 100644 --- a/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerVisitor.cs +++ b/ThinkSharp.FormulaParser/ANTLR/FormulaGrammerVisitor.cs @@ -70,13 +70,6 @@ public interface IFormulaGrammerVisitor : IParseTreeVisitor { /// The visitor result. Result VisitNegativeAtom([NotNull] FormulaGrammerParser.NegativeAtomContext context); /// - /// Visit a parse tree produced by the Function - /// labeled alternative in . - /// - /// The parse tree. - /// The visitor result. - Result VisitFunction([NotNull] FormulaGrammerParser.FunctionContext context); - /// /// Visit a parse tree produced by the UnsignedAtom /// labeled alternative in . /// @@ -90,33 +83,54 @@ public interface IFormulaGrammerVisitor : IParseTreeVisitor { /// The visitor result. Result VisitAtom([NotNull] FormulaGrammerParser.AtomContext context); /// - /// Visit a parse tree produced by the ScientificNumber + /// Visit a parse tree produced by the DecimalNumber /// labeled alternative in . /// /// The parse tree. /// The visitor result. - Result VisitScientificNumber([NotNull] FormulaGrammerParser.ScientificNumberContext context); + Result VisitDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context); /// - /// Visit a parse tree produced by the DecimalNumber + /// Visit a parse tree produced by the IntgerNumber /// labeled alternative in . /// /// The parse tree. /// The visitor result. - Result VisitDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context); + Result VisitIntgerNumber([NotNull] FormulaGrammerParser.IntgerNumberContext context); /// - /// Visit a parse tree produced by the BinaryNumber - /// labeled alternative in . + /// Visit a parse tree produced by the PrefixedDecNumber + /// labeled alternative in . /// /// The parse tree. /// The visitor result. - Result VisitBinaryNumber([NotNull] FormulaGrammerParser.BinaryNumberContext context); + Result VisitPrefixedDecNumber([NotNull] FormulaGrammerParser.PrefixedDecNumberContext context); /// - /// Visit a parse tree produced by the HexadecimalNumber - /// labeled alternative in . + /// Visit a parse tree produced by the PrefixedIntNumber + /// labeled alternative in . + /// + /// The parse tree. + /// The visitor result. + Result VisitPrefixedIntNumber([NotNull] FormulaGrammerParser.PrefixedIntNumberContext context); + /// + /// Visit a parse tree produced by the PrefixedBinNumber + /// labeled alternative in . + /// + /// The parse tree. + /// The visitor result. + Result VisitPrefixedBinNumber([NotNull] FormulaGrammerParser.PrefixedBinNumberContext context); + /// + /// Visit a parse tree produced by the PrefixedOctNumber + /// labeled alternative in . + /// + /// The parse tree. + /// The visitor result. + Result VisitPrefixedOctNumber([NotNull] FormulaGrammerParser.PrefixedOctNumberContext context); + /// + /// Visit a parse tree produced by the PrefixedHexNumber + /// labeled alternative in . /// /// The parse tree. /// The visitor result. - Result VisitHexadecimalNumber([NotNull] FormulaGrammerParser.HexadecimalNumberContext context); + Result VisitPrefixedHexNumber([NotNull] FormulaGrammerParser.PrefixedHexNumberContext context); /// /// Visit a parse tree produced by . /// diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/BinaryOperator.cs b/ThinkSharp.FormulaParser/Ast/Nodes/BinaryOperator.cs index 94452a8..d22c558 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/BinaryOperator.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/BinaryOperator.cs @@ -7,13 +7,28 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes public sealed class BinaryOperator { readonly Func evaluation; - private static readonly IEnumerable allBinaryOperators = new[] + private static readonly BinaryOperator[] allBinaryOperators; + + public static BinaryOperator Plus { get; } + public static BinaryOperator Minus { get; } + public static BinaryOperator Times { get; } + public static BinaryOperator DividedBy { get; } + + static BinaryOperator() { - new BinaryOperator("+", (x, y) => x + y), - new BinaryOperator( "-", (x, y) => x - y), - new BinaryOperator( "/", (x, y) => x / y), - new BinaryOperator("*", (x, y) => x* y), - }; + Plus = new BinaryOperator("+", (x, y) => x + y); + Minus = new BinaryOperator("-", (x, y) => x - y); + Times = new BinaryOperator("*", (x, y) => x * y); + DividedBy = new BinaryOperator("/", (x, y) => x / y); + + allBinaryOperators = new[] + { + Plus, + Minus, + Times, + DividedBy + }; + } private BinaryOperator(string symbol, Func evaluation) { diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/NumericNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/DecimalNode.cs similarity index 72% rename from ThinkSharp.FormulaParser/Ast/Nodes/NumericNode.cs rename to ThinkSharp.FormulaParser/Ast/Nodes/DecimalNode.cs index 16665b4..2c51d14 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/NumericNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/DecimalNode.cs @@ -7,16 +7,13 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { - public class NumberNode : Node + public class DecimalNode : Node { - public NumberNode(string token, double value) + public DecimalNode(double value) { - this.Token = token; this.Value = value; } - public string Token { get; } - public double Value { get; } public override TReturn Visit(INodeVisitor visitor) => visitor.Visit(this); diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/IntegerNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/IntegerNode.cs new file mode 100644 index 0000000..d46fb61 --- /dev/null +++ b/ThinkSharp.FormulaParser/Ast/Nodes/IntegerNode.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Visitors; + +namespace ThinkSharp.FormulaParsing.Ast.Nodes +{ + public class IntegerNode : Node + { + public IntegerNode(long value) : this(NumberFormat.Dec, value) + { + } + public IntegerNode(NumberFormat format, long value) + { + this.Format = format; + this.Value = value; + } + + public NumberFormat Format { get; } + + public long Value { get; } + + public override TReturn Visit(INodeVisitor visitor) => visitor.Visit(this); + } +} diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/NumberFormat.cs b/ThinkSharp.FormulaParser/Ast/Nodes/NumberFormat.cs new file mode 100644 index 0000000..6c55faf --- /dev/null +++ b/ThinkSharp.FormulaParser/Ast/Nodes/NumberFormat.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ThinkSharp.FormulaParsing.Ast.Nodes +{ + public enum NumberFormat + { + Dec, + Hex, + Bin, + Oct + } +} diff --git a/ThinkSharp.FormulaParser/Ast/Visitors/CloneTreeVisitor.cs b/ThinkSharp.FormulaParser/Ast/Visitors/CloneTreeVisitor.cs index b978c26..03c71e5 100644 --- a/ThinkSharp.FormulaParser/Ast/Visitors/CloneTreeVisitor.cs +++ b/ThinkSharp.FormulaParser/Ast/Visitors/CloneTreeVisitor.cs @@ -36,9 +36,14 @@ public override Node Visit(FunctionNode node) return new FunctionNode(node.FunctionName, node.Parameters.Select(p => p.Visit(this)).ToArray()); } - public override Node Visit(NumberNode node) + public override Node Visit(DecimalNode node) { - return new NumberNode(node.Token, node.Value); + return new DecimalNode(node.Value); + } + + public override Node Visit(IntegerNode node) + { + return new IntegerNode(node.Format, node.Value); } public override Node Visit(PowerNode node) diff --git a/ThinkSharp.FormulaParser/Ast/Visitors/EvaluateAstVisitor.cs b/ThinkSharp.FormulaParser/Ast/Visitors/EvaluateAstVisitor.cs index ae34a44..e2f6b4b 100644 --- a/ThinkSharp.FormulaParser/Ast/Visitors/EvaluateAstVisitor.cs +++ b/ThinkSharp.FormulaParser/Ast/Visitors/EvaluateAstVisitor.cs @@ -26,7 +26,12 @@ public EvaluateAstVisitor(IConfigurationEvaluator configurationEvaluation, IRead } } - public override double Visit(NumberNode node) + public override double Visit(DecimalNode node) + { + return node.Value; + } + + public override double Visit(IntegerNode node) { return node.Value; } diff --git a/ThinkSharp.FormulaParser/Ast/Visitors/INodeVisitor.cs b/ThinkSharp.FormulaParser/Ast/Visitors/INodeVisitor.cs index f982e03..b5fb893 100644 --- a/ThinkSharp.FormulaParser/Ast/Visitors/INodeVisitor.cs +++ b/ThinkSharp.FormulaParser/Ast/Visitors/INodeVisitor.cs @@ -13,7 +13,9 @@ public interface INodeVisitor TReturn Visit(BracketedNode node); - TReturn Visit(NumberNode node); + TReturn Visit(DecimalNode node); + + TReturn Visit(IntegerNode node); TReturn Visit(VariableNode node); diff --git a/ThinkSharp.FormulaParser/Ast/Visitors/NodeVisitor.cs b/ThinkSharp.FormulaParser/Ast/Visitors/NodeVisitor.cs index 3998f93..4209d93 100644 --- a/ThinkSharp.FormulaParser/Ast/Visitors/NodeVisitor.cs +++ b/ThinkSharp.FormulaParser/Ast/Visitors/NodeVisitor.cs @@ -13,7 +13,9 @@ public abstract class NodeVisitor : INodeVisitor public virtual TResult Visit(BracketedNode node) => node.ChildNode.Visit(this); - public virtual TResult Visit(NumberNode node) => DefaultResult(); + public virtual TResult Visit(DecimalNode node) => DefaultResult(); + + public virtual TResult Visit(IntegerNode node) => DefaultResult(); public virtual TResult Visit(VariableNode node) => DefaultResult(); diff --git a/ThinkSharp.FormulaParser/Ast/Visitors/NodesToTextDebugVisitor.cs b/ThinkSharp.FormulaParser/Ast/Visitors/NodesToTextDebugVisitor.cs new file mode 100644 index 0000000..b15c693 --- /dev/null +++ b/ThinkSharp.FormulaParser/Ast/Visitors/NodesToTextDebugVisitor.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.Ast.Visitors +{ + internal class NodesToTextDebugVisitor : INodeVisitor + { + public string Visit(FormulaNode node) + { + return node.ChildNode.Visit(this); + } + + public string Visit(BracketedNode node) => $"({node.ChildNode.Visit(this)})"; + + public string Visit(DecimalNode node) => node.Value.ToString("0.00", CultureInfo.InvariantCulture); + + public string Visit(VariableNode node) => node.Name; + + public string Visit(ConstantNode node) => node.Name; + + public string Visit(BinaryOperatorNode node) => $"{node.LeftNode.Visit(this)}{node.BinaryOperator.Symbol}{node.RightNode.Visit(this)}"; + + public string Visit(PowerNode node) => $"{node.BaseNode.Visit(this)}^{node.ExponentNode.Visit(this)}"; + + public string Visit(SignedNode node) => (node.Sign == Sign.Minus ? "-" : "") + node.Node.Visit(this); + + public string Visit(FunctionNode node) => $"{node.FunctionName}({string.Join(", ", node.Parameters.Select(p => p.Visit(this)))})"; + + public string Visit(IntegerNode node) => node.Value.ToString(); + } +} diff --git a/ThinkSharp.FormulaParser/Configuration.cs b/ThinkSharp.FormulaParser/Configuration.cs index 6e97bbb..7c082c6 100644 --- a/ThinkSharp.FormulaParser/Configuration.cs +++ b/ThinkSharp.FormulaParser/Configuration.cs @@ -65,6 +65,8 @@ public Configuration() public bool IsHexadecimalNumberNotationSupportDisabled { get; private set; } = false; + public bool IsOctalNumberNotationSupportDisabled { get; private set; } = false; + bool IConfiguration.HasFunction(string name, int argumentCount) { if (this.MatchFunction0To5(name, argumentCount)) @@ -274,6 +276,7 @@ IEnumerable> IConfigurationEvaluator.EnumerateConst void IConfigureSupportedFeatures.DisableScientificNotation() => this.IsScientificNotationSupportDisabled = true; void IConfigureSupportedFeatures.DisableBinaryNumberNotation() => this.IsBinaryNumberNotationSupportDisabled = true; void IConfigureSupportedFeatures.DisableHexadecimalNumberNotation() => this.IsHexadecimalNumberNotationSupportDisabled = true; + void IConfigureSupportedFeatures.DisableOctalNumberNotation() => this.IsOctalNumberNotationSupportDisabled = true; void IConfigureSupportedFeatures.DisableBracket() => this.IsBracketSupportDisabled = true; void IConfigureSupportedFeatures.DisablePow() => this.IsPowSupportDisabled = true; void IConfigureSupportedFeatures.DisableVariables() => this.IsVariablesSupportDisabled = true; diff --git a/ThinkSharp.FormulaParser/IConfiguration.cs b/ThinkSharp.FormulaParser/IConfiguration.cs index ec0871d..7fe1bda 100644 --- a/ThinkSharp.FormulaParser/IConfiguration.cs +++ b/ThinkSharp.FormulaParser/IConfiguration.cs @@ -14,6 +14,8 @@ internal interface IConfiguration bool IsHexadecimalNumberNotationSupportDisabled { get; } + bool IsOctalNumberNotationSupportDisabled { get; } + bool IsBracketSupportDisabled { get; } bool IsPowSupportDisabled { get; } diff --git a/ThinkSharp.FormulaParser/IConfigureSupportedFeatures.cs b/ThinkSharp.FormulaParser/IConfigureSupportedFeatures.cs index 01fcdac..779aa9b 100644 --- a/ThinkSharp.FormulaParser/IConfigureSupportedFeatures.cs +++ b/ThinkSharp.FormulaParser/IConfigureSupportedFeatures.cs @@ -20,6 +20,11 @@ public interface IConfigureSupportedFeatures /// void DisableHexadecimalNumberNotation(); + /// + /// Prevents the usage of octal notation (e.g. 0o10 = 8) + /// + void DisableOctalNumberNotation(); + /// /// Prevents the usage of brackets. /// diff --git a/ThinkSharp.FormulaParser/ParserConfiguration.cs b/ThinkSharp.FormulaParser/ParserConfiguration.cs index 88053ef..92e839f 100644 --- a/ThinkSharp.FormulaParser/ParserConfiguration.cs +++ b/ThinkSharp.FormulaParser/ParserConfiguration.cs @@ -35,6 +35,8 @@ public ParserConfiguration(IConfiguration configuration, IReadOnlyDictionary this.configuration.IsHexadecimalNumberNotationSupportDisabled; + public bool IsOctalNumberNotationSupportDisabled => this.configuration.IsOctalNumberNotationSupportDisabled; + public bool HasConstant(string name) => this.configuration.HasConstant(name); public bool HasFunction(string name, int argumentCount) => this.configuration.HasFunction(name, argumentCount); diff --git a/ThinkSharp.FormulaParser/ParsingException.cs b/ThinkSharp.FormulaParser/ParsingException.cs index f91225c..d37233c 100644 --- a/ThinkSharp.FormulaParser/ParsingException.cs +++ b/ThinkSharp.FormulaParser/ParsingException.cs @@ -27,6 +27,8 @@ private ParsingException(int line, int column, string invalidToken, string messa internal static void ThrowInvalidTokenException(IToken token) => ThrowException(token.Line, token.Column, token.Text, $"Invalid token '{token.Text}'."); + internal static void ThrowInvalidScientificNumberException(IToken token) => ThrowException(token.Line, token.Column, token.Text, $"Invalid scientific number: '{token.Text}'."); + internal static void ThrowUnknownFunctionException(IToken token) => ThrowException(token.Line, token.Column, token.Text, $"Unknown function '{token.Text}'."); internal static void ThrowFunctionArgumentCountDoesNotExistException(IToken token, int argumentCount) => ThrowException(token.Line, token.Column, token.Text, $"There is no function '{token.Text}' that takes {argumentCount} argument(s)."); diff --git a/ThinkSharp.FormulaParser/TermRewriting/ReplaceRuleTreeVisitor.cs b/ThinkSharp.FormulaParser/TermRewriting/ReplaceRuleTreeVisitor.cs index a7b2657..f15a41a 100644 --- a/ThinkSharp.FormulaParser/TermRewriting/ReplaceRuleTreeVisitor.cs +++ b/ThinkSharp.FormulaParser/TermRewriting/ReplaceRuleTreeVisitor.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; using ThinkSharp.FormulaParsing.Ast.Nodes; using ThinkSharp.FormulaParsing.Ast.Visitors; @@ -7,9 +8,25 @@ namespace ThinkSharp.FormulaParsing.TermRewriting { - internal class ReplaceRuleTreeVisitor : INodeVisitor + public class ReplaceRuleTreeVisitor : INodeVisitor { private readonly Rule rule; + private readonly ParentNodeContex parentContext = new ParentNodeContex(); + + private class ParentNodeContex : IDisposable + { + private Stack stackedNodes = new Stack(); + + public Node Parent => stackedNodes.Count == 0 ? null : stackedNodes.Peek(); + + public IDisposable Push(Node parent) + { + stackedNodes.Push(parent); + return this; + } + + void IDisposable.Dispose() => stackedNodes.Pop(); + } public ReplaceRuleTreeVisitor(Rule rule) { @@ -17,87 +34,91 @@ public ReplaceRuleTreeVisitor(Rule rule) } public Node Visit(FormulaNode node) - => TryRewrite(node.ChildNode, out Node rewrittenNode) - ? new FormulaNode(rewrittenNode) - : node; + { + using (parentContext.Push(node)) + { + var child = node.ChildNode.Visit(this); + return child == node.ChildNode ? node : new FormulaNode(child); + } + } public Node Visit(BracketedNode node) - => TryRewrite(node.ChildNode, out Node rewrittenNode) - ? new BracketedNode(rewrittenNode) - : node; + { + using (parentContext.Push(node)) + { + var child = node.ChildNode.Visit(this); + node = node.ChildNode == child ? node : new BracketedNode(child); + } - public Node Visit(NumberNode node) - => node; + return TryRewrite(node); + } - public Node Visit(VariableNode node) - => node; + public Node Visit(DecimalNode node) => TryRewrite(node); - public Node Visit(ConstantNode node) - => node; + public Node Visit(IntegerNode node) => TryRewrite(node); + + public Node Visit(VariableNode node) => TryRewrite(node); + + public Node Visit(ConstantNode node) => TryRewrite(node); public Node Visit(BinaryOperatorNode node) { - if (TryRewrite(node.LeftNode, out Node leftRewritten)) - { - return new BinaryOperatorNode(node.BinaryOperator, leftRewritten, node.RightNode); - } - if (TryRewrite(node.RightNode, out Node rightRewritten)) + using (parentContext.Push(node)) { - return new BinaryOperatorNode(node.BinaryOperator, node.LeftNode, rightRewritten); + var left = node.LeftNode.Visit(this); + var right = node.RightNode.Visit(this); + node = left == node.LeftNode && right == node.RightNode + ? node + : new BinaryOperatorNode(node.BinaryOperator, left, right); } - return node; + return TryRewrite(node); } public Node Visit(PowerNode node) { - if (TryRewrite(node.BaseNode, out Node rewrittenBaseNode)) - { - return new PowerNode(rewrittenBaseNode, node.ExponentNode); - } - if (TryRewrite(node.BaseNode, out Node rewrittenExponentNode)) + using (parentContext.Push(node)) { - return new PowerNode(node.BaseNode, rewrittenExponentNode); + var baseNode = node.BaseNode.Visit(this); + var exponentNode = node.ExponentNode.Visit(this); + node = baseNode == node.BaseNode && exponentNode == node.ExponentNode + ? node + : new PowerNode(baseNode, exponentNode); } - return node; + return TryRewrite(node); } public Node Visit(SignedNode node) - => TryRewrite(node.Node, out Node rewrittenNode) - ? new SignedNode(node.Sign, rewrittenNode) - : node; + { + + using (parentContext.Push(node)) + { + var child = node.Node.Visit(this); + node = child == node.Node ? node : new SignedNode(node.Sign, child); + } + return TryRewrite(node); + } public Node Visit(FunctionNode node) { - var rewrittenParameters = new List(); - var hasRewrittenParameters = false; - foreach (var argumentNode in node.Parameters) + using (parentContext.Push(node)) { - if (TryRewrite(argumentNode, out Node rewrittenNode)) - { - rewrittenParameters.Add(rewrittenNode); - hasRewrittenParameters = true; - } - else - { - rewrittenParameters.Add(argumentNode); - } + var rewrittenParameters = node.Parameters.Select(p => p.Visit(this)).ToArray(); + node = rewrittenParameters.SequenceEqual(node.Parameters) + ? node + : new FunctionNode(node.FunctionName, rewrittenParameters); } - - return hasRewrittenParameters - ? new FunctionNode(node.FunctionName, rewrittenParameters.ToArray()) - : node; + + return TryRewrite(node); } - private bool TryRewrite(Node node, out Node rewrittenNode) + private Node TryRewrite(Node node) { - if (this.rule.Match(node)) + if (this.rule.Match(node, this.parentContext.Parent)) { - rewrittenNode = rule.Rewrite(node); - return true; + return rule.Rewrite(node, this.parentContext.Parent); } - rewrittenNode = node.Visit(this); - return rewrittenNode != node; + return node; } } } diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/ConvertDecimalToLong.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/ConvertDecimalToLong.cs new file mode 100644 index 0000000..8f23b01 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/ConvertDecimalToLong.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.Ast.Visitors; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class ConvertDecimalToLong : Rule + { + protected override bool MatchInternal(Node node, Node Parent) + { + return node is DecimalNode dec && dec.Value % 1 == 0; + } + + protected override Node RewriteInternal(Node node, Node Parent) + { + if (node is DecimalNode dec && dec.Value % 1 == 0) + { + try + { + return new IntegerNode(NumberFormat.Dec, (long)dec.Value); + } + catch + { + Debug.Fail("Unable to convert decimal to long."); + // ignore + } + } + + Debug.Fail("Should not happen"); + return node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/MoveOuterMinusToInnerTerm.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/MoveOuterMinusToInnerTerm.cs deleted file mode 100644 index 63dd5d6..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/MoveOuterMinusToInnerTerm.cs +++ /dev/null @@ -1,155 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.Ast.Visitors; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class MoveOuterMinusToInnerTerm : Rule - { - private class SwitchSignWithinBracketsVisitor : INodeVisitor - { - public Node Visit(FormulaNode node) => node.ChildNode.Visit(this); - - public Node Visit(BracketedNode node) => node; - - public Node Visit(NumberNode node) => node; - - public Node Visit(VariableNode node) => node; - - public Node Visit(ConstantNode node) => node; - - public Node Visit(BinaryOperatorNode node) - { - var newLeft = node.LeftNode.Visit(this); - var newRight = node.RightNode.Visit(this); - - var symbol = node.BinaryOperator.Symbol; - var op = symbol == "+" ? BinaryOperator.BySymbol("-") - : symbol == "-" ? BinaryOperator.BySymbol("+") - : node.BinaryOperator; - - return new BinaryOperatorNode(op, newLeft, newRight); - } - - public Node Visit(PowerNode node) => node; - - public Node Visit(SignedNode node) => node; - - public Node Visit(FunctionNode node) => node; - } - - public override bool Match(Node node) - { - if (node is SignedNode signNode) - { - if (signNode.Sign == Sign.Plus) - { - return true; - } - - var targetNode = signNode.Node; - while (targetNode is BinaryOperatorNode binaryOperationNode) - { - targetNode = binaryOperationNode.LeftNode; - } - - if (targetNode == signNode.Node) - { - return targetNode is BracketedNode || - targetNode is NumberNode; - } - - return targetNode is BracketedNode || - targetNode is SignedNode || - targetNode is ConstantNode || - targetNode is FunctionNode || - targetNode is NumberNode || - targetNode is PowerNode || - targetNode is VariableNode; - } - - return false; - } - - public override Node Rewrite(Node node) - { - if (node is SignedNode signNode) - { - if (signNode.Sign == Sign.Plus) - { - return signNode.Node; - } - - var targetNode = signNode.Node; - if (targetNode is BracketedNode targetBracketedNode) - { - var newBracketedContentNode = targetBracketedNode.ChildNode.Visit(new SwitchSignWithinBracketsVisitor()); - return new SignedNode(Sign.Minus, newBracketedContentNode); - } - - var binOpStack = new Stack(); - while (targetNode is BinaryOperatorNode binaryOperationNode) - { - binOpStack.Push(binaryOperationNode); - targetNode = binaryOperationNode.LeftNode; - } - - var transformedNode = TransformedNode(targetNode); - - if (transformedNode != null) - { - Node leftNode = transformedNode; - while (binOpStack.Count > 0) - { - var binOpFromQueue = binOpStack.Pop(); - leftNode = new BinaryOperatorNode(binOpFromQueue.BinaryOperator, leftNode, binOpFromQueue.RightNode); - } - return leftNode; - } - } - - Debug.Fail("Should not happen"); - return node; - } - - private Node TransformedNode(Node targetNode) - { - if (targetNode is BracketedNode targetBracketedNode) - { - var newBracketedContentNode = targetBracketedNode.Visit(new SwitchSignWithinBracketsVisitor()); - var newSignedBracketedContentNode = new SignedNode(Sign.Minus, newBracketedContentNode); - return new BracketedNode(newSignedBracketedContentNode); - } - - if (targetNode is SignedNode targetSignedNode) - { - if (targetSignedNode.Sign == Sign.Minus) - { - return targetSignedNode.Node; - } - return new SignedNode(Sign.Minus, targetSignedNode.Node); - } - - if (targetNode is ConstantNode - || targetNode is FunctionNode - || targetNode is PowerNode - || targetNode is VariableNode) - { - return new SignedNode(Sign.Minus, targetNode); - } - - if (targetNode is NumberNode numberNode) - { - var token = numberNode.Token[0] == '-' - ? numberNode.Token.Substring(1) - : "-" + numberNode.Token; - return new NumberNode(token, numberNode.Value * -1); - } - - return null; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/NodeExtensions.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/NodeExtensions.cs new file mode 100644 index 0000000..4a9177d --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/NodeExtensions.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.Ast.Visitors; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + internal static class NodeExtensions + { + private class SwitchSignForTermsWithinBracketsVisitor : INodeVisitor + { + public Node Visit(FormulaNode node) => node.ChildNode.Visit(this); + public Node Visit(BracketedNode node) => node; + public Node Visit(DecimalNode node) => node; + public Node Visit(VariableNode node) => node; + public Node Visit(ConstantNode node) => node; + public Node Visit(PowerNode node) => node; + public Node Visit(SignedNode node) => node; + public Node Visit(FunctionNode node) => node; + public Node Visit(IntegerNode node) => node; + public Node Visit(BinaryOperatorNode node) + { + var newLeft = node.LeftNode.Visit(this); + var newRight = node.RightNode.Visit(this); + + var symbol = node.BinaryOperator.Symbol; + var op = symbol == "+" ? BinaryOperator.BySymbol("-") + : symbol == "-" ? BinaryOperator.BySymbol("+") + : node.BinaryOperator; + + return new BinaryOperatorNode(op, newLeft, newRight); + } + } + + private class SwitchSignConcreteNodeVisitor : INodeVisitor + { + public Node Visit(FormulaNode node) => node.ChildNode.Visit(this); + public Node Visit(BracketedNode node) + => new SignedNode(Sign.Minus, new BracketedNode(node.SwitchSignForAllSummands())); + public Node Visit(DecimalNode node) => new DecimalNode(node.Value * -1); + public Node Visit(VariableNode node) => new SignedNode(Sign.Minus, node); + public Node Visit(ConstantNode node) => new SignedNode(Sign.Minus, node); + public Node Visit(PowerNode node) => new SignedNode(Sign.Minus, node); + public Node Visit(SignedNode node) => + node.Sign == Sign.Minus + ? node.Node + : new SignedNode(Sign.Minus, node.Node); + + public Node Visit(FunctionNode node) => new SignedNode(Sign.Minus, node); + public Node Visit(IntegerNode node) => new IntegerNode(node.Format, node.Value * -1); + public Node Visit(BinaryOperatorNode node) => new SignedNode(Sign.Minus, node); + } + + private class TransformNodeWithinMinusSignNodeVisitor : INodeVisitor + { + public Node Visit(FormulaNode node) => + throw new InvalidOperationException("Formula node is always the root node."); + public Node Visit(BracketedNode node) + => new BracketedNode(node.ChildNode.SwitchSignForAllSummands()); + public Node Visit(DecimalNode node) => new DecimalNode(node.Value * -1); + public Node Visit(VariableNode node) => new SignedNode(Sign.Minus, node); + public Node Visit(ConstantNode node) => new SignedNode(Sign.Minus, node); + public Node Visit(PowerNode node) => new SignedNode(Sign.Minus, node); + public Node Visit(SignedNode node) => + node.Sign == Sign.Minus + ? node.Node + : new SignedNode(Sign.Minus, node); + + public Node Visit(FunctionNode node) => new SignedNode(Sign.Minus, node); + public Node Visit(IntegerNode node) => new IntegerNode(node.Format, node.Value * -1); + public Node Visit(BinaryOperatorNode node) => new SignedNode(Sign.Minus, node); + } + + public static bool EqualsNumber(this Node node, int number) + => (node is DecimalNode rightDecNode && rightDecNode.Value == number) || + (node is IntegerNode rightIntNode && rightIntNode.Value == number); + + + public static bool IsPlus(this BinaryOperatorNode node) + => node.BinaryOperator.Symbol == "+"; + + public static bool IsMinus(this BinaryOperatorNode node) + => node.BinaryOperator.Symbol == "-"; + + public static bool IsPlusOrMinus(this BinaryOperatorNode node) + => node.IsPlus() || node.IsMinus(); + + public static Node SwitchSign(this Node node) + => node.Visit(new SwitchSignConcreteNodeVisitor()); + + public static Node SwitchSignForAllSummands(this Node node) + => node.Visit(new SwitchSignForTermsWithinBracketsVisitor()); + + public static Node ResolveMinusSignedNodeContent(this Node node) + => node.Visit(new TransformNodeWithinMinusSignNodeVisitor()); + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBrackets.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBrackets.cs new file mode 100644 index 0000000..5e37d65 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBrackets.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class RemoveBracketsInTermPlusMinusBrackets : Rule + { + protected override bool MatchInternal(Node node, Node parent) + { + return (parent == null || parent is FormulaNode) + && node is BinaryOperatorNode binaryOperatorNode + && binaryOperatorNode.IsPlusOrMinus() + && (binaryOperatorNode.LeftNode is BracketedNode || binaryOperatorNode.RightNode is BracketedNode); + } + + protected override Node RewriteInternal(Node node, Node parent) + { + if ((parent == null || parent is FormulaNode) + && node is BinaryOperatorNode binaryOperatorNode) + { + if (binaryOperatorNode.IsPlus()) + { + if (TryRemoveBrackets(binaryOperatorNode.LeftNode, out Node left) + | TryRemoveBrackets(binaryOperatorNode.RightNode, out Node right)) + { + return new BinaryOperatorNode(binaryOperatorNode.BinaryOperator, left, right); + } + } + + if (binaryOperatorNode.IsMinus()) + { + if (TryRemoveBrackets(binaryOperatorNode.LeftNode, out Node left)) + { + return new BinaryOperatorNode(binaryOperatorNode.BinaryOperator, left, binaryOperatorNode.RightNode); + } + + if (TryRemoveBrackets(binaryOperatorNode.RightNode, out Node right)) + { + return new BinaryOperatorNode(binaryOperatorNode.BinaryOperator, binaryOperatorNode.LeftNode, right.SwitchSignForAllSummands()); + } + } + } + + Debug.Fail("Should not happen"); + return node; + } + + private static bool TryRemoveBrackets(Node node, out Node rewritten) + { + if (node is BracketedNode bracketed) + { + rewritten = bracketed.ChildNode; + return true; + } + + rewritten = node; + return false; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTerm.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTerm.cs new file mode 100644 index 0000000..71132cf --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTerm.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class RemoveBracketsInTermPlusMinusBracketsPlusMinusTerm : Rule + { + protected override bool MatchInternal(Node node, Node parent) + { + return (parent is BinaryOperatorNode parentBinNode + && parentBinNode.IsPlusOrMinus() + && node is BinaryOperatorNode binNode + && binNode.IsPlusOrMinus() + && ((parentBinNode.LeftNode == node + && binNode.RightNode is BracketedNode) + || (parentBinNode.RightNode == node + && binNode.LeftNode is BracketedNode))); + } + + protected override Node RewriteInternal(Node node, Node parent) + { + if (parent is BinaryOperatorNode parentBinNode + && parentBinNode.IsPlusOrMinus() + && node is BinaryOperatorNode binNode + && binNode.IsPlusOrMinus()) + { + if (parentBinNode.LeftNode == binNode && binNode.RightNode is BracketedNode rightBracketed) + { + var rightNode = rightBracketed.ChildNode; + + if (binNode.IsMinus()) + { + rightNode = rightNode.SwitchSignForAllSummands(); + } + + return new BinaryOperatorNode( + binNode.BinaryOperator, + binNode.LeftNode, + rightNode); + } + + if (parentBinNode.RightNode == binNode && binNode.LeftNode is BracketedNode leftBracketed) + { + var leftNode = leftBracketed.ChildNode; + + if (parentBinNode.IsMinus()) + { + leftNode = leftNode.SwitchSignForAllSummands(); + } + + return new BinaryOperatorNode( + binNode.BinaryOperator, + leftNode, + binNode.RightNode); + } + } + + Debug.Fail("Should not happen"); + return node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignFromNumber.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignFromNumber.cs new file mode 100644 index 0000000..6bd9a88 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignFromNumber.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class RemoveNegativeSignFromNumber : Rule + { + protected override bool MatchInternal(Node node, Node Parent) + { + return node is SignedNode signedNode + && signedNode.Sign == Sign.Minus + && (signedNode.Node is DecimalNode || signedNode.Node is IntegerNode); + } + + protected override Node RewriteInternal(Node node, Node Parent) + { + if (node is SignedNode signedNode && signedNode.Sign == Sign.Minus) + { + if (signedNode.Node is DecimalNode dnode) + { + return new DecimalNode(dnode.Value * -1); + } + if (signedNode.Node is IntegerNode inode) + { + return new IntegerNode(inode.Format, inode.Value * -1); + } + } + + Debug.Fail("Should not happen"); + return node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInFrontOfBrackets.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInFrontOfBrackets.cs new file mode 100644 index 0000000..a68fa82 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInFrontOfBrackets.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class RemoveNegativeSignInFrontOfBrackets : Rule + { + protected override bool MatchInternal(Node node, Node parent) + { + if (node is SignedNode signNode + && signNode.Sign == Sign.Minus + && signNode.Node is BracketedNode bracketedNode) + { + return true; + } + + return false; + } + + protected override Node RewriteInternal(Node node, Node parent) + { + if (node is SignedNode signNode && signNode.Sign == Sign.Minus && signNode.Node is BracketedNode bracketedNode) + { + var child = this.Process(bracketedNode.ChildNode, true); + return new BracketedNode(child); + } + + Debug.Fail("Should not happen"); + return node; + } + + private Node Process(Node node, bool isLeftBranch) + { + if (node is BinaryOperatorNode binOp) + { + var left = Process(binOp.LeftNode, isLeftBranch); + var right = Process(binOp.RightNode, false); + + var symbol = binOp.BinaryOperator.Symbol; + var op = symbol == "+" ? BinaryOperator.BySymbol("-") + : symbol == "-" ? BinaryOperator.BySymbol("+") + : binOp.BinaryOperator; + + return new BinaryOperatorNode(op, left, right); + } + + return isLeftBranch ? new SignedNode(Sign.Minus, node) : node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInInSubtract.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInInSubtract.cs new file mode 100644 index 0000000..6f4da1e --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInInSubtract.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class RemoveNegativeSignInInSubtract : Rule + { + protected override bool MatchInternal(Node node, Node Parent) + { + return node is BinaryOperatorNode binOp + && binOp.BinaryOperator.Symbol == "-" + && binOp.RightNode is SignedNode signedNode + && signedNode.Sign == Sign.Minus; + } + + protected override Node RewriteInternal(Node node, Node Parent) + { + if (node is BinaryOperatorNode binOp + && binOp.BinaryOperator.Symbol == "-" + && binOp.RightNode is SignedNode signedNode + && signedNode.Sign == Sign.Minus) + { + return new BinaryOperatorNode( + BinaryOperator.BySymbol("+"), + binOp.LeftNode, + signedNode.Node); + } + + Debug.Fail("Should not happen"); + return node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInInSum.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInInSum.cs new file mode 100644 index 0000000..e617424 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInInSum.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class RemoveNegativeSignInInSum : Rule + { + protected override bool MatchInternal(Node node, Node Parent) + { + return node is BinaryOperatorNode binOp + && binOp.BinaryOperator.Symbol == "+" + && binOp.LeftNode is SignedNode signedNode + && signedNode.Sign == Sign.Minus; + } + + protected override Node RewriteInternal(Node node, Node Parent) + { + if (node is BinaryOperatorNode binOp + && binOp.BinaryOperator.Symbol == "+" + && binOp.LeftNode is SignedNode signedNode + && signedNode.Sign == Sign.Minus) + { + return new BinaryOperatorNode( + BinaryOperator.BySymbol("-"), + binOp.RightNode, + signedNode.Node); + } + + Debug.Fail("Should not happen"); + return node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSign.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSign.cs new file mode 100644 index 0000000..52cf36b --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSign.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class RemoveNegativeSignTimesNegatieSign : Rule + { + protected override bool MatchInternal(Node node, Node Parent) + { + if (node is SignedNode signedNode + && signedNode.Sign == Sign.Minus) + { + var innerNode = signedNode.Node; + + while (true) + { + if (innerNode is SignedNode innersignedNode + && innersignedNode.Sign == Sign.Minus) + { + return true; + } + + if (innerNode is BinaryOperatorNode binNode) + { + innerNode = binNode.LeftNode; + } + else + { + break; + } + } + } + + return false; + } + + protected override Node RewriteInternal(Node node, Node Parent) + { + if (node is SignedNode signedNode + && signedNode.Sign == Sign.Minus) + { + var innerNode = signedNode.Node; + var binNodes = new Stack(); + while (true) + { + if (innerNode is SignedNode innersignedNode + && innersignedNode.Sign == Sign.Minus) + { + var rewrittenNode = innersignedNode.Node; + while (binNodes.Count > 0) + { + var current = binNodes.Pop(); + rewrittenNode = new BinaryOperatorNode(current.BinaryOperator, rewrittenNode, current.RightNode); + } + + return rewrittenNode; + } + + if (innerNode is BinaryOperatorNode binNode) + { + binNodes.Push(binNode); + innerNode = binNode.LeftNode; + } + else + { + break; + } + } + } + + Debug.Fail("Should not happen"); + return node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNestedBrackets.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNestedBrackets.cs new file mode 100644 index 0000000..dd36ec0 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNestedBrackets.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class RemoveNestedBrackets : Rule + { + protected override bool MatchInternal(Node node, Node Parent) + { + return node is BracketedNode outerBrackets + && outerBrackets.ChildNode is BracketedNode; + } + + protected override Node RewriteInternal(Node node, Node Parent) + { + if (node is BracketedNode outerNode && + outerNode.ChildNode is BracketedNode innerNode) + { + return innerNode; + } + + Debug.Fail("Should not happen"); + return node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemovePositiveSign.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemovePositiveSign.cs new file mode 100644 index 0000000..4b88b5a --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemovePositiveSign.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class RemovePositiveSign : Rule + { + protected override bool MatchInternal(Node node, Node Parent) + { + return node is SignedNode signedNode && signedNode.Sign == Sign.Plus; + } + + protected override Node RewriteInternal(Node node, Node Parent) + { + if (node is SignedNode signedNode && signedNode.Sign == Sign.Plus) + { + return signedNode.Node; + } + + Debug.Fail("Should not happen"); + return node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveRootBrackets.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveRootBrackets.cs new file mode 100644 index 0000000..5fc0c77 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveRootBrackets.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class RemoveRootBrackets : Rule + { + protected override bool MatchInternal(Node node, Node parent) + { + return (parent == null || parent is FormulaNode) && node is BracketedNode; + } + + protected override Node RewriteInternal(Node node, Node parent) + { + if ((parent == null || parent is FormulaNode) && node is BracketedNode bracketNode) + { + return bracketNode.ChildNode; + } + + Debug.Fail("Should not happen"); + return node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/Rule.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/Rule.cs index 6a06a0d..97782e9 100644 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/Rule.cs +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/Rule.cs @@ -1,14 +1,32 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Text; using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.Ast.Visitors; namespace ThinkSharp.FormulaParsing.TermRewriting.Rules { public abstract class Rule { - public abstract bool Match(Node node); + public bool Match(Node node, Node parent = null) => this.MatchInternal(node, parent); - public abstract Node Rewrite(Node node); + public Node Rewrite(Node node, Node parent = null) + { + var rewrittenNode = this.RewriteInternal(node, parent); + + var nodeToText = new NodesToTextDebugVisitor(); + + var from = node.Visit(nodeToText); + var to = rewrittenNode.Visit(nodeToText); + + Debug.WriteLine($"Rewrite: '{from}' to '{to}' Type: (${this.GetType()})"); + + return rewrittenNode; + } + + protected abstract bool MatchInternal(Node node, Node parent); + + protected abstract Node RewriteInternal(Node node, Node parent); } } diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermDividesByTermIsOne.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermDividesByTermIsOne.cs index 3dc0e31..f75d50d 100644 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermDividesByTermIsOne.cs +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermDividesByTermIsOne.cs @@ -8,14 +8,14 @@ namespace ThinkSharp.FormulaParsing.TermRewriting.Rules { public class TermDividesByTermIsOne : Rule { - public override bool Match(Node node) + protected override bool MatchInternal(Node node, Node Parent) { if (node is BinaryOperatorNode opNode) { if (opNode.BinaryOperator.Symbol == "+" || opNode.BinaryOperator.Symbol == "-") { - if (opNode.LeftNode is NumberNode leftNumNode) + if (opNode.LeftNode is DecimalNode leftNumNode) { if (leftNumNode.Value == 0.0) { @@ -23,7 +23,7 @@ public override bool Match(Node node) } } - if (opNode.RightNode is NumberNode rightNumNode) + if (opNode.RightNode is DecimalNode rightNumNode) { if (rightNumNode.Value == 0.0) { @@ -36,7 +36,7 @@ public override bool Match(Node node) return false; } - public override Node Rewrite(Node node) + protected override Node RewriteInternal(Node node, Node Parent) { if (node is BinaryOperatorNode opNode) { @@ -45,7 +45,7 @@ public override Node Rewrite(Node node) if (isAddOperation || isSubOperation) { - if (opNode.LeftNode is NumberNode leftNumNode) + if (opNode.LeftNode is DecimalNode leftNumNode) { if (leftNumNode.Value == 0.0) { @@ -55,7 +55,7 @@ public override Node Rewrite(Node node) } } - if (opNode.RightNode is NumberNode rightNumNode) + if (opNode.RightNode is DecimalNode rightNumNode) { if (rightNumNode.Value == 0.0) { diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermPlusOrMinusZeroIsTerm.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermPlusOrMinusZeroIsTerm.cs index 745398d..41f7cd4 100644 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermPlusOrMinusZeroIsTerm.cs +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermPlusOrMinusZeroIsTerm.cs @@ -8,59 +8,39 @@ namespace ThinkSharp.FormulaParsing.TermRewriting.Rules { public class TermPlusOrMinusZeroIsTermRule : Rule { - public override bool Match(Node node) + protected override bool MatchInternal(Node node, Node Parent) { if (node is BinaryOperatorNode opNode) { if (opNode.BinaryOperator.Symbol == "+" || opNode.BinaryOperator.Symbol == "-") { - if (opNode.LeftNode is NumberNode leftNumNode) - { - if (leftNumNode.Value == 0.0) - { - return true; - } - } - - if (opNode.RightNode is NumberNode rightNumNode) - { - if (rightNumNode.Value == 0.0) - { - return true; - } - } + return opNode.LeftNode.EqualsNumber(0) || opNode.RightNode.EqualsNumber(0); } } return false; } - public override Node Rewrite(Node node) + protected override Node RewriteInternal(Node node, Node Parent) { if (node is BinaryOperatorNode opNode) { var isAddOperation = opNode.BinaryOperator.Symbol == "+"; - var isSubOperation = opNode.BinaryOperator.Symbol == "-"; + var isMinusOperation = opNode.BinaryOperator.Symbol == "-"; - if (isAddOperation || isSubOperation) + if (isAddOperation || isMinusOperation) { - if (opNode.LeftNode is NumberNode leftNumNode) + if (opNode.LeftNode.EqualsNumber(0)) { - if (leftNumNode.Value == 0.0) - { - return isSubOperation - ? new SignedNode(Sign.Minus, opNode.RightNode) - : opNode.RightNode; - } + return isMinusOperation + ? new SignedNode(Sign.Minus, opNode.RightNode) + : opNode.RightNode; } - if (opNode.RightNode is NumberNode rightNumNode) + if (opNode.RightNode.EqualsNumber(0)) { - if (rightNumNode.Value == 0.0) - { - return opNode.LeftNode; - } + return opNode.LeftNode; } } } diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTerm.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTerm.cs index da4da89..a240b30 100644 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTerm.cs +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTerm.cs @@ -8,73 +8,43 @@ namespace ThinkSharp.FormulaParsing.TermRewriting.Rules { public class TermTimesOrDividedByMinusOneIsMinusTerm : Rule { - public override bool Match(Node node) + protected override bool MatchInternal(Node node, Node Parent) { if (node is BinaryOperatorNode opNode) { var isTimes = opNode.BinaryOperator.Symbol == "*"; var isDividedBy = opNode.BinaryOperator.Symbol == "/"; - - if (isTimes && opNode.LeftNode is NumberNode leftNumNode) - { - if (leftNumNode.Value == -1.0) - { - return true; - } - } - if ((isTimes || isDividedBy) && opNode.RightNode is NumberNode rightNumNode) - { - if (rightNumNode.Value == -1.0) - { - return true; - } - } + return (isTimes || isDividedBy) && + (opNode.LeftNode.EqualsNumber(-1) || opNode.RightNode.EqualsNumber(-1)); } return false; } - public override Node Rewrite(Node node) + protected override Node RewriteInternal(Node node, Node Parent) { if (node is BinaryOperatorNode opNode) { var isTimes = opNode.BinaryOperator.Symbol == "*"; var isDividedBy = opNode.BinaryOperator.Symbol == "/"; - if (isTimes && opNode.LeftNode is NumberNode leftNumNode) + if (isTimes && opNode.LeftNode.EqualsNumber(-1)) { - if (leftNumNode.Value == -1.0) - { - if (opNode.RightNode is SignedNode rightSignedNode) - { - if (rightSignedNode.Sign == Sign.Minus) - { - return rightSignedNode.Node; - } - return new SignedNode(Sign.Minus, rightSignedNode.Node); - } - - return new SignedNode(Sign.Minus, opNode.RightNode); - } + return opNode.RightNode.SwitchSign(); } - if ((isTimes || isDividedBy) && opNode.RightNode is NumberNode rightNumNode) + if (isDividedBy && opNode.LeftNode.EqualsNumber(-1)) { - if (rightNumNode.Value == -1.0) - { - if (opNode.LeftNode is SignedNode leftSignedNode) - { - if (leftSignedNode.Sign == Sign.Minus) - { - return leftSignedNode.Node; - } - - return new SignedNode(Sign.Minus, leftSignedNode.Node); - } + return new BinaryOperatorNode( + opNode.BinaryOperator, + new IntegerNode(1), + opNode.RightNode.SwitchSign()); + } - return new SignedNode(Sign.Minus, opNode.LeftNode); - } + if ((isTimes || isDividedBy) && opNode.RightNode.EqualsNumber(-1)) + { + return opNode.LeftNode.SwitchSign(); } } diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByOneIsTerm.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByOneIsTerm.cs index fb8da57..0acbdeb 100644 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByOneIsTerm.cs +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByOneIsTerm.cs @@ -8,54 +8,42 @@ namespace ThinkSharp.FormulaParsing.TermRewriting.Rules { public class TermTimesOrDividedByOneIsTerm : Rule { - public override bool Match(Node node) + protected override bool MatchInternal(Node node, Node Parent) { if (node is BinaryOperatorNode opNode) { var isTimes = opNode.BinaryOperator.Symbol == "*"; var isDividedBy = opNode.BinaryOperator.Symbol == "/"; - if (isTimes && opNode.LeftNode is NumberNode leftNumNode) + if (isTimes && opNode.LeftNode.EqualsNumber(1)) { - if (leftNumNode.Value == 1.0) - { - return true; - } + return true; } - if ((isTimes || isDividedBy) && opNode.RightNode is NumberNode rightNumNode) + if ((isTimes || isDividedBy) && opNode.RightNode.EqualsNumber(1)) { - if (rightNumNode.Value == 1.0) - { - return true; - } + return true; } } return false; } - public override Node Rewrite(Node node) + protected override Node RewriteInternal(Node node, Node Parent) { if (node is BinaryOperatorNode opNode) { var isTimes = opNode.BinaryOperator.Symbol == "*"; var isDividedBy = opNode.BinaryOperator.Symbol == "/"; - if (isTimes && opNode.LeftNode is NumberNode leftNumNode) + if (isTimes && opNode.LeftNode.EqualsNumber(1)) { - if (leftNumNode.Value == 1.0) - { - return opNode.RightNode; - } + return opNode.RightNode; } - if ((isTimes || isDividedBy) && opNode.RightNode is NumberNode rightNumNode) + if ((isTimes || isDividedBy) && opNode.RightNode.EqualsNumber(1)) { - if (rightNumNode.Value == 1.0) - { - return opNode.LeftNode; - } + return opNode.LeftNode; } } diff --git a/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs b/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs index 917d651..782c626 100644 --- a/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs +++ b/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs @@ -12,7 +12,20 @@ public class TermRewritingSystem : ITermRewritingSystem public static ITermRewritingSystem Create() { var system = new TermRewritingSystem(); + system.rules.Add(new RemoveBracketsInTermPlusMinusBrackets()); + system.rules.Add(new RemoveBracketsInTermPlusMinusBracketsPlusMinusTerm()); + system.rules.Add(new RemoveNegativeSignFromNumber()); + system.rules.Add(new RemoveNegativeSignInFrontOfBrackets()); + system.rules.Add(new RemoveNegativeSignInInSubtract()); + system.rules.Add(new RemoveNegativeSignInInSum()); + system.rules.Add(new RemoveNegativeSignTimesNegatieSign()); + system.rules.Add(new RemoveNestedBrackets()); + system.rules.Add(new RemovePositiveSign()); + system.rules.Add(new RemoveRootBrackets()); + system.rules.Add(new TermDividesByTermIsOne()); system.rules.Add(new TermPlusOrMinusZeroIsTermRule()); + system.rules.Add(new TermTimesOrDividedByMinusOneIsMinusTerm()); + system.rules.Add(new TermTimesOrDividedByOneIsTerm()); return system; } diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj index bd40e7c..0d4bff1 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj @@ -49,4 +49,8 @@ removed support for alternative hex number notation: '#<hexnumber>'. Note + + + + diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml index c665a74..7e35570 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml @@ -171,6 +171,11 @@ Prevents the usage of hexadecimal notation (e.g. 0x20 = 32) + + + Prevents the usage of octal notation (e.g. 0o10 = 8) + + Prevents the usage of brackets. @@ -487,22 +492,6 @@ The parse tree. - - - Enter a parse tree produced by the Function - labeled alternative in . - The default implementation does nothing. - - The parse tree. - - - - Exit a parse tree produced by the Function - labeled alternative in . - The default implementation does nothing. - - The parse tree. - Enter a parse tree produced by the UnsignedAtom @@ -533,66 +522,114 @@ The parse tree. - + - Enter a parse tree produced by the ScientificNumber + Enter a parse tree produced by the DecimalNumber labeled alternative in . The default implementation does nothing. The parse tree. - + - Exit a parse tree produced by the ScientificNumber + Exit a parse tree produced by the DecimalNumber labeled alternative in . The default implementation does nothing. The parse tree. - + - Enter a parse tree produced by the DecimalNumber + Enter a parse tree produced by the IntgerNumber labeled alternative in . The default implementation does nothing. The parse tree. - + - Exit a parse tree produced by the DecimalNumber + Exit a parse tree produced by the IntgerNumber labeled alternative in . The default implementation does nothing. The parse tree. - + - Enter a parse tree produced by the BinaryNumber - labeled alternative in . + Enter a parse tree produced by the PrefixedDecNumber + labeled alternative in . The default implementation does nothing. The parse tree. - + - Exit a parse tree produced by the BinaryNumber - labeled alternative in . + Exit a parse tree produced by the PrefixedDecNumber + labeled alternative in . The default implementation does nothing. The parse tree. - + - Enter a parse tree produced by the HexadecimalNumber - labeled alternative in . + Enter a parse tree produced by the PrefixedIntNumber + labeled alternative in . The default implementation does nothing. The parse tree. - + - Exit a parse tree produced by the HexadecimalNumber - labeled alternative in . + Exit a parse tree produced by the PrefixedIntNumber + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by the PrefixedBinNumber + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by the PrefixedBinNumber + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by the PrefixedOctNumber + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by the PrefixedOctNumber + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Enter a parse tree produced by the PrefixedHexNumber + labeled alternative in . + The default implementation does nothing. + + The parse tree. + + + + Exit a parse tree produced by the PrefixedHexNumber + labeled alternative in . The default implementation does nothing. The parse tree. @@ -717,9 +754,9 @@ The parse tree. The visitor result. - + - Visit a parse tree produced by the Function + Visit a parse tree produced by the UnsignedAtom labeled alternative in . The default implementation returns the result of calling @@ -729,10 +766,9 @@ The parse tree. The visitor result. - + - Visit a parse tree produced by the UnsignedAtom - labeled alternative in . + Visit a parse tree produced by . The default implementation returns the result of calling on . @@ -741,9 +777,10 @@ The parse tree. The visitor result. - + - Visit a parse tree produced by . + Visit a parse tree produced by the DecimalNumber + labeled alternative in . The default implementation returns the result of calling on . @@ -752,9 +789,9 @@ The parse tree. The visitor result. - + - Visit a parse tree produced by the ScientificNumber + Visit a parse tree produced by the IntgerNumber labeled alternative in . The default implementation returns the result of calling @@ -764,10 +801,10 @@ The parse tree. The visitor result. - + - Visit a parse tree produced by the DecimalNumber - labeled alternative in . + Visit a parse tree produced by the PrefixedDecNumber + labeled alternative in . The default implementation returns the result of calling on . @@ -776,10 +813,10 @@ The parse tree. The visitor result. - + - Visit a parse tree produced by the BinaryNumber - labeled alternative in . + Visit a parse tree produced by the PrefixedIntNumber + labeled alternative in . The default implementation returns the result of calling on . @@ -788,10 +825,34 @@ The parse tree. The visitor result. - + - Visit a parse tree produced by the HexadecimalNumber - labeled alternative in . + Visit a parse tree produced by the PrefixedBinNumber + labeled alternative in . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the PrefixedOctNumber + labeled alternative in . + + The default implementation returns the result of calling + on . + + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the PrefixedHexNumber + labeled alternative in . The default implementation returns the result of calling on . @@ -904,20 +965,6 @@ The parse tree. - - - Enter a parse tree produced by the Function - labeled alternative in . - - The parse tree. - - - - Exit a parse tree produced by the Function - labeled alternative in . - - The parse tree. - Enter a parse tree produced by the UnsignedAtom @@ -944,59 +991,101 @@ The parse tree. - + - Enter a parse tree produced by the ScientificNumber + Enter a parse tree produced by the DecimalNumber labeled alternative in . The parse tree. - + - Exit a parse tree produced by the ScientificNumber + Exit a parse tree produced by the DecimalNumber labeled alternative in . The parse tree. - + - Enter a parse tree produced by the DecimalNumber + Enter a parse tree produced by the IntgerNumber labeled alternative in . The parse tree. - + - Exit a parse tree produced by the DecimalNumber + Exit a parse tree produced by the IntgerNumber labeled alternative in . The parse tree. - + - Enter a parse tree produced by the BinaryNumber - labeled alternative in . + Enter a parse tree produced by the PrefixedDecNumber + labeled alternative in . The parse tree. - + - Exit a parse tree produced by the BinaryNumber - labeled alternative in . + Exit a parse tree produced by the PrefixedDecNumber + labeled alternative in . The parse tree. - + - Enter a parse tree produced by the HexadecimalNumber - labeled alternative in . + Enter a parse tree produced by the PrefixedIntNumber + labeled alternative in . The parse tree. - + - Exit a parse tree produced by the HexadecimalNumber - labeled alternative in . + Exit a parse tree produced by the PrefixedIntNumber + labeled alternative in . + + The parse tree. + + + + Enter a parse tree produced by the PrefixedBinNumber + labeled alternative in . + + The parse tree. + + + + Exit a parse tree produced by the PrefixedBinNumber + labeled alternative in . + + The parse tree. + + + + Enter a parse tree produced by the PrefixedOctNumber + labeled alternative in . + + The parse tree. + + + + Exit a parse tree produced by the PrefixedOctNumber + labeled alternative in . + + The parse tree. + + + + Enter a parse tree produced by the PrefixedHexNumber + labeled alternative in . + + The parse tree. + + + + Exit a parse tree produced by the PrefixedHexNumber + labeled alternative in . The parse tree. @@ -1075,14 +1164,6 @@ The parse tree. The visitor result. - - - Visit a parse tree produced by the Function - labeled alternative in . - - The parse tree. - The visitor result. - Visit a parse tree produced by the UnsignedAtom @@ -1098,34 +1179,58 @@ The parse tree. The visitor result. - + - Visit a parse tree produced by the ScientificNumber + Visit a parse tree produced by the DecimalNumber labeled alternative in . The parse tree. The visitor result. - + - Visit a parse tree produced by the DecimalNumber + Visit a parse tree produced by the IntgerNumber labeled alternative in . The parse tree. The visitor result. - + - Visit a parse tree produced by the BinaryNumber - labeled alternative in . + Visit a parse tree produced by the PrefixedDecNumber + labeled alternative in . The parse tree. The visitor result. - + - Visit a parse tree produced by the HexadecimalNumber - labeled alternative in . + Visit a parse tree produced by the PrefixedIntNumber + labeled alternative in . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the PrefixedBinNumber + labeled alternative in . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the PrefixedOctNumber + labeled alternative in . + + The parse tree. + The visitor result. + + + + Visit a parse tree produced by the PrefixedHexNumber + labeled alternative in . The parse tree. The visitor result. diff --git a/ThinkSharp.FormulaParser/Utils/EnumerableExtensions.cs b/ThinkSharp.FormulaParser/Utils/EnumerableExtensions.cs new file mode 100644 index 0000000..c1c8df8 --- /dev/null +++ b/ThinkSharp.FormulaParser/Utils/EnumerableExtensions.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ThinkSharp.FormulaParsing.Utils +{ + internal static class EnumerableExtensions + { + public static IEnumerable WrapFirst(this IEnumerable items, Func projection) + { + bool isFirst = true; + foreach(var item in items) + { + yield return isFirst ? projection(item) : item; + isFirst = false; + } + } + } +} diff --git a/ThinkSharp.FormulaParser/Utils/NodeComparer.cs b/ThinkSharp.FormulaParser/Utils/NodeComparer.cs new file mode 100644 index 0000000..cb99ca3 --- /dev/null +++ b/ThinkSharp.FormulaParser/Utils/NodeComparer.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.Utils +{ + public class NodeComparer : IEqualityComparer + { + private static NodeHashCodeVisitor hashCodeVisitor = new NodeHashCodeVisitor(); + + public bool Equals(Node x, Node y) + { + if (x.GetType() != y.GetType()) + { + return false; + } + else if (x is DecimalNode d1 && y is DecimalNode d2) + { + return d1.Value == d2.Value; + } + else if (x is IntegerNode i1 && y is IntegerNode i2) + { + return i1.Value == i2.Value; + } + else if (x is VariableNode v1 && y is VariableNode v2) + { + return v1.Name == v2.Name; + } + else if (x is ConstantNode c1 && y is ConstantNode c2) + { + return c1.Name == c2.Name; + } + else if (x is PowerNode p1 && y is PowerNode p2) + { + return Equals(p1.BaseNode, p2.BaseNode) + && Equals(p1.ExponentNode, p2.ExponentNode); + } + else if (x is SignedNode s1 && y is SignedNode s2) + { + return s1.Sign == s2.Sign + && Equals(s1.Node, s2.Node); + } + else if (x is FormulaNode f1 && y is FormulaNode f2) + { + return Equals(f1.ChildNode, f2.ChildNode); + } + else if (x is FunctionNode fun1 && y is FunctionNode fun2) + { + if (fun1.FunctionName != fun2.FunctionName) + { + return false; + } + + var fun1Args = fun1.Parameters.ToArray(); + var fun2Args = fun2.Parameters.ToArray(); + + if (fun1Args.Length != fun2Args.Length) + { + return false; + } + + for (int i = 0; i < fun1Args.Length; i++) + { + if (!Equals(fun1Args[i], fun2Args[i])) + { + return false; + } + + return true; + } + } + else if (x is BracketedNode b1 && y is BracketedNode b2) + { + return Equals(b1.ChildNode, b2.ChildNode); + } + else if (x is BinaryOperatorNode bo1 && y is BinaryOperatorNode bo2) + { + switch (bo1.BinaryOperator.Symbol) + { + case "/": + if (bo1.BinaryOperator != bo2.BinaryOperator) + return false; + return Equals(bo1.LeftNode, bo2.LeftNode) && Equals(bo1.RightNode, bo2.RightNode); + case "*": + if (bo1.BinaryOperator != bo2.BinaryOperator) + return false; + var checkLLRR = Equals(bo1.LeftNode, bo2.LeftNode) && Equals(bo1.RightNode, bo2.RightNode); + var checkLRRL = Equals(bo1.LeftNode, bo2.RightNode) && Equals(bo1.RightNode, bo2.LeftNode); + return checkLLRR || checkLRRL; + case "-": + case "+": + var isMinus = bo1.BinaryOperator.Symbol == "-"; + + var summands1Left = GetSummands(bo1.LeftNode); + var summands1Right = GetSummands(bo1.RightNode); + if (isMinus) summands1Right = summands1Right.WrapFirst(n => new SignedNode(Sign.Minus, n)); + var summands1 = summands1Left.Concat(summands1Right).ToList(); + + var summands2Left = GetSummands(bo2.LeftNode); + var summands2Right = GetSummands(bo2.RightNode); + if (isMinus) summands2Right = summands2Right.WrapFirst(n => new SignedNode(Sign.Minus, n)); + var summands2 = summands2Left.Concat(summands2Right).ToList(); + + if (summands1.Count != summands2.Count) + { + return false; + } + + for (int i = 0; i < summands1.Count; i++) + { + var summand1 = summands1[i]; + var found = false; + for (int j = 0; j < summands2.Count; j++) + { + var summand2 = summands2[j]; + if (Equals(summand1, summand2)) + { + found = true; + summands2.Remove(summand2); + break; + } + } + if (!found) + { + return false; + } + } + return true; + + default: + throw new InvalidOperationException($"Unknown binary operator: {bo1.BinaryOperator.Symbol}."); + } + } + + Debug.Fail($"Node types not handled for comparison: {x.GetType()}"); + return false; + } + + private IEnumerable GetSummands(Node node) + { + if (node is BinaryOperatorNode bonPlus && bonPlus.BinaryOperator.Symbol == "+") + { + foreach (var subSummand in GetSummands(bonPlus.LeftNode)) + yield return subSummand; + foreach (var subSummand in GetSummands(bonPlus.RightNode)) + yield return subSummand; + } + else if (node is BinaryOperatorNode bonMinus && bonMinus.BinaryOperator.Symbol == "-") + { + foreach (var subSummand in GetSummands(bonMinus.LeftNode)) + yield return subSummand; + foreach (var subSummand in GetSummands(bonMinus.RightNode).WrapFirst(n => new SignedNode(Sign.Minus, n))) + yield return subSummand; + } + else + { + yield return node; + } + } + + public int GetHashCode(Node node) => node.Visit(hashCodeVisitor); + } +} diff --git a/ThinkSharp.FormulaParser/Utils/NodeHashCodeVisitor.cs b/ThinkSharp.FormulaParser/Utils/NodeHashCodeVisitor.cs new file mode 100644 index 0000000..7fa67c5 --- /dev/null +++ b/ThinkSharp.FormulaParser/Utils/NodeHashCodeVisitor.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.Ast.Visitors; + +namespace ThinkSharp.FormulaParsing.Utils +{ + public class NodeHashCodeVisitor : INodeVisitor + { + private static int formulaHash = "formula".GetHashCode(); + private static int bracketsHash = "()".GetHashCode(); + private static int powHash = "pow".GetHashCode(); + public int Visit(FormulaNode node) => formulaHash ^ node.ChildNode.Visit(this); + + public int Visit(BracketedNode node) => bracketsHash.GetHashCode() ^ node.ChildNode.Visit(this); + + public int Visit(VariableNode node) => node.Name.GetHashCode(); + + public int Visit(ConstantNode node) => node.Name.GetHashCode(); + + public int Visit(BinaryOperatorNode node) + => node.BinaryOperator.Symbol.GetHashCode() ^ node.LeftNode.Visit(this) ^ node.RightNode.Visit(this); + public int Visit(PowerNode node) + => powHash.GetHashCode() ^ node.BaseNode.Visit(this) ^ node.ExponentNode.Visit(this); + + public int Visit(SignedNode node) + => node.Sign.GetHashCode() ^ node.Node.Visit(this); + + public int Visit(FunctionNode node) + => node.Parameters.Select(n => n.Visit(this)).Aggregate(node.FunctionName.GetHashCode(), (x, y) => x ^ y); + + public int Visit(DecimalNode node) + => node.Value.GetHashCode(); + + public int Visit(IntegerNode node) + => node.Value.GetHashCode(); + } +} From 3a2de0aa6b1807cde382ab4f1fb8b0ca9555198a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Mon, 4 Nov 2019 08:20:36 +0100 Subject: [PATCH 30/45] Improved BinaryOperator Added term rewriting rule "Evaluate Integers" --- .../Rules/EvaluateIntegersTest.cs | 44 +++++++++++++++++++ .../RemoveNegativeSignTimesNegatieSignTest.cs | 4 +- .../TermRewriting/TermWritingSystemTest.cs | 2 +- ...nkSharp.FluentFormulaParser.Test.projitems | 3 +- .../Ast/Nodes/BinaryOperator.cs | 27 +++++++----- .../TermRewriting/Rules/EvaluateIntegers.cs | 34 ++++++++++++++ .../TermRewriting/Rules/NodeExtensions.cs | 8 ++++ .../TermRewriting/TermRewritingSystem.cs | 2 +- .../ThinkSharp.FormulaParser.csproj | 6 +-- 9 files changed, 112 insertions(+), 18 deletions(-) create mode 100644 ThinkSharp.FormulaParser.Test/TermRewriting/Rules/EvaluateIntegersTest.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/EvaluateIntegers.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/EvaluateIntegersTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/EvaluateIntegersTest.cs new file mode 100644 index 0000000..f80af1c --- /dev/null +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/EvaluateIntegersTest.cs @@ -0,0 +1,44 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; +using ThinkSharp.FormulaParsing.Test; + +namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules +{ + [TestClass] + public class EvaluateIntegersTest : RuleTest + { + protected override Rule CreateRule() => new EvaluateIntegers(); + + [TestMethod] + public void Test_TenPlusTen () => AssertRewritten( + new IntegerNode(20), + new BinaryOperatorNode( + BinaryOperator.Plus, + new IntegerNode(10), + new IntegerNode(10))); + + [TestMethod] + public void Test_TenMinusTen() => AssertRewritten( + new IntegerNode(0), + new BinaryOperatorNode( + BinaryOperator.Minus, + new IntegerNode(10), + new IntegerNode(10))); + + [TestMethod] + public void Test_TenTimesTen() => AssertRewritten( + new IntegerNode(100), + new BinaryOperatorNode( + BinaryOperator.Multiply, + new IntegerNode(10), + new IntegerNode(10))); + + [TestMethod] + public void Test_TenDividedByTen() => AssertNotMatching("10/10"); + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs index 7f61f6d..b28b420 100644 --- a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs @@ -36,12 +36,12 @@ public void Test_MinusMinusAPlusB() => AssertRewritten( [TestMethod] public void Test_MinusMinusATimesB() => AssertRewritten( new BinaryOperatorNode( - BinaryOperator.Times, + BinaryOperator.Multiply, new VariableNode("a"), new VariableNode("b")), new SignedNode(Sign.Minus, new BinaryOperatorNode( - BinaryOperator.Times, + BinaryOperator.Multiply, new SignedNode(Sign.Minus, new VariableNode("a")), new VariableNode("b")))); } diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/TermWritingSystemTest.cs b/ThinkSharp.FormulaParser.Test/TermRewriting/TermWritingSystemTest.cs index 6c8775c..5dfdda6 100644 --- a/ThinkSharp.FormulaParser.Test/TermRewriting/TermWritingSystemTest.cs +++ b/ThinkSharp.FormulaParser.Test/TermRewriting/TermWritingSystemTest.cs @@ -34,7 +34,7 @@ public class TermWritingSystemTest public void Test_ATimeBTimeCInBrackets() => AssertRewritten("-a*b*c", "-(a*b*c)"); [TestMethod] - public void Test_ATimeBMinusCInBracketsPlus3Times4() => AssertRewritten("-a*b+c+3*4", "-(a*b-c)+3*4"); + public void Test_ATimeBMinusCInBracketsPlus3Times4() => AssertRewritten("-a*b+c+12", "-(a*b-c)+3*4"); [TestMethod] public void Test_MaxOneTwoInBackets() => AssertRewritten("-max(1, 2)", "-(max(1, 2))"); diff --git a/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems b/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems index 86241f1..20d47dd 100644 --- a/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems +++ b/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems @@ -23,8 +23,9 @@ - + + diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/BinaryOperator.cs b/ThinkSharp.FormulaParser/Ast/Nodes/BinaryOperator.cs index d22c558..2d2fad5 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/BinaryOperator.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/BinaryOperator.cs @@ -6,34 +6,39 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { public sealed class BinaryOperator { - readonly Func evaluation; + private readonly Func evaluationDouble; + private readonly Func evaluationInt; private static readonly BinaryOperator[] allBinaryOperators; public static BinaryOperator Plus { get; } public static BinaryOperator Minus { get; } - public static BinaryOperator Times { get; } + public static BinaryOperator Multiply { get; } public static BinaryOperator DividedBy { get; } static BinaryOperator() { - Plus = new BinaryOperator("+", (x, y) => x + y); - Minus = new BinaryOperator("-", (x, y) => x - y); - Times = new BinaryOperator("*", (x, y) => x * y); - DividedBy = new BinaryOperator("/", (x, y) => x / y); + Plus = new BinaryOperator("+", (x, y) => x + y, (x, y) => x + y); + Minus = new BinaryOperator("-", (x, y) => x - y, (x, y) => x - y); + Multiply = new BinaryOperator("*", (x, y) => x * y, (x, y) => x * y); + DividedBy = new BinaryOperator("/", (x, y) => x / y, (x, y) => x / y); allBinaryOperators = new[] { Plus, Minus, - Times, + Multiply, DividedBy }; } - private BinaryOperator(string symbol, Func evaluation) + private BinaryOperator(string symbol, + Func evaluateDouble, + Func evaluateInt) { this.Symbol = symbol; - this.evaluation = evaluation; + this.evaluationDouble = evaluateDouble; + this.evaluationInt = evaluateInt; +; } public string Symbol { get; } @@ -41,6 +46,8 @@ private BinaryOperator(string symbol, Func evaluation) public static BinaryOperator BySymbol(string symbol) => allBinaryOperators.FirstOrDefault(o => o.Symbol == symbol) ?? throw new InvalidOperationException($"Unknonw binary operator symbol '{0}'."); - public double Evaluate(double left, double right) => this.evaluation(left, right); + public double Evaluate(double left, double right) => this.evaluationDouble(left, right); + + public long Evaluate(long left, long right) => this.evaluationInt(left, right); } } diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/EvaluateIntegers.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/EvaluateIntegers.cs new file mode 100644 index 0000000..8ea3e82 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/EvaluateIntegers.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class EvaluateIntegers : Rule + { + protected override bool MatchInternal(Node node, Node parent) + { + return node is BinaryOperatorNode binOpNode + && (binOpNode.IsPlusOrMinus() || binOpNode.IsMultipy()) + && binOpNode.LeftNode is IntegerNode + && binOpNode.RightNode is IntegerNode; + } + + protected override Node RewriteInternal(Node node, Node parent) + { + if (node is BinaryOperatorNode binOpNode + && (binOpNode.IsPlusOrMinus() || binOpNode.IsMultipy()) + && binOpNode.LeftNode is IntegerNode leftInt + && binOpNode.RightNode is IntegerNode rightInt) + { + var value = binOpNode.BinaryOperator.Evaluate(leftInt.Value, rightInt.Value); + return new IntegerNode(NumberFormat.Dec, value); + } + + Debug.Fail("Should not happen"); + return node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/NodeExtensions.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/NodeExtensions.cs index 4a9177d..d4ac9bc 100644 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/NodeExtensions.cs +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/NodeExtensions.cs @@ -82,10 +82,18 @@ public static bool IsPlus(this BinaryOperatorNode node) public static bool IsMinus(this BinaryOperatorNode node) => node.BinaryOperator.Symbol == "-"; + public static bool IsMultipy(this BinaryOperatorNode node) + => node.BinaryOperator.Symbol == "*"; + + public static bool IsDividedBy(this BinaryOperatorNode node) + => node.BinaryOperator.Symbol == "/"; public static bool IsPlusOrMinus(this BinaryOperatorNode node) => node.IsPlus() || node.IsMinus(); + public static bool IsMultiplyOrDividedBy(this BinaryOperatorNode node) + => node.IsMultipy() || node.IsDividedBy(); + public static Node SwitchSign(this Node node) => node.Visit(new SwitchSignConcreteNodeVisitor()); diff --git a/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs b/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs index 782c626..993ad3e 100644 --- a/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs +++ b/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using ThinkSharp.FormulaParsing.Ast.Nodes; using ThinkSharp.FormulaParsing.TermRewriting.Rules; @@ -12,6 +11,7 @@ public class TermRewritingSystem : ITermRewritingSystem public static ITermRewritingSystem Create() { var system = new TermRewritingSystem(); + system.rules.Add(new EvaluateIntegers()); system.rules.Add(new RemoveBracketsInTermPlusMinusBrackets()); system.rules.Add(new RemoveBracketsInTermPlusMinusBracketsPlusMinusTerm()); system.rules.Add(new RemoveNegativeSignFromNumber()); diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj index 0d4bff1..57fcc87 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj @@ -9,8 +9,8 @@ ThinkSharp A formula parser with fluent API that allows parsing and evaluation of mathematically formulas. Features: functions, constants, variables, scientific numbers, focus on customization and flexibility. © 2019 Jan-Niklas Schäfer - 0.5.0.0 - 0.5.0.0 + 0.6.1.0 + 0.6.1.0 LICENSE.txt changed variables API from IDictionary to IReadOnlyDictionary added '$' as valid character for variables @@ -18,7 +18,7 @@ removed support for alternative hex number notation: '#<hexnumber>'. Note https://github.com/JanDotNet/ThinkSharp.FormulaParser true - 0.5.0 + 0.6.1 From 19271f60b0c26f0dfbe35cfa263a747b862c19b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Thu, 7 Nov 2019 09:09:07 +0100 Subject: [PATCH 31/45] removed shared test and .net 46 test projects added rearrabge integers in sum --- .../AST/ParsingHelperTest.cs | 0 .../BinaryOperatorTest.cs | 0 .../FormulaParserTest.cs | 0 .../FormularParser.Configuration.Test.cs | 0 .../FormularParser.CustomVisitor.Test.cs | 0 .../FormularParser.NumberFormats.Test.cs | 0 .../FormularParser.ParsingBehavior.Test.cs | 0 .../FormularParser.SupportedFeatures.Test.cs | 0 .../FormularParser.VariableNames.Test.cs | 0 .../NodesToFormulaTextVisitor.cs | 0 .../Rules/EvaluateIntegersTest.cs | 0 .../Rules/RearrangeIntegersInSumTest.cs | 32 +++++ ...nTermPlusMinusBracketsPlusMinusTermTest.cs | 0 ...moveBracketsInTermPlusMinusBracketsTest.cs | 0 .../Rules/RemoveNegativSignFromNumberTest.cs | 0 ...RemoveNegativeSignInFrontOfBracketsTest.cs | 0 .../RemoveNegativeSignInInSubtractTest.cs | 0 .../Rules/RemoveNegativeSignInInSumTest.cs | 0 .../RemoveNegativeSignTimesNegatieSignTest.cs | 0 .../Rules/RemoveNestedBracketsTest.cs | 0 .../Rules/RemovePositiveSignTest.cs | 0 .../Rules/RemoveRootBracketsTest.cs | 0 .../TermRewriting/Rules/RuleTest.cs | 0 .../Rules/TermPlusOrMinusZeroIsTermTest.cs | 0 ...TimesOrDividedByMinusOneIsMinusTermTest.cs | 0 .../TermTimesOrDividedByOneIsTermTest.cs | 0 .../TermRewriting/TermWritingSystemTest.cs | 5 +- .../ThinkSharp.FormulaParser.Test.Core.csproj | 2 - .../Utils/BinaryOperatorTest.cs | 0 .../Properties/AssemblyInfo.cs | 20 --- ...hinkSharp.FormulaParser.Test.Net461.csproj | 78 ----------- .../packages.config | 6 - ...nkSharp.FluentFormulaParser.Test.projitems | 40 ------ .../ThinkSharp.FormulaParser.Test.shproj | 13 -- ThinkSharp.FormulaParser.sln | 12 -- .../Ast/Visitors/TransformNodesVisitor.cs | 100 +++++++++++++++ .../Rules/RearrangeIntegersInSum.cs | 121 ++++++++++++++++++ .../TermRewriting/TermRewritingSystem.cs | 1 + .../ThinkSharp.FormulaParser.csproj | 6 +- 39 files changed, 261 insertions(+), 175 deletions(-) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/AST/ParsingHelperTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/BinaryOperatorTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/FormulaParserTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/FormularParser.Configuration.Test.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/FormularParser.CustomVisitor.Test.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/FormularParser.NumberFormats.Test.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/FormularParser.ParsingBehavior.Test.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/FormularParser.SupportedFeatures.Test.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/FormularParser.VariableNames.Test.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/NodesToFormulaTextVisitor.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/TermRewriting/Rules/EvaluateIntegersTest.cs (100%) create mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RearrangeIntegersInSumTest.cs rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTermTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/TermRewriting/Rules/RemoveNegativSignFromNumberTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/TermRewriting/Rules/RemoveNegativeSignInFrontOfBracketsTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/TermRewriting/Rules/RemoveNegativeSignInInSubtractTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/TermRewriting/Rules/RemoveNegativeSignInInSumTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/TermRewriting/Rules/RemoveNestedBracketsTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/TermRewriting/Rules/RemovePositiveSignTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/TermRewriting/Rules/RemoveRootBracketsTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/TermRewriting/Rules/RuleTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/TermRewriting/Rules/TermPlusOrMinusZeroIsTermTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTermTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/TermRewriting/Rules/TermTimesOrDividedByOneIsTermTest.cs (100%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/TermRewriting/TermWritingSystemTest.cs (97%) rename {ThinkSharp.FormulaParser.Test => ThinkSharp.FormulaParser.Test.Core}/Utils/BinaryOperatorTest.cs (100%) delete mode 100644 ThinkSharp.FormulaParser.Test.Net461/Properties/AssemblyInfo.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Net461/ThinkSharp.FormulaParser.Test.Net461.csproj delete mode 100644 ThinkSharp.FormulaParser.Test.Net461/packages.config delete mode 100644 ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems delete mode 100644 ThinkSharp.FormulaParser.Test/ThinkSharp.FormulaParser.Test.shproj create mode 100644 ThinkSharp.FormulaParser/Ast/Visitors/TransformNodesVisitor.cs create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RearrangeIntegersInSum.cs diff --git a/ThinkSharp.FormulaParser.Test/AST/ParsingHelperTest.cs b/ThinkSharp.FormulaParser.Test.Core/AST/ParsingHelperTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/AST/ParsingHelperTest.cs rename to ThinkSharp.FormulaParser.Test.Core/AST/ParsingHelperTest.cs diff --git a/ThinkSharp.FormulaParser.Test/BinaryOperatorTest.cs b/ThinkSharp.FormulaParser.Test.Core/BinaryOperatorTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/BinaryOperatorTest.cs rename to ThinkSharp.FormulaParser.Test.Core/BinaryOperatorTest.cs diff --git a/ThinkSharp.FormulaParser.Test/FormulaParserTest.cs b/ThinkSharp.FormulaParser.Test.Core/FormulaParserTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/FormulaParserTest.cs rename to ThinkSharp.FormulaParser.Test.Core/FormulaParserTest.cs diff --git a/ThinkSharp.FormulaParser.Test/FormularParser.Configuration.Test.cs b/ThinkSharp.FormulaParser.Test.Core/FormularParser.Configuration.Test.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/FormularParser.Configuration.Test.cs rename to ThinkSharp.FormulaParser.Test.Core/FormularParser.Configuration.Test.cs diff --git a/ThinkSharp.FormulaParser.Test/FormularParser.CustomVisitor.Test.cs b/ThinkSharp.FormulaParser.Test.Core/FormularParser.CustomVisitor.Test.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/FormularParser.CustomVisitor.Test.cs rename to ThinkSharp.FormulaParser.Test.Core/FormularParser.CustomVisitor.Test.cs diff --git a/ThinkSharp.FormulaParser.Test/FormularParser.NumberFormats.Test.cs b/ThinkSharp.FormulaParser.Test.Core/FormularParser.NumberFormats.Test.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/FormularParser.NumberFormats.Test.cs rename to ThinkSharp.FormulaParser.Test.Core/FormularParser.NumberFormats.Test.cs diff --git a/ThinkSharp.FormulaParser.Test/FormularParser.ParsingBehavior.Test.cs b/ThinkSharp.FormulaParser.Test.Core/FormularParser.ParsingBehavior.Test.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/FormularParser.ParsingBehavior.Test.cs rename to ThinkSharp.FormulaParser.Test.Core/FormularParser.ParsingBehavior.Test.cs diff --git a/ThinkSharp.FormulaParser.Test/FormularParser.SupportedFeatures.Test.cs b/ThinkSharp.FormulaParser.Test.Core/FormularParser.SupportedFeatures.Test.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/FormularParser.SupportedFeatures.Test.cs rename to ThinkSharp.FormulaParser.Test.Core/FormularParser.SupportedFeatures.Test.cs diff --git a/ThinkSharp.FormulaParser.Test/FormularParser.VariableNames.Test.cs b/ThinkSharp.FormulaParser.Test.Core/FormularParser.VariableNames.Test.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/FormularParser.VariableNames.Test.cs rename to ThinkSharp.FormulaParser.Test.Core/FormularParser.VariableNames.Test.cs diff --git a/ThinkSharp.FormulaParser.Test/NodesToFormulaTextVisitor.cs b/ThinkSharp.FormulaParser.Test.Core/NodesToFormulaTextVisitor.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/NodesToFormulaTextVisitor.cs rename to ThinkSharp.FormulaParser.Test.Core/NodesToFormulaTextVisitor.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/EvaluateIntegersTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/EvaluateIntegersTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/TermRewriting/Rules/EvaluateIntegersTest.cs rename to ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/EvaluateIntegersTest.cs diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RearrangeIntegersInSumTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RearrangeIntegersInSumTest.cs new file mode 100644 index 0000000..82619f4 --- /dev/null +++ b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RearrangeIntegersInSumTest.cs @@ -0,0 +1,32 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; +using ThinkSharp.FormulaParsing.Test; + +namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules +{ + [TestClass] + public class RearrangeIntegersInSumTest : RuleTest + { + protected override Rule CreateRule() => new RearrangeIntegersInSum(); + + [TestMethod] + public void Test_A() => this.AssertNotMatching("a"); + + [TestMethod] + public void Test_TenPlusAPlusTen () => AssertRewritten("10+10+a", "10+a+10"); + + [TestMethod] + public void Test_TenPlusAMinusTen() => AssertRewritten("10+-10+a", "10+a-10"); + + [TestMethod] + public void Test_TenMinusAMinusTen() => AssertRewritten("10+-10-a", "10-a-10"); + + [TestMethod] + public void Test_LongChain() => AssertRewritten("a+b+20+10+d+e+f+g+h+j+k+l", "a+b+10+d+e+f+g+h+j+k+l+20"); + } +} diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTermTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTermTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTermTest.cs rename to ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTermTest.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsTest.cs rename to ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsTest.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativSignFromNumberTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativSignFromNumberTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativSignFromNumberTest.cs rename to ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativSignFromNumberTest.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInFrontOfBracketsTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInFrontOfBracketsTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInFrontOfBracketsTest.cs rename to ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInFrontOfBracketsTest.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInInSubtractTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInInSubtractTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInInSubtractTest.cs rename to ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInInSubtractTest.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInInSumTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInInSumTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignInInSumTest.cs rename to ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInInSumTest.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs rename to ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNestedBracketsTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNestedBracketsTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveNestedBracketsTest.cs rename to ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNestedBracketsTest.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemovePositiveSignTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemovePositiveSignTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemovePositiveSignTest.cs rename to ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemovePositiveSignTest.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveRootBracketsTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveRootBracketsTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RemoveRootBracketsTest.cs rename to ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveRootBracketsTest.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RuleTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RuleTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/TermRewriting/Rules/RuleTest.cs rename to ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RuleTest.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermPlusOrMinusZeroIsTermTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermPlusOrMinusZeroIsTermTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermPlusOrMinusZeroIsTermTest.cs rename to ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermPlusOrMinusZeroIsTermTest.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTermTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTermTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTermTest.cs rename to ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTermTest.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermTimesOrDividedByOneIsTermTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermTimesOrDividedByOneIsTermTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/TermRewriting/Rules/TermTimesOrDividedByOneIsTermTest.cs rename to ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermTimesOrDividedByOneIsTermTest.cs diff --git a/ThinkSharp.FormulaParser.Test/TermRewriting/TermWritingSystemTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/TermWritingSystemTest.cs similarity index 97% rename from ThinkSharp.FormulaParser.Test/TermRewriting/TermWritingSystemTest.cs rename to ThinkSharp.FormulaParser.Test.Core/TermRewriting/TermWritingSystemTest.cs index 5dfdda6..443e7a0 100644 --- a/ThinkSharp.FormulaParser.Test/TermRewriting/TermWritingSystemTest.cs +++ b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/TermWritingSystemTest.cs @@ -74,7 +74,10 @@ public class TermWritingSystemTest [TestMethod] public void Test_AManyTimeOneTimeADividedByOne() => AssertRewritten("a*a", "a*1*1*1*1*1*a/1"); - + + [TestMethod] + public void Test_TwoPluscPlus2() => AssertRewritten("4+c", "2+c+2"); + private void AssertRewritten(string expected, string forumla) { diff --git a/ThinkSharp.FormulaParser.Test.Core/ThinkSharp.FormulaParser.Test.Core.csproj b/ThinkSharp.FormulaParser.Test.Core/ThinkSharp.FormulaParser.Test.Core.csproj index 12c1dd4..45bdf51 100644 --- a/ThinkSharp.FormulaParser.Test.Core/ThinkSharp.FormulaParser.Test.Core.csproj +++ b/ThinkSharp.FormulaParser.Test.Core/ThinkSharp.FormulaParser.Test.Core.csproj @@ -19,7 +19,5 @@ - - diff --git a/ThinkSharp.FormulaParser.Test/Utils/BinaryOperatorTest.cs b/ThinkSharp.FormulaParser.Test.Core/Utils/BinaryOperatorTest.cs similarity index 100% rename from ThinkSharp.FormulaParser.Test/Utils/BinaryOperatorTest.cs rename to ThinkSharp.FormulaParser.Test.Core/Utils/BinaryOperatorTest.cs diff --git a/ThinkSharp.FormulaParser.Test.Net461/Properties/AssemblyInfo.cs b/ThinkSharp.FormulaParser.Test.Net461/Properties/AssemblyInfo.cs deleted file mode 100644 index 8eb43f5..0000000 --- a/ThinkSharp.FormulaParser.Test.Net461/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("ThinkSharp.FormulaParser.Test")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("ThinkSharp.FormulaParser")] -[assembly: AssemblyCopyright("Copyright © 2019 Jan-Niklas Schäfer")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: Guid("3bc319a0-e6a2-4667-a7e8-8c283acda823")] - -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ThinkSharp.FormulaParser.Test.Net461/ThinkSharp.FormulaParser.Test.Net461.csproj b/ThinkSharp.FormulaParser.Test.Net461/ThinkSharp.FormulaParser.Test.Net461.csproj deleted file mode 100644 index 9cfbf5f..0000000 --- a/ThinkSharp.FormulaParser.Test.Net461/ThinkSharp.FormulaParser.Test.Net461.csproj +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - Debug - AnyCPU - {3BC319A0-E6A2-4667-A7E8-8C283ACDA823} - Library - Properties - ThinkSharp.FormulaParsing.Test - ThinkSharp.FormulaParser.Test - v4.6.1 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 15.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\packages\Antlr4.Runtime.Standard.4.7.2\lib\net35\Antlr4.Runtime.Standard.dll - - - ..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll - - - ..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll - - - - - - - - - - - - - {c69728f7-cdc0-4fa2-b805-e0dd6f498e9f} - ThinkSharp.FormulaParser - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - \ No newline at end of file diff --git a/ThinkSharp.FormulaParser.Test.Net461/packages.config b/ThinkSharp.FormulaParser.Test.Net461/packages.config deleted file mode 100644 index b24600c..0000000 --- a/ThinkSharp.FormulaParser.Test.Net461/packages.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems b/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems deleted file mode 100644 index 20d47dd..0000000 --- a/ThinkSharp.FormulaParser.Test/ThinkSharp.FluentFormulaParser.Test.projitems +++ /dev/null @@ -1,40 +0,0 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - true - bc2373ca-32d9-4224-a1bb-831e0dbf839a - - - ThinkSharp.FluentFormulaParser.Test - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ThinkSharp.FormulaParser.Test/ThinkSharp.FormulaParser.Test.shproj b/ThinkSharp.FormulaParser.Test/ThinkSharp.FormulaParser.Test.shproj deleted file mode 100644 index 3982465..0000000 --- a/ThinkSharp.FormulaParser.Test/ThinkSharp.FormulaParser.Test.shproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - bc2373ca-32d9-4224-a1bb-831e0dbf839a - 14.0 - - - - - - - - diff --git a/ThinkSharp.FormulaParser.sln b/ThinkSharp.FormulaParser.sln index 354eeef..17728e6 100644 --- a/ThinkSharp.FormulaParser.sln +++ b/ThinkSharp.FormulaParser.sln @@ -7,15 +7,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThinkSharp.FormulaParser", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThinkSharp.FormulaParser.Test.Core", "ThinkSharp.FormulaParser.Test.Core\ThinkSharp.FormulaParser.Test.Core.csproj", "{1CAA5403-6EBB-4885-A51A-10533E673890}" EndProject -Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "ThinkSharp.FormulaParser.Test", "ThinkSharp.FormulaParser.Test\ThinkSharp.FormulaParser.Test.shproj", "{BC2373CA-32D9-4224-A1BB-831E0DBF839A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThinkSharp.FormulaParser.Test.Net461", "ThinkSharp.FormulaParser.Test.Net461\ThinkSharp.FormulaParser.Test.Net461.csproj", "{3BC319A0-E6A2-4667-A7E8-8C283ACDA823}" -EndProject Global - GlobalSection(SharedMSBuildProjectFiles) = preSolution - ThinkSharp.FormulaParser.Test\ThinkSharp.FluentFormulaParser.Test.projitems*{3bc319a0-e6a2-4667-a7e8-8c283acda823}*SharedItemsImports = 4 - ThinkSharp.FormulaParser.Test\ThinkSharp.FluentFormulaParser.Test.projitems*{bc2373ca-32d9-4224-a1bb-831e0dbf839a}*SharedItemsImports = 13 - EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU @@ -29,10 +21,6 @@ Global {1CAA5403-6EBB-4885-A51A-10533E673890}.Debug|Any CPU.Build.0 = Debug|Any CPU {1CAA5403-6EBB-4885-A51A-10533E673890}.Release|Any CPU.ActiveCfg = Release|Any CPU {1CAA5403-6EBB-4885-A51A-10533E673890}.Release|Any CPU.Build.0 = Release|Any CPU - {3BC319A0-E6A2-4667-A7E8-8C283ACDA823}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3BC319A0-E6A2-4667-A7E8-8C283ACDA823}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3BC319A0-E6A2-4667-A7E8-8C283ACDA823}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3BC319A0-E6A2-4667-A7E8-8C283ACDA823}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ThinkSharp.FormulaParser/Ast/Visitors/TransformNodesVisitor.cs b/ThinkSharp.FormulaParser/Ast/Visitors/TransformNodesVisitor.cs new file mode 100644 index 0000000..30ffb25 --- /dev/null +++ b/ThinkSharp.FormulaParser/Ast/Visitors/TransformNodesVisitor.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; + +namespace ThinkSharp.FormulaParsing.Ast.Visitors +{ + public abstract class TransformNodesVisitor : INodeVisitor + { + public virtual Node Visit(FormulaNode node) + { + var child = node.ChildNode.Visit(this); + + if (child == node.ChildNode) + { + return node; + } + + return new FormulaNode(child); + } + + public virtual Node Visit(BracketedNode node) + { + var child = node.ChildNode.Visit(this); + + if (child == node.ChildNode) + { + return node; + } + + return new BracketedNode(child); + } + + public virtual Node Visit(DecimalNode node) => node; + + public virtual Node Visit(IntegerNode node) => node; + + public virtual Node Visit(VariableNode node) => node; + + public virtual Node Visit(ConstantNode node) => node; + + public virtual Node Visit(BinaryOperatorNode node) + { + var left = node.LeftNode.Visit(this); + var right = node.RightNode.Visit(this); + + if (left == node.LeftNode && right == node.RightNode) + { + return node; + } + + return new BinaryOperatorNode(node.BinaryOperator, left, right); + } + + public virtual Node Visit(PowerNode node) + { + var baseNode = node.BaseNode.Visit(this); + var exponentNode = node.ExponentNode.Visit(this); + + if (baseNode == node.BaseNode && exponentNode == node.ExponentNode) + { + return node; + } + + return new PowerNode(baseNode, exponentNode); + } + + public virtual Node Visit(SignedNode node) + { + var child = node.Node.Visit(this); + + if (child == node.Node) + { + return node; + } + + return new SignedNode(node.Sign, child); + } + + public virtual Node Visit(FunctionNode node) + { + var transformedParameters = new List(); + var hasChanged = false; + + foreach (var parameter in node.Parameters) + { + var transformedParameter = parameter.Visit(this); + if (transformedParameter != parameter) hasChanged = true; + transformedParameters.Add(transformedParameter); + } + + if (!hasChanged) + { + return node; + } + + return new FunctionNode(node.FunctionName, transformedParameters.ToArray()); + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RearrangeIntegersInSum.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RearrangeIntegersInSum.cs new file mode 100644 index 0000000..e8e2084 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Rules/RearrangeIntegersInSum.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.Ast.Visitors; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Rules +{ + public class RearrangeIntegersInSum : Rule + { + protected override bool MatchInternal(Node node, Node parent) + => FindBinaryNodesWithInteger(node).Skip(1).Any(); + + private class RearrangeVisitor : TransformNodesVisitor + { + private readonly BinaryOperatorNode first; + private readonly BinaryOperatorNode second; + + private readonly Node firstReplacement; + private readonly Node firstInteger; + + public RearrangeVisitor(BinaryOperatorNode first, BinaryOperatorNode second) + { + this.first = first; + this.second = second; + + if (first.LeftNode is IntegerNode firstLeftInteger) + { + firstInteger = firstLeftInteger; + firstReplacement = first.IsMinus() + ? new SignedNode(Sign.Minus, first.RightNode) + : first.RightNode; + } + else if (first.RightNode is IntegerNode firstRightInteger) + { + firstReplacement = first.LeftNode; + firstInteger = first.IsMinus() + ? new IntegerNode(firstRightInteger.Format, firstRightInteger.Value * -1) + : firstRightInteger; + } + else + { + throw new ArgumentException("first: left or right node must be an integer."); + } + } + + public override Node Visit(BinaryOperatorNode node) + { + if (node == first) + { + return firstReplacement.Visit(this); + } + + if (node == second) + { + if (node.LeftNode is IntegerNode) + { + return new BinaryOperatorNode(node.BinaryOperator, + new BinaryOperatorNode(BinaryOperator.Plus, + node.LeftNode.Visit(this), + firstInteger), + node.RightNode.Visit(this)); + } + if (node.RightNode is IntegerNode) + { + return new BinaryOperatorNode(BinaryOperator.Plus, + node.LeftNode.Visit(this), + new BinaryOperatorNode(node.BinaryOperator, + firstInteger, + node.RightNode.Visit(this))); + } + else + { + throw new ArgumentException("second: left or right node must be an integer."); + } + } + + return base.Visit(node); + } + } + + private static IEnumerable FindBinaryNodesWithInteger(Node node) + { + if (node is BinaryOperatorNode binOpNode && binOpNode.IsPlusOrMinus()) + { + var isLeftInteger = binOpNode.LeftNode is IntegerNode; + var isRightInteger = binOpNode.RightNode is IntegerNode; + if (isLeftInteger ^ isRightInteger) + { + yield return binOpNode; + } + + foreach (var children in FindBinaryNodesWithInteger(binOpNode.LeftNode)) + { + yield return children; + } + + foreach (var children in FindBinaryNodesWithInteger(binOpNode.RightNode)) + { + yield return children; + } + } + } + + protected override Node RewriteInternal(Node node, Node parent) + { + var binOpNodesIntegers = FindBinaryNodesWithInteger(node).Take(2).ToArray(); + + if (binOpNodesIntegers.Length == 2) + { + var visitor = new RearrangeVisitor(binOpNodesIntegers[0], binOpNodesIntegers[1]); + return node.Visit(visitor); + } + + Debug.Fail("Should not happen"); + return node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs b/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs index 993ad3e..07461db 100644 --- a/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs +++ b/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs @@ -26,6 +26,7 @@ public static ITermRewritingSystem Create() system.rules.Add(new TermPlusOrMinusZeroIsTermRule()); system.rules.Add(new TermTimesOrDividedByMinusOneIsMinusTerm()); system.rules.Add(new TermTimesOrDividedByOneIsTerm()); + system.rules.Add(new RearrangeIntegersInSum()); return system; } diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj index 57fcc87..3feb883 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj @@ -9,8 +9,8 @@ ThinkSharp A formula parser with fluent API that allows parsing and evaluation of mathematically formulas. Features: functions, constants, variables, scientific numbers, focus on customization and flexibility. © 2019 Jan-Niklas Schäfer - 0.6.1.0 - 0.6.1.0 + 0.6.2.0 + 0.6.2.0 LICENSE.txt changed variables API from IDictionary to IReadOnlyDictionary added '$' as valid character for variables @@ -18,7 +18,7 @@ removed support for alternative hex number notation: '#<hexnumber>'. Note https://github.com/JanDotNet/ThinkSharp.FormulaParser true - 0.6.1 + 0.6.2 From 91549b6cfcb48573f62451788d4bfaf9b4b9342a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Sun, 10 Nov 2019 19:36:59 +0100 Subject: [PATCH 32/45] added DebuggerDisplay attribute to node implementations --- ThinkSharp.FormulaParser/Ast/Nodes/BinaryOperatorNode.cs | 2 ++ ThinkSharp.FormulaParser/Ast/Nodes/BracketedNode.cs | 2 ++ ThinkSharp.FormulaParser/Ast/Nodes/ConstantNode.cs | 2 ++ ThinkSharp.FormulaParser/Ast/Nodes/DecimalNode.cs | 2 ++ ThinkSharp.FormulaParser/Ast/Nodes/FormulaNode.cs | 2 ++ ThinkSharp.FormulaParser/Ast/Nodes/FunctionNode.cs | 5 ++--- ThinkSharp.FormulaParser/Ast/Nodes/IntegerNode.cs | 2 ++ ThinkSharp.FormulaParser/Ast/Nodes/PowerNode.cs | 2 ++ ThinkSharp.FormulaParser/Ast/Nodes/SignedNode.cs | 2 ++ ThinkSharp.FormulaParser/Ast/Nodes/VariableNode.cs | 2 ++ 10 files changed, 20 insertions(+), 3 deletions(-) diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/BinaryOperatorNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/BinaryOperatorNode.cs index 5a29ab8..8a50ca0 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/BinaryOperatorNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/BinaryOperatorNode.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -7,6 +8,7 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { + [DebuggerDisplay("({LeftNode} {BinaryOperator.Symbol} {RightNode})")] public class BinaryOperatorNode : Node { public BinaryOperatorNode(BinaryOperator binaryOperator, Node leftNode, Node rightNode) diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/BracketedNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/BracketedNode.cs index 1c5351b..67d7e14 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/BracketedNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/BracketedNode.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -7,6 +8,7 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { + [DebuggerDisplay("({ChildNode})")] public class BracketedNode : Node { public BracketedNode(Node childNode) diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/ConstantNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/ConstantNode.cs index 66e17b3..a6de78b 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/ConstantNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/ConstantNode.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -7,6 +8,7 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { + [DebuggerDisplay("{Name}")] public class ConstantNode : Node { public ConstantNode(string name) diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/DecimalNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/DecimalNode.cs index 2c51d14..b65fba8 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/DecimalNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/DecimalNode.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -7,6 +8,7 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { + [DebuggerDisplay("{Value}")] public class DecimalNode : Node { public DecimalNode(double value) diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/FormulaNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/FormulaNode.cs index fa010a3..b786800 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/FormulaNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/FormulaNode.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -7,6 +8,7 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { + [DebuggerDisplay("{ChildNode}")] public class FormulaNode : Node { public FormulaNode(Node childNode) diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/FunctionNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/FunctionNode.cs index b406481..e32e109 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/FunctionNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/FunctionNode.cs @@ -1,12 +1,11 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Diagnostics; using ThinkSharp.FormulaParsing.Ast.Visitors; namespace ThinkSharp.FormulaParsing.Ast.Nodes { + [DebuggerDisplay("{Name}()")] public class FunctionNode : Node { public FunctionNode(string functionName, params Node[] parameters) diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/IntegerNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/IntegerNode.cs index d46fb61..2ab3ae2 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/IntegerNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/IntegerNode.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Text; using ThinkSharp.FormulaParsing.Ast.Visitors; namespace ThinkSharp.FormulaParsing.Ast.Nodes { + [DebuggerDisplay("{Value}")] public class IntegerNode : Node { public IntegerNode(long value) : this(NumberFormat.Dec, value) diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/PowerNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/PowerNode.cs index 350df24..28c8ccc 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/PowerNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/PowerNode.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -7,6 +8,7 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { + [DebuggerDisplay("{BaseNode}^{ExponentNode}")] public class PowerNode : Node { public PowerNode(Node baseNode, Node exponentNode) diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/SignedNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/SignedNode.cs index f7a0f7c..f343abf 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/SignedNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/SignedNode.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -9,6 +10,7 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { public enum Sign { Plus, Minus } + [DebuggerDisplay("{Sign} {Node}")] public class SignedNode : Node { public SignedNode(Sign sign, Node node) diff --git a/ThinkSharp.FormulaParser/Ast/Nodes/VariableNode.cs b/ThinkSharp.FormulaParser/Ast/Nodes/VariableNode.cs index 363b1f1..d12a9e8 100644 --- a/ThinkSharp.FormulaParser/Ast/Nodes/VariableNode.cs +++ b/ThinkSharp.FormulaParser/Ast/Nodes/VariableNode.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -7,6 +8,7 @@ namespace ThinkSharp.FormulaParsing.Ast.Nodes { + [DebuggerDisplay("{Name}")] public class VariableNode : Node { public VariableNode(string name) From 39980c17c02879c559f5529afe3bcfb333c3cec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Sun, 10 Nov 2019 19:41:49 +0100 Subject: [PATCH 33/45] make parser configuration public --- ThinkSharp.FormulaParser/FormulaParser.cs | 5 +++++ ThinkSharp.FormulaParser/IConfiguration.cs | 2 +- ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ThinkSharp.FormulaParser/FormulaParser.cs b/ThinkSharp.FormulaParser/FormulaParser.cs index 49ad08e..1eb7cbd 100644 --- a/ThinkSharp.FormulaParser/FormulaParser.cs +++ b/ThinkSharp.FormulaParser/FormulaParser.cs @@ -41,6 +41,11 @@ internal FormulaParser(Configuration configuration) /// public static IFormulaParserBuilder CreateBuilder() => new FormulaParserBuilder(); + /// + /// Gets the configuration for the parser. + /// + public IConfiguration Configuration => this.configuration; + public FormulaParserResult Evaluate(string formula) { return this.Evaluate(formula, null); diff --git a/ThinkSharp.FormulaParser/IConfiguration.cs b/ThinkSharp.FormulaParser/IConfiguration.cs index 7fe1bda..10ca6cc 100644 --- a/ThinkSharp.FormulaParser/IConfiguration.cs +++ b/ThinkSharp.FormulaParser/IConfiguration.cs @@ -6,7 +6,7 @@ namespace ThinkSharp.FormulaParsing { - internal interface IConfiguration + public interface IConfiguration { bool IsScientificNotationSupportDisabled { get; } diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml index 7e35570..43b4e3d 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml @@ -27,6 +27,11 @@ a . + + + Gets the configuration for the parser. + + Interface encapsulating the API for configuring constants. From a6731efc46b11210f1942a7c24badd870018e1e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Sun, 10 Nov 2019 19:49:29 +0100 Subject: [PATCH 34/45] added property Configuration to IFormulaParser interface --- ThinkSharp.FormulaParser/IFormulaParser.cs | 5 +++++ ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ThinkSharp.FormulaParser/IFormulaParser.cs b/ThinkSharp.FormulaParser/IFormulaParser.cs index 7353628..f6c07ac 100644 --- a/ThinkSharp.FormulaParser/IFormulaParser.cs +++ b/ThinkSharp.FormulaParser/IFormulaParser.cs @@ -10,6 +10,11 @@ namespace ThinkSharp.FormulaParsing { public interface IFormulaParser { + /// + /// Gets the configuration for the parser. + /// + IConfiguration Configuration { get; } + /// /// Evaluates the provided formula to a numeric value. /// diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj index 3feb883..3d5edda 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj @@ -9,8 +9,8 @@ ThinkSharp A formula parser with fluent API that allows parsing and evaluation of mathematically formulas. Features: functions, constants, variables, scientific numbers, focus on customization and flexibility. © 2019 Jan-Niklas Schäfer - 0.6.2.0 - 0.6.2.0 + 0.6.4.0 + 0.6.4.0 LICENSE.txt changed variables API from IDictionary to IReadOnlyDictionary added '$' as valid character for variables @@ -18,7 +18,7 @@ removed support for alternative hex number notation: '#<hexnumber>'. Note https://github.com/JanDotNet/ThinkSharp.FormulaParser true - 0.6.2 + 0.6.4 From 123ac7d789577de7eeb21597d29dd20473fdc392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Wed, 13 Nov 2019 08:35:15 +0100 Subject: [PATCH 35/45] Create build-master.yml --- .github/workflows/build-master.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/build-master.yml diff --git a/.github/workflows/build-master.yml b/.github/workflows/build-master.yml new file mode 100644 index 0000000..3d1397c --- /dev/null +++ b/.github/workflows/build-master.yml @@ -0,0 +1,23 @@ +name: .NET Core + +on: + push: + branches: + - master + +jobs: + build: + + runs-on: windows-latest + + steps: + - uses: actions/checkout@v1 + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 2.2.108 + - name: Run Tests + run: dotnet test + - name: Build with dotnet + run: dotnet build --configuration Release + From 037af74d482a1a0ea43ad2f1d74ec917e2a4c7b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Wed, 13 Nov 2019 21:18:54 +0100 Subject: [PATCH 36/45] Create dotnetcore.yml --- .github/workflows/dotnetcore.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/dotnetcore.yml diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml new file mode 100644 index 0000000..6aba16c --- /dev/null +++ b/.github/workflows/dotnetcore.yml @@ -0,0 +1,22 @@ +name: .NET Core + +on: + push: + branches: + - master + +jobs: + build: + + runs-on: windows-latest + + steps: + - uses: actions/checkout@v1 + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 2.2.108 + - name: Run Tests + run: dotnet test + - name: Build with dotnet + run: dotnet build --configuration Release From f1b0553622c2bc6b86646e844d7830fc8cf91d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Wed, 13 Nov 2019 21:20:16 +0100 Subject: [PATCH 37/45] Update and rename build-master.yml to build-dev.yml --- .github/workflows/{build-master.yml => build-dev.yml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{build-master.yml => build-dev.yml} (95%) diff --git a/.github/workflows/build-master.yml b/.github/workflows/build-dev.yml similarity index 95% rename from .github/workflows/build-master.yml rename to .github/workflows/build-dev.yml index 3d1397c..f91ee74 100644 --- a/.github/workflows/build-master.yml +++ b/.github/workflows/build-dev.yml @@ -3,7 +3,7 @@ name: .NET Core on: push: branches: - - master + - develop jobs: build: From 2b85cb5df594013a7c2aa8526c31edb70f5a8f7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Wed, 13 Nov 2019 21:25:37 +0100 Subject: [PATCH 38/45] WIP: Improve rewriting while replacing identical sub trees with variables --- .../Utils/BinaryOperatorTest.cs | 2 +- .../Helper/CollectNonTerminalNodes.cs | 76 +++++++++++++++++++ .../TermRewriting/TermRewritingSystem.cs | 10 +++ .../ThinkSharp.FormulaParser.csproj | 4 - .../ThinkSharp.FormulaParser.xml | 5 ++ .../Utils/NodeComparer.cs | 12 ++- 6 files changed, 100 insertions(+), 9 deletions(-) create mode 100644 ThinkSharp.FormulaParser/TermRewriting/Helper/CollectNonTerminalNodes.cs diff --git a/ThinkSharp.FormulaParser.Test.Core/Utils/BinaryOperatorTest.cs b/ThinkSharp.FormulaParser.Test.Core/Utils/BinaryOperatorTest.cs index cdf0aad..9f5ee94 100644 --- a/ThinkSharp.FormulaParser.Test.Core/Utils/BinaryOperatorTest.cs +++ b/ThinkSharp.FormulaParser.Test.Core/Utils/BinaryOperatorTest.cs @@ -42,7 +42,7 @@ public void TestCompareFunctionEquals() public void TestCompareDividedByEquals() => AssertAreEqual("3*(a+b+c)/2*(f*d*s)", "(c+a+b)*3/2*(d*f*s)"); - //[TestMethod] + [TestMethod] public void TestCompareMinusEquals() { AssertAreEqual("1-3", "-3+1"); diff --git a/ThinkSharp.FormulaParser/TermRewriting/Helper/CollectNonTerminalNodes.cs b/ThinkSharp.FormulaParser/TermRewriting/Helper/CollectNonTerminalNodes.cs new file mode 100644 index 0000000..2d48339 --- /dev/null +++ b/ThinkSharp.FormulaParser/TermRewriting/Helper/CollectNonTerminalNodes.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Text; +using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.Ast.Visitors; + +namespace ThinkSharp.FormulaParsing.TermRewriting.Helper +{ + public class CollectNonTerminalNodes : INodeVisitor> + { + public IEnumerable Visit(FormulaNode node) + { + return node.ChildNode.Visit(this); + } + + public IEnumerable Visit(BracketedNode node) + { + yield return node; + foreach (var childNode in node.ChildNode.Visit(this)) + yield return node; + } + + public IEnumerable Visit(DecimalNode node) + { + yield break; + } + + public IEnumerable Visit(IntegerNode node) + { + yield break; + } + + public IEnumerable Visit(VariableNode node) + { + yield break; + } + + public IEnumerable Visit(ConstantNode node) + { + yield break; + } + + public IEnumerable Visit(BinaryOperatorNode node) + { + yield return node; + foreach (var childNode in node.LeftNode.Visit(this)) + yield return node; + foreach (var childNode in node.RightNode.Visit(this)) + yield return node; + } + + public IEnumerable Visit(PowerNode node) + { + yield return node; + foreach (var childNode in node.BaseNode.Visit(this)) + yield return node; + foreach (var childNode in node.ExponentNode.Visit(this)) + yield return node; + } + + public IEnumerable Visit(SignedNode node) + { + yield return node; + foreach (var childNode in node.Node.Visit(this)) + yield return node; + } + + public IEnumerable Visit(FunctionNode node) + { + yield return node; + foreach (var parameter in node.Parameters) + foreach (var childNode in parameter.Visit(this)) + yield return node; + } + } +} diff --git a/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs b/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs index 07461db..adcbfdf 100644 --- a/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs +++ b/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs @@ -57,5 +57,15 @@ private Node SimplyfyInternal(Node node) return simlifiedNode; } + + //private Node CollapseIdenticalNodes(Node node, IDictionary collapsedNodes) + //{ + + //} + + //private Node ExpandCollapsedNodes(Node node, IDictionary collapsedNodes) + //{ + + //} } } diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj index 3d5edda..108ba3b 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj @@ -49,8 +49,4 @@ removed support for alternative hex number notation: '#<hexnumber>'. Note - - - - diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml index 43b4e3d..e897a6b 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.xml @@ -216,6 +216,11 @@ Diables the validation of functions names when creating a parsing tree. + + + Gets the configuration for the parser. + + Evaluates the provided formula to a numeric value. diff --git a/ThinkSharp.FormulaParser/Utils/NodeComparer.cs b/ThinkSharp.FormulaParser/Utils/NodeComparer.cs index cb99ca3..d2d7bf2 100644 --- a/ThinkSharp.FormulaParser/Utils/NodeComparer.cs +++ b/ThinkSharp.FormulaParser/Utils/NodeComparer.cs @@ -4,12 +4,15 @@ using System.Linq; using System.Text; using ThinkSharp.FormulaParsing.Ast.Nodes; +using ThinkSharp.FormulaParsing.TermRewriting; +using ThinkSharp.FormulaParsing.TermRewriting.Rules; namespace ThinkSharp.FormulaParsing.Utils { public class NodeComparer : IEqualityComparer { private static NodeHashCodeVisitor hashCodeVisitor = new NodeHashCodeVisitor(); + private static ITermRewritingSystem termRewriteSystem = TermRewritingSystem.Create(); public bool Equals(Node x, Node y) { @@ -96,13 +99,14 @@ public bool Equals(Node x, Node y) var summands1Left = GetSummands(bo1.LeftNode); var summands1Right = GetSummands(bo1.RightNode); - if (isMinus) summands1Right = summands1Right.WrapFirst(n => new SignedNode(Sign.Minus, n)); - var summands1 = summands1Left.Concat(summands1Right).ToList(); + if (isMinus) summands1Right = summands1Right.WrapFirst(n => n.SwitchSign()); + var summands1 = summands1Left.Concat(summands1Right).Select(termRewriteSystem.Simplify).ToList(); + isMinus = bo2.BinaryOperator.Symbol == "-"; var summands2Left = GetSummands(bo2.LeftNode); var summands2Right = GetSummands(bo2.RightNode); - if (isMinus) summands2Right = summands2Right.WrapFirst(n => new SignedNode(Sign.Minus, n)); - var summands2 = summands2Left.Concat(summands2Right).ToList(); + if (isMinus) summands2Right = summands2Right.WrapFirst(n => n.SwitchSign()); + var summands2 = summands2Left.Concat(summands2Right).Select(termRewriteSystem.Simplify).ToList(); if (summands1.Count != summands2.Count) { From ce5eefb34170151b9044d10fdec0413c25268f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Wed, 13 Nov 2019 21:28:11 +0100 Subject: [PATCH 39/45] Delete dotnetcore.yml --- .github/workflows/dotnetcore.yml | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 .github/workflows/dotnetcore.yml diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml deleted file mode 100644 index 6aba16c..0000000 --- a/.github/workflows/dotnetcore.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: .NET Core - -on: - push: - branches: - - master - -jobs: - build: - - runs-on: windows-latest - - steps: - - uses: actions/checkout@v1 - - name: Setup .NET Core - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 2.2.108 - - name: Run Tests - run: dotnet test - - name: Build with dotnet - run: dotnet build --configuration Release From 11b0a29f999d8dd867cae4eeb223f95eefa37d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Wed, 13 Nov 2019 21:34:06 +0100 Subject: [PATCH 40/45] Create build-branch-TermRewriting.yml --- .../workflows/build-branch-TermRewriting.yml | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/build-branch-TermRewriting.yml diff --git a/.github/workflows/build-branch-TermRewriting.yml b/.github/workflows/build-branch-TermRewriting.yml new file mode 100644 index 0000000..2cf64b6 --- /dev/null +++ b/.github/workflows/build-branch-TermRewriting.yml @@ -0,0 +1,22 @@ +name: branch TermRewriting + +on: + push: + branches: + - feature/TermRewriting + +jobs: + build: + + runs-on: windows-latest + + steps: + - uses: actions/checkout@v1 + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 2.2.108 + - name: Run Tests + run: dotnet test + - name: Build with dotnet + run: dotnet build --configuration Release From b440c0e469aedec957e2665cc4b72718b461dcfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Wed, 13 Nov 2019 21:39:49 +0100 Subject: [PATCH 41/45] Update build-branch-TermRewriting.yml --- .github/workflows/build-branch-TermRewriting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-branch-TermRewriting.yml b/.github/workflows/build-branch-TermRewriting.yml index 2cf64b6..7f0deec 100644 --- a/.github/workflows/build-branch-TermRewriting.yml +++ b/.github/workflows/build-branch-TermRewriting.yml @@ -19,4 +19,4 @@ jobs: - name: Run Tests run: dotnet test - name: Build with dotnet - run: dotnet build --configuration Release + run: dotnet build .\ThinkSharp.FormulaParser\ThinkSharp.FormulaParser.csproj --configuration Release From 6d407a74606a02ea5c820d054677eb79a38ef3f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Wed, 13 Nov 2019 21:40:16 +0100 Subject: [PATCH 42/45] Update build-dev.yml --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index f91ee74..51d6721 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -19,5 +19,5 @@ jobs: - name: Run Tests run: dotnet test - name: Build with dotnet - run: dotnet build --configuration Release + run: dotnet build .\ThinkSharp.FormulaParser\ThinkSharp.FormulaParser.csproj --configuration Release From 29882868e7728c4f695e5d54d7fcbe874f8e0e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Niklas=20Sch=C3=A4fer?= Date: Sun, 31 May 2020 18:26:30 +0200 Subject: [PATCH 43/45] Update README.md --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 19afe4d..e6925f8 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ var variables = new Dictionary { ["x"] = 2.0 }; var result2 = parser.Evaluate("1+x", variables).Value; // result2 = 3.0 // Usage of functions -var result3 = parser.Evaluate("1+min(3,4)").Value; // result2 = 4.0 +var result3 = parser.Evaluate("1+min(3,4)").Value; // result3 = 4.0 // Handle errors var parsingResult = parser.Evaluate("2*?"); @@ -93,17 +93,18 @@ var parser = FormulaParser { // functions.RemoveAll() for removing all default functions // functions.Remove("sum") for removing function by name - // define function with 2 to n number of parameters (typeof(nums) = double[]) - functions.Add("product", nums => nums.Aggregate((p1, p2) => p1 * p2)); - // define functions with specified number of parameters (1-5 parameters are supported) + // define functions with certain number of parameters (1-5 parameters are supported) functions.Add("celsiusToFarenheit", celsius => celsius * 1.8 + 32); functions.Add("fahrenheitToCelsius", fahrenheit => (fahrenheit - 32) * 5 / 9); functions.Add("p1_plus_p2_plus_p3", (p1, p2, p3) => p1 + p2 + p3); + + // define function with 2 to n number of parameters (typeof(nums) = double[]) + functions.Add("product", nums => nums.Aggregate((p1, p2) => p1 * p2)); }).Build(); var poolTemperatureInCelsius = parser.Evaluate("celsiusToFarenheit(fahrenheitToCelsius(30))").Value; // poolTemperatureInCelsius = 30 -var result2 = parser.Evaluate("product(2, 2, 2, 2, 2, 2, 2)").Value; // result2 = 2^6 = 128 +var result2 = parser.Evaluate("product(2, 2, 2, 2, 2, 2)").Value; // result2 = 2^6 = 128 var result3 = parser.Evaluate("p1_plus_p2_plus_p3(1, 2, 3)").Value; // result3 = 6 string error1 = parser.Evaluate("celsiusToFarenheit(1, 2)").Error; // column 0: There is no function 'celsiusToFarenheit' that takes 2 argument(s). From 8a3f630aacf96f16cc56249a88ae81cd3f2959c7 Mon Sep 17 00:00:00 2001 From: Jan-Niklas Date: Sun, 31 May 2020 18:41:18 +0200 Subject: [PATCH 44/45] removed term rewriting functionallity (moved to its own project) --- .../AST/ParsingHelperTest.cs | 2 +- .../BinaryOperatorTest.cs | 2 +- .../FormulaParserTest.cs | 2 +- .../FormularParser.Configuration.Test.cs | 2 +- .../FormularParser.CustomVisitor.Test.cs | 2 +- .../FormularParser.NumberFormats.Test.cs | 2 +- .../FormularParser.ParsingBehavior.Test.cs | 2 +- .../FormularParser.SupportedFeatures.Test.cs | 2 +- .../FormularParser.VariableNames.Test.cs | 2 +- .../NodesToFormulaTextVisitor.cs | 4 +- .../Rules/EvaluateIntegersTest.cs | 44 ----- .../Rules/RearrangeIntegersInSumTest.cs | 32 ---- ...nTermPlusMinusBracketsPlusMinusTermTest.cs | 35 ---- ...moveBracketsInTermPlusMinusBracketsTest.cs | 29 --- .../Rules/RemoveNegativSignFromNumberTest.cs | 24 --- ...RemoveNegativeSignInFrontOfBracketsTest.cs | 35 ---- .../RemoveNegativeSignInInSubtractTest.cs | 20 --- .../Rules/RemoveNegativeSignInInSumTest.cs | 26 --- .../RemoveNegativeSignTimesNegatieSignTest.cs | 48 ----- .../Rules/RemoveNestedBracketsTest.cs | 32 ---- .../Rules/RemovePositiveSignTest.cs | 39 ---- .../Rules/RemoveRootBracketsTest.cs | 29 --- .../TermRewriting/Rules/RuleTest.cs | 73 -------- .../Rules/TermPlusOrMinusZeroIsTermTest.cs | 32 ---- ...TimesOrDividedByMinusOneIsMinusTermTest.cs | 60 ------- .../TermTimesOrDividedByOneIsTermTest.cs | 35 ---- .../TermRewriting/TermWritingSystemTest.cs | 93 ---------- ...j => ThinkSharp.FormulaParser.Test.csproj} | 2 +- .../Utils/BinaryOperatorTest.cs | 66 ------- ThinkSharp.FormulaParser.sln | 2 +- ThinkSharp.FormulaParser/FormulaParser.cs | 1 - .../Helper/CollectNonTerminalNodes.cs | 76 -------- .../TermRewriting/ITermRewritingSystem.cs | 12 -- .../TermRewriting/ReplaceRuleTreeVisitor.cs | 124 ------------- .../Rules/ConvertDecimalToLong.cs | 36 ---- .../TermRewriting/Rules/EvaluateIntegers.cs | 34 ---- .../TermRewriting/Rules/NodeExtensions.cs | 106 ----------- .../Rules/RearrangeIntegersInSum.cs | 121 ------------- .../RemoveBracketsInTermPlusMinusBrackets.cs | 63 ------- ...etsInTermPlusMinusBracketsPlusMinusTerm.cs | 65 ------- .../Rules/RemoveNegativeSignFromNumber.cs | 36 ---- .../RemoveNegativeSignInFrontOfBrackets.cs | 52 ------ .../Rules/RemoveNegativeSignInInSubtract.cs | 36 ---- .../Rules/RemoveNegativeSignInInSum.cs | 36 ---- .../RemoveNegativeSignTimesNegatieSign.cs | 78 -------- .../Rules/RemoveNestedBrackets.cs | 29 --- .../TermRewriting/Rules/RemovePositiveSign.cs | 27 --- .../TermRewriting/Rules/RemoveRootBrackets.cs | 27 --- .../TermRewriting/Rules/Rule.cs | 32 ---- .../Rules/TermDividesByTermIsOne.cs | 72 -------- .../Rules/TermPlusOrMinusZeroIsTerm.cs | 52 ------ ...TermTimesOrDividedByMinusOneIsMinusTerm.cs | 55 ------ .../Rules/TermTimesOrDividedByOneIsTerm.cs | 54 ------ .../TermRewriting/TermRewritingSystem.cs | 71 -------- .../ThinkSharp.FormulaParser.csproj | 18 +- .../Utils/EnumerableExtensions.cs | 19 -- .../Utils/NodeComparer.cs | 170 ------------------ .../Utils/NodeHashCodeVisitor.cs | 40 ----- 58 files changed, 21 insertions(+), 2299 deletions(-) delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/EvaluateIntegersTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RearrangeIntegersInSumTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTermTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativSignFromNumberTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInFrontOfBracketsTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInInSubtractTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInInSumTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNestedBracketsTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemovePositiveSignTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveRootBracketsTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RuleTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermPlusOrMinusZeroIsTermTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTermTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermTimesOrDividedByOneIsTermTest.cs delete mode 100644 ThinkSharp.FormulaParser.Test.Core/TermRewriting/TermWritingSystemTest.cs rename ThinkSharp.FormulaParser.Test.Core/{ThinkSharp.FormulaParser.Test.Core.csproj => ThinkSharp.FormulaParser.Test.csproj} (90%) delete mode 100644 ThinkSharp.FormulaParser.Test.Core/Utils/BinaryOperatorTest.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Helper/CollectNonTerminalNodes.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/ITermRewritingSystem.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/ReplaceRuleTreeVisitor.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/ConvertDecimalToLong.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/EvaluateIntegers.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/NodeExtensions.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RearrangeIntegersInSum.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBrackets.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTerm.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignFromNumber.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInFrontOfBrackets.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInInSubtract.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInInSum.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSign.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNestedBrackets.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemovePositiveSign.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveRootBrackets.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/Rule.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/TermDividesByTermIsOne.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/TermPlusOrMinusZeroIsTerm.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTerm.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByOneIsTerm.cs delete mode 100644 ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs delete mode 100644 ThinkSharp.FormulaParser/Utils/EnumerableExtensions.cs delete mode 100644 ThinkSharp.FormulaParser/Utils/NodeComparer.cs delete mode 100644 ThinkSharp.FormulaParser/Utils/NodeHashCodeVisitor.cs diff --git a/ThinkSharp.FormulaParser.Test.Core/AST/ParsingHelperTest.cs b/ThinkSharp.FormulaParser.Test.Core/AST/ParsingHelperTest.cs index f3c3133..dd91da2 100644 --- a/ThinkSharp.FormulaParser.Test.Core/AST/ParsingHelperTest.cs +++ b/ThinkSharp.FormulaParser.Test.Core/AST/ParsingHelperTest.cs @@ -4,7 +4,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using ThinkSharp.FormulaParsing.Ast.Nodes; -namespace ThinkSharp.FormulaParsing.Test +namespace ThinkSharp.FormulaParsing { [TestClass] public class ParsingHelperTest diff --git a/ThinkSharp.FormulaParser.Test.Core/BinaryOperatorTest.cs b/ThinkSharp.FormulaParser.Test.Core/BinaryOperatorTest.cs index 0c5ffe0..cab5630 100644 --- a/ThinkSharp.FormulaParser.Test.Core/BinaryOperatorTest.cs +++ b/ThinkSharp.FormulaParser.Test.Core/BinaryOperatorTest.cs @@ -4,7 +4,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using ThinkSharp.FormulaParsing.Ast.Nodes; -namespace ThinkSharp.FormulaParsing.Test +namespace ThinkSharp.FormulaParsing { [TestClass] public class BinaryOperatorTest diff --git a/ThinkSharp.FormulaParser.Test.Core/FormulaParserTest.cs b/ThinkSharp.FormulaParser.Test.Core/FormulaParserTest.cs index 7e0eba2..f1eb365 100644 --- a/ThinkSharp.FormulaParser.Test.Core/FormulaParserTest.cs +++ b/ThinkSharp.FormulaParser.Test.Core/FormulaParserTest.cs @@ -4,7 +4,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using ThinkSharp.FormulaParsing.Ast.Nodes; -namespace ThinkSharp.FormulaParsing.Test +namespace ThinkSharp.FormulaParsing { [TestClass] public class FormulaParserTest diff --git a/ThinkSharp.FormulaParser.Test.Core/FormularParser.Configuration.Test.cs b/ThinkSharp.FormulaParser.Test.Core/FormularParser.Configuration.Test.cs index 8511688..c6264e9 100644 --- a/ThinkSharp.FormulaParser.Test.Core/FormularParser.Configuration.Test.cs +++ b/ThinkSharp.FormulaParser.Test.Core/FormularParser.Configuration.Test.cs @@ -7,7 +7,7 @@ using ThinkSharp.FormulaParsing.Ast.Nodes; using ThinkSharp.FormulaParsing.Ast.Visitors; -namespace ThinkSharp.FormulaParsing.Test +namespace ThinkSharp.FormulaParsing { [TestClass] public class FormularParserConfigurationTest diff --git a/ThinkSharp.FormulaParser.Test.Core/FormularParser.CustomVisitor.Test.cs b/ThinkSharp.FormulaParser.Test.Core/FormularParser.CustomVisitor.Test.cs index d011d2b..a587da8 100644 --- a/ThinkSharp.FormulaParser.Test.Core/FormularParser.CustomVisitor.Test.cs +++ b/ThinkSharp.FormulaParser.Test.Core/FormularParser.CustomVisitor.Test.cs @@ -8,7 +8,7 @@ using ThinkSharp.FormulaParsing.Ast.Nodes; using ThinkSharp.FormulaParsing.Ast.Visitors; -namespace ThinkSharp.FormulaParsing.Test +namespace ThinkSharp.FormulaParsing { [TestClass] public class FormularParserCustomVisitorTest diff --git a/ThinkSharp.FormulaParser.Test.Core/FormularParser.NumberFormats.Test.cs b/ThinkSharp.FormulaParser.Test.Core/FormularParser.NumberFormats.Test.cs index 66996e5..93d1ec2 100644 --- a/ThinkSharp.FormulaParser.Test.Core/FormularParser.NumberFormats.Test.cs +++ b/ThinkSharp.FormulaParser.Test.Core/FormularParser.NumberFormats.Test.cs @@ -7,7 +7,7 @@ using ThinkSharp.FormulaParsing.Ast.Nodes; using ThinkSharp.FormulaParsing.Ast.Visitors; -namespace ThinkSharp.FormulaParsing.Test +namespace ThinkSharp.FormulaParsing { [TestClass] public class FormularParserNumberFormatsTest diff --git a/ThinkSharp.FormulaParser.Test.Core/FormularParser.ParsingBehavior.Test.cs b/ThinkSharp.FormulaParser.Test.Core/FormularParser.ParsingBehavior.Test.cs index a78ef95..d75b5f7 100644 --- a/ThinkSharp.FormulaParser.Test.Core/FormularParser.ParsingBehavior.Test.cs +++ b/ThinkSharp.FormulaParser.Test.Core/FormularParser.ParsingBehavior.Test.cs @@ -7,7 +7,7 @@ using ThinkSharp.FormulaParsing.Ast.Nodes; using ThinkSharp.FormulaParsing.Ast.Visitors; -namespace ThinkSharp.FormulaParsing.Test +namespace ThinkSharp.FormulaParsing { [TestClass] public class ConfigureValidationBehaviorTest diff --git a/ThinkSharp.FormulaParser.Test.Core/FormularParser.SupportedFeatures.Test.cs b/ThinkSharp.FormulaParser.Test.Core/FormularParser.SupportedFeatures.Test.cs index 6d33404..da9dd07 100644 --- a/ThinkSharp.FormulaParser.Test.Core/FormularParser.SupportedFeatures.Test.cs +++ b/ThinkSharp.FormulaParser.Test.Core/FormularParser.SupportedFeatures.Test.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; -namespace ThinkSharp.FormulaParsing.Test +namespace ThinkSharp.FormulaParsing { [TestClass] public class ConfigureSupportedFeaturesTest diff --git a/ThinkSharp.FormulaParser.Test.Core/FormularParser.VariableNames.Test.cs b/ThinkSharp.FormulaParser.Test.Core/FormularParser.VariableNames.Test.cs index fff019b..ced15bb 100644 --- a/ThinkSharp.FormulaParser.Test.Core/FormularParser.VariableNames.Test.cs +++ b/ThinkSharp.FormulaParser.Test.Core/FormularParser.VariableNames.Test.cs @@ -7,7 +7,7 @@ using ThinkSharp.FormulaParsing.Ast.Nodes; using ThinkSharp.FormulaParsing.Ast.Visitors; -namespace ThinkSharp.FormulaParsing.Test +namespace ThinkSharp.FormulaParsing { [TestClass] public class FormularParserVariableNamesTest diff --git a/ThinkSharp.FormulaParser.Test.Core/NodesToFormulaTextVisitor.cs b/ThinkSharp.FormulaParser.Test.Core/NodesToFormulaTextVisitor.cs index 6f01050..44732b4 100644 --- a/ThinkSharp.FormulaParser.Test.Core/NodesToFormulaTextVisitor.cs +++ b/ThinkSharp.FormulaParser.Test.Core/NodesToFormulaTextVisitor.cs @@ -6,9 +6,9 @@ using ThinkSharp.FormulaParsing.Ast.Nodes; using ThinkSharp.FormulaParsing.Ast.Visitors; -namespace ThinkSharp.FormulaParsing.Test +namespace ThinkSharp.FormulaParsing { - internal class NodesToFormulaTextVisitor : INodeVisitor + public class NodesToFormulaTextVisitor : INodeVisitor { public string Visit(FormulaNode node) { diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/EvaluateIntegersTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/EvaluateIntegersTest.cs deleted file mode 100644 index f80af1c..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/EvaluateIntegersTest.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; -using ThinkSharp.FormulaParsing.Test; - -namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules -{ - [TestClass] - public class EvaluateIntegersTest : RuleTest - { - protected override Rule CreateRule() => new EvaluateIntegers(); - - [TestMethod] - public void Test_TenPlusTen () => AssertRewritten( - new IntegerNode(20), - new BinaryOperatorNode( - BinaryOperator.Plus, - new IntegerNode(10), - new IntegerNode(10))); - - [TestMethod] - public void Test_TenMinusTen() => AssertRewritten( - new IntegerNode(0), - new BinaryOperatorNode( - BinaryOperator.Minus, - new IntegerNode(10), - new IntegerNode(10))); - - [TestMethod] - public void Test_TenTimesTen() => AssertRewritten( - new IntegerNode(100), - new BinaryOperatorNode( - BinaryOperator.Multiply, - new IntegerNode(10), - new IntegerNode(10))); - - [TestMethod] - public void Test_TenDividedByTen() => AssertNotMatching("10/10"); - } -} diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RearrangeIntegersInSumTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RearrangeIntegersInSumTest.cs deleted file mode 100644 index 82619f4..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RearrangeIntegersInSumTest.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; -using ThinkSharp.FormulaParsing.Test; - -namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules -{ - [TestClass] - public class RearrangeIntegersInSumTest : RuleTest - { - protected override Rule CreateRule() => new RearrangeIntegersInSum(); - - [TestMethod] - public void Test_A() => this.AssertNotMatching("a"); - - [TestMethod] - public void Test_TenPlusAPlusTen () => AssertRewritten("10+10+a", "10+a+10"); - - [TestMethod] - public void Test_TenPlusAMinusTen() => AssertRewritten("10+-10+a", "10+a-10"); - - [TestMethod] - public void Test_TenMinusAMinusTen() => AssertRewritten("10+-10-a", "10-a-10"); - - [TestMethod] - public void Test_LongChain() => AssertRewritten("a+b+20+10+d+e+f+g+h+j+k+l", "a+b+10+d+e+f+g+h+j+k+l+20"); - } -} diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTermTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTermTest.cs deleted file mode 100644 index 0986df5..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTermTest.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; -using ThinkSharp.FormulaParsing.Test; - -namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules -{ - [TestClass] - public class RemoveBracketsInTermPlusMinusBracketsPlusMinusTermTest : RuleTest - { - protected override Rule CreateRule() => new RemoveBracketsInTermPlusMinusBracketsPlusMinusTerm(); - - [TestMethod] - public void Test_APlusAPlusAInBracketsPlusC() => AssertRewritten("a+a+a+c", "a+(a+a)+c"); - - [TestMethod] - public void Test_APlusAMinusAInBracketsPlusC() => AssertRewritten("a+a-a+c", "a+(a-a)+c"); - - [TestMethod] - public void Test_AMinusAMinusAInBracketsMinusC() => AssertRewritten("a-a+a-c", "a-(a-a)-c"); - - [TestMethod] - public void Test_AMinusAPlusAInBracketsPlusC() => AssertRewritten("a-a-a+c", "a-(a+a)+c"); - - [TestMethod] - public void Test_APlusAPlusAInBracketsMinusC() => AssertRewritten("a+a+a-c", "a+(a+a)-c"); - - [TestMethod] - public void Test_APlusAMinusAInBracketsMinusC() => AssertRewritten("a+a-a-c", "a+(a-a)-c"); - } -} diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsTest.cs deleted file mode 100644 index 3f173f3..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsTest.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; -using ThinkSharp.FormulaParsing.Test; - -namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules -{ - [TestClass] - public class RemoveBracketsInTermPlusMinusBracketsTest : RuleTest - { - protected override Rule CreateRule() => new RemoveBracketsInTermPlusMinusBrackets(); - - [TestMethod] - public void Test_APlusAInBracketsPlusA() => AssertRewritten("a+a+a", "(a+a)+a"); - - [TestMethod] - public void Test_APlusAPlusAInBrackets() => AssertRewritten("a+a+a", "a+(a+a)"); - - [TestMethod] - public void Test_APlusAInBracketsMinusA() => AssertRewritten("a+a-a", "(a+a)-a"); - - [TestMethod] - public void Test_AMinusAPlusAInBrackets() => AssertRewritten("a-a-a", "a-(a+a)"); - } -} diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativSignFromNumberTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativSignFromNumberTest.cs deleted file mode 100644 index 0724892..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativSignFromNumberTest.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; -using ThinkSharp.FormulaParsing.Test; - -namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules -{ - [TestClass] - public class RemoveNegativSignFromNumberTest : RuleTest - { - protected override Rule CreateRule() => new RemoveNegativeSignFromNumber(); - - [TestMethod] - public void Test_MinusOne() => AssertRewritten(new IntegerNode(-1), new SignedNode(Sign.Minus, new IntegerNode(1))); - [TestMethod] - public void Test_MinusDecimal() => AssertRewritten(new DecimalNode(-1), new SignedNode(Sign.Minus, new DecimalNode(1))); - [TestMethod] - public void Test_MinusVariable() => AssertNotMatching(new SignedNode(Sign.Minus, new VariableNode("TEST"))); - } -} diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInFrontOfBracketsTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInFrontOfBracketsTest.cs deleted file mode 100644 index 803fecd..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInFrontOfBracketsTest.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; -using ThinkSharp.FormulaParsing.Test; - -namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules -{ - [TestClass] - public class RemoveNegativeSignInFrontOfBracketsTest : RuleTest - { - protected override Rule CreateRule() => new RemoveNegativeSignInFrontOfBrackets(); - - [TestMethod] - public void Test_MinusA() => AssertRewritten("(-a)", "-(a)"); - - [TestMethod] - public void Test_MinusAPlusB() => AssertRewritten("(-a-b)", "-(a+b)"); - - [TestMethod] - public void Test_MinusMinusB() => AssertRewritten("(--a+b)", "-(-a-b)"); - - [TestMethod] - public void Test_MinusAPlusBTimesBracket() => AssertRewritten("(-a-b*(a-b))", "-(a+b*(a-b))"); - - [TestMethod] - public void Test_MinusMinusA() => AssertRewritten("(--a)", "-(-a)"); - - [TestMethod] - public void Test_MinusProduct() => AssertRewritten("(--a*b*c*d)", "-(-a*b*c*d)"); - } -} diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInInSubtractTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInInSubtractTest.cs deleted file mode 100644 index 2936067..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInInSubtractTest.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; -using ThinkSharp.FormulaParsing.Test; - -namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules -{ - [TestClass] - public class RemoveNegativeSignInInSubtractTest : RuleTest - { - protected override Rule CreateRule() => new RemoveNegativeSignInInSubtract(); - - [TestMethod] - public void Test_AMinusMinusB() => AssertRewritten("a+b", "a--b"); - } -} diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInInSumTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInInSumTest.cs deleted file mode 100644 index 6980f91..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignInInSumTest.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; -using ThinkSharp.FormulaParsing.Test; - -namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules -{ - [TestClass] - public class RemoveNegativeSignInInSumTest : RuleTest - { - protected override Rule CreateRule() => new RemoveNegativeSignInInSum(); - - [TestMethod] - public void Test_MinusAPlusB() => AssertRewritten("b-a", "-a+b"); - - [TestMethod] - public void Test_AMinusB() => AssertNotMatching("a-b"); - - [TestMethod] - public void Test_AMinusMinusB() => AssertNotMatching("a--b"); - } -} diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs deleted file mode 100644 index b28b420..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSignTest.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; -using ThinkSharp.FormulaParsing.Test; - -namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules -{ - [TestClass] - public class RemoveNegativeSignTimesNegatieSignTest : RuleTest - { - protected override Rule CreateRule() => new RemoveNegativeSignTimesNegatieSign(); - - [TestMethod] - public void Test_MinusMinusA () => AssertRewritten( - new VariableNode("a"), - new SignedNode(Sign.Minus, - new SignedNode(Sign.Minus, - new VariableNode("a")))); - - [TestMethod] - public void Test_MinusMinusAPlusB() => AssertRewritten( - new BinaryOperatorNode( - BinaryOperator.Plus, - new VariableNode("a"), - new VariableNode("b")), - new SignedNode(Sign.Minus, - new BinaryOperatorNode( - BinaryOperator.Plus, - new SignedNode(Sign.Minus, new VariableNode("a")), - new VariableNode("b")))); - - [TestMethod] - public void Test_MinusMinusATimesB() => AssertRewritten( - new BinaryOperatorNode( - BinaryOperator.Multiply, - new VariableNode("a"), - new VariableNode("b")), - new SignedNode(Sign.Minus, - new BinaryOperatorNode( - BinaryOperator.Multiply, - new SignedNode(Sign.Minus, new VariableNode("a")), - new VariableNode("b")))); - } -} diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNestedBracketsTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNestedBracketsTest.cs deleted file mode 100644 index 169d727..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveNestedBracketsTest.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; -using ThinkSharp.FormulaParsing.Test; - -namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules -{ - [TestClass] - public class RemoveNestedBracketsTest : RuleTest - { - protected override Rule CreateRule() => new RemoveNestedBrackets(); - - [TestMethod] - public void Test_APlusAInBrackets() => AssertRewritten("(a+a)", "((a+a))"); - - [TestMethod] - public void Test_APlusAInBracketsPlusA() => AssertNotMatching("((a+a)+a)"); - - [TestMethod] - public void Test_APlusAPlusAInBrackets() => AssertNotMatching("(a+(a+a))"); - - [TestMethod] - public void Test_APlusAPlusAInBracketsPlusC() => AssertNotMatching("(a+(a+a)+c)"); - - [TestMethod] - public void Test_APlusA() => AssertRewritten("(a+a)", "(((a+a)))"); - } -} diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemovePositiveSignTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemovePositiveSignTest.cs deleted file mode 100644 index 2208743..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemovePositiveSignTest.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; -using ThinkSharp.FormulaParsing.Test; - -namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules -{ - [TestClass] - public class RemovePositiveSignTest : RuleTest - { - protected override Rule CreateRule() => new RemovePositiveSign(); - [TestMethod] - public void Test_PlusPointFourOne() => AssertRewritten("1.40", "+1.4"); - [TestMethod] - public void Test_PlusOne() => AssertRewritten("1", "+1"); - [TestMethod] - public void Test_MinusOne() => AssertNotMatching("-1"); - [TestMethod] - public void Test_PlusOneMinusOneInBrackets() => AssertRewritten("(1-1)", "+(1-1)"); - [TestMethod] - public void Test_MinusOneMinusOneInBrackets() => AssertNotMatching("-(1-1)"); - [TestMethod] - public void Test_PlusOnePlusOneInBrackets() => AssertRewritten("(1+1)", "+(1+1)"); - [TestMethod] - public void Test_MinusOnePlusOneInBrackets() => AssertNotMatching("-(1+1)"); - [TestMethod] - public void Test_PlusVariable() => AssertRewritten("a", "+a"); - [TestMethod] - public void Test_MinusVariable() => AssertNotMatching("-a"); - [TestMethod] - public void Test_PlusFunction() => AssertRewritten("max(3, 2)", "+max(3,2)"); - [TestMethod] - public void Test_MinusFunction() => AssertNotMatching("-max(3,2)"); - } -} diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveRootBracketsTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveRootBracketsTest.cs deleted file mode 100644 index ac666b7..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RemoveRootBracketsTest.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; -using ThinkSharp.FormulaParsing.Test; - -namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules -{ - [TestClass] - public class RemoveRootBracketsTest : RuleTest - { - protected override Rule CreateRule() => new RemoveRootBrackets(); - - [TestMethod] - public void Test_APlusAInBrackets() => AssertRewritten("a+a", "(a+a)"); - - [TestMethod] - public void Test_APlusAInBracketsPlusAInBrackets() => AssertRewritten("(a+a)+a", "((a+a)+a)"); - - [TestMethod] - public void Test_APlusAPlusAInBracketsInBrackets() => AssertRewritten("a+(a+a)", "(a+(a+a))"); - - [TestMethod] - public void Test_APlusAPlusAInBracketsPlusCInBrackets() => AssertRewritten("a+(a+a)+c", "(a+(a+a)+c)"); - } -} diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RuleTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RuleTest.cs deleted file mode 100644 index 33e03f8..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/RuleTest.cs +++ /dev/null @@ -1,73 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; -using ThinkSharp.FormulaParsing.Test; -using ThinkSharp.FormulaParsing.Utils; - -namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules -{ - public abstract class RuleTest - { - private static IFormulaParser parser = FormulaParser - .CreateBuilder() - .ConfigureValidationBehavior(v => v.DisableVariableNameValidation()) - .Build(); - - protected abstract Rule CreateRule(); - - protected void AssertNotMatching(string formula) - { - var node = parser.Parse(formula).Value; - node = node is FormulaNode formulaNode - ? formulaNode.ChildNode - : node; - - AssertNotMatching(node); - } - - protected void AssertNotMatching(Node node) - { - var rule = CreateRule(); - - Assert.IsFalse(rule.Match(node)); - } - - protected void AssertRewritten(string expected, string formula) - { - var node = parser.Parse(formula).Value; - var rule = CreateRule(); - - var visitor = new ReplaceRuleTreeVisitor(rule); - - var simplifiedNode = node.Visit(visitor); - - Assert.IsTrue(simplifiedNode != node, "Rule matching fails."); - - var nodeToTExtVisitor = new NodesToFormulaTextVisitor(); - - var actual = simplifiedNode.Visit(nodeToTExtVisitor); - - Assert.AreEqual(expected, actual, "Simplified formula is not equal to actual."); - } - - protected void AssertRewritten(Node expected, Node input) - { - var rule = CreateRule(); - - var visitor = new ReplaceRuleTreeVisitor(rule); - - var simplifiedNode = input.Visit(visitor); - - Assert.IsTrue(simplifiedNode != input, "Rule matching fails."); - - var comparer = new NodeComparer(); - - Assert.IsTrue(comparer.Equals(expected, simplifiedNode), "Expected and actual trees are not equal."); - } - } -} \ No newline at end of file diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermPlusOrMinusZeroIsTermTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermPlusOrMinusZeroIsTermTest.cs deleted file mode 100644 index 272fd70..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermPlusOrMinusZeroIsTermTest.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; -using ThinkSharp.FormulaParsing.Test; - -namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules -{ - [TestClass] - public class TermPlusOrMinusZeroIsTermTest : RuleTest - { - protected override Rule CreateRule() => new TermPlusOrMinusZeroIsTermRule(); - - [TestMethod] - public void Test_OnePlusZeroIsOne() => AssertRewritten("1", "1+0"); - - [TestMethod] - public void Test_ZeroPlusOneIsOne() => AssertRewritten("1", "1+0"); - - [TestMethod] - public void Test_OneMinusZeroIsOne() => AssertRewritten("1", "1-0"); - - [TestMethod] - public void Test_ZeroMinusOneIsMinusOne() => AssertRewritten("-1", "0-1"); - - [TestMethod] - public void Test_OneTimesOnePlusZeroIsOneTimesOne() => AssertRewritten("1*1", "1*1+0"); - } -} diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTermTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTermTest.cs deleted file mode 100644 index 71228a5..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTermTest.cs +++ /dev/null @@ -1,60 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; -using ThinkSharp.FormulaParsing.Test; - -namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules -{ - [TestClass] - public class TermTimesOrDividedByMinusOneIsMinusTermTest : RuleTest - { - protected override Rule CreateRule() => new TermTimesOrDividedByMinusOneIsMinusTerm(); - - [TestMethod] - public void Test_OneTImesOne() => AssertRewritten( - new IntegerNode(-1), - new BinaryOperatorNode( - BinaryOperator.BySymbol("*"), - new IntegerNode(1), - new IntegerNode(-1))); - - [TestMethod] - public void Test_ATimesOne() => AssertRewritten( - new SignedNode(Sign.Minus, new VariableNode("a")), - new BinaryOperatorNode( - BinaryOperator.BySymbol("*"), - new VariableNode("a"), - new IntegerNode(-1))); - - [TestMethod] - public void Test_OneTimesA() => AssertRewritten( - new SignedNode(Sign.Minus, new VariableNode("a")), - new BinaryOperatorNode( - BinaryOperator.BySymbol("*"), - new IntegerNode(-1), - new VariableNode("a"))); - - [TestMethod] - public void Test_ADividedByOne() => AssertRewritten( - new BinaryOperatorNode( - BinaryOperator.BySymbol("/"), - new IntegerNode(1), - new SignedNode(Sign.Minus, new VariableNode("a"))), - new BinaryOperatorNode( - BinaryOperator.BySymbol("/"), - new IntegerNode(-1), - new VariableNode("a"))); - - [TestMethod] - public void Test_MinsADividedByMinusOne() => AssertRewritten( - new VariableNode("a"), - new BinaryOperatorNode( - BinaryOperator.BySymbol("/"), - new SignedNode(Sign.Minus, new VariableNode("a")), - new IntegerNode(-1))); - } -} diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermTimesOrDividedByOneIsTermTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermTimesOrDividedByOneIsTermTest.cs deleted file mode 100644 index d9faf87..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/Rules/TermTimesOrDividedByOneIsTermTest.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; -using ThinkSharp.FormulaParsing.Test; - -namespace ThinkSharp.FluentFormulaParser.Test.TermRewriting.Rules -{ - [TestClass] - public class TermTimesOrDividedByOneIsTermTest : RuleTest - { - protected override Rule CreateRule() => new TermTimesOrDividedByOneIsTerm(); - - [TestMethod] - public void Test_OneTImesOne() => AssertRewritten("1", "1*1"); - - [TestMethod] - public void Test_ATimesOne() => AssertRewritten("a", "a*1"); - - [TestMethod] - public void Test_OneTimesA() => AssertRewritten("a", "1*a"); - - [TestMethod] - public void Test_ADividedByOne() => AssertRewritten("a", "a/1"); - - [TestMethod] - public void Test_TermInBracketsDividedByOne() => AssertRewritten("(1+2+4)", "(1+2+4)/1"); - - [TestMethod] - public void Test_OneDividedByA() => AssertNotMatching("1/a"); - } -} diff --git a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/TermWritingSystemTest.cs b/ThinkSharp.FormulaParser.Test.Core/TermRewriting/TermWritingSystemTest.cs deleted file mode 100644 index 443e7a0..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/TermRewriting/TermWritingSystemTest.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; - -namespace ThinkSharp.FormulaParsing.Test.TermRewriting -{ - [TestClass] - public class TermWritingSystemTest - { - private static IFormulaParser parser = FormulaParser - .CreateBuilder() - .ConfigureValidationBehavior(v => v.DisableVariableNameValidation()) - .Build(); - - private static ITermRewritingSystem rewritingSystem = TermRewritingSystem.Create(); - - [TestMethod] - public void Test_APlusMinusManyZerosPlusAIsAPlusA() => AssertRewritten("a+a", "a+0-0+0-0+0-0+0+0+0+a"); - - [TestMethod] - public void Test_MinusOneInBrackets() => AssertRewritten("-1", "-(1)"); - - [TestMethod] - public void Test_APlusBInBrackets() => AssertRewritten("-a-b", "-(a+b)"); - - [TestMethod] - public void Test_MinusAMinusBInBrackets() => AssertRewritten("b+a", "-(-a-b)"); - - [TestMethod] - public void Test_ATimeBTimeCInBrackets() => AssertRewritten("-a*b*c", "-(a*b*c)"); - - [TestMethod] - public void Test_ATimeBMinusCInBracketsPlus3Times4() => AssertRewritten("-a*b+c+12", "-(a*b-c)+3*4"); - - [TestMethod] - public void Test_MaxOneTwoInBackets() => AssertRewritten("-max(1, 2)", "-(max(1, 2))"); - - [TestMethod] - public void Test_Compley1InBackets() => AssertRewritten("-pi-3*abc+max(1, 2)*3*10^4-2*10^5/3", "-(pi + 3 * abc - max(1, 2) * 3*10^4 +2*10^5 / 3)"); - - [TestMethod] - public void Test_OneTimesMinusOne() => AssertRewritten("-1", "1*-1"); - - [TestMethod] - public void Test_ATimesMinusOne() => AssertRewritten("-a", "a*-1"); - - [TestMethod] - public void Test_MinusOneTimesA() => AssertRewritten("-a", "-1*a"); - - [TestMethod] - public void Test_ADividedByMinusOne() => AssertRewritten("-a", "a/-1"); - - [TestMethod] - public void Test_MinusOneDividedByA() => AssertRewritten("1/-a", "-1/a"); - - [TestMethod] - public void Test_MinsADividedByMinusOne() => AssertRewritten("a", "-a/-1"); - - [TestMethod] - public void Test_MinusOneTimesMinsADividedByMinusOne() => AssertRewritten("-a", "-1*-a/-1"); - - [TestMethod] - public void Test_MinusOneTimesMinsADividedByMinusOne2() => AssertRewritten("-a*-a", "a*-a/-1"); - - [TestMethod] - public void Test_MinusOneTimesMinsADividedByMinusOne3() => AssertRewritten("a*-a", "a*-1*-a/-1"); - - [TestMethod] - public void Test_AManyTimeMinusOneTimeADividedByMinusOne() => AssertRewritten("a*a", "a*-1*-1*-1*-1*-1*a/-1"); - - [TestMethod] - public void Test_AManyTimeOneTimeADividedByOne() => AssertRewritten("a*a", "a*1*1*1*1*1*a/1"); - - [TestMethod] - public void Test_TwoPluscPlus2() => AssertRewritten("4+c", "2+c+2"); - - - private void AssertRewritten(string expected, string forumla) - { - var tree = parser.Parse(forumla).Value; - - var simlifiedTree = rewritingSystem.Simplify(tree); - - var nodeToTExtVisitor = new NodesToFormulaTextVisitor(); - - Assert.AreEqual(expected, simlifiedTree.Visit(nodeToTExtVisitor)); - } - } -} diff --git a/ThinkSharp.FormulaParser.Test.Core/ThinkSharp.FormulaParser.Test.Core.csproj b/ThinkSharp.FormulaParser.Test.Core/ThinkSharp.FormulaParser.Test.csproj similarity index 90% rename from ThinkSharp.FormulaParser.Test.Core/ThinkSharp.FormulaParser.Test.Core.csproj rename to ThinkSharp.FormulaParser.Test.Core/ThinkSharp.FormulaParser.Test.csproj index 45bdf51..232823b 100644 --- a/ThinkSharp.FormulaParser.Test.Core/ThinkSharp.FormulaParser.Test.Core.csproj +++ b/ThinkSharp.FormulaParser.Test.Core/ThinkSharp.FormulaParser.Test.csproj @@ -7,7 +7,7 @@ ThinkSharp.FormulaParser.Test.Core - ThinkSharp.FormulaParsing.Test + ThinkSharp.FormulaParsing diff --git a/ThinkSharp.FormulaParser.Test.Core/Utils/BinaryOperatorTest.cs b/ThinkSharp.FormulaParser.Test.Core/Utils/BinaryOperatorTest.cs deleted file mode 100644 index 9f5ee94..0000000 --- a/ThinkSharp.FormulaParser.Test.Core/Utils/BinaryOperatorTest.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.Utils; - -namespace ThinkSharp.FormulaParsing.Test -{ - [TestClass] - public class NodeComparerTest - { - private static IEqualityComparer comparer = new NodeComparer(); - private static IFormulaParser parser = FormulaParser - .CreateBuilder() - .ConfigureValidationBehavior(b => - { - b.DisableVariableNameValidation(); - b.DisableFunctionNameValidation(); - }) - .Build(); - - [TestMethod] - public void TestComparePlusEquals() - { - AssertAreEqual("1+2", "2+1"); - AssertAreEqual("1*2", "2*1"); - AssertAreEqual("1+a*c+3", "3+c*a+1"); - AssertAreEqual("1+a*c+3", "1+3+c*a"); - AssertAreEqual("a+c*(1+3*3+4)+2+3+4", "2+3+(3*3+4+1)*c+a+4"); - } - - [TestMethod] - public void TestComparePowEquals() - => AssertAreEqual("(a+b)^(1+2*b+3)", "(b+a)^(3+b*2+1)"); - - [TestMethod] - public void TestCompareFunctionEquals() - => AssertAreEqual("3*test(a+1,1+b,d*c)", "test(1+a,b+1,c*d)*3"); - - [TestMethod] - public void TestCompareDividedByEquals() - => AssertAreEqual("3*(a+b+c)/2*(f*d*s)", "(c+a+b)*3/2*(d*f*s)"); - - [TestMethod] - public void TestCompareMinusEquals() - { - AssertAreEqual("1-3", "-3+1"); - } - - private void AssertAreEqual(params string[] formulas) - { - if (formulas.Length < 2) - Assert.Fail("Need at least 2 formulas!"); - - var nodes = formulas.Select(f => parser.Parse(f).Value).ToArray(); - for (int i = 0; i < nodes.Length; i++) - { - for (int j = i; j < nodes.Length; j++) - { - Assert.IsTrue(comparer.Equals(nodes[i], nodes[j])); - } - } - } - } -} diff --git a/ThinkSharp.FormulaParser.sln b/ThinkSharp.FormulaParser.sln index 17728e6..17b0604 100644 --- a/ThinkSharp.FormulaParser.sln +++ b/ThinkSharp.FormulaParser.sln @@ -5,7 +5,7 @@ VisualStudioVersion = 16.0.28922.388 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThinkSharp.FormulaParser", "ThinkSharp.FormulaParser\ThinkSharp.FormulaParser.csproj", "{C69728F7-CDC0-4FA2-B805-E0DD6F498E9F}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThinkSharp.FormulaParser.Test.Core", "ThinkSharp.FormulaParser.Test.Core\ThinkSharp.FormulaParser.Test.Core.csproj", "{1CAA5403-6EBB-4885-A51A-10533E673890}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThinkSharp.FormulaParser.Test", "ThinkSharp.FormulaParser.Test.Core\ThinkSharp.FormulaParser.Test.csproj", "{1CAA5403-6EBB-4885-A51A-10533E673890}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/ThinkSharp.FormulaParser/FormulaParser.cs b/ThinkSharp.FormulaParser/FormulaParser.cs index 1eb7cbd..d6d458b 100644 --- a/ThinkSharp.FormulaParser/FormulaParser.cs +++ b/ThinkSharp.FormulaParser/FormulaParser.cs @@ -136,7 +136,6 @@ private static FormulaParserResult WrapWithExceptionHandling(F { return new FormulaParserResult(new Error(ex.Message)); } - } private Node ParseFormula(string formula, IReadOnlyDictionary variables) diff --git a/ThinkSharp.FormulaParser/TermRewriting/Helper/CollectNonTerminalNodes.cs b/ThinkSharp.FormulaParser/TermRewriting/Helper/CollectNonTerminalNodes.cs deleted file mode 100644 index 2d48339..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Helper/CollectNonTerminalNodes.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.Ast.Visitors; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Helper -{ - public class CollectNonTerminalNodes : INodeVisitor> - { - public IEnumerable Visit(FormulaNode node) - { - return node.ChildNode.Visit(this); - } - - public IEnumerable Visit(BracketedNode node) - { - yield return node; - foreach (var childNode in node.ChildNode.Visit(this)) - yield return node; - } - - public IEnumerable Visit(DecimalNode node) - { - yield break; - } - - public IEnumerable Visit(IntegerNode node) - { - yield break; - } - - public IEnumerable Visit(VariableNode node) - { - yield break; - } - - public IEnumerable Visit(ConstantNode node) - { - yield break; - } - - public IEnumerable Visit(BinaryOperatorNode node) - { - yield return node; - foreach (var childNode in node.LeftNode.Visit(this)) - yield return node; - foreach (var childNode in node.RightNode.Visit(this)) - yield return node; - } - - public IEnumerable Visit(PowerNode node) - { - yield return node; - foreach (var childNode in node.BaseNode.Visit(this)) - yield return node; - foreach (var childNode in node.ExponentNode.Visit(this)) - yield return node; - } - - public IEnumerable Visit(SignedNode node) - { - yield return node; - foreach (var childNode in node.Node.Visit(this)) - yield return node; - } - - public IEnumerable Visit(FunctionNode node) - { - yield return node; - foreach (var parameter in node.Parameters) - foreach (var childNode in parameter.Visit(this)) - yield return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/ITermRewritingSystem.cs b/ThinkSharp.FormulaParser/TermRewriting/ITermRewritingSystem.cs deleted file mode 100644 index 06910b8..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/ITermRewritingSystem.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; - -namespace ThinkSharp.FormulaParsing.TermRewriting -{ - public interface ITermRewritingSystem - { - Node Simplify(Node node); - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/ReplaceRuleTreeVisitor.cs b/ThinkSharp.FormulaParser/TermRewriting/ReplaceRuleTreeVisitor.cs deleted file mode 100644 index f15a41a..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/ReplaceRuleTreeVisitor.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.Ast.Visitors; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; - -namespace ThinkSharp.FormulaParsing.TermRewriting -{ - public class ReplaceRuleTreeVisitor : INodeVisitor - { - private readonly Rule rule; - private readonly ParentNodeContex parentContext = new ParentNodeContex(); - - private class ParentNodeContex : IDisposable - { - private Stack stackedNodes = new Stack(); - - public Node Parent => stackedNodes.Count == 0 ? null : stackedNodes.Peek(); - - public IDisposable Push(Node parent) - { - stackedNodes.Push(parent); - return this; - } - - void IDisposable.Dispose() => stackedNodes.Pop(); - } - - public ReplaceRuleTreeVisitor(Rule rule) - { - this.rule = rule; - } - - public Node Visit(FormulaNode node) - { - using (parentContext.Push(node)) - { - var child = node.ChildNode.Visit(this); - return child == node.ChildNode ? node : new FormulaNode(child); - } - } - - public Node Visit(BracketedNode node) - { - using (parentContext.Push(node)) - { - var child = node.ChildNode.Visit(this); - node = node.ChildNode == child ? node : new BracketedNode(child); - } - - return TryRewrite(node); - } - - public Node Visit(DecimalNode node) => TryRewrite(node); - - public Node Visit(IntegerNode node) => TryRewrite(node); - - public Node Visit(VariableNode node) => TryRewrite(node); - - public Node Visit(ConstantNode node) => TryRewrite(node); - - public Node Visit(BinaryOperatorNode node) - { - using (parentContext.Push(node)) - { - var left = node.LeftNode.Visit(this); - var right = node.RightNode.Visit(this); - node = left == node.LeftNode && right == node.RightNode - ? node - : new BinaryOperatorNode(node.BinaryOperator, left, right); - } - return TryRewrite(node); - } - - public Node Visit(PowerNode node) - { - using (parentContext.Push(node)) - { - var baseNode = node.BaseNode.Visit(this); - var exponentNode = node.ExponentNode.Visit(this); - node = baseNode == node.BaseNode && exponentNode == node.ExponentNode - ? node - : new PowerNode(baseNode, exponentNode); - } - return TryRewrite(node); - } - - public Node Visit(SignedNode node) - { - - using (parentContext.Push(node)) - { - var child = node.Node.Visit(this); - node = child == node.Node ? node : new SignedNode(node.Sign, child); - } - return TryRewrite(node); - } - - public Node Visit(FunctionNode node) - { - using (parentContext.Push(node)) - { - var rewrittenParameters = node.Parameters.Select(p => p.Visit(this)).ToArray(); - node = rewrittenParameters.SequenceEqual(node.Parameters) - ? node - : new FunctionNode(node.FunctionName, rewrittenParameters); - } - - return TryRewrite(node); - } - - private Node TryRewrite(Node node) - { - if (this.rule.Match(node, this.parentContext.Parent)) - { - return rule.Rewrite(node, this.parentContext.Parent); - } - - return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/ConvertDecimalToLong.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/ConvertDecimalToLong.cs deleted file mode 100644 index 8f23b01..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/ConvertDecimalToLong.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.Ast.Visitors; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class ConvertDecimalToLong : Rule - { - protected override bool MatchInternal(Node node, Node Parent) - { - return node is DecimalNode dec && dec.Value % 1 == 0; - } - - protected override Node RewriteInternal(Node node, Node Parent) - { - if (node is DecimalNode dec && dec.Value % 1 == 0) - { - try - { - return new IntegerNode(NumberFormat.Dec, (long)dec.Value); - } - catch - { - Debug.Fail("Unable to convert decimal to long."); - // ignore - } - } - - Debug.Fail("Should not happen"); - return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/EvaluateIntegers.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/EvaluateIntegers.cs deleted file mode 100644 index 8ea3e82..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/EvaluateIntegers.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class EvaluateIntegers : Rule - { - protected override bool MatchInternal(Node node, Node parent) - { - return node is BinaryOperatorNode binOpNode - && (binOpNode.IsPlusOrMinus() || binOpNode.IsMultipy()) - && binOpNode.LeftNode is IntegerNode - && binOpNode.RightNode is IntegerNode; - } - - protected override Node RewriteInternal(Node node, Node parent) - { - if (node is BinaryOperatorNode binOpNode - && (binOpNode.IsPlusOrMinus() || binOpNode.IsMultipy()) - && binOpNode.LeftNode is IntegerNode leftInt - && binOpNode.RightNode is IntegerNode rightInt) - { - var value = binOpNode.BinaryOperator.Evaluate(leftInt.Value, rightInt.Value); - return new IntegerNode(NumberFormat.Dec, value); - } - - Debug.Fail("Should not happen"); - return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/NodeExtensions.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/NodeExtensions.cs deleted file mode 100644 index d4ac9bc..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/NodeExtensions.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.Ast.Visitors; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - internal static class NodeExtensions - { - private class SwitchSignForTermsWithinBracketsVisitor : INodeVisitor - { - public Node Visit(FormulaNode node) => node.ChildNode.Visit(this); - public Node Visit(BracketedNode node) => node; - public Node Visit(DecimalNode node) => node; - public Node Visit(VariableNode node) => node; - public Node Visit(ConstantNode node) => node; - public Node Visit(PowerNode node) => node; - public Node Visit(SignedNode node) => node; - public Node Visit(FunctionNode node) => node; - public Node Visit(IntegerNode node) => node; - public Node Visit(BinaryOperatorNode node) - { - var newLeft = node.LeftNode.Visit(this); - var newRight = node.RightNode.Visit(this); - - var symbol = node.BinaryOperator.Symbol; - var op = symbol == "+" ? BinaryOperator.BySymbol("-") - : symbol == "-" ? BinaryOperator.BySymbol("+") - : node.BinaryOperator; - - return new BinaryOperatorNode(op, newLeft, newRight); - } - } - - private class SwitchSignConcreteNodeVisitor : INodeVisitor - { - public Node Visit(FormulaNode node) => node.ChildNode.Visit(this); - public Node Visit(BracketedNode node) - => new SignedNode(Sign.Minus, new BracketedNode(node.SwitchSignForAllSummands())); - public Node Visit(DecimalNode node) => new DecimalNode(node.Value * -1); - public Node Visit(VariableNode node) => new SignedNode(Sign.Minus, node); - public Node Visit(ConstantNode node) => new SignedNode(Sign.Minus, node); - public Node Visit(PowerNode node) => new SignedNode(Sign.Minus, node); - public Node Visit(SignedNode node) => - node.Sign == Sign.Minus - ? node.Node - : new SignedNode(Sign.Minus, node.Node); - - public Node Visit(FunctionNode node) => new SignedNode(Sign.Minus, node); - public Node Visit(IntegerNode node) => new IntegerNode(node.Format, node.Value * -1); - public Node Visit(BinaryOperatorNode node) => new SignedNode(Sign.Minus, node); - } - - private class TransformNodeWithinMinusSignNodeVisitor : INodeVisitor - { - public Node Visit(FormulaNode node) => - throw new InvalidOperationException("Formula node is always the root node."); - public Node Visit(BracketedNode node) - => new BracketedNode(node.ChildNode.SwitchSignForAllSummands()); - public Node Visit(DecimalNode node) => new DecimalNode(node.Value * -1); - public Node Visit(VariableNode node) => new SignedNode(Sign.Minus, node); - public Node Visit(ConstantNode node) => new SignedNode(Sign.Minus, node); - public Node Visit(PowerNode node) => new SignedNode(Sign.Minus, node); - public Node Visit(SignedNode node) => - node.Sign == Sign.Minus - ? node.Node - : new SignedNode(Sign.Minus, node); - - public Node Visit(FunctionNode node) => new SignedNode(Sign.Minus, node); - public Node Visit(IntegerNode node) => new IntegerNode(node.Format, node.Value * -1); - public Node Visit(BinaryOperatorNode node) => new SignedNode(Sign.Minus, node); - } - - public static bool EqualsNumber(this Node node, int number) - => (node is DecimalNode rightDecNode && rightDecNode.Value == number) || - (node is IntegerNode rightIntNode && rightIntNode.Value == number); - - - public static bool IsPlus(this BinaryOperatorNode node) - => node.BinaryOperator.Symbol == "+"; - - public static bool IsMinus(this BinaryOperatorNode node) - => node.BinaryOperator.Symbol == "-"; - public static bool IsMultipy(this BinaryOperatorNode node) - => node.BinaryOperator.Symbol == "*"; - - public static bool IsDividedBy(this BinaryOperatorNode node) - => node.BinaryOperator.Symbol == "/"; - - public static bool IsPlusOrMinus(this BinaryOperatorNode node) - => node.IsPlus() || node.IsMinus(); - - public static bool IsMultiplyOrDividedBy(this BinaryOperatorNode node) - => node.IsMultipy() || node.IsDividedBy(); - - public static Node SwitchSign(this Node node) - => node.Visit(new SwitchSignConcreteNodeVisitor()); - - public static Node SwitchSignForAllSummands(this Node node) - => node.Visit(new SwitchSignForTermsWithinBracketsVisitor()); - - public static Node ResolveMinusSignedNodeContent(this Node node) - => node.Visit(new TransformNodeWithinMinusSignNodeVisitor()); - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RearrangeIntegersInSum.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RearrangeIntegersInSum.cs deleted file mode 100644 index e8e2084..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/RearrangeIntegersInSum.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.Ast.Visitors; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class RearrangeIntegersInSum : Rule - { - protected override bool MatchInternal(Node node, Node parent) - => FindBinaryNodesWithInteger(node).Skip(1).Any(); - - private class RearrangeVisitor : TransformNodesVisitor - { - private readonly BinaryOperatorNode first; - private readonly BinaryOperatorNode second; - - private readonly Node firstReplacement; - private readonly Node firstInteger; - - public RearrangeVisitor(BinaryOperatorNode first, BinaryOperatorNode second) - { - this.first = first; - this.second = second; - - if (first.LeftNode is IntegerNode firstLeftInteger) - { - firstInteger = firstLeftInteger; - firstReplacement = first.IsMinus() - ? new SignedNode(Sign.Minus, first.RightNode) - : first.RightNode; - } - else if (first.RightNode is IntegerNode firstRightInteger) - { - firstReplacement = first.LeftNode; - firstInteger = first.IsMinus() - ? new IntegerNode(firstRightInteger.Format, firstRightInteger.Value * -1) - : firstRightInteger; - } - else - { - throw new ArgumentException("first: left or right node must be an integer."); - } - } - - public override Node Visit(BinaryOperatorNode node) - { - if (node == first) - { - return firstReplacement.Visit(this); - } - - if (node == second) - { - if (node.LeftNode is IntegerNode) - { - return new BinaryOperatorNode(node.BinaryOperator, - new BinaryOperatorNode(BinaryOperator.Plus, - node.LeftNode.Visit(this), - firstInteger), - node.RightNode.Visit(this)); - } - if (node.RightNode is IntegerNode) - { - return new BinaryOperatorNode(BinaryOperator.Plus, - node.LeftNode.Visit(this), - new BinaryOperatorNode(node.BinaryOperator, - firstInteger, - node.RightNode.Visit(this))); - } - else - { - throw new ArgumentException("second: left or right node must be an integer."); - } - } - - return base.Visit(node); - } - } - - private static IEnumerable FindBinaryNodesWithInteger(Node node) - { - if (node is BinaryOperatorNode binOpNode && binOpNode.IsPlusOrMinus()) - { - var isLeftInteger = binOpNode.LeftNode is IntegerNode; - var isRightInteger = binOpNode.RightNode is IntegerNode; - if (isLeftInteger ^ isRightInteger) - { - yield return binOpNode; - } - - foreach (var children in FindBinaryNodesWithInteger(binOpNode.LeftNode)) - { - yield return children; - } - - foreach (var children in FindBinaryNodesWithInteger(binOpNode.RightNode)) - { - yield return children; - } - } - } - - protected override Node RewriteInternal(Node node, Node parent) - { - var binOpNodesIntegers = FindBinaryNodesWithInteger(node).Take(2).ToArray(); - - if (binOpNodesIntegers.Length == 2) - { - var visitor = new RearrangeVisitor(binOpNodesIntegers[0], binOpNodesIntegers[1]); - return node.Visit(visitor); - } - - Debug.Fail("Should not happen"); - return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBrackets.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBrackets.cs deleted file mode 100644 index 5e37d65..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBrackets.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class RemoveBracketsInTermPlusMinusBrackets : Rule - { - protected override bool MatchInternal(Node node, Node parent) - { - return (parent == null || parent is FormulaNode) - && node is BinaryOperatorNode binaryOperatorNode - && binaryOperatorNode.IsPlusOrMinus() - && (binaryOperatorNode.LeftNode is BracketedNode || binaryOperatorNode.RightNode is BracketedNode); - } - - protected override Node RewriteInternal(Node node, Node parent) - { - if ((parent == null || parent is FormulaNode) - && node is BinaryOperatorNode binaryOperatorNode) - { - if (binaryOperatorNode.IsPlus()) - { - if (TryRemoveBrackets(binaryOperatorNode.LeftNode, out Node left) - | TryRemoveBrackets(binaryOperatorNode.RightNode, out Node right)) - { - return new BinaryOperatorNode(binaryOperatorNode.BinaryOperator, left, right); - } - } - - if (binaryOperatorNode.IsMinus()) - { - if (TryRemoveBrackets(binaryOperatorNode.LeftNode, out Node left)) - { - return new BinaryOperatorNode(binaryOperatorNode.BinaryOperator, left, binaryOperatorNode.RightNode); - } - - if (TryRemoveBrackets(binaryOperatorNode.RightNode, out Node right)) - { - return new BinaryOperatorNode(binaryOperatorNode.BinaryOperator, binaryOperatorNode.LeftNode, right.SwitchSignForAllSummands()); - } - } - } - - Debug.Fail("Should not happen"); - return node; - } - - private static bool TryRemoveBrackets(Node node, out Node rewritten) - { - if (node is BracketedNode bracketed) - { - rewritten = bracketed.ChildNode; - return true; - } - - rewritten = node; - return false; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTerm.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTerm.cs deleted file mode 100644 index 71132cf..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveBracketsInTermPlusMinusBracketsPlusMinusTerm.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class RemoveBracketsInTermPlusMinusBracketsPlusMinusTerm : Rule - { - protected override bool MatchInternal(Node node, Node parent) - { - return (parent is BinaryOperatorNode parentBinNode - && parentBinNode.IsPlusOrMinus() - && node is BinaryOperatorNode binNode - && binNode.IsPlusOrMinus() - && ((parentBinNode.LeftNode == node - && binNode.RightNode is BracketedNode) - || (parentBinNode.RightNode == node - && binNode.LeftNode is BracketedNode))); - } - - protected override Node RewriteInternal(Node node, Node parent) - { - if (parent is BinaryOperatorNode parentBinNode - && parentBinNode.IsPlusOrMinus() - && node is BinaryOperatorNode binNode - && binNode.IsPlusOrMinus()) - { - if (parentBinNode.LeftNode == binNode && binNode.RightNode is BracketedNode rightBracketed) - { - var rightNode = rightBracketed.ChildNode; - - if (binNode.IsMinus()) - { - rightNode = rightNode.SwitchSignForAllSummands(); - } - - return new BinaryOperatorNode( - binNode.BinaryOperator, - binNode.LeftNode, - rightNode); - } - - if (parentBinNode.RightNode == binNode && binNode.LeftNode is BracketedNode leftBracketed) - { - var leftNode = leftBracketed.ChildNode; - - if (parentBinNode.IsMinus()) - { - leftNode = leftNode.SwitchSignForAllSummands(); - } - - return new BinaryOperatorNode( - binNode.BinaryOperator, - leftNode, - binNode.RightNode); - } - } - - Debug.Fail("Should not happen"); - return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignFromNumber.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignFromNumber.cs deleted file mode 100644 index 6bd9a88..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignFromNumber.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class RemoveNegativeSignFromNumber : Rule - { - protected override bool MatchInternal(Node node, Node Parent) - { - return node is SignedNode signedNode - && signedNode.Sign == Sign.Minus - && (signedNode.Node is DecimalNode || signedNode.Node is IntegerNode); - } - - protected override Node RewriteInternal(Node node, Node Parent) - { - if (node is SignedNode signedNode && signedNode.Sign == Sign.Minus) - { - if (signedNode.Node is DecimalNode dnode) - { - return new DecimalNode(dnode.Value * -1); - } - if (signedNode.Node is IntegerNode inode) - { - return new IntegerNode(inode.Format, inode.Value * -1); - } - } - - Debug.Fail("Should not happen"); - return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInFrontOfBrackets.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInFrontOfBrackets.cs deleted file mode 100644 index a68fa82..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInFrontOfBrackets.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using ThinkSharp.FormulaParsing.Ast.Nodes; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class RemoveNegativeSignInFrontOfBrackets : Rule - { - protected override bool MatchInternal(Node node, Node parent) - { - if (node is SignedNode signNode - && signNode.Sign == Sign.Minus - && signNode.Node is BracketedNode bracketedNode) - { - return true; - } - - return false; - } - - protected override Node RewriteInternal(Node node, Node parent) - { - if (node is SignedNode signNode && signNode.Sign == Sign.Minus && signNode.Node is BracketedNode bracketedNode) - { - var child = this.Process(bracketedNode.ChildNode, true); - return new BracketedNode(child); - } - - Debug.Fail("Should not happen"); - return node; - } - - private Node Process(Node node, bool isLeftBranch) - { - if (node is BinaryOperatorNode binOp) - { - var left = Process(binOp.LeftNode, isLeftBranch); - var right = Process(binOp.RightNode, false); - - var symbol = binOp.BinaryOperator.Symbol; - var op = symbol == "+" ? BinaryOperator.BySymbol("-") - : symbol == "-" ? BinaryOperator.BySymbol("+") - : binOp.BinaryOperator; - - return new BinaryOperatorNode(op, left, right); - } - - return isLeftBranch ? new SignedNode(Sign.Minus, node) : node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInInSubtract.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInInSubtract.cs deleted file mode 100644 index 6f4da1e..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInInSubtract.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class RemoveNegativeSignInInSubtract : Rule - { - protected override bool MatchInternal(Node node, Node Parent) - { - return node is BinaryOperatorNode binOp - && binOp.BinaryOperator.Symbol == "-" - && binOp.RightNode is SignedNode signedNode - && signedNode.Sign == Sign.Minus; - } - - protected override Node RewriteInternal(Node node, Node Parent) - { - if (node is BinaryOperatorNode binOp - && binOp.BinaryOperator.Symbol == "-" - && binOp.RightNode is SignedNode signedNode - && signedNode.Sign == Sign.Minus) - { - return new BinaryOperatorNode( - BinaryOperator.BySymbol("+"), - binOp.LeftNode, - signedNode.Node); - } - - Debug.Fail("Should not happen"); - return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInInSum.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInInSum.cs deleted file mode 100644 index e617424..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignInInSum.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class RemoveNegativeSignInInSum : Rule - { - protected override bool MatchInternal(Node node, Node Parent) - { - return node is BinaryOperatorNode binOp - && binOp.BinaryOperator.Symbol == "+" - && binOp.LeftNode is SignedNode signedNode - && signedNode.Sign == Sign.Minus; - } - - protected override Node RewriteInternal(Node node, Node Parent) - { - if (node is BinaryOperatorNode binOp - && binOp.BinaryOperator.Symbol == "+" - && binOp.LeftNode is SignedNode signedNode - && signedNode.Sign == Sign.Minus) - { - return new BinaryOperatorNode( - BinaryOperator.BySymbol("-"), - binOp.RightNode, - signedNode.Node); - } - - Debug.Fail("Should not happen"); - return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSign.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSign.cs deleted file mode 100644 index 52cf36b..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNegativeSignTimesNegatieSign.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class RemoveNegativeSignTimesNegatieSign : Rule - { - protected override bool MatchInternal(Node node, Node Parent) - { - if (node is SignedNode signedNode - && signedNode.Sign == Sign.Minus) - { - var innerNode = signedNode.Node; - - while (true) - { - if (innerNode is SignedNode innersignedNode - && innersignedNode.Sign == Sign.Minus) - { - return true; - } - - if (innerNode is BinaryOperatorNode binNode) - { - innerNode = binNode.LeftNode; - } - else - { - break; - } - } - } - - return false; - } - - protected override Node RewriteInternal(Node node, Node Parent) - { - if (node is SignedNode signedNode - && signedNode.Sign == Sign.Minus) - { - var innerNode = signedNode.Node; - var binNodes = new Stack(); - while (true) - { - if (innerNode is SignedNode innersignedNode - && innersignedNode.Sign == Sign.Minus) - { - var rewrittenNode = innersignedNode.Node; - while (binNodes.Count > 0) - { - var current = binNodes.Pop(); - rewrittenNode = new BinaryOperatorNode(current.BinaryOperator, rewrittenNode, current.RightNode); - } - - return rewrittenNode; - } - - if (innerNode is BinaryOperatorNode binNode) - { - binNodes.Push(binNode); - innerNode = binNode.LeftNode; - } - else - { - break; - } - } - } - - Debug.Fail("Should not happen"); - return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNestedBrackets.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNestedBrackets.cs deleted file mode 100644 index dd36ec0..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveNestedBrackets.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class RemoveNestedBrackets : Rule - { - protected override bool MatchInternal(Node node, Node Parent) - { - return node is BracketedNode outerBrackets - && outerBrackets.ChildNode is BracketedNode; - } - - protected override Node RewriteInternal(Node node, Node Parent) - { - if (node is BracketedNode outerNode && - outerNode.ChildNode is BracketedNode innerNode) - { - return innerNode; - } - - Debug.Fail("Should not happen"); - return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemovePositiveSign.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemovePositiveSign.cs deleted file mode 100644 index 4b88b5a..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemovePositiveSign.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class RemovePositiveSign : Rule - { - protected override bool MatchInternal(Node node, Node Parent) - { - return node is SignedNode signedNode && signedNode.Sign == Sign.Plus; - } - - protected override Node RewriteInternal(Node node, Node Parent) - { - if (node is SignedNode signedNode && signedNode.Sign == Sign.Plus) - { - return signedNode.Node; - } - - Debug.Fail("Should not happen"); - return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveRootBrackets.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveRootBrackets.cs deleted file mode 100644 index 5fc0c77..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/RemoveRootBrackets.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class RemoveRootBrackets : Rule - { - protected override bool MatchInternal(Node node, Node parent) - { - return (parent == null || parent is FormulaNode) && node is BracketedNode; - } - - protected override Node RewriteInternal(Node node, Node parent) - { - if ((parent == null || parent is FormulaNode) && node is BracketedNode bracketNode) - { - return bracketNode.ChildNode; - } - - Debug.Fail("Should not happen"); - return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/Rule.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/Rule.cs deleted file mode 100644 index 97782e9..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/Rule.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.Ast.Visitors; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public abstract class Rule - { - public bool Match(Node node, Node parent = null) => this.MatchInternal(node, parent); - - public Node Rewrite(Node node, Node parent = null) - { - var rewrittenNode = this.RewriteInternal(node, parent); - - var nodeToText = new NodesToTextDebugVisitor(); - - var from = node.Visit(nodeToText); - var to = rewrittenNode.Visit(nodeToText); - - Debug.WriteLine($"Rewrite: '{from}' to '{to}' Type: (${this.GetType()})"); - - return rewrittenNode; - } - - protected abstract bool MatchInternal(Node node, Node parent); - - protected abstract Node RewriteInternal(Node node, Node parent); - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermDividesByTermIsOne.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermDividesByTermIsOne.cs deleted file mode 100644 index f75d50d..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermDividesByTermIsOne.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class TermDividesByTermIsOne : Rule - { - protected override bool MatchInternal(Node node, Node Parent) - { - if (node is BinaryOperatorNode opNode) - { - if (opNode.BinaryOperator.Symbol == "+" || - opNode.BinaryOperator.Symbol == "-") - { - if (opNode.LeftNode is DecimalNode leftNumNode) - { - if (leftNumNode.Value == 0.0) - { - return true; - } - } - - if (opNode.RightNode is DecimalNode rightNumNode) - { - if (rightNumNode.Value == 0.0) - { - return true; - } - } - } - } - - return false; - } - - protected override Node RewriteInternal(Node node, Node Parent) - { - if (node is BinaryOperatorNode opNode) - { - var isAddOperation = opNode.BinaryOperator.Symbol == "+"; - var isSubOperation = opNode.BinaryOperator.Symbol == "-"; - - if (isAddOperation || isSubOperation) - { - if (opNode.LeftNode is DecimalNode leftNumNode) - { - if (leftNumNode.Value == 0.0) - { - return isSubOperation - ? new SignedNode(Sign.Minus, opNode.RightNode) - : opNode.RightNode; - } - } - - if (opNode.RightNode is DecimalNode rightNumNode) - { - if (rightNumNode.Value == 0.0) - { - return opNode.LeftNode; - } - } - } - } - - Debug.Fail("Should not happen"); - return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermPlusOrMinusZeroIsTerm.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermPlusOrMinusZeroIsTerm.cs deleted file mode 100644 index 41f7cd4..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermPlusOrMinusZeroIsTerm.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class TermPlusOrMinusZeroIsTermRule : Rule - { - protected override bool MatchInternal(Node node, Node Parent) - { - if (node is BinaryOperatorNode opNode) - { - if (opNode.BinaryOperator.Symbol == "+" || - opNode.BinaryOperator.Symbol == "-") - { - return opNode.LeftNode.EqualsNumber(0) || opNode.RightNode.EqualsNumber(0); - } - } - - return false; - } - - protected override Node RewriteInternal(Node node, Node Parent) - { - if (node is BinaryOperatorNode opNode) - { - var isAddOperation = opNode.BinaryOperator.Symbol == "+"; - var isMinusOperation = opNode.BinaryOperator.Symbol == "-"; - - if (isAddOperation || isMinusOperation) - { - if (opNode.LeftNode.EqualsNumber(0)) - { - return isMinusOperation - ? new SignedNode(Sign.Minus, opNode.RightNode) - : opNode.RightNode; - } - - if (opNode.RightNode.EqualsNumber(0)) - { - return opNode.LeftNode; - } - } - } - - Debug.Fail("Should not happen"); - return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTerm.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTerm.cs deleted file mode 100644 index a240b30..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByMinusOneIsMinusTerm.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class TermTimesOrDividedByMinusOneIsMinusTerm : Rule - { - protected override bool MatchInternal(Node node, Node Parent) - { - if (node is BinaryOperatorNode opNode) - { - var isTimes = opNode.BinaryOperator.Symbol == "*"; - var isDividedBy = opNode.BinaryOperator.Symbol == "/"; - - return (isTimes || isDividedBy) && - (opNode.LeftNode.EqualsNumber(-1) || opNode.RightNode.EqualsNumber(-1)); - } - - return false; - } - - protected override Node RewriteInternal(Node node, Node Parent) - { - if (node is BinaryOperatorNode opNode) - { - var isTimes = opNode.BinaryOperator.Symbol == "*"; - var isDividedBy = opNode.BinaryOperator.Symbol == "/"; - - if (isTimes && opNode.LeftNode.EqualsNumber(-1)) - { - return opNode.RightNode.SwitchSign(); - } - - if (isDividedBy && opNode.LeftNode.EqualsNumber(-1)) - { - return new BinaryOperatorNode( - opNode.BinaryOperator, - new IntegerNode(1), - opNode.RightNode.SwitchSign()); - } - - if ((isTimes || isDividedBy) && opNode.RightNode.EqualsNumber(-1)) - { - return opNode.LeftNode.SwitchSign(); - } - } - - Debug.Fail("Should not happen"); - return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByOneIsTerm.cs b/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByOneIsTerm.cs deleted file mode 100644 index 0acbdeb..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/Rules/TermTimesOrDividedByOneIsTerm.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; - -namespace ThinkSharp.FormulaParsing.TermRewriting.Rules -{ - public class TermTimesOrDividedByOneIsTerm : Rule - { - protected override bool MatchInternal(Node node, Node Parent) - { - if (node is BinaryOperatorNode opNode) - { - var isTimes = opNode.BinaryOperator.Symbol == "*"; - var isDividedBy = opNode.BinaryOperator.Symbol == "/"; - - if (isTimes && opNode.LeftNode.EqualsNumber(1)) - { - return true; - } - - if ((isTimes || isDividedBy) && opNode.RightNode.EqualsNumber(1)) - { - return true; - } - } - - return false; - } - - protected override Node RewriteInternal(Node node, Node Parent) - { - if (node is BinaryOperatorNode opNode) - { - var isTimes = opNode.BinaryOperator.Symbol == "*"; - var isDividedBy = opNode.BinaryOperator.Symbol == "/"; - - if (isTimes && opNode.LeftNode.EqualsNumber(1)) - { - return opNode.RightNode; - } - - if ((isTimes || isDividedBy) && opNode.RightNode.EqualsNumber(1)) - { - return opNode.LeftNode; - } - } - - Debug.Fail("Should not happen"); - return node; - } - } -} diff --git a/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs b/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs deleted file mode 100644 index adcbfdf..0000000 --- a/ThinkSharp.FormulaParser/TermRewriting/TermRewritingSystem.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; - -namespace ThinkSharp.FormulaParsing.TermRewriting -{ - public class TermRewritingSystem : ITermRewritingSystem - { - public static ITermRewritingSystem Create() - { - var system = new TermRewritingSystem(); - system.rules.Add(new EvaluateIntegers()); - system.rules.Add(new RemoveBracketsInTermPlusMinusBrackets()); - system.rules.Add(new RemoveBracketsInTermPlusMinusBracketsPlusMinusTerm()); - system.rules.Add(new RemoveNegativeSignFromNumber()); - system.rules.Add(new RemoveNegativeSignInFrontOfBrackets()); - system.rules.Add(new RemoveNegativeSignInInSubtract()); - system.rules.Add(new RemoveNegativeSignInInSum()); - system.rules.Add(new RemoveNegativeSignTimesNegatieSign()); - system.rules.Add(new RemoveNestedBrackets()); - system.rules.Add(new RemovePositiveSign()); - system.rules.Add(new RemoveRootBrackets()); - system.rules.Add(new TermDividesByTermIsOne()); - system.rules.Add(new TermPlusOrMinusZeroIsTermRule()); - system.rules.Add(new TermTimesOrDividedByMinusOneIsMinusTerm()); - system.rules.Add(new TermTimesOrDividedByOneIsTerm()); - system.rules.Add(new RearrangeIntegersInSum()); - return system; - } - - public static ITermRewritingSystem ForTesting(params Rule[] rulesToTest) - { - var system = new TermRewritingSystem(); - foreach (var rule in rulesToTest) - system.rules.Add(rule); - return system; - } - - private List rules = new List(); - public Node Simplify(Node node) => SimplyfyInternal(node); - - private Node SimplyfyInternal(Node node) - { - - var visitors = rules.Select(r => new ReplaceRuleTreeVisitor(r)).ToArray(); - - Node simlifiedNode = node; - Node previousSimlifiedNode = node; - do - { - previousSimlifiedNode = simlifiedNode; - foreach (var visitor in visitors) - simlifiedNode = simlifiedNode.Visit(visitor); - } while (simlifiedNode != previousSimlifiedNode); - - return simlifiedNode; - } - - //private Node CollapseIdenticalNodes(Node node, IDictionary collapsedNodes) - //{ - - //} - - //private Node ExpandCollapsedNodes(Node node, IDictionary collapsedNodes) - //{ - - //} - } -} diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj index 108ba3b..3b48427 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj @@ -8,17 +8,15 @@ Jan-Niklas Schäfer ThinkSharp A formula parser with fluent API that allows parsing and evaluation of mathematically formulas. Features: functions, constants, variables, scientific numbers, focus on customization and flexibility. - © 2019 Jan-Niklas Schäfer - 0.6.4.0 - 0.6.4.0 + © 2020 Jan-Niklas Schäfer + 0.9.0.0 + 0.9.0.0 LICENSE.txt - changed variables API from IDictionary to IReadOnlyDictionary -added '$' as valid character for variables -removed support for alternative hex number notation: '#<hexnumber>'. Note that the main notation '0x<hexnumber' is still supported. - + Removed term rewriting functionality (has been moved to its own project) + https://github.com/JanDotNet/ThinkSharp.FormulaParser true - 0.6.4 + 0.9.0 @@ -42,10 +40,10 @@ removed support for alternative hex number notation: '#<hexnumber>'. Note - <_Parameter1>$(MSBuildProjectName).Test.Core + <_Parameter1>$(MSBuildProjectName).Test - <_Parameter1>$(MSBuildProjectName).Test.Net461 + <_Parameter1>$(MSBuildProjectName).TermRewriting diff --git a/ThinkSharp.FormulaParser/Utils/EnumerableExtensions.cs b/ThinkSharp.FormulaParser/Utils/EnumerableExtensions.cs deleted file mode 100644 index c1c8df8..0000000 --- a/ThinkSharp.FormulaParser/Utils/EnumerableExtensions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace ThinkSharp.FormulaParsing.Utils -{ - internal static class EnumerableExtensions - { - public static IEnumerable WrapFirst(this IEnumerable items, Func projection) - { - bool isFirst = true; - foreach(var item in items) - { - yield return isFirst ? projection(item) : item; - isFirst = false; - } - } - } -} diff --git a/ThinkSharp.FormulaParser/Utils/NodeComparer.cs b/ThinkSharp.FormulaParser/Utils/NodeComparer.cs deleted file mode 100644 index d2d7bf2..0000000 --- a/ThinkSharp.FormulaParser/Utils/NodeComparer.cs +++ /dev/null @@ -1,170 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.TermRewriting; -using ThinkSharp.FormulaParsing.TermRewriting.Rules; - -namespace ThinkSharp.FormulaParsing.Utils -{ - public class NodeComparer : IEqualityComparer - { - private static NodeHashCodeVisitor hashCodeVisitor = new NodeHashCodeVisitor(); - private static ITermRewritingSystem termRewriteSystem = TermRewritingSystem.Create(); - - public bool Equals(Node x, Node y) - { - if (x.GetType() != y.GetType()) - { - return false; - } - else if (x is DecimalNode d1 && y is DecimalNode d2) - { - return d1.Value == d2.Value; - } - else if (x is IntegerNode i1 && y is IntegerNode i2) - { - return i1.Value == i2.Value; - } - else if (x is VariableNode v1 && y is VariableNode v2) - { - return v1.Name == v2.Name; - } - else if (x is ConstantNode c1 && y is ConstantNode c2) - { - return c1.Name == c2.Name; - } - else if (x is PowerNode p1 && y is PowerNode p2) - { - return Equals(p1.BaseNode, p2.BaseNode) - && Equals(p1.ExponentNode, p2.ExponentNode); - } - else if (x is SignedNode s1 && y is SignedNode s2) - { - return s1.Sign == s2.Sign - && Equals(s1.Node, s2.Node); - } - else if (x is FormulaNode f1 && y is FormulaNode f2) - { - return Equals(f1.ChildNode, f2.ChildNode); - } - else if (x is FunctionNode fun1 && y is FunctionNode fun2) - { - if (fun1.FunctionName != fun2.FunctionName) - { - return false; - } - - var fun1Args = fun1.Parameters.ToArray(); - var fun2Args = fun2.Parameters.ToArray(); - - if (fun1Args.Length != fun2Args.Length) - { - return false; - } - - for (int i = 0; i < fun1Args.Length; i++) - { - if (!Equals(fun1Args[i], fun2Args[i])) - { - return false; - } - - return true; - } - } - else if (x is BracketedNode b1 && y is BracketedNode b2) - { - return Equals(b1.ChildNode, b2.ChildNode); - } - else if (x is BinaryOperatorNode bo1 && y is BinaryOperatorNode bo2) - { - switch (bo1.BinaryOperator.Symbol) - { - case "/": - if (bo1.BinaryOperator != bo2.BinaryOperator) - return false; - return Equals(bo1.LeftNode, bo2.LeftNode) && Equals(bo1.RightNode, bo2.RightNode); - case "*": - if (bo1.BinaryOperator != bo2.BinaryOperator) - return false; - var checkLLRR = Equals(bo1.LeftNode, bo2.LeftNode) && Equals(bo1.RightNode, bo2.RightNode); - var checkLRRL = Equals(bo1.LeftNode, bo2.RightNode) && Equals(bo1.RightNode, bo2.LeftNode); - return checkLLRR || checkLRRL; - case "-": - case "+": - var isMinus = bo1.BinaryOperator.Symbol == "-"; - - var summands1Left = GetSummands(bo1.LeftNode); - var summands1Right = GetSummands(bo1.RightNode); - if (isMinus) summands1Right = summands1Right.WrapFirst(n => n.SwitchSign()); - var summands1 = summands1Left.Concat(summands1Right).Select(termRewriteSystem.Simplify).ToList(); - - isMinus = bo2.BinaryOperator.Symbol == "-"; - var summands2Left = GetSummands(bo2.LeftNode); - var summands2Right = GetSummands(bo2.RightNode); - if (isMinus) summands2Right = summands2Right.WrapFirst(n => n.SwitchSign()); - var summands2 = summands2Left.Concat(summands2Right).Select(termRewriteSystem.Simplify).ToList(); - - if (summands1.Count != summands2.Count) - { - return false; - } - - for (int i = 0; i < summands1.Count; i++) - { - var summand1 = summands1[i]; - var found = false; - for (int j = 0; j < summands2.Count; j++) - { - var summand2 = summands2[j]; - if (Equals(summand1, summand2)) - { - found = true; - summands2.Remove(summand2); - break; - } - } - if (!found) - { - return false; - } - } - return true; - - default: - throw new InvalidOperationException($"Unknown binary operator: {bo1.BinaryOperator.Symbol}."); - } - } - - Debug.Fail($"Node types not handled for comparison: {x.GetType()}"); - return false; - } - - private IEnumerable GetSummands(Node node) - { - if (node is BinaryOperatorNode bonPlus && bonPlus.BinaryOperator.Symbol == "+") - { - foreach (var subSummand in GetSummands(bonPlus.LeftNode)) - yield return subSummand; - foreach (var subSummand in GetSummands(bonPlus.RightNode)) - yield return subSummand; - } - else if (node is BinaryOperatorNode bonMinus && bonMinus.BinaryOperator.Symbol == "-") - { - foreach (var subSummand in GetSummands(bonMinus.LeftNode)) - yield return subSummand; - foreach (var subSummand in GetSummands(bonMinus.RightNode).WrapFirst(n => new SignedNode(Sign.Minus, n))) - yield return subSummand; - } - else - { - yield return node; - } - } - - public int GetHashCode(Node node) => node.Visit(hashCodeVisitor); - } -} diff --git a/ThinkSharp.FormulaParser/Utils/NodeHashCodeVisitor.cs b/ThinkSharp.FormulaParser/Utils/NodeHashCodeVisitor.cs deleted file mode 100644 index 7fa67c5..0000000 --- a/ThinkSharp.FormulaParser/Utils/NodeHashCodeVisitor.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using ThinkSharp.FormulaParsing.Ast.Nodes; -using ThinkSharp.FormulaParsing.Ast.Visitors; - -namespace ThinkSharp.FormulaParsing.Utils -{ - public class NodeHashCodeVisitor : INodeVisitor - { - private static int formulaHash = "formula".GetHashCode(); - private static int bracketsHash = "()".GetHashCode(); - private static int powHash = "pow".GetHashCode(); - public int Visit(FormulaNode node) => formulaHash ^ node.ChildNode.Visit(this); - - public int Visit(BracketedNode node) => bracketsHash.GetHashCode() ^ node.ChildNode.Visit(this); - - public int Visit(VariableNode node) => node.Name.GetHashCode(); - - public int Visit(ConstantNode node) => node.Name.GetHashCode(); - - public int Visit(BinaryOperatorNode node) - => node.BinaryOperator.Symbol.GetHashCode() ^ node.LeftNode.Visit(this) ^ node.RightNode.Visit(this); - public int Visit(PowerNode node) - => powHash.GetHashCode() ^ node.BaseNode.Visit(this) ^ node.ExponentNode.Visit(this); - - public int Visit(SignedNode node) - => node.Sign.GetHashCode() ^ node.Node.Visit(this); - - public int Visit(FunctionNode node) - => node.Parameters.Select(n => n.Visit(this)).Aggregate(node.FunctionName.GetHashCode(), (x, y) => x ^ y); - - public int Visit(DecimalNode node) - => node.Value.GetHashCode(); - - public int Visit(IntegerNode node) - => node.Value.GetHashCode(); - } -} From 41fb0a385fa40bf53ca18b5ab97f74f752823c18 Mon Sep 17 00:00:00 2001 From: JanDotNet Date: Fri, 5 Apr 2024 16:29:18 +0200 Subject: [PATCH 45/45] fixed bug: decimal numbers has been parsed, based on the OS's culture. --- .../FormularParser.NumberFormats.Test.cs | 16 +++++++++++++++- .../ThinkSharp.FormulaParser.Test.csproj | 9 +++++---- .../ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs | 9 +++++---- .../ThinkSharp.FormulaParser.csproj | 15 ++++++++++----- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/ThinkSharp.FormulaParser.Test.Core/FormularParser.NumberFormats.Test.cs b/ThinkSharp.FormulaParser.Test.Core/FormularParser.NumberFormats.Test.cs index 93d1ec2..fb620ff 100644 --- a/ThinkSharp.FormulaParser.Test.Core/FormularParser.NumberFormats.Test.cs +++ b/ThinkSharp.FormulaParser.Test.Core/FormularParser.NumberFormats.Test.cs @@ -1,8 +1,10 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; using ThinkSharp.FormulaParsing.Ast.Nodes; using ThinkSharp.FormulaParsing.Ast.Visitors; @@ -50,7 +52,19 @@ public void TestDecimalNotation() Assert.AreEqual(202.0, parser.Evaluate("0d101 + 101").Value); } - [TestMethod] + [TestMethod] + public void TestDifferentCultures() + { + var parser = FormulaParser.Create(); + + Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE"); + Assert.AreEqual(0.1, parser.Evaluate("0.1").Value); + + Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); + Assert.AreEqual(0.1, parser.Evaluate("0.1").Value); + } + + [TestMethod] [Ignore] public void TestScientificNotation() { diff --git a/ThinkSharp.FormulaParser.Test.Core/ThinkSharp.FormulaParser.Test.csproj b/ThinkSharp.FormulaParser.Test.Core/ThinkSharp.FormulaParser.Test.csproj index 232823b..4648127 100644 --- a/ThinkSharp.FormulaParser.Test.Core/ThinkSharp.FormulaParser.Test.csproj +++ b/ThinkSharp.FormulaParser.Test.Core/ThinkSharp.FormulaParser.Test.csproj @@ -1,9 +1,10 @@  - netcoreapp2.0 + net7.0 false + true ThinkSharp.FormulaParser.Test.Core @@ -11,9 +12,9 @@ - - - + + + diff --git a/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs b/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs index 6f0a097..381423f 100644 --- a/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs +++ b/ThinkSharp.FormulaParser/ANTLR/AntlrToAstNodesGrammerTreeVisitor.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using Antlr4.Runtime.Misc; using ThinkSharp.FormulaParsing.Ast.Nodes; @@ -131,7 +132,7 @@ public override Node VisitAtom([NotNull] FormulaGrammerParser.AtomContext contex // //var pow = new PowerNode(new IntegerNode("10", 10), exponentNumber); // //return new BinaryOperatorNode(BinaryOperator.BySymbol("*"), baseNumber, exponentNumber); - // return new DecimalNode(scientificNumber, double.Parse(scientificNumber)); + // return new DecimalNode(scientificNumber, double.Parse(scientificNumber.Parse)); //} public override Node VisitPrefixedIntNumber([NotNull] FormulaGrammerParser.PrefixedIntNumberContext context) @@ -154,7 +155,7 @@ public override Node VisitPrefixedBinNumber([NotNull] FormulaGrammerParser.Prefi public override Node VisitPrefixedDecNumber([NotNull] FormulaGrammerParser.PrefixedDecNumberContext context) { var token = context.PREFIX_DEC_NUMBER().Symbol.Text; - return new DecimalNode(double.Parse(token.Substring(2))); + return new DecimalNode(double.Parse(token.Substring(2), CultureInfo.InvariantCulture)); } public override Node VisitPrefixedHexNumber([NotNull] FormulaGrammerParser.PrefixedHexNumberContext context) @@ -182,13 +183,13 @@ public override Node VisitPrefixedOctNumber([NotNull] FormulaGrammerParser.Prefi public override Node VisitDecimalNumber([NotNull] FormulaGrammerParser.DecimalNumberContext context) { var token = context.DECIMAL_NUMBER().Symbol.Text; - return new DecimalNode(double.Parse(token)); + return new DecimalNode(double.Parse(token, CultureInfo.InvariantCulture)); } public override Node VisitIntgerNumber([NotNull] FormulaGrammerParser.IntgerNumberContext context) { var token = context.INTEGER_NUMBER().Symbol.Text; - return new IntegerNode(NumberFormat.Dec, long.Parse(token)); + return new IntegerNode(NumberFormat.Dec, long.Parse(token, CultureInfo.InvariantCulture)); } public override Node VisitVariable([NotNull] FormulaGrammerParser.VariableContext context) diff --git a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj index 3b48427..b556f14 100644 --- a/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj +++ b/ThinkSharp.FormulaParser/ThinkSharp.FormulaParser.csproj @@ -8,16 +8,17 @@ Jan-Niklas Schäfer ThinkSharp A formula parser with fluent API that allows parsing and evaluation of mathematically formulas. Features: functions, constants, variables, scientific numbers, focus on customization and flexibility. - © 2020 Jan-Niklas Schäfer - 0.9.0.0 - 0.9.0.0 + © 2020-2024 Jan-Niklas Schäfer + 0.10.0.0 + 0.10.0.0 LICENSE.txt Removed term rewriting functionality (has been moved to its own project) - + 0.10.0 Bugfix: decimal parsing should not depend on OS Culture https://github.com/JanDotNet/ThinkSharp.FormulaParser true - 0.9.0 + 0.10.0 + README.md @@ -32,6 +33,10 @@ True + + True + \ +