Beispiel #1
0
        //If token is MultiToken then push all its child tokens into _bufferdTokens and return first token in buffer
        private Token UnpackMultiToken(Token token)
        {
            var mtoken = token as MultiToken;

            if (mtoken == null)
            {
                return(null);
            }
            for (int i = mtoken.ChildTokens.Count - 1; i >= 0; i--)
            {
                _bufferedTokens.Insert(0, mtoken.ChildTokens[i]);
            }
            return(ReadBufferedToken());
        }
        public void TokenList_Simple()
        {
            TokenList tokens = new TokenList();

            Assert.AreEqual(0, tokens.Count);

            CssToken[] expect = new CssToken[]
            {
                new CssToken(CssTokenType.Asterisk, 10, 1),
                new CssToken(CssTokenType.Asterisk, 20, 1),
                new CssToken(CssTokenType.Asterisk, 30, 1),
                new CssToken(CssTokenType.Asterisk, 40, 1),
                new CssToken(CssTokenType.Asterisk, 50, 1),
                new CssToken(CssTokenType.Asterisk, 60, 1),
            };

            // The token collection is supposed to automatically sort its contents,
            // so add the tokens in a weird order.

            tokens.Add(expect[3]);
            tokens.Add(expect[0]);
            tokens.Add(expect[1]);
            tokens.Add(expect[4]);
            tokens.Add(expect[2]);
            tokens.Insert(tokens.Count, expect[5]);

            Assert.AreEqual(expect.Length, tokens.Count);

            for (int i = 0; i < expect.Length; i++)
            {
                Assert.AreEqual(expect[i], tokens[i]);
                Assert.IsTrue(tokens.Contains(expect[i]));
                Assert.AreEqual(i, tokens.IndexOf(expect[i]));
            }

            // Test the binary search for the token collection

            Assert.AreEqual(0, tokens.FindInsertIndex(0, beforeExisting: true));
            Assert.AreEqual(0, tokens.FindInsertIndex(10, beforeExisting: true));
            Assert.AreEqual(1, tokens.FindInsertIndex(10, beforeExisting: false));
            Assert.AreEqual(3, tokens.FindInsertIndex(35, beforeExisting: true));
            Assert.AreEqual(3, tokens.FindInsertIndex(35, beforeExisting: false));
            Assert.AreEqual(4, tokens.FindInsertIndex(50, beforeExisting: true));
            Assert.AreEqual(5, tokens.FindInsertIndex(50, beforeExisting: false));
            Assert.AreEqual(6, tokens.FindInsertIndex(61, beforeExisting: true));
            Assert.AreEqual(6, tokens.FindInsertIndex(61, beforeExisting: false));
            Assert.AreEqual(6, tokens.FindInsertIndex(100, beforeExisting: true));
            Assert.AreEqual(6, tokens.FindInsertIndex(100, beforeExisting: false));

            Assert.IsTrue(tokens.Remove(expect[2]));
            Assert.AreEqual(expect.Length - 1, tokens.Count);
            Assert.AreEqual(expect[3], tokens[2]);

            tokens.Clear();
            Assert.AreEqual(0, tokens.Count);
        }
