tupac-amaru / Yacep
Programming Languages
Projects that are alternatives of or similar to Yacep
link:README-en_US.adoc[English (United States)] | 中文
YACEP : yet another csharp expression parser
image:https://dev.azure.com/tupac-amaru/yacep/_apis/build/status/tupac-amaru.yacep?branchName=master["Build Status", link="https://dev.azure.com/tupac-amaru/yacep/_build/latest?definitionId=5&branchName=master"] image:https://img.shields.io/azure-devops/coverage/tupac-amaru/yacep/5.svg?label=azure%20pipelines%20coverage&color=#49bb1e[Azure DevOps coverage, link="https://dev.azure.com/tupac-amaru/yacep/_build/latest?definitionId=5&branchName=master"] image:https://codecov.io/gh/tupac-amaru/yacep/branch/master/graph/badge.svg["Build Status", link="https://codecov.io/gh/tupac-amaru/yacep"] image:https://travis-ci.com/tupac-amaru/yacep.svg?branch=master["Build Status", link="https://travis-ci.com/tupac-amaru/yacep"] image:https://img.shields.io/appveyor/ci/wushilong/yacep.svg?color=#49bb1e[AppVeyor, link="https://ci.appveyor.com/project/wushilong/yacep/branch/master"] image:https://img.shields.io/sonar/https/sonarcloud.io/tupac-amaru_yacep/quality_gate.svg?color=#49bb1e[Sonar Quality Gate, link="https://sonarcloud.io/dashboard?id=tupac-amaru_yacep"] image:https://img.shields.io/appveyor/tests/wushilong/yacep.svg?color=#49bb1e[AppVeyor tests, link="https://ci.appveyor.com/project/wushilong/yacep/branch/master"] image:https://img.shields.io/nuget/v/TupacAmaru.Yacep.svg?color=#49bb1e[Nuget, link="https://www.nuget.org/packages/TupacAmaru.Yacep"] image:https://img.shields.io/github/license/tupac-amaru/yacep.svg?color=#49bb1e["License",link="https://opensource.org/licenses/MIT"]
https://github.com/tupac-amaru/yacep/wiki[文档]
https://github.com/tupac-amaru/yacep/tree/_benchmark[基准测试报告]
简介
YACEP 是一个轻量级的表达式解析库。 能够将一段有效的字符串并转换成一棵抽象语法树. 同时具备把抽象语法树转换成一段可以执行的代码的能力。
[IMPORTANT] YACEP 不支持多行表达式,以后也不会支持. 如果需要多行表达式,个人推荐使用 https://github.com/IronLanguages[IronLanguages]
示例代码
[source,csharp]
"x+', '+y".Compile().EvaluateAs(new { x = "hello", y = "world" }); // value is "hello, world" "x + y".Compile().EvaluateAs(new { x = 1, y = 2 }); // value is 3
var state = new { x = 7, y = 43.0f, z = new Dictionary<string, string> { ["yacep"] = "yet another csharp expression parser", ["tupac-amaru"] = "was the last indigenous monarch (Sapa Inca) of the Neo-Inca State" }, rand = new Func(() => new Random().Next(1, 3)), array = Enumerable.Range(1971, 1996 - 1971) }; var expr = "x + y - z['yacep'].Length + max([1, 2, 3]) + (this.rand() > 2 ? 1971 : 1996) - len(array)"; var evaluator = expr.Compile(); var value = evaluator.EvaluateAs(state);
为什么会写这样一个库?
- 在使用 https://www.docker.com/[docker] 的时候看到了一个很好玩的东西 https://casbin.org/[Casbin], 在读过 https://casbin.org/[Casbin] 的源码之后, 发现 https://casbin.org/[Casbin] 使用了一种极其简单的DSL解决一系列授权问题. 在 https://casbin.org/[Casbin] 的官网上可以看到已经有很多门语言的实现, 但是.net平台的工作 https://github.com/Devolutions/casbin-net[Casbin-Net] 一直处于WIP状态. 在读了 https://github.com/Devolutions/casbin-net[Casbin-Net] 的源码之后, 发现这个库没有再继续写下去的原因是因为找不到一个好用的表达式解析库. 所以就使用简化之后 https://en.wikibooks.org/wiki/Algorithms/Hill_Climbing[爬山算法] 写了一个简单的实现.
特性
- 开箱即用 - 零配置
- 自定义一元操作符 - 支持指定字符串为一元操作符
- 自定义二元操作符 - 支持指定字符串为二元操作符, 且支持 https://en.wikipedia.org/wiki/Order_of_operations#Programming_language[优先级]
- 自定义字面量 - 支持自定义字面量
- 自定义函数 - 支持自定义函数
- 内置三目运算符 - 就和C#中的 https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/conditional-operator[?:] 一样
- 内置in操作符 - 查看一个对象是否在一个序列中
- 支持索引器 - 支持使用索引器来访问对象的方法,属性,字段等,对于字典数组等原生支持使用索引器访问元素
- 跨平台 - 基于 https://github.com/dotnet/standard/blob/master/docs/versions/netstandard2.0.md[netstandard2.0] 构建
- 轻量级 - 核心代码500+
- 低消耗 - 使用了 https://docs.microsoft.com/en-za/dotnet/api/system.readonlyspan-1?view=netcore-2.2[ReadOnlySpan Struct] 来解析字符串
- 高性能 - 相对于使用反射, YACEP 使用 https://docs.microsoft.com/zh-cn/dotnet/api/system.reflection.emit?view=netstandard-2.0[emit] 用创建动态代理的方式来访问对象公开的方法,属性,字段. https://github.com/tupac-amaru/yacep/tree/_benchmark[基准测试报告]
快速上手
https://github.com/tupac-amaru/yacep/wiki[文档]
- 创建一个控制台项目 [source,shell]
mkdir yacep-demo cd yacep-demo dotnet new console
- 添加依赖TupacAmaru.Yacep [source,shell]
dotnet add package TupacAmaru.Yacep
- 修改Program.cs的内容 [source,shell]
cat>Program.cs<<EOF using TupacAmaru.Yacep.Extensions;
namespace yacep_demo { class Program { static void Main() => System.Console.WriteLine("x+', '+y".Compile().EvaluateAs(new { x = "hello", y = "world" })); } } EOF
如果是windows系统,请复制以下内容到Program.cs中
[source,csharp]
using TupacAmaru.Yacep.Extensions;
namespace yacep_demo { class Program { static void Main() => System.Console.WriteLine("x+', '+y".Compile().EvaluateAs(new { x = "hello", y = "world" })); } }
- 运行项目 [source,shell]
dotnet run
hello, world
就说明已经成功了
看到输出 鸣谢
工具&库
- https://github.com/xunit/xunit[xUnit.net]: 测试框架
- https://github.com/dotnet/BenchmarkDotNet[BenchmarkDotNet]: 性能基准测试库
- https://github.com/tonerdo/coverlet[Coverlet]: 代码测试覆盖率库
- https://github.com/danielpalme/ReportGenerator[ReportGenerator]: 测试覆盖率报表转换工具