Skip to content

Commit 797b1d0

Browse files
committed
Initial commit
0 parents  commit 797b1d0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+4340
-0
lines changed

.editorconfig

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
indent_size = 4
6+
indent_style = space
7+
insert_final_newline = true
8+
trim_trailing_whitespace = true
9+
10+
[*.{yml,props,targets,csproj}]
11+
indent_size = 2
12+
13+
# IDE0079: Remove unnecessary suppression
14+
dotnet_remove_unnecessary_suppression_exclusions = category:ReSharper
15+
16+
# IDE0079: Remove unnecessary suppression
17+
# dotnet_diagnostic.IDE0079.severity = none
18+
19+
# CA2255: The 'ModuleInitializer' attribute should not be used in libraries
20+
dotnet_diagnostic.CA2255.severity = none
21+
22+
# CS8600: Converting null literal or possible null value to non-nullable type.
23+
dotnet_diagnostic.CS8600.severity = error
24+
25+
# CS8601: Possible null reference assignment.
26+
dotnet_diagnostic.CS8601.severity = error
27+
28+
# CS8602: Dereference of a possibly null reference.
29+
dotnet_diagnostic.CS8602.severity = error
30+
31+
# CS8603: Possible null reference return.
32+
dotnet_diagnostic.CS8603.severity = error
33+
34+
# CS8604: Possible null reference argument.
35+
dotnet_diagnostic.CS8604.severity = error
36+
37+
# CS8610: Nullability of reference types in type of parameter doesn't match overridden member.
38+
dotnet_diagnostic.CS8610.severity = error
39+
40+
# CS8613: Nullability of reference types in return type doesn't match implicitly implemented member.
41+
dotnet_diagnostic.CS8613.severity = error
42+
43+
# CS8614: Nullability of reference types in type of parameter doesn't match implicitly implemented member.
44+
dotnet_diagnostic.CS8614.severity = error
45+
46+
# CS8618: Non-nullable field is uninitialized. Consider declaring as nullable.
47+
dotnet_diagnostic.CS8618.severity = error
48+
49+
# CS8619: Nullability of reference types in value doesn't match target type.
50+
dotnet_diagnostic.CS8619.severity = error
51+
52+
# CS8620: Argument cannot be used for parameter due to differences in the nullability of reference types.
53+
dotnet_diagnostic.CS8620.severity = error
54+
55+
# CS8625: Cannot convert null literal to non-nullable reference type.
56+
dotnet_diagnostic.CS8625.severity = error
57+
58+
# CS8634: The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.
59+
dotnet_diagnostic.CS8634.severity = error
60+
61+
# CS8643: Nullability of reference types in explicit interface specifier doesn't match interface implemented by the type.
62+
dotnet_diagnostic.CS8643.severity = error
63+
64+
# CS8653: A default expression introduces a null value for a type parameter.
65+
dotnet_diagnostic.CS8653.severity = error
66+
67+
# CS8714: The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'notnull' constraint.
68+
dotnet_diagnostic.CS8714.severity = error
69+
70+
# IDE0059: Unnecessary assigment of a value
71+
dotnet_diagnostic.IDE0059.severity = none
72+
73+
# IDE0060: Remove unused parameter
74+
dotnet_diagnostic.IDE0060.severity = none

.github/workflows/publish.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Publish
2+
3+
on:
4+
push:
5+
tags:
6+
- "[0-9]+.[0-9]+.[0-9]+"
7+
- "[0-9]+.[0-9]+.[0-9]+-[a-z]+.[0-9]+"
8+
9+
permissions:
10+
contents: write
11+
12+
jobs:
13+
publish:
14+
name: Publish packages
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- name: Install .NET
19+
uses: actions/setup-dotnet@v4
20+
with:
21+
dotnet-version: 9.0.x
22+
23+
- name: Checkout
24+
uses: actions/checkout@v4
25+
26+
- name: Build Solution
27+
run: dotnet build -c Release -p:SkipInternalsVisibleTo=true
28+
29+
- name: Create NuGet Packages
30+
run: dotnet pack -c Release -o ./nuget --no-build
31+
32+
- name: Publish NuGet Packages
33+
run: dotnet nuget push ./nuget/*.nupkg --api-key ${{secrets.NUGET_API_KEY}} --skip-duplicate -s https://api.nuget.org/v3/index.json
34+
35+
- name: Create GitHub Release
36+
uses: softprops/action-gh-release@v2
37+
with:
38+
draft: true
39+
files: nuget/*

.github/workflows/test.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Build & Test
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
7+
jobs:
8+
build-and-test:
9+
name: "Test projects"
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Install .NET
13+
uses: actions/setup-dotnet@v4
14+
with:
15+
dotnet-version: |
16+
6.x
17+
7.x
18+
8.x
19+
9.x
20+
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
24+
- name: Test Projects (Debug)
25+
run: dotnet test -c Debug
26+
27+
- name: Test Projects (Release)
28+
run: dotnet test -c Release

.gitignore

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#Ignore thumbnails created by windows
2+
[Tt]humbs.db
3+
4+
#Ignore files build by Visual Studio
5+
*.obj
6+
*.exe
7+
*.pdb
8+
*.user
9+
*.patch
10+
*.aps
11+
*.pch
12+
*.vspscc
13+
*_i.c
14+
*_p.c
15+
*.ncb
16+
*.suo
17+
*.tlb
18+
*.tlh
19+
*.bak
20+
*.cache
21+
*.ilk
22+
*.log
23+
*.lib
24+
*.sbr
25+
*.cs.ide
26+
[Dd]ebug*/
27+
[Rr]elease*/
28+
bin/
29+
obj/
30+
.vs/
31+
.vscode/
32+
*.ReSharper
33+
*.ReSharper.user
34+
[Tt]est[Rr]esult*
35+
36+
#Ignore Rider/Idea files
37+
.idea/