Beispiel #3
0
        private void Calculate_Click(object sender, EventArgs e)
        {
            if (IsEval == true)
            {
                string evalExpress = view.Text;
                view.Text = "";

                if (evalExpress.Length <= 0)
                {
                    view.Text    = "입력 수식이 없습니다.";
                    IsEval       = false;
                    view.Enabled = false;
                    return;
                }

                else if (evalExpress.Equals("-"))
                {
                    view.Text    = "계산 불가";
                    IsEval       = false;
                    view.Enabled = false;
                    return;
                }

                TokenList tl = new TokenList();

                for (int i = 0; i < evalExpress.Length; i++)
                {
                    string patchStr = evalExpress[i].ToString();
                    if (IsOperator(patchStr) == true)            // patch 한 것이 문자(연산자) 라면
                    {
                        if (tl.getTokenNum() == tl.getCapacity())
                        {
                            tl.IncreaseCapacity();
                        }

                        tl.Insert(patchStr);
                    }

                    else                                        // patch 한 것이 숫자(피연산자) 라면
                    {
                        int num = Convert.ToChar(patchStr) - '0';

                        while (true)
                        {
                            if (i + 1 >= evalExpress.Length)
                            {
                                break;
                            }

                            string nextStr = evalExpress[++i].ToString();

                            if (IsOperator(nextStr) == true)
                            {
                                i--;
                                break;
                            }

                            else
                            {
                                num = num * 10 + Convert.ToChar(nextStr) - '0';
                            }
                        }

                        if (tl.getTokenNum() == tl.getCapacity())
                        {
                            tl.IncreaseCapacity();
                        }

                        tl.Insert(num.ToString());
                    }
                }

                tl.setArraySize();
                //Tokenization

                Token[] newToken = new Token[tl.getTokenNum()];
                // 후위 계산에 사용될 Token 배열 생성
                int newTokenNum = 0;
                // 후위 계산에 사용될 토큰 개수

                int openBracketCnt  = 0;    // 여는 괄호 개수
                int closeBracketCnt = 0;    // 닫는 괄호 개수

                for (int i = 0; i < tl.getTokenNum(); i++)
                {
                    Token patchToken = tl.getToken(i);

                    string patchStr = patchToken.getT();

                    if (IsOperator(patchStr) == true)    // Token이 연산자
                    {
                        if (patchStr == "+")
                        {
                            if (i == 0)
                            {
                                view.Text    = "계산 불가";
                                IsEval       = false;
                                view.Enabled = false;
                                return;
                            }

                            else if (i == tl.getTokenNum() - 1)
                            {
                                view.Text    = "계산 불가";
                                IsEval       = false;
                                view.Enabled = false;
                                return;
                            }

                            else
                            {
                                Token prevToken = tl.getToken(i - 1);
                                Token nextToken = tl.getToken(i + 1);

                                string prevStr = prevToken.getT();
                                string nextStr = nextToken.getT();

                                if (IsOperator(prevStr) == true)         // 이전 토큰 연산자(문자)
                                {
                                    if (IsOperator(nextStr) == true)     // 이후 토큰 연산자(문자)
                                    {
                                        if (prevStr.Equals(")") && (nextStr.Equals("(") || nextStr.Equals("-")))
                                        {
                                            newToken[newTokenNum++] = tl.getToken(i);
                                        }

                                        else
                                        {
                                            view.Text    = "계산 불가";
                                            IsEval       = false;
                                            view.Enabled = false;
                                            return;
                                        }
                                    }

                                    else                                // 이후 토큰 피연산자(숫자)
                                    {
                                        if (prevStr.Equals(")"))
                                        {
                                            newToken[newTokenNum++] = tl.getToken(i);
                                        }

                                        else
                                        {
                                            view.Text    = "계산 불가";
                                            IsEval       = false;
                                            view.Enabled = false;
                                            return;
                                        }
                                    }
                                }

                                else                                    // 이전 토큰 피연산자(숫자)
                                {
                                    if (IsOperator(nextStr) == true)    // 이후 토큰 연산자(문자)
                                    {
                                        if (nextStr.Equals("-") || nextStr.Equals("("))
                                        {
                                            newToken[newTokenNum++] = tl.getToken(i);
                                        }

                                        else
                                        {
                                            view.Text    = "계산 불가";
                                            IsEval       = false;
                                            view.Enabled = false;
                                            return;
                                        }
                                    }

                                    else                                // 이후 토큰 피연산자(숫자)
                                    {
                                        newToken[newTokenNum++] = tl.getToken(i);
                                    }
                                }
                            }
                        }

                        else if (patchStr == "-")
                        {
                            if (i == 0)
                            {
                                Token tilda = new Token("~");
                                newToken[newTokenNum++] = tilda;
                            }

                            else if (i == tl.getTokenNum() - 1)
                            {
                                view.Text    = "계산 불가";
                                IsEval       = false;
                                view.Enabled = false;
                                return;
                            }

                            else
                            {
                                Token prevToken = tl.getToken(i - 1);
                                Token nextToken = tl.getToken(i + 1);

                                string prevStr = prevToken.getT();
                                string nextStr = nextToken.getT();

                                if (nextStr.Equals("+") || nextStr.Equals("*") || nextStr.Equals("/") || nextStr.Equals(")"))
                                {
                                    view.Text    = "계산 불가";
                                    IsEval       = false;
                                    view.Enabled = false;
                                    return;
                                }

                                else
                                {
                                    if (prevStr.Equals("(") || prevStr.Equals("+") || prevStr.Equals("-") || prevStr.Equals("*") || prevStr.Equals("/"))
                                    {
                                        Token tilda = new Token("~");
                                        newToken[newTokenNum++] = tilda;
                                    }

                                    else
                                    {
                                        newToken[newTokenNum++] = tl.getToken(i);
                                    }
                                }
                            }
                        }

                        else if (patchStr == "*")
                        {
                            if (i == 0)
                            {
                                view.Text    = "계산 불가";
                                IsEval       = false;
                                view.Enabled = false;
                                return;
                            }

                            else if (i == tl.getTokenNum() - 1)
                            {
                                view.Text    = "계산 불가";
                                IsEval       = false;
                                view.Enabled = false;
                                return;
                            }

                            else
                            {
                                Token prevToken = tl.getToken(i - 1);
                                Token nextToken = tl.getToken(i + 1);

                                string prevStr = prevToken.getT();
                                string nextStr = nextToken.getT();

                                if (IsOperator(prevStr) == true)         // 이전 토큰 연산자(문자)
                                {
                                    if (IsOperator(nextStr) == true)     // 이후 토큰 연산자(문자)
                                    {
                                        if (prevStr.Equals(")") && (nextStr.Equals("(") || nextStr.Equals("-")))
                                        {
                                            newToken[newTokenNum++] = tl.getToken(i);
                                        }

                                        else
                                        {
                                            view.Text    = "계산 불가";
                                            IsEval       = false;
                                            view.Enabled = false;
                                            return;
                                        }
                                    }

                                    else                                // 이후 토큰 피연산자(숫자)
                                    {
                                        if (prevStr.Equals(")"))
                                        {
                                            newToken[newTokenNum++] = tl.getToken(i);
                                        }

                                        else
                                        {
                                            view.Text    = "계산 불가";
                                            IsEval       = false;
                                            view.Enabled = false;
                                            return;
                                        }
                                    }
                                }

                                else                                    // 이전 토큰 피연산자(숫자)
                                {
                                    if (IsOperator(nextStr) == true)    // 이후 토큰 연산자(문자)
                                    {
                                        if (nextStr.Equals("-") || nextStr.Equals("("))
                                        {
                                            newToken[newTokenNum++] = tl.getToken(i);
                                        }

                                        else
                                        {
                                            view.Text    = "계산 불가";
                                            IsEval       = false;
                                            view.Enabled = false;
                                            return;
                                        }
                                    }

                                    else                                // 이후 토큰 피연산자(숫자)
                                    {
                                        newToken[newTokenNum++] = tl.getToken(i);
                                    }
                                }
                            }
                        }

                        else if (patchStr == "/")
                        {
                            if (i == 0)
                            {
                                view.Text    = "계산 불가";
                                IsEval       = false;
                                view.Enabled = false;
                                return;
                            }

                            else if (i == tl.getTokenNum() - 1)
                            {
                                view.Text    = "계산 불가";
                                IsEval       = false;
                                view.Enabled = false;
                                return;
                            }

                            else
                            {
                                Token prevToken = tl.getToken(i - 1);
                                Token nextToken = tl.getToken(i + 1);

                                string prevStr = prevToken.getT();
                                string nextStr = nextToken.getT();

                                if (IsOperator(prevStr) == true)         // 이전 토큰 연산자(문자)
                                {
                                    if (IsOperator(nextStr) == true)     // 이후 토큰 연산자(문자)
                                    {
                                        if (prevStr.Equals(")") && (nextStr.Equals("(") || nextStr.Equals("-")))
                                        {
                                            newToken[newTokenNum++] = tl.getToken(i);
                                        }

                                        else
                                        {
                                            view.Text    = "계산 불가";
                                            IsEval       = false;
                                            view.Enabled = false;
                                            return;
                                        }
                                    }

                                    else                                // 이후 토큰 피연산자(숫자)
                                    {
                                        if (prevStr.Equals(")"))
                                        {
                                            newToken[newTokenNum++] = tl.getToken(i);
                                        }

                                        else
                                        {
                                            view.Text    = "계산 불가";
                                            IsEval       = false;
                                            view.Enabled = false;
                                            return;
                                        }
                                    }
                                }

                                else                                    // 이전 토큰 피연산자(숫자)
                                {
                                    if (IsOperator(nextStr) == true)    // 이후 토큰 연산자(문자)
                                    {
                                        if (nextStr.Equals("-") || nextStr.Equals("("))
                                        {
                                            newToken[newTokenNum++] = tl.getToken(i);
                                        }

                                        else
                                        {
                                            view.Text    = "계산 불가";
                                            IsEval       = false;
                                            view.Enabled = false;
                                            return;
                                        }
                                    }

                                    else                                // 이후 토큰 피연산자(숫자)
                                    {
                                        newToken[newTokenNum++] = tl.getToken(i);
                                    }
                                }
                            }
                        }

                        else if (patchStr == "(")
                        {
                            openBracketCnt++;

                            if (i == 0)
                            {
                                Token  nextToken = tl.getToken(i + 1);
                                string nextStr   = nextToken.getT();

                                if (nextStr.Equals(")"))
                                {
                                    view.Text    = "계산 불가";
                                    IsEval       = false;
                                    view.Enabled = false;
                                    return;
                                }


                                newToken[newTokenNum++] = tl.getToken(i);
                            }

                            else if (i == tl.getTokenNum() - 1)
                            {
                                view.Text    = "계산 불가";
                                IsEval       = false;
                                view.Enabled = false;
                                return;
                            }

                            else
                            {
                                Token prevToken = tl.getToken(i - 1);
                                Token nextToken = tl.getToken(i + 1);

                                string prevStr = prevToken.getT();
                                string nextStr = nextToken.getT();

                                if (IsOperator(prevStr) == true)         // 이전 토큰 연산자(문자)
                                {
                                    if (IsOperator(nextStr) == true)     // 이후 토큰 연산자(문자)
                                    {
                                        if (prevStr.Equals(")") || nextStr.Equals("+") || nextStr.Equals("*") || nextStr.Equals("/") || nextStr.Equals(")") || nextStr.Equals(")"))
                                        {
                                            view.Text    = "계산 불가";
                                            IsEval       = false;
                                            view.Enabled = false;
                                            return;
                                        }

                                        else
                                        {
                                            newToken[newTokenNum++] = tl.getToken(i);
                                        }
                                    }

                                    else                                // 이후 토큰 피연산자(숫자)
                                    {
                                        if (prevStr.Equals(")"))
                                        {
                                            view.Text    = "계산 불가";
                                            IsEval       = false;
                                            view.Enabled = false;
                                            return;
                                        }

                                        else
                                        {
                                            newToken[newTokenNum++] = tl.getToken(i);
                                        }
                                    }
                                }

                                else                                    // 이전 토큰 피연산자(숫자)
                                {
                                    view.Text    = "계산 불가";
                                    IsEval       = false;
                                    view.Enabled = false;
                                    return;
                                }
                            }
                        }

                        else if (patchStr == ")")
                        {
                            closeBracketCnt++;

                            if (closeBracketCnt > openBracketCnt)
                            {
                                view.Text    = "계산 불가";
                                IsEval       = false;
                                view.Enabled = false;
                                return;
                            }
                            if (i == 0)
                            {
                                view.Text    = "계산 불가";
                                IsEval       = false;
                                view.Enabled = false;
                                return;
                            }

                            else if (i == tl.getTokenNum() - 1)
                            {
                                newToken[newTokenNum++] = tl.getToken(i);
                            }

                            else
                            {
                                Token prevToken = tl.getToken(i - 1);
                                Token nextToken = tl.getToken(i + 1);

                                string prevStr = prevToken.getT();
                                string nextStr = nextToken.getT();

                                if (IsOperator(prevStr) == true)         // 이전 토큰 연산자(문자)
                                {
                                    if (IsOperator(nextStr) == true)     // 이후 토큰 연산자(문자)
                                    {
                                        if (prevStr.Equals(")") && (nextStr.Equals("+") || nextStr.Equals("-") || nextStr.Equals("*") || nextStr.Equals("/") || nextStr.Equals(")")))
                                        {
                                            newToken[newTokenNum++] = tl.getToken(i);
                                        }

                                        else
                                        {
                                            view.Text    = "계산 불가";
                                            IsEval       = false;
                                            view.Enabled = false;
                                            return;
                                        }
                                    }

                                    else                                // 이후 토큰 피연산자(숫자)
                                    {
                                        view.Text    = "계산 불가";
                                        IsEval       = false;
                                        view.Enabled = false;
                                        return;
                                    }
                                }

                                else                                     // 이전 토큰 피연산자(숫자)
                                {
                                    if (IsOperator(nextStr) == true)     // 이후 토큰 연산자(문자)
                                    {
                                        if (nextStr.Equals("("))
                                        {
                                            view.Text    = "계산 불가";
                                            IsEval       = false;
                                            view.Enabled = false;
                                            return;
                                        }

                                        else
                                        {
                                            newToken[newTokenNum++] = tl.getToken(i);
                                        }
                                    }

                                    else                                // 이후 토큰 피연산자(숫자)
                                    {
                                        view.Text    = "계산 불가";
                                        IsEval       = false;
                                        view.Enabled = false;
                                        return;
                                    }
                                }
                            }
                        }
                    }

                    else                                // Token이 피연산자
                    {
                        newToken[newTokenNum++] = tl.getToken(i);
                    }
                }

                if (openBracketCnt != closeBracketCnt)
                {
                    view.Text    = "계산 불가";
                    IsEval       = false;
                    view.Enabled = false;
                    return;
                }
                // Inspection

                Token[] evalToken = new Token[newTokenNum];
                // 후위 연산을 하기 위한 토큰 배열
                int evalTokenNum = 0;

                Stack <String> s = new Stack <String>();
                s.Push("#");

                for (int i = 0; i < newTokenNum; i++)
                {
                    Token  patchToken = newToken[i];
                    string patchStr   = patchToken.getT();

                    if (IsOperator(patchStr) == false)
                    {
                        Token inputToken = new Token(patchStr);
                        evalToken[evalTokenNum++] = inputToken;
                    }

                    else
                    {
                        if (patchStr.Equals(")"))
                        {
                            while (s.Peek() != "(")
                            {
                                Token inputToken = new Token(s.Peek());
                                evalToken[evalTokenNum++] = inputToken;
                                s.Pop();
                            }

                            s.Pop();
                        }

                        else
                        {
                            while (isp(s.Peek()) >= icp(patchStr))
                            {
                                Token inputToken = new Token(s.Peek());
                                evalToken[evalTokenNum++] = inputToken;
                                s.Pop();
                            }

                            s.Push(patchStr);
                        }
                    }
                }

                while (s.Peek() != "#")
                {
                    Token inputToken = new Token(s.Peek());
                    evalToken[evalTokenNum++] = inputToken;
                    s.Pop();
                }
                // token화 연산식


                Stack <string> finalStack = new Stack <String>();

                for (int i = 0; i < evalTokenNum; i++)
                {
                    Token  patchT = evalToken[i];
                    string patchS = patchT.getT();

                    if (IsOperator(patchS) == true)
                    {
                        if (patchS.Equals("+"))
                        {
                            string op2 = finalStack.Peek();
                            finalStack.Pop();
                            string op1 = finalStack.Peek();
                            finalStack.Pop();
                            double num2   = Convert.ToDouble(op2);
                            double num1   = Convert.ToDouble(op1);
                            double sum    = num1 + num2;
                            string result = sum.ToString();
                            finalStack.Push(result);
                        }

                        else if (patchS.Equals("-"))
                        {
                            string op2 = finalStack.Peek();
                            finalStack.Pop();
                            string op1 = finalStack.Peek();
                            finalStack.Pop();
                            double num2     = Convert.ToDouble(op2);
                            double num1     = Convert.ToDouble(op1);
                            double subtract = num1 - num2;
                            string result   = subtract.ToString();
                            finalStack.Push(result);
                        }

                        else if (patchS.Equals("*"))
                        {
                            string op2 = finalStack.Peek();
                            finalStack.Pop();
                            string op1 = finalStack.Peek();
                            finalStack.Pop();
                            double num2     = Convert.ToDouble(op2);
                            double num1     = Convert.ToDouble(op1);
                            double multiply = num1 * num2;
                            string result   = multiply.ToString();
                            finalStack.Push(result);
                        }

                        else if (patchS.Equals("/"))
                        {
                            string op2 = finalStack.Peek();
                            finalStack.Pop();
                            string op1 = finalStack.Peek();
                            finalStack.Pop();
                            double num2 = Convert.ToDouble(op2);
                            double num1 = Convert.ToDouble(op1);
                            if (num2 == 0)
                            {
                                view.Text    = "연산 오류";
                                IsEval       = false;
                                view.Enabled = false;
                                return;
                            }
                            double divide = num1 / num2;
                            string result = divide.ToString();
                            finalStack.Push(result);
                        }

                        else if (patchS.Equals("~"))
                        {
                            string op = finalStack.Peek();
                            finalStack.Pop();
                            double num    = Convert.ToDouble(op);
                            double tilda  = (-1) * num;
                            string result = tilda.ToString();
                            finalStack.Push(result);
                        }
                    }

                    else
                    {
                        finalStack.Push(patchS);
                    }
                }

                string resultStr = finalStack.Peek();
                view.Text = resultStr;
            }

            IsEval       = false;
            view.Enabled = false;
        }