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