13 Commits
0.2.2 ... 0.2.7

29 changed files with 824 additions and 615 deletions

21
LICENSE.txt Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2019-2021 Valeriano Alfonso Rodriguez
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

26
README.md Normal file
View File

@@ -0,0 +1,26 @@
# Expression Evaluation Library
## Usage
### VAR.ExpressionEvaluator
Add the resulting assembly as reference in your projects, and this line on code:
```csharp
using VAR.ExpressionEvaluator;
```
## Building
A Visual Studio solution is provided. Simply, click build on the IDE.
The build generates a DLL and a Nuget package.
## Contributing
1. Fork it!
2. Create your feature branch: `git checkout -b my-new-feature`
3. Commit your changes: `git commit -am 'Add some feature'`
4. Push to the branch: `git push origin my-new-feature`
5. Submit a pull request :D
## Credits
* Valeriano Alfonso Rodriguez.

View File

@@ -1,8 +0,0 @@
using System.Reflection;
[assembly: AssemblyCompany("VAR")]
[assembly: AssemblyCopyright("Copyright © VAR 2019-2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("0.2.2.0")]
[assembly: AssemblyFileVersion("0.2.2.0")]

View File

@@ -1,11 +1,10 @@
using Microsoft.VisualStudio.TestTools.UnitTesting; using Xunit;
namespace VAR.ExpressionEvaluator.Tests namespace VAR.ExpressionEvaluator.Tests
{ {
[TestClass()]
public class ExpressionBinaryNodeTests public class ExpressionBinaryNodeTests
{ {
[TestMethod()] [Fact]
public void ExpressionBinaryNode__Plus() public void ExpressionBinaryNode__Plus()
{ {
var expr = new ExpressionBinaryNode( var expr = new ExpressionBinaryNode(
@@ -16,10 +15,10 @@ namespace VAR.ExpressionEvaluator.Tests
var result = expr.Eval(null); var result = expr.Eval(null);
Assert.AreEqual(30m, result); Assert.Equal(30m, result);
} }
[TestMethod()] [Fact]
public void ExpressionBinaryNode__Minus() public void ExpressionBinaryNode__Minus()
{ {
var expr = new ExpressionBinaryNode( var expr = new ExpressionBinaryNode(
@@ -30,10 +29,10 @@ namespace VAR.ExpressionEvaluator.Tests
var result = expr.Eval(null); var result = expr.Eval(null);
Assert.AreEqual(-10m, result); Assert.Equal(-10m, result);
} }
[TestMethod()] [Fact]
public void ExpressionBinaryNode__Multiply() public void ExpressionBinaryNode__Multiply()
{ {
var expr = new ExpressionBinaryNode( var expr = new ExpressionBinaryNode(
@@ -44,10 +43,10 @@ namespace VAR.ExpressionEvaluator.Tests
var result = expr.Eval(null); var result = expr.Eval(null);
Assert.AreEqual(200m, result); Assert.Equal(200m, result);
} }
[TestMethod()] [Fact]
public void ExpressionBinaryNode__Division() public void ExpressionBinaryNode__Division()
{ {
var expr = new ExpressionBinaryNode( var expr = new ExpressionBinaryNode(
@@ -58,7 +57,7 @@ namespace VAR.ExpressionEvaluator.Tests
var result = expr.Eval(null); var result = expr.Eval(null);
Assert.AreEqual(2m, result); Assert.Equal(2m, result);
} }
} }
} }

View File

@@ -1,29 +1,28 @@
using Microsoft.VisualStudio.TestTools.UnitTesting; using Xunit;
namespace VAR.ExpressionEvaluator.Tests namespace VAR.ExpressionEvaluator.Tests
{ {
[TestClass()]
public class ExpressionNumberNodeTests public class ExpressionNumberNodeTests
{ {
[TestMethod()] [Fact]
public void ExpressionNumberNode__One() public void ExpressionNumberNode__One()
{ {
IExpressionNode node = new ExpressionNumberNode(1); IExpressionNode node = new ExpressionNumberNode(1);
Assert.AreEqual(1m, node.Eval(null)); Assert.Equal(1m, node.Eval(null));
} }
[TestMethod()] [Fact]
public void ExpressionNumberNode__Two() public void ExpressionNumberNode__Two()
{ {
IExpressionNode node = new ExpressionNumberNode(2); IExpressionNode node = new ExpressionNumberNode(2);
Assert.AreEqual(2m, node.Eval(null)); Assert.Equal(2m, node.Eval(null));
} }
[TestMethod()] [Fact]
public void ExpressionNumberNode__OneHundredDotFortyFive() public void ExpressionNumberNode__OneHundredDotFortyFive()
{ {
IExpressionNode node = new ExpressionNumberNode(100.45m); IExpressionNode node = new ExpressionNumberNode(100.45m);
Assert.AreEqual(100.45m, node.Eval(null)); Assert.Equal(100.45m, node.Eval(null));
} }
} }
} }

View File

@@ -1,29 +1,28 @@
using Microsoft.VisualStudio.TestTools.UnitTesting; using Xunit;
namespace VAR.ExpressionEvaluator.Tests namespace VAR.ExpressionEvaluator.Tests
{ {
[TestClass()]
public class ExpressionStringNodeTests public class ExpressionStringNodeTests
{ {
[TestMethod()] [Fact]
public void ExpressionNumberNode__Hello() public void ExpressionNumberNode__Hello()
{ {
IExpressionNode node = new ExpressionStringNode("Hello"); IExpressionNode node = new ExpressionStringNode("Hello");
Assert.AreEqual("Hello", node.Eval(null)); Assert.Equal("Hello", node.Eval(null));
} }
[TestMethod()] [Fact]
public void ExpressionNumberNode__World() public void ExpressionNumberNode__World()
{ {
IExpressionNode node = new ExpressionStringNode("World"); IExpressionNode node = new ExpressionStringNode("World");
Assert.AreEqual("World", node.Eval(null)); Assert.Equal("World", node.Eval(null));
} }
[TestMethod()] [Fact]
public void ExpressionNumberNode__Hello_World() public void ExpressionNumberNode__Hello_World()
{ {
IExpressionNode node = new ExpressionStringNode("Hello World"); IExpressionNode node = new ExpressionStringNode("Hello World");
Assert.AreEqual("Hello World", node.Eval(null)); Assert.Equal("Hello World", node.Eval(null));
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("VAR.ExpressionEvaluator.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("VAR.ExpressionEvaluator.Tests")]
[assembly: ComVisible(false)]
[assembly: Guid("3195f0e0-9489-49ce-8fc2-627a73f80cc7")]

View File

@@ -1,230 +1,229 @@
using System.IO; using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Xunit;
namespace VAR.ExpressionEvaluator.Tests namespace VAR.ExpressionEvaluator.Tests
{ {
[TestClass()]
public class TokenizerTests public class TokenizerTests
{ {
[TestMethod()] [Fact]
public void Tokenizer__Plus() public void Tokenizer__Plus()
{ {
var testString = "10 + 20"; var testString = "10 + 20";
var t = new Tokenizer(new StringReader(testString)); var t = new Tokenizer(new StringReader(testString));
// "10" // "10"
Assert.AreEqual(t.Token, Token.Number); Assert.Equal(Token.Number, t.Token);
Assert.AreEqual(t.Number, 10); Assert.Equal(10, t.Number);
t.NextToken(); t.NextToken();
// "+" // "+"
Assert.AreEqual(t.Token, Token.Plus); Assert.Equal(Token.Plus, t.Token);
t.NextToken(); t.NextToken();
// "20" // "20"
Assert.AreEqual(t.Token, Token.Number); Assert.Equal(Token.Number, t.Token);
Assert.AreEqual(t.Number, 20); Assert.Equal(20, t.Number);
t.NextToken(); t.NextToken();
Assert.AreEqual(t.Token, Token.EOF); Assert.Equal(Token.EOF, t.Token);
} }
[TestMethod()] [Fact]
public void Tokenizer__PlusMinusAndDecimal() public void Tokenizer__PlusMinusAndDecimal()
{ {
var testString = "10 + 20 - 30.123"; var testString = "10 + 20 - 30.123";
var t = new Tokenizer(new StringReader(testString)); var t = new Tokenizer(new StringReader(testString));
// "10" // "10"
Assert.AreEqual(t.Token, Token.Number); Assert.Equal(Token.Number, t.Token);
Assert.AreEqual(t.Number, 10); Assert.Equal(10, t.Number);
t.NextToken(); t.NextToken();
// "+" // "+"
Assert.AreEqual(t.Token, Token.Plus); Assert.Equal(Token.Plus, t.Token);
t.NextToken(); t.NextToken();
// "20" // "20"
Assert.AreEqual(t.Token, Token.Number); Assert.Equal(Token.Number, t.Token);
Assert.AreEqual(t.Number, 20); Assert.Equal(20, t.Number);
t.NextToken(); t.NextToken();
// "-" // "-"
Assert.AreEqual(t.Token, Token.Minus); Assert.Equal(Token.Minus, t.Token);
t.NextToken(); t.NextToken();
// "20" // "20"
Assert.AreEqual(t.Token, Token.Number); Assert.Equal(Token.Number, t.Token);
Assert.AreEqual(t.Number, 30.123m); Assert.Equal(30.123m, t.Number);
t.NextToken(); t.NextToken();
Assert.AreEqual(t.Token, Token.EOF); Assert.Equal(Token.EOF, t.Token);
} }
[TestMethod()] [Fact]
public void Tokenizer__SimpleString() public void Tokenizer__SimpleString()
{ {
var testString = "\"Hello World\""; var testString = "\"Hello World\"";
var t = new Tokenizer(new StringReader(testString)); var t = new Tokenizer(new StringReader(testString));
// "Hello World" // "Hello World"
Assert.AreEqual(t.Token, Token.String); Assert.Equal(Token.String, t.Token);
Assert.AreEqual(t.Text, "Hello World"); Assert.Equal("Hello World", t.Text);
t.NextToken(); t.NextToken();
Assert.AreEqual(t.Token, Token.EOF); Assert.Equal(Token.EOF, t.Token);
} }
[TestMethod()] [Fact]
public void Tokenizer__StringWithEscaping() public void Tokenizer__StringWithEscaping()
{ {
var testString = "\"Hello \\\"World\\\"\""; var testString = "\"Hello \\\"World\\\"\"";
var t = new Tokenizer(new StringReader(testString)); var t = new Tokenizer(new StringReader(testString));
// "Hello \"World\"" // "Hello \"World\""
Assert.AreEqual(t.Token, Token.String); Assert.Equal(Token.String, t.Token);
Assert.AreEqual(t.Text, "Hello \"World\""); Assert.Equal("Hello \"World\"", t.Text);
t.NextToken(); t.NextToken();
Assert.AreEqual(t.Token, Token.EOF); Assert.Equal(Token.EOF, t.Token);
} }
[TestMethod()] [Fact]
public void Tokenizer__Identifiers() public void Tokenizer__Identifiers()
{ {
var testString = "null true false _$variable1 $variable2 [;{}#]"; var testString = "null true false _$variable1 $variable2 [;{}#]";
var t = new Tokenizer(new StringReader(testString)); var t = new Tokenizer(new StringReader(testString));
// "null" // "null"
Assert.AreEqual(t.Token, Token.Identifier); Assert.Equal(Token.Identifier, t.Token);
Assert.AreEqual(t.Text, "null"); Assert.Equal("null", t.Text);
t.NextToken(); t.NextToken();
// "true" // "true"
Assert.AreEqual(t.Token, Token.Identifier); Assert.Equal(Token.Identifier, t.Token);
Assert.AreEqual(t.Text, "true"); Assert.Equal("true", t.Text);
t.NextToken(); t.NextToken();
// "false" // "false"
Assert.AreEqual(t.Token, Token.Identifier); Assert.Equal(Token.Identifier, t.Token);
Assert.AreEqual(t.Text, "false"); Assert.Equal("false", t.Text);
t.NextToken(); t.NextToken();
// "_$variable1" // "_$variable1"
Assert.AreEqual(t.Token, Token.Identifier); Assert.Equal(Token.Identifier, t.Token);
Assert.AreEqual(t.Text, "_$variable1"); Assert.Equal("_$variable1", t.Text);
t.NextToken(); t.NextToken();
// "$variable2" // "$variable2"
Assert.AreEqual(t.Token, Token.Identifier); Assert.Equal(Token.Identifier, t.Token);
Assert.AreEqual(t.Text, "$variable2"); Assert.Equal("$variable2", t.Text);
t.NextToken(); t.NextToken();
// ";{}#" // ";{}#"
Assert.AreEqual(t.Token, Token.Identifier); Assert.Equal(Token.Identifier, t.Token);
Assert.AreEqual(t.Text, ";{}#"); Assert.Equal(";{}#", t.Text);
t.NextToken(); t.NextToken();
Assert.AreEqual(t.Token, Token.EOF); Assert.Equal(Token.EOF, t.Token);
} }
[TestMethod()] [Fact]
public void Tokenizer__AllTogether() public void Tokenizer__AllTogether()
{ {
var testString = "(10 + 20) * -30.123 + \"Hello \\\"World\\\"\" = false"; var testString = "(10 + 20) * -30.123 + \"Hello \\\"World\\\"\" = false";
var t = new Tokenizer(new StringReader(testString)); var t = new Tokenizer(new StringReader(testString));
// "(" // "("
Assert.AreEqual(t.Token, Token.ParenthesisStart); Assert.Equal(Token.ParenthesisStart, t.Token);
t.NextToken(); t.NextToken();
// "10" // "10"
Assert.AreEqual(t.Token, Token.Number); Assert.Equal(Token.Number, t.Token);
Assert.AreEqual(t.Number, 10); Assert.Equal(10, t.Number);
t.NextToken(); t.NextToken();
// "+" // "+"
Assert.AreEqual(t.Token, Token.Plus); Assert.Equal(Token.Plus, t.Token);
t.NextToken(); t.NextToken();
// "20" // "20"
Assert.AreEqual(t.Token, Token.Number); Assert.Equal(Token.Number, t.Token);
Assert.AreEqual(t.Number, 20); Assert.Equal(20, t.Number);
t.NextToken(); t.NextToken();
// ")" // ")"
Assert.AreEqual(t.Token, Token.ParenthesisEnd); Assert.Equal(Token.ParenthesisEnd, t.Token);
t.NextToken(); t.NextToken();
// "*" // "*"
Assert.AreEqual(t.Token, Token.Multiply); Assert.Equal(Token.Multiply, t.Token);
t.NextToken(); t.NextToken();
// "-" // "-"
Assert.AreEqual(t.Token, Token.Minus); Assert.Equal(Token.Minus, t.Token);
t.NextToken(); t.NextToken();
// "20" // "20"
Assert.AreEqual(t.Token, Token.Number); Assert.Equal(Token.Number, t.Token);
Assert.AreEqual(t.Number, 30.123m); Assert.Equal(30.123m, t.Number);
t.NextToken(); t.NextToken();
// "+" // "+"
Assert.AreEqual(t.Token, Token.Plus); Assert.Equal(Token.Plus, t.Token);
t.NextToken(); t.NextToken();
// "Hello \"World\"" // "Hello \"World\""
Assert.AreEqual(t.Token, Token.String); Assert.Equal(Token.String, t.Token);
Assert.AreEqual(t.Text, "Hello \"World\""); Assert.Equal("Hello \"World\"", t.Text);
t.NextToken(); t.NextToken();
// "=" // "="
Assert.AreEqual(t.Token, Token.Equals); Assert.Equal(Token.Equals, t.Token);
t.NextToken(); t.NextToken();
// "false" // "false"
Assert.AreEqual(t.Token, Token.Identifier); Assert.Equal(Token.Identifier, t.Token);
Assert.AreEqual(t.Text, "false"); Assert.Equal("false", t.Text);
t.NextToken(); t.NextToken();
Assert.AreEqual(t.Token, Token.EOF); Assert.Equal(Token.EOF, t.Token);
} }
[TestMethod()] [Fact]
public void Tokenizer__MoreTokens() public void Tokenizer__MoreTokens()
{ {
var testString = "= < > <= >= == === "; var testString = "= < > <= >= == === ";
var t = new Tokenizer(new StringReader(testString)); var t = new Tokenizer(new StringReader(testString));
// "=" // "="
Assert.AreEqual(t.Token, Token.Equals); Assert.Equal(Token.Equals, t.Token);
t.NextToken(); t.NextToken();
// "<" // "<"
Assert.AreEqual(t.Token, Token.LessThan); Assert.Equal(Token.LessThan, t.Token);
t.NextToken(); t.NextToken();
// ">" // ">"
Assert.AreEqual(t.Token, Token.GreaterThan); Assert.Equal(Token.GreaterThan, t.Token);
t.NextToken(); t.NextToken();
// "<=" // "<="
Assert.AreEqual(t.Token, Token.LessOrEqualThan); Assert.Equal(Token.LessOrEqualThan, t.Token);
t.NextToken(); t.NextToken();
// ">=" // ">="
Assert.AreEqual(t.Token, Token.GreaterOrEqualThan); Assert.Equal(Token.GreaterOrEqualThan, t.Token);
t.NextToken(); t.NextToken();
// "==" // "=="
Assert.AreEqual(t.Token, Token.Equals); Assert.Equal(Token.Equals, t.Token);
t.NextToken(); t.NextToken();
// "===" // "==="
Assert.AreEqual(t.Token, Token.ExclusiveEquals); Assert.Equal(Token.ExclusiveEquals, t.Token);
t.NextToken(); t.NextToken();
Assert.AreEqual(t.Token, Token.EOF); Assert.Equal(Token.EOF, t.Token);
} }
} }

View File

@@ -1,97 +1,26 @@
<?xml version="1.0" encoding="utf-8"?> <Project Sdk="Microsoft.NET.Sdk">
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <TargetFramework>net5.0</TargetFramework>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{3195F0E0-9489-49CE-8FC2-627A73F80CC7}</ProjectGuid> <IsPackable>false</IsPackable>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>VAR.ExpressionEvaluator.Tests</RootNamespace>
<AssemblyName>VAR.ExpressionEvaluator.Tests</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup> </ItemGroup>
<Choose>
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
</ItemGroup>
</Otherwise>
</Choose>
<ItemGroup> <ItemGroup>
<Compile Include="..\SharedAssemblyInfo.cs"> <ProjectReference Include="..\VAR.ExpressionEvaluator\VAR.ExpressionEvaluator.csproj" />
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="ExpressionBinaryNodeTests.cs" />
<Compile Include="ExpressionNumberNodeTests.cs" />
<Compile Include="ExpressionStringNodeTests.cs" />
<Compile Include="ParserTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TokenizerTests.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VAR.ExpressionEvaluator\VAR.ExpressionEvaluator.csproj">
<Project>{74635F68-55B1-4819-84A3-9EA818D396D9}</Project>
<Name>VAR.ExpressionEvaluator</Name>
</ProjectReference>
</ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
</ItemGroup>
</When>
</Choose>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project> </Project>

View File

@@ -1,11 +1,17 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio Version 16
VisualStudioVersion = 15.0.28307.902 VisualStudioVersion = 16.0.31402.337
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VAR.ExpressionEvaluator", "VAR.ExpressionEvaluator\VAR.ExpressionEvaluator.csproj", "{74635F68-55B1-4819-84A3-9EA818D396D9}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VAR.ExpressionEvaluator", "VAR.ExpressionEvaluator\VAR.ExpressionEvaluator.csproj", "{74635F68-55B1-4819-84A3-9EA818D396D9}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VAR.ExpressionEvaluator.Tests", "VAR.ExpressionEvaluator.Tests\VAR.ExpressionEvaluator.Tests.csproj", "{3195F0E0-9489-49CE-8FC2-627A73F80CC7}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Notes", "Notes", "{E4F0EB17-0866-42A7-A1BE-2357C3245C12}"
ProjectSection(SolutionItems) = preProject
LICENSE.txt = LICENSE.txt
README.md = README.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VAR.ExpressionEvaluator.Tests", "VAR.ExpressionEvaluator.Tests\VAR.ExpressionEvaluator.Tests.csproj", "{89474ADF-B420-4774-BAC8-EFB3FBE28DA6}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -17,10 +23,10 @@ Global
{74635F68-55B1-4819-84A3-9EA818D396D9}.Debug|Any CPU.Build.0 = Debug|Any CPU {74635F68-55B1-4819-84A3-9EA818D396D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74635F68-55B1-4819-84A3-9EA818D396D9}.Release|Any CPU.ActiveCfg = Release|Any CPU {74635F68-55B1-4819-84A3-9EA818D396D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{74635F68-55B1-4819-84A3-9EA818D396D9}.Release|Any CPU.Build.0 = Release|Any CPU {74635F68-55B1-4819-84A3-9EA818D396D9}.Release|Any CPU.Build.0 = Release|Any CPU
{3195F0E0-9489-49CE-8FC2-627A73F80CC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {89474ADF-B420-4774-BAC8-EFB3FBE28DA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3195F0E0-9489-49CE-8FC2-627A73F80CC7}.Debug|Any CPU.Build.0 = Debug|Any CPU {89474ADF-B420-4774-BAC8-EFB3FBE28DA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3195F0E0-9489-49CE-8FC2-627A73F80CC7}.Release|Any CPU.ActiveCfg = Release|Any CPU {89474ADF-B420-4774-BAC8-EFB3FBE28DA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3195F0E0-9489-49CE-8FC2-627A73F80CC7}.Release|Any CPU.Build.0 = Release|Any CPU {89474ADF-B420-4774-BAC8-EFB3FBE28DA6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@@ -1,26 +0,0 @@
@echo off
:: MSBuild and tools path
if exist "%windir%\Microsoft.Net\Framework\v4.0.30319" set MsBuildPath=%windir%\Microsoft.NET\Framework\v4.0.30319
if exist "%windir%\Microsoft.Net\Framework64\v4.0.30319" set MsBuildPath=%windir%\Microsoft.NET\Framework64\v4.0.30319
if exist "C:\Program Files (x86)\MSBuild\14.0\Bin" set MsBuildPath=C:\Program Files (x86)\MSBuild\14.0\Bin
if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin" set MsBuildPath=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin
if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin" set MsBuildPath=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin
set PATH=%MsBuildPath%;%PATH%
echo %MsBuildPath%
:: NuGet
set nuget="nuget"
if exist "%~dp0\..\packages\NuGet.CommandLine.5.3.1\tools\NuGet.exe" set nuget="%~dp0\..\packages\NuGet.CommandLine.5.3.1\tools\NuGet.exe"
:: Release
Title Building Release
msbuild VAR.ExpressionEvaluator.csproj /t:Build /p:Configuration="Release" /p:Platform="AnyCPU"
:: Packing Nuget
Title Packing Nuget
%nuget% pack VAR.ExpressionEvaluator.csproj -Verbosity detailed -OutputDir "NuGet" -Properties Configuration="Release" -Prop Platform=AnyCPU
title Finished
pause

View File

@@ -48,7 +48,7 @@ namespace VAR.ExpressionEvaluator
{ {
value = ((DateTime)value).ToString("s"); value = ((DateTime)value).ToString("s");
} }
if ((value is string) == false && (value is bool) == false) if ((value is string) == false && (value is bool) == false && value != null)
{ {
value = Convert.ToDecimal(value); value = Convert.ToDecimal(value);
} }

View File

@@ -18,7 +18,7 @@ namespace VAR.ExpressionEvaluator
if (leftValue is string) if (leftValue is string)
{ {
if (decimal.TryParse((string)leftValue, out decimal dec) == false) if (decimal.TryParse((string)leftValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{ {
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue)); throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue));
} }
@@ -26,7 +26,7 @@ namespace VAR.ExpressionEvaluator
} }
if (rightValue is string) if (rightValue is string)
{ {
if (decimal.TryParse((string)rightValue, out decimal dec) == false) if (decimal.TryParse((string)rightValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{ {
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue)); throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue));
} }

View File

@@ -1,6 +1,4 @@
using System; namespace VAR.ExpressionEvaluator
namespace VAR.ExpressionEvaluator
{ {
public class ExpressionEqualsNode : ExpressionBinaryNode public class ExpressionEqualsNode : ExpressionBinaryNode
{ {
@@ -9,44 +7,17 @@ namespace VAR.ExpressionEvaluator
{ {
} }
private static object EqualsOp(object leftValue, object rightValue) public static object EqualsOp(object leftValue, object rightValue)
{ {
if (leftValue is string && rightValue is string) // Null
if (leftValue is string && string.IsNullOrEmpty(leftValue as string))
{ {
return string.Compare((string)leftValue, (string)rightValue) == 0; leftValue = null;
} }
if (rightValue is string && string.IsNullOrEmpty(rightValue as string))
if (leftValue is string)
{ {
if (string.IsNullOrEmpty((string)leftValue)) rightValue = null;
{
leftValue = null;
}
else
{
if (decimal.TryParse((string)leftValue, out decimal dec) == false)
{
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue));
}
leftValue = dec;
}
} }
if (rightValue is string)
{
if (string.IsNullOrEmpty((string)rightValue))
{
leftValue = null;
}
else
{
if (decimal.TryParse((string)rightValue, out decimal dec) == false)
{
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue));
}
rightValue = dec;
}
}
if (leftValue == null && rightValue == null) if (leftValue == null && rightValue == null)
{ {
return true; return true;
@@ -56,11 +27,85 @@ namespace VAR.ExpressionEvaluator
return false; return false;
} }
// String
if (leftValue is string && rightValue is string)
{
return string.Compare((string)leftValue, (string)rightValue) == 0;
}
// Bool
if (leftValue is bool || rightValue is bool)
{
bool? leftBool = ConvertToNullableBool(leftValue);
bool? rightBool = ConvertToNullableBool(rightValue);
return leftBool == rightBool;
}
// Decimal
if (leftValue is string)
{
if (decimal.TryParse((string)leftValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{
leftValue = null;
}
else
{
leftValue = dec;
}
}
if (rightValue is string)
{
if (decimal.TryParse((string)rightValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{
rightValue = null;
}
else
{
rightValue = dec;
}
}
if ((leftValue is decimal) == false || (rightValue is decimal) == false) if ((leftValue is decimal) == false || (rightValue is decimal) == false)
{ {
throw new Exception("Can't compare non decimal values"); return false;
} }
return (decimal)leftValue == (decimal)rightValue; return (decimal)leftValue == (decimal)rightValue;
} }
private static bool? ConvertToNullableBool(object value)
{
if (value is bool)
{
return (bool)value;
}
if (value is string)
{
string text = value as string;
if (string.IsNullOrEmpty(text))
{
return null;
}
decimal decValue;
if (decimal.TryParse(text, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decValue))
{
return decValue != 0;
}
string textLower = text.ToLower();
if (textLower == "false" || textLower == "no" || textLower == "ez" || textLower == "non" || textLower == "nein")
{
return false;
}
if (textLower == "true" || textLower == "si" || textLower == "sí" || textLower == "yes" || textLower == "bai" || textLower == "oui" || textLower == "ja")
{
return true;
}
return null;
}
if (value is decimal)
{
return ((decimal)value) != 0;
}
return false;
}
} }
} }

View File

@@ -24,7 +24,7 @@ namespace VAR.ExpressionEvaluator
} }
else else
{ {
if (decimal.TryParse((string)leftValue, out decimal dec) == false) if (decimal.TryParse((string)leftValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{ {
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue)); throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue));
} }
@@ -39,7 +39,7 @@ namespace VAR.ExpressionEvaluator
} }
else else
{ {
if (decimal.TryParse((string)rightValue, out decimal dec) == false) if (decimal.TryParse((string)rightValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{ {
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue)); throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue));
} }

View File

@@ -24,7 +24,7 @@ namespace VAR.ExpressionEvaluator
} }
else else
{ {
if (decimal.TryParse((string)leftValue, out decimal dec) == false) if (decimal.TryParse((string)leftValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{ {
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue)); throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue));
} }
@@ -39,7 +39,7 @@ namespace VAR.ExpressionEvaluator
} }
else else
{ {
if (decimal.TryParse((string)rightValue, out decimal dec) == false) if (decimal.TryParse((string)rightValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{ {
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue)); throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue));
} }

View File

@@ -24,7 +24,7 @@ namespace VAR.ExpressionEvaluator
} }
else else
{ {
if (decimal.TryParse((string)leftValue, out decimal dec) == false) if (decimal.TryParse((string)leftValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{ {
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue)); throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue));
} }
@@ -39,7 +39,7 @@ namespace VAR.ExpressionEvaluator
} }
else else
{ {
if (decimal.TryParse((string)rightValue, out decimal dec) == false) if (decimal.TryParse((string)rightValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{ {
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue)); throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue));
} }

View File

@@ -24,7 +24,7 @@ namespace VAR.ExpressionEvaluator
} }
else else
{ {
if (decimal.TryParse((string)leftValue, out decimal dec) == false) if (decimal.TryParse((string)leftValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{ {
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue)); throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue));
} }
@@ -39,7 +39,7 @@ namespace VAR.ExpressionEvaluator
} }
else else
{ {
if (decimal.TryParse((string)rightValue, out decimal dec) == false) if (decimal.TryParse((string)rightValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{ {
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue)); throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue));
} }

View File

@@ -18,7 +18,7 @@ namespace VAR.ExpressionEvaluator
if (leftValue is string) if (leftValue is string)
{ {
if (decimal.TryParse((string)leftValue, out decimal dec) == false) if (decimal.TryParse((string)leftValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{ {
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue)); throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue));
} }
@@ -26,7 +26,7 @@ namespace VAR.ExpressionEvaluator
} }
if (rightValue is string) if (rightValue is string)
{ {
if (decimal.TryParse((string)rightValue, out decimal dec) == false) if (decimal.TryParse((string)rightValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{ {
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue)); throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue));
} }

View File

@@ -18,7 +18,7 @@ namespace VAR.ExpressionEvaluator
if (leftValue is string) if (leftValue is string)
{ {
if (decimal.TryParse((string)leftValue, out decimal dec) == false) if (decimal.TryParse((string)leftValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{ {
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue)); throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue));
} }
@@ -26,7 +26,7 @@ namespace VAR.ExpressionEvaluator
} }
if (rightValue is string) if (rightValue is string)
{ {
if (decimal.TryParse((string)rightValue, out decimal dec) == false) if (decimal.TryParse((string)rightValue, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{ {
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue)); throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue));
} }

