/**
*
* Copyright 2015 Patrick Ahlbrecht
*
* 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 de.onyxbits.jbee;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.List;
/**
* Declares hooks into the parser that are called in various stages of parsing.
* The general contract is: the parser knows "when" to do something while the
* mathlib knows "how" to do it.
* <p>
* The most common reason for implementing this interface is adding a custom
* catalog of mathematical functions. In that case, however, it is best to
* subclass {@link ReflectedMathLib} instead, as this interface is a) complex
* and b) likely to get new methods when new features are added to the parser.
* <p>
* Implementors are strongly discouraged from keeping any global state that can
* be modified via expressions (in particular, mapping/clearing names from
* within custom functions). MathLib is designed for being reusable and
* expressions should evaluate independant of each other.
*/
public interface MathLib {
/**
* Get the {@link MathContext} in use by the {@link MathLib}.
*
* @return the {@link MathContext} or null if none is used.
*/
public MathContext getMathContext();
/**
* Bind a number to a symbolic name, so it can be referenced in an expression.
* NOTE: this method should never be called from within an implementation of
* this interface.
*
* @param name
* the symbolic name by which the value may be referenced in an
* expression.
* @param value
* number to associate with the symbol or null to clear it.
*/
public void map(String name, BigDecimal value);
/**
* Clear all mapped constants. NOTE: this method should never be called from
* within an implementation of this interface.
*/
public void clearMappings();
/**
* Called on evaluating a function.
*
* @param name
* identifier of the requested function. It is legal to "generate"
* functions on the fly, based on the name.
* @param args
* submitted parameters (never null, but potentially empty).
* @return the number, the requested function evaluates to. May not be null.
*
* @throws NotDefinedException
* must be thrown if no matching function exists.
* @throws ArithmeticException
* should be thrown when a function cannot be evaluated.
*/
public BigDecimal onCall(String name, List<BigDecimal> args) throws NotDefinedException,
ArithmeticException;
/**
* Called when the input string won't tokenize properly. Tokenize errors are
* always fatal and cannot be recovered from. This method must always throw an
* exception.
*
* @param input
* the character sequence that failed to tokenize
* @param offset
* position of the error.
*/
public void onTokenizeError(final char[] input, int offset);
/**
* Called on Addition
*
* @param augend
* lhs number
* @param addend
* rhs number
* @return the sum of augend and addend
*/
public BigDecimal onAddition(BigDecimal augend, BigDecimal addend);
/**
* Called on Addition
*
* @param minuend
* lhs number
* @param subtrahend
* rhs number
* @return the difference.
*/
public BigDecimal onSubtraction(BigDecimal minuend, BigDecimal subtrahend);
/**
* Called on multiplication
*
* @param multiplicant
* lhs number
* @param multiplier
* rhs number
* @return product
*/
public BigDecimal onMultiplication(BigDecimal multiplicant, BigDecimal multiplier);
/**
* Called on division
*
* @param dividend
* lhs number
* @param divisor
* rhs number
* @return quotient
*/
public BigDecimal onDivision(BigDecimal dividend, BigDecimal divisor);
/**
* Called on negation
*
* @param num
* number to negate
* @return number * -1
*/
public BigDecimal onNegation(BigDecimal num);
/**
* Called on modulation
*
* @param dividend
* lhs number
* @param moddivisor
* rhs number
* @return remainder
*/
public BigDecimal onModulation(BigDecimal dividend, BigDecimal moddivisor);
/**
* Called on adding a percentage
*
* @param base
* base number
* @param percent
* percentage
* @return sum/product
*/
public BigDecimal onPercentAddition(BigDecimal base, BigDecimal percent);
/**
* Called on subtracting a percentage
*
* @param base
* base number
* @param percent
* percentage
* @return difference/product
*/
public BigDecimal onPercentSubtraction(BigDecimal base, BigDecimal percent);
/**
* Called on moving the decimal mark
*
* @param num
* base number
* @param dir
* direction (expressed by the sign) and amount to move.
* @return scaled number
*/
public BigDecimal onMovePoint(BigDecimal num, BigDecimal dir);
/**
* Called on exponentiation
*
* @param base
* the base
* @param exponent
* the exponent
* @return the power
*/
public BigDecimal onExponentiation(BigDecimal base, BigDecimal exponent);
/**
* Called when the expression to evaluate is empty.
*
* @return the number, the empty expression should evaluate to. NOTE: Instead
* of returning a number, it is usually more meaningful to throw an
* exception.
*/
public BigDecimal onEmptyExpression();
/**
* Called on the first syntax error. This method should not return, but throw
* an exception instead.
*
* @param pos
* start position of the troublesome token.
* @param token
* the string representation of the troublesome token.
*/
public void onSyntaxError(int pos, String token);
/**
* Called when a symbol needs to be resolved.
*
* @param name
* name of the symbol
* @return the value of the requested symbol or null if it is not defined.
* @throws NotDefinedException
* if the named symbol does not exist.
*/
public BigDecimal onLookup(String name) throws NotDefinedException;
/**
* Called on bitwise not
*
* @param num
* number to negate
* @return negated number
* @throws ArithmeticException
* if num cannot be converted to an integer
*/
public BigDecimal onBitwiseNot(BigDecimal num) throws ArithmeticException;
/**
* Called on bitwise AND
*
* @param lhs
* left hand side
* @param rhs
* right hand side
* @return result
* @throws ArithmeticException
* if either parameter cannot be converted to an integer
*/
public BigDecimal onBitwiseAnd(BigDecimal lhs, BigDecimal rhs) throws ArithmeticException;
/**
* Called on bitwise OR
*
* @param lhs
* left hand side
* @param rhs
* right hand side
* @return result
* @throws ArithmeticException
* if either parameter cannot be converted to an integer
*/
public BigDecimal onBitwiseOr(BigDecimal lhs, BigDecimal rhs) throws ArithmeticException;
/**
* Called on bitwise XOR
*
* @param lhs
* left hand side
* @param rhs
* right hand side
* @return result
* @throws ArithmeticException
* if either parameter cannot be converted to an integer
*/
public BigDecimal onBitwiseXor(BigDecimal lhs, BigDecimal rhs) throws ArithmeticException;
/**
* Called on bitshift left
*
* @param num
* number to operate on
* @param amount
* shift amount
* @return result
* @throws ArithmeticException
* if either parameter cannot be converted to an integer
*/
public BigDecimal onBitshiftLeft(BigDecimal num, BigDecimal amount) throws ArithmeticException;
/**
* Called on bitshift right
*
* @param num
* number to operate on
* @param amount
* shift amount
* @return result
* @throws ArithmeticException
* if either parameter cannot be converted to an integer
*/
public BigDecimal onBitshiftRight(BigDecimal num, BigDecimal amount) throws ArithmeticException;
}