Skip to content

tupac-amaru/yacep

Repository files navigation

YACEP : yet another csharp expression parser

Build Status Azure DevOps coverage Build Status Build Status AppVeyor Sonar Quality Gate AppVeyor tests Nuget License

简介

YACEP 是一个轻量级的表达式解析库。 能够将一段有效的字符串并转换成一棵抽象语法树. 同时具备把抽象语法树转换成一段可以执行的代码的能力。

Important
YACEP 不支持多行表达式,以后也不会支持. 如果需要多行表达式,个人推荐使用 IronLanguages

示例代码

"x+', '+y".Compile().EvaluateAs<string>(new { x = "hello", y = "world" });
// value is  "hello, world"
"x + y".Compile().EvaluateAs<int>(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<object>(() => 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<decimal>(state);

为什么会写这样一个库?

  • 在使用 docker 的时候看到了一个很好玩的东西 Casbin, 在读过 Casbin 的源码之后, 发现 Casbin 使用了一种极其简单的DSL解决一系列授权问题. 在 Casbin 的官网上可以看到已经有很多门语言的实现, 但是.net平台的工作 Casbin-Net 一直处于WIP状态. 在读了 Casbin-Net 的源码之后, 发现这个库没有再继续写下去的原因是因为找不到一个好用的表达式解析库. 所以就使用简化之后 爬山算法 写了一个简单的实现.

特性

  • 开箱即用 - 零配置

  • 自定义一元操作符 - 支持指定字符串为一元操作符

  • 自定义二元操作符 - 支持指定字符串为二元操作符, 且支持 优先级

  • 自定义字面量 - 支持自定义字面量

  • 自定义函数 - 支持自定义函数

  • 内置三目运算符 - 就和C#中的 ?: 一样

  • 内置in操作符 - 查看一个对象是否在一个序列中

  • 支持索引器 - 支持使用索引器来访问对象的方法,属性,字段等,对于字典数组等原生支持使用索引器访问元素

  • 跨平台 - 基于 netstandard2.0 构建

  • 轻量级 - 核心代码500+

  • 低消耗 - 使用了 ReadOnlySpan<T> Struct 来解析字符串

  • 高性能 - 相对于使用反射, YACEP 使用 emit 用创建动态代理的方式来访问对象公开的方法,属性,字段. 基准测试报告

快速上手

  • 创建一个控制台项目

mkdir yacep-demo
cd yacep-demo
dotnet new console
  • 添加依赖TupacAmaru.Yacep

dotnet add package TupacAmaru.Yacep
  • 修改Program.cs的内容

cat>Program.cs<<EOF
using TupacAmaru.Yacep.Extensions;

namespace yacep_demo
{
    class Program
    {
        static void Main()
          => System.Console.WriteLine("x+', '+y".Compile().EvaluateAs<string>(new { x = "hello", y = "world" }));
    }
}
EOF

如果是windows系统,请复制以下内容到Program.cs中

using TupacAmaru.Yacep.Extensions;

namespace yacep_demo
{
    class Program
    {
        static void Main()
          => System.Console.WriteLine("x+', '+y".Compile().EvaluateAs<string>(new { x = "hello", y = "world" }));
    }
}
  • 运行项目

dotnet run

看到输出 hello, world 就说明已经成功了

鸣谢

工具&库