Hello World!
Toggle navigation
Home
开发
运维部署
旧博客搬家
About Me
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Archives
Tags
NCalc表达式学习笔记
2018-08-01 09:28:48
59
0
0
lion
#基本用法 string str = " 3 + (4*5) "; var expression = new Expression(str); var list = expression.Evaluate(); #参数用法 string str = " [three] + (4*5) "; var expression = new Expression(str); expression.Parameters = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase) { { "Three", 3 } }; //不传StringComparer.OrdinalIgnoreCase则区分大小写 var list = expression.Evaluate(); Console.WriteLine(list); Console.Read(); #参数用法2 public static void Main(string[] args) { string str = " [three] + (4*5) "; var expression = new Expression(str); expression.EvaluateParameter += expression_EvaluateParameter; var list = expression.Evaluate(); Console.WriteLine(list); Console.Read(); return; } static void expression_EvaluateParameter(string name, ParameterArgs args) { if (name.Equals("Three", StringComparison.OrdinalIgnoreCase)) { args.Result = 3; } else { throw new Exception(name + "不存在"); } } #添加自定义函数 string str = " combine('a','b') "; var expression = new Expression(str); expression.EvaluateFunction += (_name, _args) => { switch (_name) { case "combine": var argvalues = _args.EvaluateParameters(); #先获取函数参数 _args.Result = string.Join("|", argvalues.Select(o => o.ToString()).ToArray()); break; } }; var list = expression.Evaluate(); Console.WriteLine(list); 输出:a|b #修改计算逻辑 #修改Numbers.cs #找到对应函数,如Divide为除法 #修改对应类型逻辑即可。例如,判断除数为0抛出自定义异常等 #判断一个表达式是否为函数 string str = " combine('a','b') "; var expression = new Expression(Expression.Compile(str, true)); //一定要先Compile,否则只有在Evaluate时才会自动触发解析 //调用Compile返回的LogicalExpression其实就是expression.ParsedExpression,也就是解析完还没执行的表达式语法树 if (expression.ParsedExpression, is NCalc.Domain.Function) { Console.WriteLine("true"); } #查找所有用到的外部参数 #需要递归,很麻烦 public static void Main(string[] args) { string str = " combine([a],[b]) "; var expression = new Expression(Expression.Compile(str, true)); //一定要先Compile,否则只有在Evaluate时才会自动触发解析 var hashset = new HashSet<string>(); getParameterNamesOfExpression(hashset, expression.ParsedExpression); Console.WriteLine(string.Join(",", hashset.ToArray())); #输出 a,b Console.Read(); return; } protected static void getParameterNamesOfExpression(HashSet<string> total, LogicalExpression expression, bool ignorCurr = false) { if (expression == null) return; LogicalExpression[] arr = getChildExpression(expression); if (arr != null && arr.Length > 0) { //递归子表达式 foreach (var le in arr) getParameterNamesOfExpression(total, le); } else { //当前表达式 string name = GetParameterExpressionName(expression); if (!string.IsNullOrEmpty(name)) { total.Add(name); } } } protected static string GetParameterExpressionName(LogicalExpression cc) { if (cc is NCalc.Domain.Identifier) { return (cc as NCalc.Domain.Identifier).Name; //参数名 } return string.Empty; } //取子表达式 protected static LogicalExpression[] getChildExpression(LogicalExpression cc) { if (cc is NCalc.Domain.BinaryExpression) { var cd = (cc as NCalc.Domain.BinaryExpression); //二进制运算表达式,取左右操作数,如 [a] & [b] return new LogicalExpression[] { cd.LeftExpression, cd.RightExpression }; } else if (cc is NCalc.Domain.Function) //函数表达式,取函数参数 { var cd = (cc as NCalc.Domain.Function); return cd.Expressions; } else if (cc is NCalc.Domain.UnaryExpression) //单元素,可能括号([a]) { var cd = (cc as NCalc.Domain.UnaryExpression); if (cd.Expression == cd) return null; return new LogicalExpression[] { cd.Expression }; } else if (cc is NCalc.Domain.TernaryExpression) { var cd = (cc as NCalc.Domain.TernaryExpression); //三无素表达式,取左右操作数 return new LogicalExpression[] { cd.LeftExpression, cd.MiddleExpression, cd.RightExpression }; } return null; } #修改表达式 #一般需求加个外部函数或参数都能搞定,但如果非要加自己的关键字,就要改表达式解析啦。 #NCalc使用antlr来解析表达式,所以需要重新用antlr工具生成解析器代码: 1、先下载NCalc源码,找到 Grammar/NCalc.g,这是语法描述语言,用来生成解析器代码。 2、修改 Grammar/NCalc.g中的语法描述,具体语法规则看文档,简单的用猜也行^^ 3、去antlr3官网,下载antlr-dotnet-tool-x.xx.zip,也就是解析器代码生成工具。 (注意生成器版本和NCalc引用的Antlr版本匹配) 4、执行生成代码命令:Antlr3.exe NCalc.g -o out (-o为代码输出目录) 5、在out目录下找到NCalcLexer和NCalcParser.cs 更新到NCalc源代码目录,(可能要稍微改一些语法错误),就可以编译啦。
Pre:
N2N性能和原理解析
Next:
Openwrt用Python通过BMC_ILO100控制HP_DL2000服务器自动开关机
0
likes
59
Weibo
Wechat
Tencent Weibo
QQ Zone
RenRen
目录