package org.dcache.util.expression;
/**
* Interpreter for the expression language.
*/
public class ExpressionEvaluator
{
private final SymbolTable _symbols;
public ExpressionEvaluator(SymbolTable symbols)
{
_symbols = symbols;
}
/**
* The expression must be type annotated and correct before the
* interpreter is invoked. Otherwise the interpreter will fail
* with IllegalArgumentException.
*/
public Object evaluate(Expression expression)
{
switch (expression.getType()) {
case DOUBLE:
return evaluateDouble(expression);
case BOOLEAN:
return evaluateBoolean(expression);
case STRING:
return evaluateString(expression);
}
throw new IllegalArgumentException("Expression lacks type annotation");
}
/**
* The expression must be type annotated and correct before the
* interpreter is invoked. Otherwise the interpreter will fail
* with IllegalArgumentException.
*/
public double evaluateDouble(Expression expression)
{
switch (expression.getToken()) {
case NUMBER_LITERAL:
return expression.getNumber();
case IDENTIFIER:
String identifier = expression.getString();
Symbol value = _symbols.get(identifier);
if (value == null) {
throw new IllegalArgumentException("Unknown identifier: " + identifier);
}
return (Double) value.getValue();
case PLUS:
return
evaluateDouble(expression.get(0)) +
evaluateDouble(expression.get(1));
case MINUS:
return
evaluateDouble(expression.get(0)) -
evaluateDouble(expression.get(1));
case MULT:
return
evaluateDouble(expression.get(0)) *
evaluateDouble(expression.get(1));
case DIV:
return
evaluateDouble(expression.get(0)) /
evaluateDouble(expression.get(1));
case MOD:
return
evaluateDouble(expression.get(0)) %
evaluateDouble(expression.get(1));
case POWER:
return Math.pow(evaluateDouble(expression.get(0)),
evaluateDouble(expression.get(1)));
case IF:
return (evaluateBoolean(expression.get(0))
? evaluateDouble(expression.get(1))
: evaluateDouble(expression.get(2)));
case UMINUS:
return -evaluateDouble(expression.get(0));
default:
throw new IllegalArgumentException("Invalid operator: " + expression.getToken());
}
}
/**
* The expression must be type annotated and correct before the
* interpreter is invoked. Otherwise the interpreter will fail
* with IllegalArgumentException.
*/
public boolean evaluateBoolean(Expression expression)
{
switch (expression.getToken()) {
case IDENTIFIER:
String identifier = expression.getString();
Symbol value = _symbols.get(identifier);
if (value == null) {
throw new IllegalArgumentException("Unknown identifier: " + identifier);
}
return (Boolean) value.getValue();
case TRUE:
return true;
case FALSE:
return false;
case LT:
return
evaluateDouble(expression.get(0)) <
evaluateDouble(expression.get(1));
case LE:
return
evaluateDouble(expression.get(0)) <=
evaluateDouble(expression.get(1));
case GT:
return
evaluateDouble(expression.get(0)) >
evaluateDouble(expression.get(1));
case GE:
return
evaluateDouble(expression.get(0)) >=
evaluateDouble(expression.get(1));
case EQ:
switch (expression.get(0).getType()) {
case DOUBLE:
return
evaluateDouble(expression.get(0)) ==
evaluateDouble(expression.get(1));
case BOOLEAN:
return
evaluateBoolean(expression.get(1)) ==
evaluateBoolean(expression.get(1));
case STRING:
return
evaluateString(expression.get(0)).equals(evaluateString(expression.get(1)));
}
throw new IllegalStateException("Expression lacks type annotation");
case NE:
switch (expression.get(0).getType()) {
case DOUBLE:
return
evaluateDouble(expression.get(0)) !=
evaluateDouble(expression.get(1));
case BOOLEAN:
return
evaluateBoolean(expression.get(0)) !=
evaluateBoolean(expression.get(1));
case STRING:
return
!evaluateString(expression.get(0)).equals(evaluateString(expression.get(1)));
}
throw new IllegalStateException("Expression lacks type annotation");
case IF:
return (evaluateBoolean(expression.get(0))
? evaluateBoolean(expression.get(1))
: evaluateBoolean(expression.get(2)));
case AND:
return
evaluateBoolean(expression.get(0)) &&
evaluateBoolean(expression.get(1));
case OR:
return
evaluateBoolean(expression.get(0)) ||
evaluateBoolean(expression.get(1));
case NOT:
return !evaluateBoolean(expression.get(0));
case MATCH:
return evaluateString(expression.get(0)).matches(evaluateString(expression.get(1)));
case NOT_MATCH:
return !evaluateString(expression.get(0)).matches(evaluateString(expression.get(1)));
default:
throw new IllegalArgumentException("Invalid operator: " +
expression.getToken());
}
}
public String evaluateString(Expression expression)
{
switch (expression.getToken()) {
case STRING_LITERAL:
return expression.getString();
case IDENTIFIER:
String identifier = expression.getString();
Symbol value = _symbols.get(identifier);
if (value == null) {
throw new IllegalArgumentException("Unknown identifier: " + identifier);
}
return (String) value.getValue();
case IF:
return (evaluateBoolean(expression.get(0))
? evaluateString(expression.get(1))
: evaluateString(expression.get(2)));
default:
throw new IllegalArgumentException("Invalid operator: " +
expression.getToken());
}
}
}