View File

@@ -1,6 +1,4 @@
using System; namespace VAR.ExpressionEvaluator
namespace VAR.ExpressionEvaluator
{ {
public class ExpressionNotEqualsNode : ExpressionBinaryNode public class ExpressionNotEqualsNode : ExpressionBinaryNode
{ {
@@ -11,56 +9,8 @@ namespace VAR.ExpressionEvaluator
private static object NotEqualsOp(object leftValue, object rightValue) private static object NotEqualsOp(object leftValue, object rightValue)
{ {
if (leftValue is string && rightValue is string) bool result = (bool)ExpressionEqualsNode.EqualsOp(leftValue, rightValue);
{ return !result;
return string.Compare((string)leftValue, (string)rightValue) != 0;
}
if (leftValue is string)
{
if (string.IsNullOrEmpty((string)leftValue))
{
leftValue = null;
}
else
{
if (decimal.TryParse((string)leftValue, out decimal dec) == false)
{
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)leftValue));
}
leftValue = dec;
}
}
if (rightValue is string)
{
if (string.IsNullOrEmpty((string)rightValue))
{
leftValue = null;
}
else
{
if (decimal.TryParse((string)rightValue, out decimal dec) == false)
{
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)rightValue));
}
rightValue = dec;
}
}
if (leftValue == null && rightValue == null)
{
return false;
}
if (leftValue == null || rightValue == null)
{
return true;
}
if ((leftValue is decimal) == false || (rightValue is decimal) == false)
{
throw new Exception("Can't compare non decimal values");
}
return (decimal)leftValue != (decimal)rightValue;
} }
} }
} }

