Last active
December 7, 2016 23:37
-
-
Save timmolderez/d0cf8993648777130f402d27cf324d7d to your computer and use it in GitHub Desktop.
Design patterns exercise: composite, iterator, visitor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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