Thomas Darimont
Erfahrenes Mitglied
Hallo,
dieser Beitrag erklärt das Verhaltensmuster: Interpreter
Ausgabe:
Gruß Tom
dieser Beitrag erklärt das Verhaltensmuster: Interpreter
Java:
package de.tutorials.design.patterns.behavioral;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
public class InterpreterExample {
public static void main(String[] args) {
Interpreter interpreter = new Interpreter();
interpreter.eval("+ 3 4");
interpreter.eval("* 6 7");
interpreter.eval("^ 2 10");
interpreter.eval("sqrt 9");
interpreter.eval("cos 37");
}
static class Interpreter {
public Double eval(String input) {
Expression expression = ASTParser.INSTANCE.parse(input.trim());
System.out.println(expression);
Double result = eval(expression);
System.out.println(" = " + result);
return result;
}
public Double eval(Expression input) {
if (input instanceof NumberExpression) {
return ((NumberExpression) input).value;
} else if (input instanceof UnaryOperation) {
UnaryOperation uo = (UnaryOperation) input;
switch (uo.operator) {
case "sin": return Math.sin(eval(uo.argument));
case "cos": return Math.cos(eval(uo.argument));
case "tan": return Math.tan(eval(uo.argument));
case "ln": return Math.log(eval(uo.argument));
case "sqrt": return Math.sqrt(eval(uo.argument));
}
} else if (input instanceof BinaryOperation) {
BinaryOperation bo = (BinaryOperation) input;
switch (bo.operation) {
case "+": return eval(bo.left) + eval(bo.right);
case "-": return eval(bo.left) - eval(bo.right);
case "*": return eval(bo.left) * eval(bo.right);
case "/": return eval(bo.left) / eval(bo.right);
case "^": return Math.pow(eval(bo.left), eval(bo.right));
}
}
return Double.NaN;
}
}
static abstract class Expression {}
static class NumberExpression extends Expression {
private final Double value;
public NumberExpression(Double value) {
this.value = value;
}
@Override
public String toString() {
return value.toString();
}
}
static class UnaryOperation extends Expression {
private final String operator;
private final Expression argument;
public UnaryOperation(String operator, Expression argument) {
this.operator = operator;
this.argument = argument;
}
@Override
public String toString() {
return operator + "(" + argument + ")";
}
}
static class BinaryOperation extends Expression {
private final String operation;
private final Expression left;
private final Expression right;
public BinaryOperation(String operation, Expression left, Expression right) {
this.operation = operation;
this.left = left;
this.right = right;
}
@Override
public String toString() {
return "(" + left + " " + operation + " " + right + ")";
}
}
enum ASTParser {
INSTANCE;
public Expression parse(String input) {
List<String> tokens = Arrays.asList(input.split(" "));
Collections.reverse(tokens);
Stack<Expression> stack = new Stack<Expression>();
for (String token : tokens) {
switch (token) {
case "+": stack.push(new BinaryOperation("+", stack.pop(), stack.pop())); break;
case "-": stack.push(new BinaryOperation("-", stack.pop(), stack.pop())); break;
case "*": stack.push(new BinaryOperation("*", stack.pop(), stack.pop())); break;
case "/": stack.push(new BinaryOperation("/", stack.pop(), stack.pop())); break;
case "^": stack.push(new BinaryOperation("^", stack.pop(), stack.pop())); break;
case "sin": stack.push(new UnaryOperation("sin", stack.pop())); break;
case "cos": stack.push(new UnaryOperation("cos", stack.pop())); break;
case "tan": stack.push(new UnaryOperation("tan", stack.pop())); break;
case "sqrt": stack.push(new UnaryOperation("sqrt", stack.pop())); break;
case "ln": stack.push(new UnaryOperation("ln", stack.pop())); break;
default: stack.push(new NumberExpression(Double.parseDouble(token)));
}
}
return stack.pop();
}
}
}
Ausgabe:
Code:
(3.0 + 4.0)
= 7.0
(6.0 * 7.0)
= 42.0
(2.0 ^ 10.0)
= 1024.0
sqrt(9.0)
= 3.0
cos(37.0)
= 0.7654140519453434
Gruß Tom