C# 解析表达式和检索解析树的最简单方法是什么?
我只想解析一些简单的表达式,比如-C# 解析表达式和检索解析树的最简单方法是什么?,c#,vb.net,parsing,.net-2.0,expression-trees,C#,Vb.net,Parsing,.net 2.0,Expression Trees,我只想解析一些简单的表达式,比如- IIF(FVAL(PFC) = TRUE, (IIF((ORGVAL(BAS, "2012/12/31") + ORGVAL(DA)) < 6500, (FVAL(BAS) + FVAL(DA)) * 12%, 780)), 0)` 我一直使用.NETFramework2.0,因此没有Linq或lambda表达式适合我。此外,我希望在自定义库中包含代码,而不仅仅是引用它。谁能告诉我一些好的库或代码 我只需要解析表达式,而不是对表达式求值,然后找到正在
IIF(FVAL(PFC) = TRUE, (IIF((ORGVAL(BAS, "2012/12/31") + ORGVAL(DA)) < 6500, (FVAL(BAS) + FVAL(DA)) * 12%, 780)), 0)`
我一直使用.NETFramework2.0,因此没有Linq或lambda表达式适合我。此外,我希望在自定义库中包含代码,而不仅仅是引用它。谁能告诉我一些好的库或代码
我只需要解析表达式,而不是对表达式求值,然后找到正在使用的标记。在找到标记之后,我需要在解析之前更改表达式字符串,比如如果使用函数ORGVAL
,那么传递的参数必须以下划线作为前缀。LikeORGVAL(BAS)
将转换为ORGVAL(\u BAS)
。一些函数可以有两个参数,如ORGVAL(BAS,“2012/12/31”)
,这将转换为ORGVAL(_BAS,“2012/12/31”)
注意:如果有其他方法,请告诉我。我希望避免使用解析器和词法分析器。这看起来像是一个未经修饰但完整的表达式解析器(尚未测试,但可能是一个起点)
它很老了,但你提到了C#2.0,所以它可能没问题。不过,我不确定它针对的是哪个版本的C。如果您不介意使用.NET语言中的一种来编写代码,您可以使用CodeDom动态编译代码,然后将其作为只在内存中运行的程序集来执行。例如,这与您展示的示例表达式最接近:
private abstract class Logic
{
protected double FVAL(object arg)
{
// put code here
return 0;
}
protected double ORGVAL(object arg)
{
// put code here
return 0;
}
protected double ORGVAL(object arg, string date)
{
// put code here
return 0;
}
public abstract double GetValue(object PFC, object BAS, object DA);
}
private class DynamicLogic : Logic
{
public override double GetValue(object PFC, object BAS, object DA)
{
return (FVAL(PFC) = true ? ((ORGVAL(BAS, "2012/12/31") + ORGVAL(DA)) < 6500 ? (FVAL(BAS) + FVAL(DA)) * .12 : 780) : 0);
}
}
private Logic GenerateLogic(string code)
{
using (CSharpCodeProvider provider = new CSharpCodeProvider())
{
StringBuilder classCode = new StringBuilder();
classCode.AppendLine("private class DynamicLogic : Logic");
classCode.AppendLine(" {");
classCode.AppendLine(" public override int GetValue(object PFC, object BAS, object DA)");
classCode.AppendLine(" {");
classCode.AppendLine(" return (" + code + ");");
classCode.AppendLine(" }");
classCode.AppendLine(" }");
CompilerParameters p = new CompilerParameters();
p.GenerateInMemory = true;
p.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
CompilerResults results = provider.CompileAssemblyFromSource(p, code);
return (Logic)Activator.CreateInstance(type);
if (results.Errors.HasErrors)
{
throw new Exception("Failed to compile DynamicLogic class");
}
return (Logic)results.CompiledAssembly.CreateInstance("DynamicLogic");
}
}
private double evaluate(object PFC, object BAS, object DA)
{
Logic logic = GenerateLogic("FVAL(PFC) = true ? ((ORGVAL(BAS, \"2012/12/31\") + ORGVAL(DA)) < 6500 ? (FVAL(BAS) + FVAL(DA)) * .12 : 780) : 0");
return logic.GetValue(PFC, BAS, DA);
}
私有抽象类逻辑
{
受保护的双FVAL(对象参数)
{
//把代码放在这里
返回0;
}
受保护的双重组织(对象参数)
{
//把代码放在这里
返回0;
}
受保护的双重组织(对象参数、字符串日期)
{
//把代码放在这里
返回0;
}
公共抽象双GetValue(对象PFC、对象BAS、对象DA);
}
私有类动态逻辑:逻辑
{
公共覆盖双GetValue(对象PFC、对象BAS、对象DA)
{
回报率(FVAL(PFC)=真?((原值(BAS),2012/12/31)+原值(DA))<6500?(原值(BAS)+原值(DA))*.12:780:0);
}
}
专用逻辑生成器逻辑(字符串代码)
{
使用(CSharpCodeProvider provider=new CSharpCodeProvider())
{
StringBuilder类代码=新的StringBuilder();
AppendLine(“私有类dynamicologic:Logic”);
类代码。追加行(“{”);
AppendLine(“public override int GetValue(对象PFC、对象BAS、对象DA)”;
类代码。追加行(“{”);
AppendLine(“return(“+code+”);”);
classCode.AppendLine(“}”);
classCode.AppendLine(“}”);
CompilerParameters p=新的CompilerParameters();
p、 GenerateInMemory=true;
p、 添加(Assembly.getExecutionGassembly().Location);
CompilerResults results=provider.compileAsemblyFromSource(p,代码);
return(逻辑)Activator.CreateInstance(类型);
if(results.Errors.HasErrors)
{
抛出新异常(“未能编译DynamicLogic类”);
}
返回(逻辑)结果.CompiledAssembly.CreateInstance(“DynamicLogic”);
}
}
私人双重评估(对象PFC、对象BAS、对象DA)
{
逻辑逻辑=生成逻辑(“FVAL(PFC)=真”((原值(BAS),“2012/12/31”)和原值(DA))<6500?(原值(BAS)+原值(DA))*.12:780:0);
返回逻辑.GetValue(PFC、BAS、DA);
}
编辑:我知道你说你需要得到表达式三,它本身,不仅仅是计算它,而是我整理了代码,所以我想我应该继续写下去,然后发布给未来的路人。你想做的事情听起来很像解析,因此,我认为找到一个不涉及解析的解决方案不会有太大的运气。如果您想说的是您不想自己编写解析器,那么有几个数学表达式解析库可用 我是Jep.Net的作者之一(http://www.singularsys.com/jep.net)这是一个表达式解析组件,可能适合您的需要。它有很好的文档记录,高度可定制,并且肯定会让您跳过实现自己的自定义解析器的繁琐且容易出错的过程。如果它不适合您,谷歌搜索“.net表达式解析库”将获得其他库
祝你好运 ANTLR。或者另一个语法分析器。@Yossarian ANTLR对我来说太难了。我什么都不懂。也许更简单一些。忽略一个常见的解决方案会使这成为购物问题的特征。在所有SE站点上都是离题的。我们已经尝试过这种方法,但速度非常慢。我们已经转而使用。这要快得多。但是对于一些仍在进行的糟糕的技术设计,我需要根据一些逻辑更改表达式。无论如何,我想做的就是用
\u BAS
替换BAS
。
private abstract class Logic
{
protected double FVAL(object arg)
{
// put code here
return 0;
}
protected double ORGVAL(object arg)
{
// put code here
return 0;
}
protected double ORGVAL(object arg, string date)
{
// put code here
return 0;
}
public abstract double GetValue(object PFC, object BAS, object DA);
}
private class DynamicLogic : Logic
{
public override double GetValue(object PFC, object BAS, object DA)
{
return (FVAL(PFC) = true ? ((ORGVAL(BAS, "2012/12/31") + ORGVAL(DA)) < 6500 ? (FVAL(BAS) + FVAL(DA)) * .12 : 780) : 0);
}
}
private Logic GenerateLogic(string code)
{
using (CSharpCodeProvider provider = new CSharpCodeProvider())
{
StringBuilder classCode = new StringBuilder();
classCode.AppendLine("private class DynamicLogic : Logic");
classCode.AppendLine(" {");
classCode.AppendLine(" public override int GetValue(object PFC, object BAS, object DA)");
classCode.AppendLine(" {");
classCode.AppendLine(" return (" + code + ");");
classCode.AppendLine(" }");
classCode.AppendLine(" }");
CompilerParameters p = new CompilerParameters();
p.GenerateInMemory = true;
p.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
CompilerResults results = provider.CompileAssemblyFromSource(p, code);
return (Logic)Activator.CreateInstance(type);
if (results.Errors.HasErrors)
{
throw new Exception("Failed to compile DynamicLogic class");
}
return (Logic)results.CompiledAssembly.CreateInstance("DynamicLogic");
}
}
private double evaluate(object PFC, object BAS, object DA)
{
Logic logic = GenerateLogic("FVAL(PFC) = true ? ((ORGVAL(BAS, \"2012/12/31\") + ORGVAL(DA)) < 6500 ? (FVAL(BAS) + FVAL(DA)) * .12 : 780) : 0");
return logic.GetValue(PFC, BAS, DA);
}