View File

@@ -18,7 +18,7 @@ namespace VAR.ExpressionEvaluator
if (value is string) if (value is string)
{ {
if (decimal.TryParse((string)value, out decimal dec) == false) if (decimal.TryParse((string)value, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out decimal dec) == false)
{ {
throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)value)); throw new Exception(string.Format("Can't convert to decimal string value \"{0}\"", (string)value));
} }

View File

@@ -6,24 +6,42 @@ namespace VAR.ExpressionEvaluator
{ {
public class Parser public class Parser
{ {
private ITokenizer _tokenizer; #region Custom exceptions
public class UnexpectedCharactersAtEndException : Exception
{
public UnexpectedCharactersAtEndException() : base("Unexpected characters at end of expression") { }
}
public class MissingCloseParenthesisException : Exception
{
public MissingCloseParenthesisException() : base("Missing close parenthesis") { }
}
public class UnexpectedEOFException : Exception
{
public UnexpectedEOFException() : base("Unexpected EOF") { }
}
public class UnexpectedTokenException : Exception
{
public UnexpectedTokenException(string token) : base(string.Format("Unexpected token: {0}", token)) { }
}
#endregion Custom exceptions
#region Creator
private readonly ITokenizer _tokenizer;
public Parser(ITokenizer tokenizer) public Parser(ITokenizer tokenizer)
{ {
_tokenizer = tokenizer; _tokenizer = tokenizer;
} }
public IExpressionNode ParseExpression() #endregion Creator
{
var expr = ParseBooleanOp();
if (_tokenizer.Token != Token.EOF) #region Parsing methods
{
throw new Exception("Unexpected characters at end of expression");
}
return expr;
}
private IExpressionNode ParseBooleanOp() private IExpressionNode ParseBooleanOp()
{ {
@@ -42,7 +60,7 @@ namespace VAR.ExpressionEvaluator
IExpressionNode rightNode = ParseRelations(); IExpressionNode rightNode = ParseRelations();
leftNode = new ExpressionBooleanAndNode(leftNode, rightNode); leftNode = new ExpressionBooleanAndNode(leftNode, rightNode);
} }
if (_tokenizer.Token == Token.Or) else if (_tokenizer.Token == Token.Or)
{ {
_tokenizer.NextToken(); _tokenizer.NextToken();
IExpressionNode rightNode = ParseRelations(); IExpressionNode rightNode = ParseRelations();
@@ -66,6 +84,13 @@ namespace VAR.ExpressionEvaluator
IExpressionNode rightNode = ParsePlusAndMinus(); IExpressionNode rightNode = ParsePlusAndMinus();
leftNode = new ExpressionEqualsNode(leftNode, rightNode); leftNode = new ExpressionEqualsNode(leftNode, rightNode);
} }
else if (_tokenizer.Token == Token.ExclusiveEquals)
{
// TODO: Implement ExpressionExclusiveEqualsNode
_tokenizer.NextToken();
IExpressionNode rightNode = ParsePlusAndMinus();
leftNode = new ExpressionEqualsNode(leftNode, rightNode);
}
else if (_tokenizer.Token == Token.NotEquals) else if (_tokenizer.Token == Token.NotEquals)
{ {
_tokenizer.NextToken(); _tokenizer.NextToken();
@@ -226,7 +251,7 @@ namespace VAR.ExpressionEvaluator
} }
if (_tokenizer.Token != Token.ParenthesisEnd) if (_tokenizer.Token != Token.ParenthesisEnd)
{ {
throw new Exception("Missing close parenthesis"); throw new MissingCloseParenthesisException();
} }
_tokenizer.NextToken(); _tokenizer.NextToken();
@@ -241,13 +266,34 @@ namespace VAR.ExpressionEvaluator
IExpressionNode node = ParseBooleanOp(); IExpressionNode node = ParseBooleanOp();
if (_tokenizer.Token != Token.ParenthesisEnd) if (_tokenizer.Token != Token.ParenthesisEnd)
{ {
throw new Exception("Missing close parenthesis"); throw new MissingCloseParenthesisException();
} }
_tokenizer.NextToken(); _tokenizer.NextToken();
return node; return node;
} }
throw new Exception(string.Format("Unexpected token: {0}", _tokenizer.Token.ToString())); if (_tokenizer.Token == Token.EOF)
{
throw new UnexpectedEOFException();
}
throw new UnexpectedTokenException(_tokenizer.Token.ToString());
}
#endregion Parsing methods
#region Public API
public IExpressionNode ParseExpression()
{
var expr = ParseBooleanOp();
if (_tokenizer.Token != Token.EOF)
{
throw new UnexpectedCharactersAtEndException();
}
return expr;
} }
public static IExpressionNode ParseString(string str) public static IExpressionNode ParseString(string str)
@@ -263,5 +309,7 @@ namespace VAR.ExpressionEvaluator
IExpressionNode node = ParseString(str); IExpressionNode node = ParseString(str);
return node.Eval(evaluationContext); return node.Eval(evaluationContext);
} }
#endregion Public API
} }
} }

