我的计算器——5 计算求值

 
关键词:C# .NET 计算器 词法分析 语法分析 表达式计算 ConExpress Calculator
 
以上分析部分结束了,这里介绍调用方法以及主程序。
如果把计算器的功能打包成一个dll,那入口只有一个,SyntaxAnalyse类。new一个SyntaxAnalyse类之后,调用其中的Analyse方法,将要计算的运算表达式作为参数传递进去,返回一个顶级TokenRecord对象,再根据返回的TokenRecord对象的值类型取得结果,整个计算过程就结束了,使用起来非常方便。
    /// <summary>

    /// 表达式分析计算类,功能入口

    /// </summary>

    /// <remarks>Author:Alex Leo @ ConExpress</remarks>

    public class SyntaxAnalyse

        {

        /// <summary>

        /// 构造函数

        /// </summary>

        /// <remarks>Author:Alex Leo; Date:2007-8-2</remarks>

        public SyntaxAnalyse()

        { }



        /// <summary>

        /// 分析语句并返回记号记录对象

        /// </summary>

        /// <param name="Code">运算表达式</param>

        /// <returns>顶级TokenRecord对象</returns>

        public TokenRecord Analyse(string Code)

        {

            if (Code.Trim().Equals(string.Empty))

            {

                return new TokenValue(0);

            }



            List<TokenRecord> ListToken = new List<TokenRecord>();//TokenRecord列表



            int intIndex = 0;

            TokenFactory.LexicalAnalysis(ListToken, Code, ref intIndex);//词法分析,将代码转换为TokenRecord列表



            //语法树分析,将Token列表按优先级转换为树

            TokenRecord TokenTop = SyntaxTreeAnalyse.SyntaxTreeGetTopTokenAnalyse(ListToken, 0, ListToken.Count - 1);

            TokenTop.Execute();

            return TokenTop;

        }

       }



 

窗体的调用也很简单,并没有设计漂亮的外观和高级设置等。

在窗体类中建立一个字段SyntaxAnalyse myAnalyse = new SyntaxAnalyse();

在计算按钮中执行计算操作:

        private void btnExecute_Click(object sender, EventArgs e)

        {

            string strInput = this.rtbInput.Text.Trim().Replace("/n", "");//将回车换行删除

            if (strInput == "")

            {

                this.rtbOutput.Text = "输入的表达式不能为空,请重新输入。";

            }

            else

            {

                try

                {

                    TokenRecord TokenTop = myAnalyse.Analyse(strInput);//计算表达式

                    this.rtbOutput.Text = TokenTop.GetValueString();//显示计算结果

                    this.LoadSyntaxTree(TokenTop);//加载语法树到TreeView控件

                }

                catch (Exception ex)

                {

                    this.rtbOutput.Text = "发生错误,错误信息为:/n" + ex.Message;//显示错误信息

                }

            }

        }

这里提供了一个TreeView控件来显示程序对表达式的分析情况,在LoadSyntaxTree方法中实现树的加载。在TreeView中节点的显示信息为TokenRecord的类名称++值类型,如果需要修改显示信息,只需要对TokenRecord类中的ToString方法进行修改即可。

        /// <summary>

        /// 加载语法树

        /// </summary>

        /// <param name="TokenTop">顶级记号对象</param>

        /// <remarks>Author:Alex Leo @ ConExpress</remarks>

        private void LoadSyntaxTree(TokenRecord TokenTop)

        {

            this.trvSyntaxTree.BeginUpdate();

            this.trvSyntaxTree.Nodes.Clear();



            TreeNode nodRoot = new TreeNode(TokenTop.ToString());//新建根节点

            nodRoot.Tag = TokenTop;

            this.LoadSyntaxTreeSubNode(nodRoot, TokenTop);//递归加载下级节点



            this.trvSyntaxTree.Nodes.Add(nodRoot);//添加根节点到TreeView控件

            this.trvSyntaxTree.EndUpdate();

        }



        /// <summary>

        /// 加载语法树下级节点

        /// </summary>

        /// <param name="ParentNode">上级节点</param>

        /// <param name="ParentToken">上级记号</param>

        /// <remarks>Author:Alex Leo @ ConExpress</remarks>

        private void LoadSyntaxTreeSubNode(TreeNode ParentNode, TokenRecord ParentToken)

        {

            //循环加载下级节点

            for (int intIndex = 0; intIndex < ParentToken.ChildList.Count; intIndex++)

            {

                TokenRecord TokenChild = ParentToken.ChildList[intIndex];

                TreeNode nodChild = new TreeNode(TokenChild.ToString());

                nodChild.Tag = TokenChild;

                ParentNode.Nodes.Add(nodChild);

                LoadSyntaxTreeSubNode(nodChild, TokenChild);//递归加载下级节点

            }

        }



主界面中设置了AcceptButtonCancelButtonAcceptButton为“计算”按钮,CancelButton为“退出”按钮。输入计算表达式之后,按回车即可执行计算,如果需要退出程序,按Esc即可,方便操作。

以下是主界面:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值