Skip to content

Instantly share code, notes, and snippets.

@timmolderez
Last active December 7, 2016 23:37
Show Gist options
  • Save timmolderez/d0cf8993648777130f402d27cf324d7d to your computer and use it in GitHub Desktop.
Save timmolderez/d0cf8993648777130f402d27cf324d7d to your computer and use it in GitHub Desktop.
Design patterns exercise: composite, iterator, visitor
package be.ac.vub.patterns;
import java.util.Stack;
public class ArithmeticParser {
public enum Parentheses { LEFT, RIGHT }
public enum BinaryOperator {
ADD('+', 1) {
public Double eval(Double leftValue, Double rightValue) { return leftValue + rightValue; }
},
SUB('-', 1) {
public Double eval(Double leftValue, Double rightValue) { return leftValue - rightValue; }
},
MUL('*', 2) {
public Double eval(Double leftValue, Double rightValue) { return leftValue * rightValue; }
},
DIV('/', 2) {
public Double eval(Double leftValue, Double rightValue) { return leftValue / rightValue; }
};
public final char symbol;
public final int precedence;
BinaryOperator(char symbol, int precedence) {
this.symbol = symbol;
this.precedence = precedence;
}
public abstract Double eval(Double leftValue, Double rightValue);
}
public class BinaryExpression {
public Object leftOperand = null;
public BinaryOperator operator = null;
public Object rightOperand = null;
public BinaryExpression(Object leftOperand, BinaryOperator operator, Object rightOperand) {
this.leftOperand = leftOperand;
this.operator = operator;
this.rightOperand = rightOperand;
}
public Double eval() {
Double leftValue = (leftOperand instanceof BinaryExpression) ? ((BinaryExpression)leftOperand).eval() : (Double)leftOperand;
Double rightValue = (rightOperand instanceof BinaryExpression) ? ((BinaryExpression)rightOperand).eval() : (Double)rightOperand;
return operator.eval(leftValue, rightValue);
}
public String toString() {
return "(" + leftOperand + " " + operator.symbol + " " + rightOperand + ")"; }
}
public void createNewOperand(BinaryOperator operator, Stack<Object> operands) {
Object rightOperand = operands.pop();
operands.push(new BinaryExpression(operands.pop(), operator, rightOperand));
return;
}
public Object parseExpression(String inputString) {
int curIndex = 0;
boolean afterOperand = false;
Stack<Object> operands = new Stack<Object>();
Stack<Object> operators = new Stack<Object>();
inputStringLoop:
while (curIndex < inputString.length()) {
int startIndex = curIndex;
char c = inputString.charAt(curIndex++);
if (Character.isWhitespace(c))
continue;
if (afterOperand) {
if (c == ')') {
Object operator = null;
while (!operators.isEmpty() && ((operator = operators.pop()) != Parentheses.LEFT))
createNewOperand((BinaryOperator)operator, operands);
continue;
}
afterOperand = false;
for (BinaryOperator operator : BinaryOperator.values()) {
if (c == operator.symbol) {
while (!operators.isEmpty() && (operators.peek() != Parentheses.LEFT) && (((BinaryOperator)operators.peek()).precedence >= operator.precedence))
createNewOperand((BinaryOperator)operators.pop(), operands);
operators.push(operator);
continue inputStringLoop;
}
}
throw new IllegalArgumentException();
}
if (c == '(') {
operators.push(Parentheses.LEFT);
continue;
}
afterOperand = true;
while (curIndex < inputString.length()) {
c = inputString.charAt(curIndex);
if (((c < '0') || (c > '9')) && (c != '.'))
break;
curIndex++;
}
operands.push(Double.valueOf(inputString.substring(startIndex, curIndex)));
}
while (!operators.isEmpty()) {
Object operator = operators.pop();
createNewOperand((BinaryOperator)operator, operands);
}
Object expression = operands.pop();
return expression;
}
public static void main(String[] args) {
ArithmeticParser p = new ArithmeticParser();
String[] testExpressions = { "2+3", "2+3/4", "2*3-4", "2*(3+4)+5/6", "2 * (3 + (4 * 5 + (6 * 7) * 8) - 9) * 10"};
for (String testExpression : testExpressions) {
Object expression = p.parseExpression(testExpression);
System.out.println("Input: \"" + testExpression + "\", AST: \"" + expression + "\", eval=" + (expression instanceof BinaryExpression ? ((BinaryExpression)expression).eval() : expression));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment