利用System.Linq.Expressions实现四则运算计算器(二)

利用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下面的类。请大家留意!

posted on 2007-08-28 22:09  sdxd.bgl  阅读(1497)  评论(0编辑  收藏  举报

导航