moodlee 发表于 2016-3-21 12:55

【原创源码】C#编写一款自己的脚本语言.第八章.下

第八章.下
——————————
此章为代码章
解决问题:能处理有括号的运算。(括号暂时只有圆括号)(运算符号暂时只有-+*%/^)
——————————
比较第六章,除了添加了括号运算,还添加了负值运算。(有心人,其实不难发现,第六章的代码无法进行负值运算)
——————————

——————————
using System;
using System.Collections.Generic;

namespace ScriptCode
{
    public class ScriptCodeU
    {
      /*
      */

      public string Eval(string myScript)
      {
            string myResult = string.Empty;
            //-----
            myResult = eval_seniorElement(myScript);
            myResult = SpecialTran_ToNormal(myResult);
            return myResult;
      }
      /*用于解决没有括号的运算*/
      private string eval_basicElement(string myScript)
      {
            string myResult;
            //-----
            /*定义储存变量*/
            string LeftVar = string.Empty;//左变量
            string RightVar = string.Empty;//右变量
            string unRunCode = string.Empty;//非执行代码
            bool SwitchOfRun = false;//运算开关
            char nowRunChar = char.MinValue;//当前运算符号
            string cmdResult;//计算结果
            /*定义优先级*/
            List<string> rankRunChar = new List<string>();
            rankRunChar.Add("^");
            rankRunChar.Add("*/%");
            rankRunChar.Add("+-");
            /*前期准备*/
            string tempScript = myScript;
            /*正式执行*/
            for(int c=0;c<rankRunChar.Count; c++)
            {
                for (int i = 0; i < tempScript.Length; i++)
                {

                  int CharType = judgeChar(tempScript, rankRunChar.ToArray(), c);
                  if (CharType == 0)
                  {//如果为:非当前优先级运算符号
                        if (SwitchOfRun)
                        {
                            //如果运算开关为真
                            cmdResult = cmd(nowRunChar, LeftVar, RightVar);
                            unRunCode += cmdResult+tempScript;
                            LeftVar = string.Empty;
                            RightVar = string.Empty;
                            SwitchOfRun = false;
                        }
                        else
                        {
                            //如果运算开关为假
                            unRunCode += LeftVar;
                            LeftVar = string.Empty;
                            unRunCode += tempScript;
                        }

                  }
                  else if (CharType == 1)
                  {//当前优先级运算符号
                        if (SwitchOfRun)
                        {
                            cmdResult = cmd(nowRunChar, LeftVar, RightVar);
                            LeftVar = string.Empty;
                            LeftVar += cmdResult;
                            RightVar = string.Empty;
                            SwitchOfRun = true;
                            nowRunChar = tempScript;
                        }
                        else
                        {
                            //如果运算开关为假
                            SwitchOfRun = true;
                            nowRunChar = tempScript;
                        }
                  }
                  else if (CharType == 2)
                  {
                        //数值
                        if (SwitchOfRun)
                        {
                            //如果运算开关为真
                            RightVar += tempScript;

                        }
                        else
                        {
                            //如果运算开关为假
                            LeftVar += tempScript;

                        }
                  }

                }
                //做最后一次运算
                if (SwitchOfRun)
                {
                  cmdResult = cmd(nowRunChar, LeftVar, RightVar);
                  unRunCode += cmdResult;
                }else
                {
                  unRunCode +=LeftVar;
                }

                //递交给下一次计算
                tempScript = unRunCode;
                //重置
                unRunCode = string.Empty;
                LeftVar = string.Empty;
                RightVar = string.Empty;
                SwitchOfRun = false;
                nowRunChar = char.MinValue;
                cmdResult = string.Empty;

            }
            myResult = tempScript;
            

            //-----
            return myResult;
      }
      /*用于解决有括号的运算,使用到basic*/
      private string eval_seniorElement(string myScript)
      {
            string myResult = string.Empty;
            //-----
            /*首先定义以下变量*/
            int IndexOfBracket = -1;//圆括号的编号
            char TypeOfBracket = char.MinValue;//圆括号的类型
            string unRunCode = string.Empty;//非执行代码
            string ContentOfBracket = string.Empty;//括号里的内容
            /*正式执行解析*/
            /*首先判断是否存在圆括号*/
            bool ExistOfBracket = myScript.IndexOf("(") != -1 && myScript.IndexOf(")") != -1;
            if (ExistOfBracket)
            {
                //如果存在
                for (int i=0;i<myScript.Length; i++)
                {
                  int TypeOfChar = judgeCharOfBracket(myScript );
                  if(TypeOfChar == -1)
                  {
                        //如果为非()
                        if(IndexOfBracket == -1)
                        {
                            //判断【圆括号的编号】为-1
                            unRunCode += myScript;
                        }else
                        {
                            //判断【圆括号的编号】非-1
                            ContentOfBracket += myScript;
                        }
                  }else if (TypeOfChar == 0)
                  {
                        //如果为(
                        if (TypeOfBracket != ')')
                        {
                            IndexOfBracket++;
                        }
                        TypeOfBracket = '(';
                        if (IndexOfBracket != 0)
                        {
                            ContentOfBracket += myScript;

                        }



                  }
                  else if ( TypeOfChar == 1)
                  {
                        //如果为)
                        if(TypeOfBracket == '(')
                        {
                            TypeOfBracket = ')';
                            if(IndexOfBracket > 0)
                            {
                              ContentOfBracket += myScript;
                            }else if (IndexOfBracket == 0)
                            {
                              unRunCode +=eval_seniorElement(ContentOfBracket);
                              /*下面为重置*/
                              ContentOfBracket = string.Empty;
                              IndexOfBracket = -1;
                              TypeOfBracket = char.MinValue;
                            }
                        }else if (TypeOfBracket == ')')
                        {
                            IndexOfBracket--;
                            if(IndexOfBracket == 0)
                            {
                              unRunCode += eval_seniorElement(ContentOfBracket);
                              /*下面为重置*/
                              ContentOfBracket = string.Empty;
                              IndexOfBracket = -1;
                              TypeOfBracket = char.MinValue;
                            }else
                            {
                              ContentOfBracket += myScript;
                            }
                        }
                  }
                  /*
                  */
                  //MessageBox.Show("unRun:"+unRunCode +"\r\n"+"ContentOf:"+ContentOfBracket);
                }
                myResult = eval_basicElement(unRunCode);
            }else
            {
                //如果不存在()
                myResult= eval_basicElement(myScript);
            }
            //-----
            return myResult;
      }
      /*加减乘除取余次方*/
      /*请不要使用$作为运算符号,$在内部被使用于负号表示*/
      private string plues(string X,string Y)
      {
            string Z;
            //-----
            double lx = double.Parse(X);
            double ly = double.Parse(Y);
            Z = (lx + ly).ToString();
            //-----
            return Z;
      }
      private string minus(string X,string Y)
      {
            string Z;
            //-----
            double lx = X .Length !=0?double.Parse(X):0;
            double ly = double.Parse(Y);
            Z = (lx - ly).ToString();
            //-----
            return Z;
      }
      private string multiply(string X,string Y)
      {
            string Z;
            //-----
            double lx = double.Parse(X);
            double ly = double.Parse(Y);
            Z = (lx * ly).ToString();
            //-----
            return Z;
      }
      private string divide(string X,string Y)
      {
            string Z;
            //-----
            double lx = double.Parse(X);
            double ly = double.Parse(Y);
            Z = (lx / ly).ToString();
            //-----
            return Z;
      }
      private string module(string X,string Y)
      {
            string Z;
            //-----
            double lx = double.Parse(X);
            double ly = double.Parse(Y);
            Z = (lx % ly).ToString();
            //-----
            return Z;
      }
      private string pow(string X,string Y)
      {
            string Z;
            //-----
            Z = Math.Pow(double.Parse(X), double.Parse(Y)).ToString();
            //-----
            return Z ;
      }
      /*统一运算*/
      private string cmd(char myCmd,string X,string Y)
      {
            string myResult = string.Empty;
            //-----
            X = SpecialTran_ToNormal(X);
            Y = SpecialTran_ToNormal(Y);
            //
            switch (myCmd)
            {
                case '+':
                  myResult = plues(X ,Y);
                  break;
                case '-':
                  myResult = minus(X,Y);
                  break;
                case '*':
                  myResult = multiply(X,Y);
                  break;
                case '/':
                  myResult = divide(X,Y);
                  break;
                case '%':
                  myResult = module(X,Y);
                  break;
                case '^':
                  myResult = pow(X,Y);
                  break;
            }
            //
            myResult = SpecialTran_ToInner(myResult);
            //-----
            return myResult;
      }

