//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); }
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; }