com.objectwave.utility
Class StringCalculator
java.lang.Object
|
+--com.objectwave.utility.StringCalculator
- public class StringCalculator
- extends java.lang.Object
A class which will evaluate stringified arithmetic / boolean expressions.
Standard order of evaluation of operators is honored.
Nested parentheses are supported, only round ones though: "(" and ")".
Where each #, $, and "b" is any expression which evaluates to a numberic, string, or boolean
value, respectively:
Arithmetic operators supported are #+# #-# -# #*# #/# #^# (result type #)
Boolean operators supported are b&&b b||b !b (result type b)
Numeric comparisons supported are #==# #!=# #<=# #>=# #<# #># (result type b)
Numeric comparisons supported are $==$ $!=$ $<=$ $>=$ $<$ $>$ $in$ (result type b)
The "condition assignment" operator b?#:# (result type #)
There is a reserved keyword "null" for null comparisons. The only support for
this explicit null object is the "==" operator. All of
== null
null ==
null == null
are valid expressions, all of which return true IFF is
the "null" object. This allows expressions to handle objects that may be null:
they'd be represented in the expression by "null" rather than by their value
type. The null comparison would probably by useful in conjunction with the
"?:" operator: "(%a%==null ? 0:0 : %a%)" ==> "(23.4==null ? 0.0 : 23.4)"
(This example assumes that external methods provide symbol-substitution
capabilities.)
All numeric values are promoted to type "double" for execution. The following
patterns are recognized as numbers, where {0-9}* means 0 or more digits,
{0-9}+ means 1 or more digits, and [xxx] means "xxx" is optional:
{0-9}*.{0-9}+ or {0-9}+[.{0-9}*]
Since all numeric expressions are represented as doubles, people unfamiliar with
floating-point arithmetic may be surprised at some of the results. For
instance, the comparison "2^54 == 2^54-1" will return true, since for these
extremely large numbers (on the order of 10^16) floating point representation
cannot distingish between these numbers (their internal representations are
identical).
String are supported only for comparison operations with other strings. A string is
defined as a literal, delimited by double-quote characters ("). Note that there is no
support for escape sequences, so a string cannot contain a (") character, and "\t" will not
be translated to a tab character. Ditto for \r, \n, \\, and any other escape sequence.
The special operator for strings, "in", requires some explanation. "in" takes two string
operands, the rhs being assumed to be a comma-delimited list of substrings. The method will
return true iif the lhs string exists as one on the comma-delimited elements of the rhs
string. This match must be exact for the method to succeed: whitespace is not taken care
of for you.
The tokens "true" and "false" are recognized as static boolean values.
Note that the string "9 * -5" is not valid: two arithmetic operators cannot be
adjacent. Use the string "9 * (-5)" instead.
Note that the string "5<6<7" is not valid: the communative property of comparison
operators is not honored: you must use "5<6 && 6<7" instead.
Note that the symbol "_" is explicitly disallowed. It is substituted internally
to represent the negation operator, to distingish between subtraction and
negation operations.
Finally, note that the boolean expression "5<6 && !2<3" is valid: a "!" operator
can follow another boolean operator. Also, "!!true" is valid. Redundant, but
valid.
The order of evaluation of operators is (from highest to lowest priority):
#^#, -#, #/#, #*#, #-#, #+#, #<=#, #>=#, #==#, #!=#, #<#, #>#,
$<=$, $>=$, $==$, $!=$, $<$, $>$, $in$, !b, b&&b, b||b, b?#:#
- Version:
- $Id: StringCalculator.java,v 2.1 2002/07/31 15:55:23 dave_hoag Exp $
- Author:
- Steve Sinclair
Method Summary |
java.util.Vector |
convertToReversePolish(java.util.Vector symbols)
A call to createSymbols must be made prior to calling this method. |
java.util.Vector |
createSymbols(java.lang.String expression)
|
java.util.Vector |
createSymbols(java.lang.String expression,
boolean defaultUnknown)
|
void |
dumpSymbols(java.util.Vector v)
Used for debugging. |
void |
dumpSymbols(java.util.Vector v,
int begin,
int end)
Used for debugging. |
java.lang.Object |
evaluateExpression(java.lang.String expression)
Parse the symbols from the string, convert their ordering for easier
execution, and execute the expression. |
java.lang.Object |
executeExpression(java.util.Vector symbols)
Assuming that the "symbols" vector is a reverse-polish ordered sequence
of CalcItem objects, evaluate the expression using a simple stack. |
java.util.Vector |
getFalseResults(java.util.Vector symbols)
Find all of the permutations that will make the symbols evalutate to false. |
java.lang.Object |
getResult()
|
protected static java.util.Vector |
getResults(StringCalculator calc,
java.util.Vector symbols,
java.util.Vector settings,
boolean condition)
|
java.util.Vector |
getTrueResults(java.util.Vector symbols)
Find all of the permutations that will make the symbols evalutate to true. |
static void |
main(java.lang.String[] args)
|
static void |
main2(java.lang.String[] args)
|
protected int |
matchBracket(int idx,
java.util.Vector symbols)
Assuming that symbols[idx] is a "(" symbol, return the index of it's matching
rhs symbol. |
protected int |
nextNonWhitespace(java.lang.String str,
int idx)
Returns str.length() if EOS is reached. |
protected int |
operatorPriority(java.lang.String op)
Return the priority of the given operation "op". |
protected void |
performOperation(StringCalculator.CalcItem operation,
java.util.Stack expressionStack)
|
protected int |
prefixIsOperator(java.lang.String string,
int idx)
Return # of chars which are the operator, else 0. |
protected java.util.Vector |
processBrackets(int leftParen,
int end,
java.util.Vector symbols)
We've found a "(" in place of an atomic value: that's ok, so long as it has
a matching ")" with parsable contents in between. |
boolean |
resultIsNumeric()
|
void |
shortDump(java.util.Vector v)
|
Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
verbose
protected boolean verbose
- Private Section:
result
protected java.lang.Object result
staticCalcItem
protected static StringCalculator.CalcItem staticCalcItem
StringCalculator
public StringCalculator()
evaluateExpression
public java.lang.Object evaluateExpression(java.lang.String expression)
throws java.lang.ArithmeticException,
java.text.ParseException,
java.util.EmptyStackException
- Parse the symbols from the string, convert their ordering for easier
execution, and execute the expression.
Note that there's three types of exception thrown by this method.
java.lang.ArithmeticException
java.text.ParseException
java.util.EmptyStackException
convertToReversePolish
public java.util.Vector convertToReversePolish(java.util.Vector symbols)
throws java.text.ParseException
- A call to createSymbols must be made prior to calling this method.
java.text.ParseException
- See Also:
createSymbols(java.lang.String)
createSymbols
public java.util.Vector createSymbols(java.lang.String expression)
throws java.text.ParseException
java.text.ParseException
createSymbols
public java.util.Vector createSymbols(java.lang.String expression,
boolean defaultUnknown)
throws java.text.ParseException
- Parameters:
defaultUnknown
- - If a symbol is unknown, or unresolvable, just assume it is a string.
java.text.ParseException
dumpSymbols
public void dumpSymbols(java.util.Vector v)
- Used for debugging.
dumpSymbols
public void dumpSymbols(java.util.Vector v,
int begin,
int end)
- Used for debugging.
executeExpression
public java.lang.Object executeExpression(java.util.Vector symbols)
throws java.lang.ArithmeticException,
java.text.ParseException,
java.util.EmptyStackException
- Assuming that the "symbols" vector is a reverse-polish ordered sequence
of CalcItem objects, evaluate the expression using a simple stack.
java.lang.ArithmeticException
java.text.ParseException
java.util.EmptyStackException
getResult
public java.lang.Object getResult()
main
public static void main(java.lang.String[] args)
getTrueResults
public java.util.Vector getTrueResults(java.util.Vector symbols)
- Find all of the permutations that will make the symbols evalutate to true.
- Parameters:
symbols
- Vector of CalcItems, should have been converted to reverse polish notation prior to calling this method.
getFalseResults
public java.util.Vector getFalseResults(java.util.Vector symbols)
- Find all of the permutations that will make the symbols evalutate to false.
- Parameters:
symbols
- Vector of CalcItems, should have been converted to reverse polish notation prior to calling this method.
getResults
protected static java.util.Vector getResults(StringCalculator calc,
java.util.Vector symbols,
java.util.Vector settings,
boolean condition)
- Parameters:
symbols
- Vector of CalcItems, should have been converted to reverse polish notation prior to calling this method.calc
- - The calculator that was/will be used to evaluate the expression.settings
- Vector - A vector used internally to keep track of the value list.condition
- boolean - Get the patterns that make the condition evaluate to this value.
- Returns:
- Vector Each element in the vector is the string of conditions that would make the expression
evaluate to true.
main2
public static void main2(java.lang.String[] args)
matchBracket
protected int matchBracket(int idx,
java.util.Vector symbols)
- Assuming that symbols[idx] is a "(" symbol, return the index of it's matching
rhs symbol.
nextNonWhitespace
protected int nextNonWhitespace(java.lang.String str,
int idx)
- Returns str.length() if EOS is reached.
operatorPriority
protected int operatorPriority(java.lang.String op)
- Return the priority of the given operation "op". "op" is assumed to be
a valid operation.
performOperation
protected void performOperation(StringCalculator.CalcItem operation,
java.util.Stack expressionStack)
throws java.lang.ArithmeticException,
java.text.ParseException
java.lang.ArithmeticException
java.text.ParseException
prefixIsOperator
protected int prefixIsOperator(java.lang.String string,
int idx)
- Return # of chars which are the operator, else 0.
processBrackets
protected java.util.Vector processBrackets(int leftParen,
int end,
java.util.Vector symbols)
throws java.text.ParseException
- We've found a "(" in place of an atomic value: that's ok, so long as it has
a matching ")" with parsable contents in between.
java.text.ParseException
resultIsNumeric
public boolean resultIsNumeric()
shortDump
public void shortDump(java.util.Vector v)