import java.util.ArrayList; import java.util.List; import java.util.Stack; /** * »çÄ¢ ¿¬»ê ¼ö½Ä Çؼ® (parse four arithmetic expression) * * @author sunnyk * */ public class FourArithExprParser { // »çÄ¢¿¬»êÀÚ ¸ñ·Ï private static char[] OPERATORS = { '+', '-', '*', '/' }; // ÁÂ/¿ì °ýÈ£ private static char[] PARENTHESISES = { '(', ')' }; private String numberBuffer; private String inputExpr; private List symbols = new ArrayList(); private Stack aStack = new Stack(); /** * »ý¼ºÀÚ¿¡ ÁßÀ§½Ä »çÄ¢¿¬»ê ¼ö½ÄÀ» ÀÔ·Â. */ public FourArithExprParser(String expression) { this.inputExpr = expression; } /** * ÁßÀ§½Ä »çÄ¢¿¬»ê ¼ö½Ä¿¡¼­ Ç׸ñ(symbol)µéÀ» ÃßÃâÇÑ´Ù. */ public void parseSymbols() { // ¹®ÀÚ(character) ´ÜÀ§·Î ºÐ¼®.. for (int idx = 0; idx < inputExpr.length(); idx++) { char charInExpr = inputExpr.charAt(idx); // °ø¹é(whitespace) ¹®ÀÚ - linefeed, space, tab µî-À̸é, ÀÌÀü ¹öÆÛÀÇ ³»¿ëÀ» ºñ¿ò. if (Character.isWhitespace(charInExpr)) { handleTempBuff(); } // »çÄ¢¿¬»ê ¿¬»êÀÚ È¤Àº °ýÈ£ÀÎ °æ¿ì, Ç׸ñ Ãß°¡. else if (isMathOperatorOrParenthesis(charInExpr)) { handleTempBuff(); symbols.add(String.valueOf(charInExpr)); } // ¼ýÀÚ ¹®ÀÚÀÎ °æ¿ì, ¼ýÀÚ ¹öÆÛ¿¡ Ãß°¡.. else if (Character.isDigit(charInExpr)) { if (numberBuffer == null) { numberBuffer = String.valueOf(charInExpr); } else { numberBuffer += charInExpr; } } } handleTempBuff(); } /** * ÁßÀ§½ÄÀ» ÈÄÀ§½ÄÀ¸·Î º¯È¯. */ public void toPostfix() { List postfixExpr = new ArrayList(); // ÁßÀ§½Ä Ç¥Çö½ÄÀÇ °¢ Ç׸ñ¿¡ ´ëÇؼ­... for(String symbol : symbols) { char firstCharOfColumn = symbol.charAt(0); // ÇÇ¿¬»êÀÚÀ̸é, ÇÇ¿¬»êÀÚ¸¦ ÈÄÀ§½Ä¿¡ Ãß°¡ if(!isMathOperatorOrParenthesis(firstCharOfColumn)) { postfixExpr.add(symbol); } // Á°ýÈ£ÀÌ¸é ½ºÅÿ¡ Ãß°¡ else if('(' == firstCharOfColumn) { aStack.push(symbol); } // ¿ì°ýÈ£À̸é, Á°ýÈ£ '('°¡ ³ª¿Ã ¶§±îÁö ½ºÅÿ¡¼­ ²¨³¿. else if(')' == firstCharOfColumn) { // ½ºÅÃÀÇ ÃÖ»óÀ§ °ªÀÌ Á°ýÈ£ '('°¡ ¾Æ´Ï¸é.. while (!"(".equals(aStack.peek())) { postfixExpr.add(aStack.pop()); } // whileÀÇ ³¡ // Á°ýÈ£'(' Á¦°Å aStack.pop(); } // ¿¬»êÀÚÀ̸é, ½ºÅÿ¡ ÀÖ´Â ´õ ³ôÀº ¿ì¼±¼øÀ§ ¿¬»êÀÚ Ã³¸® else { // ¸¸¾à, ½ºÅÃÀÌ ºñ¾î Àְųª, ½ºÅÃÀÇ ÃÖ»óÀ§¿¡ Á°ýÈ£°¡ µé¾î ÀÖÀ¸¸é, ¿¬»êÀÚ¸¦ ½ºÅÿ¡ Ãß°¡ if(aStack.isEmpty() || "(".equals(aStack.peek())) { aStack.push(symbol); } // ¿¬»êÀÚÀÇ ¿ì¼±¼øÀ§°¡ ½ºÅÃÀÇ ÃÖ»óÀ§¿¡ ÀÖ´Â ¿¬»êÀÚº¸´Ù ³ôÀ¸¸é ½ºÅÿ¡ Ãß°¡ else if(priority(symbol) > priority(aStack.peek())) { aStack.push(symbol); } // ¿¬»êÀÚÀÇ ¿ì¼±¼øÀ§°¡ ½ºÅÃÀÇ ÃÖ»óÀ§¿¡ ÀÖ´Â ¿¬»êÀÚ¿Í °°À¸¸é, ¿¬°ü¿¡ µû¶ó ó¸®.. // (ÁÂÃø¿¡¼­ ¿ìÃøÀ¸·Î ¿¬»êÇÏ´Â °æ¿ì, ½ºÅÃÀÇ ÃÖ»óÀ§ ¿¬»êÀÚ¸¦ ²¨³»°í, ¿¬»êÀÚ¸¦ ½ºÅÿ¡ Ãß°¡) else if(priority(symbol) == priority(aStack.peek())) { postfixExpr.add(aStack.pop()); aStack.push(symbol); } // »õ·Î¿î ¿¬»êÀÚÀÇ ¿ì¼±¼øÀ§°¡ ½ºÅÃÀÇ ÃÖ»óÀ§¿¡ ÀÖ´Â ¿¬»êÀÚº¸´Ù ³·À¸¸é, // ½ºÅÃÀÇ ÃÖ»óÀ§ ¿¬»êÀÚ¸¦ ²¨³»°í, »õ·Î¿î ¿¬»êÀÚ¸¦ ½ºÅÿ¡ Ãß°¡ else { while(!aStack.isEmpty() && priority(symbol) <= priority(aStack.peek())) { postfixExpr.add(aStack.pop()); } aStack.push(symbol); } } } // ÈÄÀ§½Ä¿¡ ½ºÅÿ¡ ³²Àº ¿¬»êÀÚµéÀ» Ãß°¡ while(!aStack.isEmpty()) { postfixExpr.add(aStack.pop()); } // whileÀÇ ³¡ // ÁßÀ§½ÄÀ» ÈÄÀ§½ÄÀ¸·Î µ¤¾î¾²±â... symbols = postfixExpr; } /** * ÈÄÀ§½Ä °è»êÀ» ¼öÇàÇÏ°í °á°ú °ªÀ» ¹ÝȯÇÑ´Ù. */ public int calcalate() { // ÈÄÀ§½Ä ±âÈ£(symbol)µéÀ» ¼øÂ÷ÀûÀ¸·Î ó¸®ÇÑ´Ù. for(String symbol : symbols) { char firstChOfSymbol = symbol.charAt(0); // »çÄ¢¿¬»ê ¿¬»êÀÚÀÎ °æ¿ì... if(isOperator(firstChOfSymbol)) { // ÇÇ¿¬»êÀÚ(operand)¸¦ ½ºÅÿ¡¼­ ²¨³½´Ù. // (¼ø¼­°¡ ¹Ý´ë·Î ÀúÀåµÇ¾î ÀÖÀ½À» ÁÖÀÇÇÒ °Í) int secondOperand = Integer.valueOf(aStack.pop()); int firstOperand = Integer.valueOf(aStack.pop()); // ¿¬»êÀÚÀÇ À¯Çü¿¡ µû¶ó °è»êÀ» ¼öÇàÇÑ´Ù. int result = 0; switch(firstChOfSymbol) { case '+': result = firstOperand + secondOperand; break; case '-': result = firstOperand - secondOperand; break; case '*': result = firstOperand * secondOperand; break; case '/': result = firstOperand / secondOperand; break; } // ¿¬»ê °á°ú¸¦ ´Ù½Ã ½ºÅÿ¡ ´ã´Â´Ù. aStack.push(String.valueOf(result)); } // ÇÇ¿¬»êÀÚÀÎ °æ¿ì¿¡´Â ½ºÅÿ¡ ¹«Á¶°Ç ´ã´Â´Ù. else { aStack.push(symbol); } } // ¸ðµç 󸮰¡ ³¡³ª¸é, °á°ú °ªÀÌ ½ºÅÿ¡ ³²¾Æ ÀÖ´Ù. return Integer.valueOf(aStack.pop()); } /** * ¼ö½Ä ºÐ¼® °á°ú¸¦ È­¸é¿¡ Ãâ·Â. */ public void print() { for (String symbol : symbols) { System.out.print(symbol + " "); } System.out.println(); } /* * »õ·Î¿î Ç׸ñ(symbol)À» ãÀº °æ¿ì, Àӽà ¹öÆÛÀÇ ³»¿ëÀ» Ç׸ñ ¸ñ·Ï¿¡ Ãß°¡ */ private void handleTempBuff() { if (numberBuffer != null) { symbols.add(numberBuffer); numberBuffer = null; } } /* * ¿¬»êÀÚ È¤Àº °ýÈ£ÀÎÁö °Ë»ç. */ private boolean isMathOperatorOrParenthesis(char inputChar) { for (char op : OPERATORS) { if (inputChar == op) { return true; } } for(char brace : PARENTHESISES) { if (inputChar == brace) { return true; } } return false; } /* * ¿¬»êÀÚ ÀÎÁö °Ë»ç. */ private boolean isOperator(char inputChar) { for (char op : OPERATORS) { if (inputChar == op) { return true; } } return false; } /* * ¿¬»êÀÚÀÇ ¿ì¼±¼øÀ§(priority)¸¦ ¹ÝȯÇÑ´Ù. */ private int priority(String symbol) { int priority = 0; switch(symbol){ case "*": case "/": priority = 2; break; case "+": case "-": priority = 1; } return priority; } }