/* * 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: *

*

* 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(); } }