View File

@@ -1,9 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("VAR.ExpressionEvaluator")]
[assembly: AssemblyDescription("Expression Evaluation Library")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("VAR.ExpressionEvaluator")]
[assembly: ComVisible(false)]
[assembly: Guid("74635f68-55b1-4819-84a3-9ea818d396d9")]

View File

@@ -297,6 +297,12 @@ namespace VAR.ExpressionEvaluator
haveDecimalPoint = _currentChar == '.'; haveDecimalPoint = _currentChar == '.';
NextChar(); NextChar();
} }
if (haveDecimalPoint && sbNumber.Length == 1)
{
_text = sbNumber.ToString();
_currentToken = Token.String;
return;
}
_number = decimal.Parse(sbNumber.ToString(), CultureInfo.InvariantCulture); _number = decimal.Parse(sbNumber.ToString(), CultureInfo.InvariantCulture);
_currentToken = Token.Number; _currentToken = Token.Number;
return; return;

View File

@@ -1,84 +1,27 @@
<?xml version="1.0" encoding="utf-8"?> <Project Sdk="Microsoft.NET.Sdk">
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <TargetFramework>netstandard2.0</TargetFramework>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{74635F68-55B1-4819-84A3-9EA818D396D9}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <IsPackable>true</IsPackable>
<RootNamespace>VAR.ExpressionEvaluator</RootNamespace> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<AssemblyName>VAR.ExpressionEvaluator</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup>
<DebugSymbols>true</DebugSymbols> <PackageId>VAR.ExpressionEvaluator</PackageId>
<DebugType>full</DebugType> <Title>VAR.ExpressionEvaluator</Title>
<Optimize>false</Optimize> <Version>0.2.7</Version>
<OutputPath>bin\Debug\</OutputPath> <Description>Expression Evaluation Library</Description>
<DefineConstants>DEBUG;TRACE</DefineConstants> <Authors>VAR</Authors>
<ErrorReport>prompt</ErrorReport> <Company>VAR</Company>
<WarningLevel>4</WarningLevel> <Copyright>Copyright © VAR 2019-2021</Copyright>
</PropertyGroup> <RequireLicenseAcceptance>false</RequireLicenseAcceptance>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
<DebugType>pdbonly</DebugType> <PackageProjectUrl>https://github.com/Kableado/VAR.ExpressionEvaluator</PackageProjectUrl>
<Optimize>true</Optimize> <PackageTags>Expression;Evaluation;Expression Evaluation</PackageTags>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Content Include="..\LICENSE.txt" Link="LICENSE.txt" Pack="true" PackagePath="" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <Target Name="CopyPackage" AfterTargets="Pack">
<Compile Include="..\SharedAssemblyInfo.cs"> <Copy SourceFiles="$(OutputPath)..\$(PackageId).$(PackageVersion).nupkg" DestinationFolder="Nuget\" />
<Link>Properties\SharedAssemblyInfo.cs</Link> </Target>
</Compile>
<Compile Include="EvaluationContext.cs" />
<Compile Include="ExpressionNodes\ExpressionBooleanAndNode.cs" />
<Compile Include="ExpressionNodes\ExpressionBooleanNode.cs" />
<Compile Include="ExpressionNodes\ExpressionBooleanNotNode.cs" />
<Compile Include="ExpressionNodes\ExpressionBooleanOrNode.cs" />
<Compile Include="ExpressionNodes\ExpressionDivisionNode.cs" />
<Compile Include="ExpressionNodes\ExpressionEqualsNode.cs" />
<Compile Include="ExpressionNodes\ExpressionFunctionNode.cs" />
<Compile Include="ExpressionNodes\ExpressionGreaterOrEqualThanNode.cs" />
<Compile Include="ExpressionNodes\ExpressionGreaterThanNode.cs" />
<Compile Include="ExpressionNodes\ExpressionLessOrEqualThanNode.cs" />
<Compile Include="ExpressionNodes\ExpressionLessThanNode.cs" />
<Compile Include="ExpressionNodes\ExpressionMultiplyNode.cs" />
<Compile Include="ExpressionNodes\ExpressionNotEqualsNode.cs" />
<Compile Include="ExpressionNodes\ExpressionNullNode.cs" />
<Compile Include="ExpressionNodes\ExpressionUnaryNode.cs" />
<Compile Include="ExpressionNodes\ExpressionBinaryNode.cs" />
<Compile Include="ExpressionNodes\ExpressionMinusNode.cs" />
<Compile Include="ExpressionNodes\ExpressionNumberNegateNode.cs" />
<Compile Include="ExpressionNodes\ExpressionPlusNode.cs" />
<Compile Include="ExpressionNodes\ExpressionStringNode.cs" />
<Compile Include="ExpressionNodes\ExpressionNumberNode.cs" />
<Compile Include="ExpressionNodes\ExpressionVariableNode.cs" />
<Compile Include="IEvaluationContext.cs" />
<Compile Include="ExpressionNodes\IExpressionNode.cs" />
<Compile Include="ITokenizer.cs" />
<Compile Include="Parser.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Token.cs" />
<Compile Include="Tokenizer.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Build.NuGet.cmd" />
<None Include="packages.config" />
<None Include="VAR.ExpressionEvaluator.nuspec" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View File

@@ -1,20 +0,0 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$title$</title>
<authors>$author$</authors>
<owners>$author$</owners>
<licenseUrl>https://varstudio.net/VAR.ExpressionEvaluator/LICENSE.txt</licenseUrl>
<projectUrl>https://varstudio.net/VAR.ExpressionEvaluator</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<copyright>Copyright VAR 2019</copyright>
<tags>Expression Evaluation</tags>
</metadata>
<files>
<file src="bin\Release\VAR.ExpressionEvaluator.dll" target="lib\net461\VAR.ExpressionEvaluator.dll" />
<file src="bin\Release\VAR.ExpressionEvaluator.pdb" target="lib\net461\VAR.ExpressionEvaluator.pdb" />
</files>
</package>

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NuGet.CommandLine" version="5.3.1" targetFramework="net461" developmentDependency="true" />
</packages>