package uk.co.peteski.www;import javax.swing.*;import java.util.regex.Pattern;import java.util.regex.Matcher;import java.util.Stack;import java.util.Map;import java.util.HashMap;import java.awt.*;/** * Created by IntelliJ IDEA. * User: peteski * Date: 02-Dec-2004 * Time: 17:15:20 * To change this template use File | Settings | File Templates. */public class ExpressionParser extends JFrame{ private static final Pattern NUMBER = Pattern.compile("\\d+(\\.\\d+)?"); private static final Pattern OPERATOR = Pattern.compile("[()+\\-*/]"); private static final Map operatorPrecedence = new HashMap(); private Stack numberStack = new Stack(); private Stack operatorStack = new Stack(); private int currentPrecedence; static { operatorPrecedence.put("-", new Integer(1)); operatorPrecedence.put("+", new Integer(2)); operatorPrecedence.put("*", new Integer(3)); operatorPrecedence.put("/", new Integer(4)); // support for brackets ( .. ) operatorPrecedence.put("(", new Integer(0)); } public ExpressionParser(String title) throws HeadlessException { super(title); } public void performCalculation() { // work out results from number and operator stacks while(!operatorStack.empty()) { executeTopOp(); } } private void executeTopOp() { // take a number from numberStack and get Double secondNumber = new Double(0); Double firstNumber = new Double(0); String topOperator; // see if the stacks are empty before you try to pop from them if(!operatorStack.empty()) { topOperator = (String)operatorStack.pop(); if(("(".equals(topOperator)) ) { // then dont bother popping the number stacks // just drop out of the loop leaving the "(" removed from stack // we finished with the brackets } else { if(!numberStack.empty()) { secondNumber = (Double)numberStack.pop(); } if(!numberStack.empty()) { firstNumber = (Double)numberStack.pop(); } // compare the operator to operators it could be if("+".equals(topOperator)) { // perform the calculation and pop the result onto the number stack numberStack.push(new Double(firstNumber.doubleValue() + secondNumber.doubleValue())); } else if("-".equals(topOperator)) { numberStack.push(new Double(firstNumber.doubleValue() - secondNumber.doubleValue())); } else if("*".equals(topOperator)) { numberStack.push(new Double(firstNumber.doubleValue() * secondNumber.doubleValue())); } else if("/".equals(topOperator)) { numberStack.push(new Double(firstNumber.doubleValue() / secondNumber.doubleValue())); } } } } public void parseString(String textString) { while (true) { // set a matcher for matching the NUMBER pattern, give it our string Matcher matcher = NUMBER.matcher(textString); // see if that pattern exists in our string. if (matcher.lookingAt()) { //JOptionPane.showMessageDialog(this, matcher.group(0)); // add it to the number stack numberStack.push(new Double(Double.parseDouble(matcher.group(0)))); // modify the remaining string by removing the start we just parsed textString = textString.substring(matcher.end(0)); } // now we want to see if it matches the OPERATOR pattern. else if ((matcher = OPERATOR.matcher(textString)).lookingAt()) { //JOptionPane.showMessageDialog(this, matcher.group(0)); // add it to the operator stack pushOperator(matcher.group(0)); // change the textString (chop off what we parsed from the beginning of the string) textString = textString.substring(matcher.end(0)); } else { // we reached the end of the string break; } } // call the calculation stuff to pop the stacks and work out the answer performCalculation(); // display the answer which is the last number on the stack. JOptionPane.showMessageDialog(this, numberStack.pop()); } private void pushOperator(String operator) { // get the value of the operators precedence. if((")".equals(operator))) { while(!("(".equals(operatorStack.peek()))) { executeTopOp(); } } else if("(".equals(operator)) { operatorStack.push(operator); } else { currentPrecedence = getPrecedence(operator); while(!operatorStack.empty() && currentPrecedence < getPrecedence((String) operatorStack.peek())) { // keep executing the current operation executeTopOp(); } // now we can add the operator to the stack operatorStack.push(operator); } // ditch the operator now? } private int getPrecedence(String operator) { return ((Integer) operatorPrecedence.get(operator)).intValue(); }}