package org.dcache.util.expression; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import org.parboiled.trees.ImmutableTreeNode; import java.util.Arrays; import static org.dcache.util.expression.Token.NUMBER_LITERAL; import static org.dcache.util.expression.Type.UNKNOWN; /** * Homogeneous AST node for the expression language. */ public class Expression extends ImmutableTreeNode<Expression> { private final double _number; private final String _string; private final Token _token; private Type _type = UNKNOWN; public Expression(double number) { super(ImmutableList.of()); _token = NUMBER_LITERAL; _number = number; _string = null; } public Expression(Token token, String string) { super(ImmutableList.of()); _token = token; _number = 0.0; _string = string; } public Expression(Token token, Expression ... operands) { super(Arrays.asList(operands)); _token = token; _number = 0.0; _string = null; } public Type check(SymbolTable symbols) throws TypeMismatchException, UnknownIdentifierException { TypeChecker checker = new TypeChecker(symbols); return checker.check(this); } public Object evaluate(SymbolTable symbols) { ExpressionEvaluator evaluator = new ExpressionEvaluator(symbols); return evaluator.evaluate(this); } public boolean evaluateBoolean(SymbolTable symbols) { ExpressionEvaluator evaluator = new ExpressionEvaluator(symbols); return evaluator.evaluateBoolean(this); } public double evaluateDouble(SymbolTable symbols) { ExpressionEvaluator evaluator = new ExpressionEvaluator(symbols); return evaluator.evaluateDouble(this); } public String evaluateString(SymbolTable symbols) { ExpressionEvaluator evaluator = new ExpressionEvaluator(symbols); return evaluator.evaluateString(this); } public Type getType() { return _type; } public void setType(Type type) { _type = type; } public double getNumber() { return _number; } public String getString() { return _string; } public Token getToken() { return _token; } public Expression get(int child) { return getChildren().get(child); } @Override public String toString() { switch (_token) { case NUMBER_LITERAL: return String.valueOf(_number); case STRING_LITERAL: return "\"" + _string + "\""; case IDENTIFIER: return _string; default: return "(" + _token.label + " " + Joiner.on(" ").join(getChildren()) + ")"; } } }