      /*判断字符类型*/
      private int judgeChar(char myChar, string[] myRunChar, int myRank)
      {
            /*
            0:非当前优先级运算符号
            1:当前优先级运算符号
            2:数值
            3:未知符号
            4:
            */

            int myResult = 4;
            //-----
            if ((myChar >= '0' && myChar <= '9')||myChar =='.'||myChar =='$')//$用于标记负号
            {
                myResult = 2;//数值
            }
            
            bool isRunChar = false;
            for (int i = 0; i < myRunChar.Length; i++)
            {
                if (myRunChar.IndexOf(myChar) != -1)
                {
                  isRunChar = true;
                  break;
                }
            }
            if (isRunChar)
            {
                if (myRunChar.IndexOf(myChar) != -1)
                {
                  myResult = 1;
                }
                else
                {
                  myResult = 0;
                }
            }
            //-----
            return myResult;
      }
      /*用于判断是否为圆括号类型*/
      private int judgeCharOfBracket(char myChar)
      {
            /*
            -1:非()
            0:(
            1:)
            */
            int myResult = -1;
            //-----
            if(myChar == '(')
            {
                myResult = 0;
            }else if (myChar == ')')
            {
                myResult = 1;
            }
            //-----
            return myResult;
      }

      /*为了支持负值运算,使用$来表示负号*/
      /*将-1转换成$1*/
      private string SpecialTran_ToInner(string myValue)
      {
            return myValue.Replace('-','$');
      }
      /*将$1转换成-1*/
      private string SpecialTran_ToNormal(string myValue)
      {
            return myValue.Replace('$', '-');
      }

    }
}


