/* * Copyright 2008 Reg Whitton * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.java.dev.eval; import java.math.BigDecimal; import java.util.Map; /** * A simple expression evaluator. *
* This is intended for use in simple domain specific languages, and was originally written for test configuration. *
* Example of use: * *
* Expression exp = new Expression("(x + y)/2");
*
* Map<String, BigDecimal> variables = new HashMap<String, BigDecimal>();
* variables.put("x", new BigDecimal("4.32"));
* variables.put("y", new BigDecimal("342.1"));
*
* BigDecimal result = exp.eval(variables);
*
* System.out.println(result);
*
* * The following operators are supported: *
x > y ? x : y* Comparison and boolean operation yield 1 for true, or 0 for false if used directly. *
** Expressions are evaluated using the precedence rules found in Java, and parentheses can be used to control the evaluation order. *
*
* Example expressions: * *
* 2*2 * 2+2 * 100/2 * x/100 * 17.5 * 2 pow 32 - 1 * 2 pow (32 - 1) * 2 pow int 21.5 * abs -1.23E-12 * x > y ? x : y * x > y && x != 4 ? x : y * y > 4*x ? 4*y : z/3 ** * @author Reg Whitton */ public class Expression { /** * The root of the tree of arithmetic operations. */ private final Operation rootOperation; /** * Construct an {@link Expression} that may be used multiple times to evaluate the expression using different sets of variables. * This holds the results of parsing the expression to minimise further work. * * @param expression * the arithmetic expression to be parsed. */ public Expression(String expression) { this.rootOperation = new Compiler(expression).compile(); } /** * Evaluate the expression with the given set of values. * * @param variables * the values to use in the expression. * @return the result of the evaluation */ public BigDecimal eval(Map,?> variables) { return this.rootOperation.eval(variables); } /** * Evaluate the expression which does not reference any variables. * * @return the result of the evaluation */ public BigDecimal eval() { return this.eval((Map,?>) null); } /** * A convenience method that constructs an {@link Expression} and evaluates it. * * @param expression * the expression to evaluate. * @param variables * the values to use in the evaluation. * @return the result of the evaluation */ public static BigDecimal eval(String expression, Map,?> variables) { return new Expression(expression).eval(variables); } /** * A convenience method that constructs an {@link Expression} that references no variables and evaluates it. * * @param expression * the expression to evaluate. * @return the result of the evaluation */ public static BigDecimal eval(String expression) { return new Expression(expression).eval(); } /** * Creates a string showing expression as it has been parsed. */ @Override public String toString() { return this.rootOperation.toString(); } }