- /**
- * filename: InfixEvaluator.java
- * package: infix
- * author: Li Ma
- * email: nick.ma85@yahoo.com
- * date: Oct 3, 2008
- * description: this class evaluates infix by converting infix to postfix
- */
- package infix;
- import java.util.*;
- public class InfixEvaluator {
- /** the stack stores operators */
- private Stack<Character> operatorStack;
- /** the stack stores operands */
- private Stack<Integer> operandStack;
- /** each operator(char) has a integer value of priority */
- private static final Map<Character, Integer> OPERATORS;
- /** postfix exp converted from infix exp */
- private StringBuilder postfix;
- /** the infix exp */
- private String infix;
- static {
- // initialize the static field
- OPERATORS = new HashMap<Character, Integer>();
- OPERATORS.put( '+' , 1 );
- OPERATORS.put( '-' , 1 );
- OPERATORS.put( '*' , 2 );
- OPERATORS.put( '/' , 2 );
- }
- /**
- * description: the default constructor
- */
- public InfixEvaluator() {
- // TODO Auto-generated constructor stub
- operatorStack = new Stack<Character>();
- operandStack = new Stack<Integer>();
- infix = null ;
- postfix = new StringBuilder();
- }
- /**
- * description: the constructor with fields
- * @param infixStr - the infix string
- */
- public InfixEvaluator(String infixStr) {
- this ();
- this .infix = infixStr;
- }
- /**
- * description: convert a string from infix to postfix
- * @throws SyntaxErrorException
- */
- private void convertInfixToPostfix() throws SyntaxErrorException {
- StringTokenizer infixTokens = new StringTokenizer(infix);
- try {
- while (infixTokens.hasMoreTokens()) {
- String next = infixTokens.nextToken();
- char firstChar = next.charAt( 0 );
- // determine whether it is operand
- if (Character.isJavaIdentifierStart(firstChar)
- || Character.isDigit(firstChar)) {
- postfix.append(next);
- postfix.append( " " );
- } else if (isOperator(firstChar)) {
- // it is an operator
- processOperator(firstChar);
- } else {
- throw new SyntaxErrorException( "Unexpected Character Encountered: " + firstChar);
- }
- }
- // pop any remaining operators and append them to postfix
- while (!operatorStack.empty()) {
- Character op = operatorStack.pop();
- postfix.append(op);
- postfix.append( " " );
- }
- } catch (EmptyStackException e) {
- throw new SyntaxErrorException( "Syntax error: the stack is empty" );
- }
- }
- /**
- * description: process operators, let them push or add to the postfix
- * @param op - the character of the operator
- */
- private void processOperator( char op) {
- if (operatorStack.empty()) {
- operatorStack.push( new Character(op));
- } else {
- // peek the operator stack and let topOp be top
- char topOp = operatorStack.peek().charValue();
- if (OPERATORS.get(op) > OPERATORS.get(topOp)) {
- operatorStack.push( new Character(op));
- } else {
- // pop all stacked operators with equal or higher priority than op
- while (!operatorStack.empty()
- && OPERATORS.get(op) <= OPERATORS.get(topOp)) {
- operatorStack.pop();
- postfix.append(topOp);
- postfix.append( " " );
- if (!operatorStack.empty()) {
- topOp = operatorStack.peek().charValue();
- }
- }
- operatorStack.push( new Character(op));
- }
- }
- }
- /**
- * description: determine whether the character is an operator
- * @param ch - the character to be tested
- * @return true if ch is an operator
- */
- private boolean isOperator( char ch) {
- return OPERATORS.containsKey(ch);
- }
- /**
- * description: evaluate the current operation, poping the two operands off
- * the operand stack and applying the operator.
- * @param op - a character representing the operator
- * @return the result of applying the operator
- */
- private int evalOp( char op) {
- // pop the two operands off the stack
- int rhs = operandStack.pop();
- int lhs = operandStack.pop();
- int result = 0 ;
- // evaluate the operator
- switch (op) {
- case '+' :
- result = lhs + rhs;
- break ;
- case '-' :
- result = lhs - rhs;
- break ;
- case '*' :
- result = lhs * rhs;
- break ;
- case '/' :
- result = lhs / rhs;
- break ;
- }
- return result;
- }
- /**
- * description: evaluate the whole infix expression
- * @return the value of the infix expression
- * @throws SyntaxErrorException
- */
- public int eval() throws SyntaxErrorException {
- // translate the infix to postfix
- this .convertInfixToPostfix();
- // process each token
- StringTokenizer tokens = new StringTokenizer( this .postfix.toString());
- try {
- while (tokens.hasMoreTokens()) {
- String next = tokens.nextToken();
- if (Character.isDigit(next.charAt( 0 ))) {
- int value = Integer.parseInt(next);
- // push value onto operand stack
- operandStack.push(value);
- } else if (isOperator(next.charAt( 0 ))) {
- // it is an operator
- // evaluate the operator
- int result = evalOp(next.charAt( 0 ));
- operandStack.push(result);
- } else {
- throw new SyntaxErrorException( "Invalid character encountered" );
- }
- }
- // no more tokens, pop result from operand stack
- int answer = operandStack.pop();
- if (operandStack.empty()) {
- return answer;
- } else {
- // indicate syntax error
- throw new SyntaxErrorException( "Stack should be empty" );
- }
- } catch (EmptyStackException e) {
- throw new SyntaxErrorException( "the stack is empty" );
- }
- }
- }
- /**
- * filename: SyntaxErrorException.java
- * package: infix
- * author: Li Ma
- * email: nick.ma85@yahoo.com
- * date: Oct 3, 2008
- * description: this exception shows a syntax error.
- */
- package infix;
- public class SyntaxErrorException extends Exception {
- private static final long serialVersionUID = 1L;
- public SyntaxErrorException( final String message) {
- super (message);
- }
- }
Infix Expression Evaluator
最新推荐文章于 2022-04-07 22:38:18 发布