






















利用System.Linq.Expressions实现四则运算计算器(二)
如何将数学表达式转换成表达式树?
上节提到用几个类来封装数学表达式,对于数学表达式“5*4/(3+2-1)”转换成表达式树后如下图:
其中“表达式列表”和“/(3+2-1)”都是使用BWExpressionNodeCollection表示,“5”、“*4”、“3”、“+2”、“-1”都是用BWConstantExpressionNode表示。
如何将数学表达式字符串转换成表达式树呢?答案就是使用正则表达式。
匹配数字的正则表达式是“"d+("."d+)?”,匹配符号的表达式是“("+|-|"*|/)”。匹配括号的正则表达式是“"([^"(")]*(((?'Open'"()[^"(")]*)+((?'-Open'"))[^"(")]*)+)*(?(Open)(?!))")”。具体正则表达式怎么写,怎么用,请大家在网上搜索下啦!
数学表达式中,第一个数字如果是负数,则可以直接写成“-2+3”,如果负数在表达式中间,则需要使用括号括起来“2*(-2)+3”。不管负数在哪里,都有一个规律,在前面总结的简单表达式中,负数总是第一个。所以程序在做转换的时候,只需要考虑第一个数字是负数的情况(括号里面负数也只能是第一个)。可以匹配负数的正则表达式是“-?"d+("."d+)?”。
生成表达式树,请看下面流程图:

生成表达式树的工作全部交给BWExpressionNodeCollection,我在设计BWExpressionNodeCollection类时,采用构造函数传入数学表达式字符串:
///<summary>
///表达式节点集合
///</summary>
///<param name="input">表达式字符串</param>
///<param name="type">此表达式前的操作符</param>
public BWExpressionNodeCollection(string input, BWExpressionNodeType type)
{
base.ExpressionNodeType = type;
this.expressionString = input;
this.expressionNodeList = new BWExpressionNodeList();
double? val = ParseNegative();
if (val.HasValue)
{
this.expressionNodeList.Add(new BWConstantExpressionNode(val.Value, BWExpressionNodeType.Start));
}
else
{
string parenthesesContent = GetParentheses();
if (!String.IsNullOrEmpty(parenthesesContent))
{
this.expressionNodeList.Add(new BWExpressionNodeCollection(parenthesesContent, BWExpressionNodeType.Start));
}
else
{
throw Error.GenericException;
}
}
while (!String.IsNullOrEmpty(this.expressionString))
{
char? sign = GetSign();
if (sign.HasValue)
{
BWExpressionNodeType nextType;
switch (sign)
{
case '+':
nextType = BWExpressionNodeType.Addition;
break;
case '-':
nextType = BWExpressionNodeType.Subtration;
break;
case '*':
nextType = BWExpressionNodeType.Multiplication;
break;
case '/':
nextType = BWExpressionNodeType.Division;
break;
default:
throw Error.GenericException;
}
double? operand = ParsePositive();
if (operand.HasValue)
{
this.expressionNodeList.Add(new BWConstantExpressionNode(operand.Value, nextType));
}
else
{
string parenthesesContent = GetParentheses();
if (!String.IsNullOrEmpty(parenthesesContent))
{
this.expressionNodeList.Add(new BWExpressionNodeCollection(parenthesesContent, nextType));
}
else
{
throw Error.GenericException;
}
}
}
else
{
throw Error.GenericException;
}
}
}
可以看到,如果数学表达式遇到括号,则把括号内的数学表达式生成一个子BWExpressionNodeCollection对象。
到此为止,表达式树就已经生成,生成方法就是:
string input = @"1 + 5 * 9 - ( 1 + 2 ) * 3 / 4 + 6 * ( -2 )";
BWExpressionNodeCollection nodes = new BWExpressionNodeCollection(input, BWExpressionNodeType.Start);
接下来将介绍如何从表达式树生成System.Linq.Expressions下面的类。请大家留意!
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。