文法分析与解释器模式(二)

这一章建立一个语法分析器
用Stack分析算数表达式最为简单的是后缀表达式,这里简单举个例子:
               (a+b)*c-(d/e)==>ab+c*de/-                                 --------------(1)
对于1式我们分析两个变量:a,b入栈然后见到运算符+,pop()两个变量计算(b,a),其结果并入栈,c入栈,见到运算符*,pop()两个变量(c,a+b的结果),d,e入栈,见到运算符/,pop()两个变量(e,d),计算结果并入栈,见到运算符-,pop()两个变量(d/e的结果,(a+b)*c的结果),计算,这个结果就是最终结果。
下面我准备建立一个分析算数表达式的class,名为InToPost, 其间有方法名为Trans(),返回一个Queue类型的值,匹配后缀表达式,比如有(1)式有:
               <<a|b|+|c|*|d|e|/|-<<--------箭头方向为出队列的方向
  1class InToPost
  2    {
  3        Stack<string> stack;
  4        Queue<string> temp;
  5        string input;
  6        string output;
  7        public string OutString
  8        {
  9            get return output; }
 10        }

 11        public InToPost(string str)
 12        {
 13            this.input = str.Trim(); ;
 14            stack = new Stack<string>();
 15            temp = new Queue<string>();
 16        }

 17        public int Trans(out Queue<string> st)
 18        {
 19            string str;
 20            if (!Match())
 21            {
 22                st = null;
 23                return 0;
 24            }

 25            string[] tokens = GetTokens();
 26            for (int i = 0; i < tokens.Length; i++)
 27            {
 28                str = tokens[i];
 29                switch (str)
 30                {
 31                    case"":
 32                        break;
 33                    case "+":
 34                    case "-":
 35                        GetOperator(str, 1);
 36                        break;
 37                    case "*":
 38                    case "/":
 39                        GetOperator(str, 2);
 40                        break;
 41                    case "^":
 42                        GetOperator(str, 4);
 43                        break;
 44                    case "(":
 45                        stack.Push(str);
 46                    break;
 47                    case ")":          
 48                        GetParen(str);
 49                        break;
 50                    default:
 51                        output += str;
 52                        temp.Enqueue(str); ;
 53                        break;
 54                }

 55            }

 56            while (stack.Count != 0)
 57            {
 58                str = stack.Pop();
 59                temp.Enqueue(str);
 60                output += str;
 61            }

 62            st = temp;
 63            return 1;
 64        }

 65        private bool Match()
 66        {
 67            int left = 0, right = 0;
 68            for (int i = 0; i < input.Length; i++)
 69            {
 70                if (input[i] == '(') left++;
 71                else if (input[i] == ')') right++;
 72            }

 73            return left == right;
 74        }

 75        private void GetOperator(string opThis, int prec1)
 76        {
 77            while (stack.Count != 0)
 78            {
 79                string opTop = stack.Pop();
 80                if (opTop == "(")
 81                {
 82                    stack.Push(opTop);
 83                    break;
 84                }

 85                else
 86                {
 87                    int prec2 = 0;
 88                    if (opTop == "+" || opTop == "-")
 89                    { prec2 = 1; }
 90                    else if (opTop == "*" || opTop == "/")
 91                    { prec2 = 2; }
 92                    else if (opTop == "^"{ prec2 = 4; }
 93
 94                    if (prec2 < prec1)
 95                    {
 96                        stack.Push(opTop);
 97                        break;
 98                    }

 99                    else
100                    {
101                        output += opTop;
102                        temp.Enqueue(opTop);
103                    }

104                }

105            }

106            stack.Push(opThis);
107        }

108        private void GetParen(string str)
109        {
110            while (stack.Count != 0)
111            {
112                string s = stack.Pop();
113                if (s == "("break;
114                else { output += s; temp.Enqueue(s); }
115            }

116        }

117        private string[] GetTokens()
118        {
119            input = input.Replace("+"" + ");
120            input = input.Replace("-"" - ");
121            input = input.Replace("*"" * ");
122            input = input.Replace("/"" / ");
123            input = input.Replace("^"" ^ ");
124            input = input.Replace("("" ( ");
125            input = input.Replace(")"" ) ");
126            char[] sep =' '};
127            string[] ss = input.Split(sep,StringSplitOptions.None);           
128            return ss;            
129        }

130    }
鉴于这个类是在仓促下完成的,所以有待优化,经简单测试没有错误,欢迎留言指正。

posted on 2007-04-22 17:13  刘霆  阅读(115)  评论(0)    收藏  举报

导航