• 半解释器模式,解析文本+*/ ()


    前面想做一个公式编辑器,正好在学习设计模式,想起解释器模式。

    解释器模式有5个角色,抽象表达式角色、终结符表达式角色、非终结符表达式角色、上下文角色、客户角色。

    为什么 说我这是半解释器模式呢?

    我这里以我的理解分为 上下文角色 和 表达式角色 ,因为偷懒所以没有抽象表达式角色。就造成应该分为4个解释器的合并到一个里面了。

    在我这个解释器里有四个方法  OneLevel,KracketLevel,TwoLevel,ThreeLevel,分别为 %比解释、()括号解释(其中有用递归解释括号里的表达式)、*/解释、+-解释,构成了我这个解析运算功能。

    下面请大家欣赏代码。。。 

    解析器
    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace JTK.CalculateInterpreter
    {
        public class Expression
        {
            public void Interpret(Context context) //解释
            {
                try
                {
                    context.Input = OneLevel(context.Input);
                    context.Input = KracketLevel(context.Input);
                    context.Input = TwoLevel(context.Input);
                    context.Input = ThreeLevel(context.Input);
                    context.Output = Convert.ToDouble(context.Input);
                }
                catch
                {
                    throw new ExceptionExpression();
                }
            }

            private string KracketLevel(string input)//括号级别
            {
                //验证括号
                if (!CommonFunction.CheckKracket(input))
                {
                    throw new ExceptionExpression("括号不匹配");
                }
                //去除层括号 递归调用
                while (input.IndexOf(")") > 0)
                {
                    int nEndIndex = input.IndexOf(")");
                    if (nEndIndex > 0)
                    {
                        int nStartIndex = CommonFunction.DaoZhao('(', input.Substring(0, nEndIndex));

                        string strSub = input.Substring(nStartIndex + 1, nEndIndex - nStartIndex - 1);
                        Expression exp = new Expression();
                        Context context = new Context(strSub);
                        exp.Interpret(context);
                        input = input.Replace(string.Format("({0})", strSub), context.Input);
                    }
                }

                return input;
            }

            private string OneLevel(string input)//级别1 %
            {
                int SignPostion = input.IndexOf("%");
                while (SignPostion >= 0)
                {
                    string strTemp = input.Substring(0, SignPostion);
                    int nTemp1 = CommonFunction.DaoZhao('+', strTemp);
                    int nTemp2 = CommonFunction.DaoZhao('-', strTemp);
                    nTemp1 = nTemp1 >= nTemp2 ? nTemp1 : nTemp2;
                    nTemp2 = CommonFunction.DaoZhao('*', strTemp);
                    nTemp1 = nTemp1 >= nTemp2 ? nTemp1 : nTemp2;
                    nTemp2 = CommonFunction.DaoZhao('/', strTemp);
                    nTemp1 = nTemp1 >= nTemp2 ? nTemp1 : nTemp2;

                    string strResult = "";
                    if (nTemp1 == -1)
                    {
                        strResult = strTemp.Substring(0, strTemp.Length);
                    }
                    else
                    {
                        strResult = strTemp.Substring(nTemp1 + 1, strTemp.Length - nTemp1 - 1);
                    }
                    double dTemp = Convert.ToDouble(strResult);
                    dTemp /= 100;
                    dTemp = Math.Round(dTemp, 4);
                    input = input.Replace(strResult + "%", dTemp.ToString());
                    SignPostion = input.IndexOf("%");
                }
                return input;
            }

            private string TwoLevel(string input) //级别2 * /
            {
                string Sign = "*";
                int SignPostion = input.IndexOf("*");
                if ((SignPostion > input.IndexOf("/") && input.IndexOf("/") != -1) || (SignPostion == -1))
                {
                    Sign = "/";
                    SignPostion = input.IndexOf("/");
                }

                while (SignPostion >= 0)
                {
                    string[] strs = CommonFunction.ZhaoShuZi(input, SignPostion);
                    double dTemp = 0.0;
                    if (Sign == "*")
                    {
                        dTemp = Convert.ToDouble(strs[0]) * Convert.ToDouble(strs[1]);
                        dTemp = Math.Round(dTemp, 2);
                        input = input.Replace(strs[0] + "*" + strs[1], dTemp.ToString());
                    }
                    else
                    {
                        dTemp = Convert.ToDouble(strs[0]) / Convert.ToDouble(strs[1]);
                        dTemp = Math.Round(dTemp, 2);
                        input = input.Replace(strs[0] + "/" + strs[1], dTemp.ToString());
                    }

                    Sign = "*";
                    SignPostion = input.IndexOf("*");
                    if ((SignPostion > input.IndexOf("/") && input.IndexOf("/") != -1) || (SignPostion == -1))
                    {
                        Sign = "/";
                        SignPostion = input.IndexOf("/");
                    }
                }

                return input;
            }

            private string ThreeLevel(string input) //级别 3 + -
            {
                string Sign = "+";
                int SignPostion = input.IndexOf("+");
                if ((SignPostion > input.IndexOf("-") && input.IndexOf("-") != -1) || (SignPostion == -1))
                {
                    Sign = "-";
                    SignPostion = input.IndexOf("-");
                }

                while (SignPostion > 0)
                {
                    string[] strs = CommonFunction.ZhaoShuZi(input, SignPostion);
                    double dTemp = 0.0;
                    if (Sign == "+")
                    {
                        dTemp = Convert.ToDouble(strs[0]) + Convert.ToDouble(strs[1]);
                        dTemp = Math.Round(dTemp, 2);
                        input = input.Replace(strs[0] + "+" + strs[1], dTemp.ToString());
                    }
                    else
                    {
                        dTemp = Convert.ToDouble(strs[0]) - Convert.ToDouble(strs[1]);
                        dTemp = Math.Round(dTemp, 2);
                        input = input.Replace(strs[0] + "-" + strs[1], dTemp.ToString());
                    }

                    Sign = "+";
                    SignPostion = input.IndexOf("+");
                    if ((SignPostion > input.IndexOf("-") && input.IndexOf("-") != -1) || (SignPostion == -1))
                    {
                        Sign = "-";
                        SignPostion = input.IndexOf("-");
                    }
                }

                return input;
            }
        }

        public class ExceptionExpression : Exception
        {
            string message = "";
            public ExceptionExpression()
            {
            }

            public ExceptionExpression(String Message)
            {
                message = Message;
            }

            public override string Message
            {
                get
                {
                    if (message != ""return message;
                    return "表达式错误";
                }
            }
        }
    }


    公共函数

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Collections;

    namespace JTK.CalculateInterpreter
    {
        public class CommonFunction
        {
            public static int DaoZhao(char separator, string txt)
            {
                int length = txt.Length - 1;
                for (int i = length; i >= 0; i--)
                {
                    if (txt[i].CompareTo(separator) == 0)
                    {
                        return i;
                    }
                }
                return -1;
            }

            public static string[] ZhaoShuZi(string txt, int postion)
            {
                string[] strs = txt.Split('+''-''*''/');
                int n = 0;
                for (int i = 0; i < txt.Length; i++)
                {
                    switch (txt[i])
                    {
                        case '+':
                            n++;
                            break;
                        case '-':
                            n++;
                            break;
                        case '*':
                            n++;
                            break;
                        case '/':
                            n++;
                            break;
                    }
                    if (i == postion)
                    {
                        break;
                    }

                }

                string[] strsResult = new string[2];
                strsResult[0] = strs[n - 1];
                strsResult[1] = strs[n];
                return strsResult;
            }

            public static bool CheckKracket(string InputString)
            {
                bool isok = true;
                Stack stack = new Stack();
                for (int i = 0; i < InputString.Length; i++)
                {
                    if (InputString[i].ToString() == "(")
                    {
                        stack.Push(i);
                    }
                    if (InputString[i].ToString() == ")")
                    {
                        try
                        {
                            stack.Pop();
                        }
                        catch
                        {
                            isok = false;
                            break;
                        }
                    }
                }
                if (isok)
                {
                    if (stack.Count == 0) { return true; } else { return false; };
                }
                else
                {
                    return false;
                }

            }
        }


    被解析

    namespace JTK.CalculateInterpreter
    {
        public class Context
        {
            private string _input;

            public string Input
            {
                get { return _input; }
                set { _input = value; }
            }
            private double _output;

            public double Output
            {
                get { return _output; }
                set { _output = value; }
            }

            public Context(string input)
            {
                this._input = input;
            }
        }

  • 相关阅读:
    python并发编程之多进程(实践篇)
    python之网络编程
    python并发编程之协程(实践篇)
    python并发编程之IO模型(实践篇)
    复制命令(ROBOCOPY)
    创建文件命令
    创建文件夹命令
    复制命令(XCOPY)
    进程命令(tasklist)
    目录命令(tree)
  • 原文地址:https://www.cnblogs.com/topcoder/p/2305304.html
Copyright © 2020-2023  润新知