diff --git a/README.md b/README.md index 7d09a00..5c9708f 100644 --- a/README.md +++ b/README.md @@ -4,92 +4,128 @@ SharpEval is a library that allows you to parse & evaluate math expressions at r ## Features -- Parses and evaluates expressions extremely fast. -- Supports custom variables and functions. -- Compatible with Unity 3.4.0 and newer. -- Supports Unity IL2CPP. -- No reflection. -- No external dependencies. +- Parses and evaluates expressions extremely fast +- Supports custom variables and functions +- Compatible with Unity 3.4.0 and newer +- Supports Unity IL2CPP +- No reflection +- No external dependencies ## Usage -- Parse & evaluate a simple expression: +### Parse & evaluate a simple expression: ```cs using SharpEval; +using SharpEval.Tokens; internal static class Program { internal static void Main() { - Console.WriteLine(Interpreter.ParseAndEvaluate(" 2 * ( 2 + 2 ) / 2 ")); // 4 + IToken[] tokens = Tokenizer.Tokenize(" 2 * ( 2 + 2 ) / 2 "); + + Interpreter interpreter = new Interpreter(); + + Console.WriteLine(interpreter.EvaluateExpression(tokens)); // 4 } } ``` -- Parse & evaluate a more complex expression: +### Parse & evaluate a more complex expression: ```cs using SharpEval; +using SharpEval.Tokens; internal static class Program { internal static void Main() { - Console.WriteLine(Interpreter.ParseAndEvaluate(" ( ( ( 2 + 2 ) ^ 2 + 16 ) - 2 ^ ( 4 + 4 ) ) / 2")); // -112 + IToken[] tokens = Tokenizer.Tokenize(" ( ( ( 2 + 2 ) ^ 2 + 16 ) - 2 ^ ( 4 + 4 ) ) / 2"); + + Interpreter interpreter = new Interpreter(); + + Console.WriteLine(interpreter.EvaluateExpression(tokens)); // -112 } } ``` -- Define custom read-only variables: +### Define custom read-only variables: ```cs using SharpEval; +using SharpEval.Tokens; +using SharpEval.Variables; internal static class Program { internal static void Main() { - Interpreter.Variables["x"] = new ReadOnlyVariable(10.0d); - Interpreter.Variables["y"] = new ReadOnlyVariable(15.0d); + IToken[] tokens = Tokenizer.Tokenize(" x + y "); + + Dictionary variables = new Dictionary() + { + ["x"] = new ReadOnlyVariable(10.0d), + ["y"] = new ReadOnlyVariable(20.0d), + }; - Console.WriteLine(Interpreter.ParseAndEvaluate(" x + y ")); // 25 + Interpreter interpreter = new Interpreter(variables: variables); + + Console.WriteLine(interpreter.EvaluateExpression(tokens)); // 25 } } ``` -- Define custom computed variables: +### Define custom computed variables: ```cs using SharpEval; +using SharpEval.Tokens; +using SharpEval.Variables; using System; internal static class Program { internal static void Main() { - var random = new Random(); + IToken[] tokens = Tokenizer.Tokenize(" randomNumber + 1 "); + + Random random = new Random(); + + Dictionary variables = new Dictionary() + { + ["randomNumber"] = new ComputedVariable(() => random.NextDouble()), + }; - Interpreter.Variables["rnd"] = new ComputedVariable(() => random.NextDouble()); + Interpreter interpreter = new Interpreter(variables: variables); - Interpreter.ParseAndEvaluate("rnd * 100.0d"); + Console.WriteLine(interpreter.EvaluateExpression(tokens)); } } ``` -- Define custom functions: +### Define custom functions: ```cs using SharpEval; +using SharpEval.Tokens; using System.Linq; internal static class Program { internal static void Main() { - Interpreter.Functions["sum"] = args => args.Sum(); + IToken[] tokens = Tokenizer.Tokenize(" sum( 1, 2, 3 ) "); + + Dictionary> functions = new Dictionary>() + { + ["sum"] = args => args.Sum(), + }; + + Interpreter interpreter = new Interpreter(functions: functions); - Console.WriteLine(Interpreter.ParseAndEvaluate(" sum ( 2 , 2 , 2 , 2 , 2 ) ")); // 10 + Console.WriteLine(interpreter.EvaluateExpression(tokens)); // 6 } } ``` diff --git a/src/SharpEval.Tests/UnitTest1.cs b/src/SharpEval.Tests/UnitTest1.cs index 6927ce8..d1e8451 100644 --- a/src/SharpEval.Tests/UnitTest1.cs +++ b/src/SharpEval.Tests/UnitTest1.cs @@ -1,4 +1,6 @@ using SharpEval.Tokens; +using System.Diagnostics; +using Xunit; using Xunit.Abstractions; namespace SharpEval.Tests; @@ -12,18 +14,41 @@ public UnitTest1(ITestOutputHelper testOutputHelper) _testOutputHelper = testOutputHelper; } - private const string MathExpression = "-(2 + 2) - 4 * 8 / 4"; + private const string MathExpression = + "( ( 2 + 2 ) / 2 - 8 * 4 + 16 + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) ) ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) ) ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) ) ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) ) ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) ) ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) ) ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) ) ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) + ( ( 2 + 2 ) / 2 - 8 * 4 + 16 ) ) )"; [Fact] public void Test1() { IToken[] tokens = Tokenizer.Tokenize(MathExpression); - + foreach (IToken token in tokens) { _testOutputHelper.WriteLine(token.ToString()); } - Assert.Equal(new Interpreter().EvaluateExpression(tokens), -(2 + 2) - 4 * 8 / 4); + long min = long.MaxValue; + long max = long.MinValue; + + Stopwatch stopwatch = new(); + + Interpreter interpreter = new(); + + double result = 0.0d; + + for (int i = 0; i < 4_000; i++) + { + stopwatch.Restart(); + + result = interpreter.EvaluateExpression(tokens); + + stopwatch.Stop(); + + if (stopwatch.ElapsedMilliseconds < min) min = stopwatch.ElapsedMilliseconds; + + if (stopwatch.ElapsedMilliseconds > max) max = stopwatch.ElapsedMilliseconds; + } + + _testOutputHelper.WriteLine($"Result: {result}, Took: {min}ms - {max}ms"); } } diff --git a/src/SharpEval.Tests/Usings.cs b/src/SharpEval.Tests/Usings.cs deleted file mode 100644 index c802f44..0000000 --- a/src/SharpEval.Tests/Usings.cs +++ /dev/null @@ -1 +0,0 @@ -global using Xunit;