moodlee 发表于 2016-3-21 12:55

附上之前章节地址:

第一章:http://www.52pojie.cn/thread-470085-1-1.html
第二章:http://www.52pojie.cn/thread-470424-1-2.html
第三章:http://www.52pojie.cn/thread-471306-1-1.html
第四章:http://www.52pojie.cn/thread-471637-1-1.html
第五章:http://www.52pojie.cn/thread-471937-1-1.html
第六章:http://www.52pojie.cn/thread-472899-1-1.html
第六章.下:http://www.52pojie.cn/thread-473861-1-1.html
第七章:http://www.52pojie.cn/thread-476054-1-1.html
第八章:http://www.52pojie.cn/thread-478357-1-1.html

感谢支持!

moodlee 发表于 2016-3-22 07:25

lonely 发表于 2016-3-21 18:22
LZ的计算器吓到我了,这是为了教程简洁,还是LZ太懒啊

我可不是懒,这章给的代码的思想,都在之前的文章里面体现过。在此之前的文章都是为这章代码准备的。

moodlee 发表于 2016-3-21 13:01

繁华过后。荒江野老屋中,与两三人耳。
从此以后,不动如山,清湛似水,跟随钱老先生。

芯诺 发表于 2016-3-21 13:06

刚上来就看到你的教程,6!

子月 发表于 2016-3-21 13:08

看样子还是要多学点语言啊。

ykbest 发表于 2016-3-21 13:08

这个太给力了仔细看看学习一下

ZMLoveLH 发表于 2016-3-21 13:11

楼主大牛人啊,菜鸟学习一下,多谢楼主。。。

zgy150010318 发表于 2016-3-21 13:19

牛牛牛,楼主很牛

孤独飞天 发表于 2016-3-21 15:45

楼主分享,值得学习

lonely 发表于 2016-3-21 18:22

LZ的计算器吓到我了,这是为了教程简洁,还是LZ太懒啊
页: [1] 2
查看完整版本: 【原创源码】C#编写一款自己的脚本语言.第八章.下