Directory.Build.props

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<Project>
2+
<PropertyGroup>
3+
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
4+
</PropertyGroup>
5+
</Project>

Directory.Packages.props

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project>
3+
<PropertyGroup>
4+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
8+
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
9+
<PackageVersion Include="MinVer" Version="6.0.0" />
10+
<PackageVersion Include="NUnit" Version="4.3.2" />
11+
<PackageVersion Include="NUnit3TestAdapter" Version="4.6.0" />
12+
<PackageVersion Include="Ramstack.Parsing" Version="1.0.0-beta.5" />
13+
</ItemGroup>
14+
</Project>

LICENSE

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
MIT License
2+
3+
Copyright 2024 Rameel (https://github.com/rameel)
4+
5+
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:
6+
7+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8+
9+
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.

README.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Ramstack.ExpressionParser
2+
[![NuGet](https://img.shields.io/nuget/v/Ramstack.ExpressionParser.svg)](https://nuget.org/packages/Ramstack.ExpressionParser)
3+
[![MIT](https://img.shields.io/github/license/rameel/ramstack.expressionparser)](https://github.com/rameel/ramstack.expressionparser/blob/main/LICENSE)
4+
5+
**Ramstack.ExpressionParser** is a flexible expression parser library for .NET,
6+
allowing dynamic evaluation and binding of expressions with context-aware support.
7+
8+
## Getting Started
9+
10+
To install the `Ramstack.ExpressionParser` [NuGet package](https://www.nuget.org/packages/Ramstack.ExpressionParser) to your project, run the following command:
11+
```shell
12+
dotnet add package Ramstack.ExpressionParser
13+
```
14+
15+
## Usage
16+
17+
```csharp
18+
var result = ExpressionParser.Parse("math.min(2 + 3, 2 * 3)");
19+
if (result.Success)
20+
{
21+
var lambda = Expression.Lambda<Func<int>>(result.Value);
22+
var fn = lambda.Compile();
23+
24+
Console.WriteLine(fn());
25+
}
26+
```
27+
28+
### Using `ContextAwareBinder`
29+
30+
`ContextAwareBinder` allows binding expressions to a specific context,
31+
making it possible to reference its properties, fields, and methods directly within expressions.
32+
33+
- The provided context acts as an implicit **this**, meaning you can access its members without prefixes.
34+
- Case-insensitive binding: identifiers in expressions are resolved in case-insensitive manner (e.g., level, Level, and LEVEL are treated the same).
35+
36+
```csharp
37+
var parameter = Expression.Parameter(typeof(LogEvent), "logEvent");
38+
var binder = new ContextAwareBinder(parameter);
39+
40+
var result = ExpressionParser.Parse("level == LogLevel.Error && string.IsNullOrEmpty(source)", binder);
41+
var predicate = Expression
42+
.Lambda<Predicate<LogEvent>>(result.Value, parameter)
43+
.Compile();
44+
```
45+
46+
Here, `IsEnabled` evaluates the parsed expression against a `LogEvent` instance:
47+
```csharp
48+
public bool IsEnabled(LogEvent logEvent)
49+
{
50+
return _predicate(logEvent);
51+
}
52+
```
53+
54+
This makes it easy to create dynamic, human-readable expressions for filtering or evaluating objects at runtime.
55+
56+
## Supported Versions
57+
58+
| | Version |
59+
|------|------------|
60+
| .NET | 6, 7, 8, 9 |
61+
62+
## Contributions
63+
64+
Bug reports and contributions are welcome.
65+
66+
## License
67+
68+
This package is released under the **MIT License**.
69+
See the [LICENSE](https://github.com/rameel/ramstack.expressionparser/blob/main/LICENSE) file for details.

Ramstack.ExpressionParser.sln

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.14.35806.103
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".root", ".root", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
7+
ProjectSection(SolutionItems) = preProject
8+
.editorconfig = .editorconfig
9+
.gitignore = .gitignore
10+
Directory.Build.props = Directory.Build.props
11+
Directory.Packages.props = Directory.Packages.props
12+
LICENSE = LICENSE
13+
README.md = README.md
14+
EndProjectSection
15+
EndProject
16+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ramstack.ExpressionParser", "src\Ramstack.ExpressionParser\Ramstack.ExpressionParser.csproj", "{7866E867-7E25-1EE9-245D-E1DC9EA701B7}"
17+
EndProject
18+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ramstack.ExpressionParser.Tests", "tests\Rmastack.ExpressionParser.Tests\Ramstack.ExpressionParser.Tests.csproj", "{0DCB3293-053C-4A79-BD06-CD6872911886}"
19+
EndProject
20+
Global
21+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
22+
Debug|Any CPU = Debug|Any CPU
23+
Release|Any CPU = Release|Any CPU
24+
EndGlobalSection
25+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
26+
{7866E867-7E25-1EE9-245D-E1DC9EA701B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27+
{7866E867-7E25-1EE9-245D-E1DC9EA701B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
28+
{7866E867-7E25-1EE9-245D-E1DC9EA701B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
29+
{7866E867-7E25-1EE9-245D-E1DC9EA701B7}.Release|Any CPU.Build.0 = Release|Any CPU
30+
{0DCB3293-053C-4A79-BD06-CD6872911886}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31+
{0DCB3293-053C-4A79-BD06-CD6872911886}.Debug|Any CPU.Build.0 = Debug|Any CPU
32+
{0DCB3293-053C-4A79-BD06-CD6872911886}.Release|Any CPU.ActiveCfg = Release|Any CPU
33+
{0DCB3293-053C-4A79-BD06-CD6872911886}.Release|Any CPU.Build.0 = Release|Any CPU
34+
EndGlobalSection
35+
GlobalSection(SolutionProperties) = preSolution
36+
HideSolutionNode = FALSE
37+
EndGlobalSection
38+
GlobalSection(ExtensibilityGlobals) = postSolution
39+
SolutionGuid = {52EB8838-9A24-4543-99E9-9CE702252080}
40+
EndGlobalSection
41+
EndGlobal
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using System.Linq.Expressions;
2+
using System.Reflection;
3+
4+
namespace Ramstack.Parsing;
5+
6+
/// <summary>
7+
/// Provides an abstract base class for binding expressions.
8+
/// </summary>
9+
public abstract class Binder
10+
{
11+
/// <summary>
12+
/// Gets the expression context associated with this binder instance.
13+
/// </summary>
14+
public virtual Expression? Context => null;
15+
16+
/// <summary>
17+
/// Resolves the type associated with the specified name.
18+
/// </summary>
19+
/// <param name="name">The <see cref="Identifier"/> representing the name of the requested type.</param>
20+
/// <returns>
21+
/// The <see cref="Type"/> instance corresponding to the specified <paramref name="name"/>
22+
/// if resolved successfully; otherwise, <see langword="null"/>.
23+
/// </returns>
24+
public abstract Type? BindToType(Identifier name);
25+
26+
/// <summary>
27+
/// Attempts to bind to a method based on the specified type, method name, and parameter types.
28+
/// </summary>
29+
/// <param name="type">The <see cref="Type"/> from which to select the method.</param>
30+
/// <param name="methodName">The <see cref="Identifier"/> representing the name of the method to bind.</param>
31+
/// <param name="parameterTypes">An array of <see cref="Type"/> objects representing
32+
/// the types of arguments passed to the method.</param>
33+
/// <param name="isStatic">A <see cref="bool"/> indicating whether to match only static methods
34+
/// (<see langword="true"/>) or instance methods (<see langword="false"/>).</param>
35+
/// <returns>
36+
/// A <see cref="MethodInfo"/> representing the matching method if found; otherwise,
37+
/// <see langword="null"/> if no suitable method is identified.
38+
/// </returns>
39+
public abstract MethodInfo? BindToMethod(Type? type, Identifier methodName, Type[] parameterTypes, bool isStatic);
40+
41+
/// <summary>
42+
/// Attempts to bind to a member (field, property, or method) based on the specified type and member name.
43+
/// </summary>
44+
/// <param name="type">The <see cref="Type"/> from which to select the member.</param>
45+
/// <param name="memberName">The <see cref="Identifier"/> representing the name of the member to bind.</param>
46+
/// <param name="isStatic">A <see cref="bool"/> indicating whether to match only static members
47+
/// (<see langword="true"/>) or instance members (<see langword="false"/>).</param>
48+
/// <returns>
49+
/// A <see cref="MemberInfo"/> representing the matching member if found; otherwise,
50+
/// <see langword="null"/> if no suitable member is identified.
51+
/// </returns>
52+
public abstract MemberInfo? BindToMember(Type? type, Identifier memberName, bool isStatic);
53+
}

0 commit comments

Comments
 (0)