From ee4f303fba2793eb0cdc97f462e6d71722764098 Mon Sep 17 00:00:00 2001 From: uklimaschewski Date: Sun, 8 Sep 2019 14:01:51 +0200 Subject: [PATCH] Custom alpha operator precedes function recognition --- .../java/com/udojava/evalex/Expression.java | 6 +- .../com/udojava/evalex/TestTokenizer.java | 629 +++++++++--------- 2 files changed, 328 insertions(+), 307 deletions(-) diff --git a/src/main/java/com/udojava/evalex/Expression.java b/src/main/java/com/udojava/evalex/Expression.java index d56e4bd1..164c6f24 100644 --- a/src/main/java/com/udojava/evalex/Expression.java +++ b/src/main/java/com/udojava/evalex/Expression.java @@ -454,10 +454,10 @@ && isHexDigit( } pos--; } - if (ch == '(') { - token.type = TokenType.FUNCTION; - } else if (operators.containsKey(token.surface)) { + if (operators.containsKey(token.surface)) { token.type = TokenType.OPERATOR; + } else if (ch == '(') { + token.type = TokenType.FUNCTION; } else { token.type = TokenType.VARIABLE; } diff --git a/src/test/java/com/udojava/evalex/TestTokenizer.java b/src/test/java/com/udojava/evalex/TestTokenizer.java index 61182205..e70deac4 100644 --- a/src/test/java/com/udojava/evalex/TestTokenizer.java +++ b/src/test/java/com/udojava/evalex/TestTokenizer.java @@ -4,6 +4,7 @@ import com.udojava.evalex.Expression.Token; import org.junit.Test; +import java.math.BigDecimal; import java.util.Iterator; import static org.junit.Assert.*; @@ -11,105 +12,105 @@ public class TestTokenizer { - private void assertToken(String surface, Expression.TokenType type, Expression.Token actual) { - assertEquals(surface, actual.surface); - assertEquals(type, actual.type); - } - - @Test - public void testSpacesFunctions() { - Expression e; - Iterator i; - - e = new Expression("sin (30)"); - i = e.getExpressionTokenizer(); - assertToken("sin", TokenType.FUNCTION, i.next()); - assertToken("(", TokenType.OPEN_PAREN, i.next()); - assertToken("30", TokenType.LITERAL, i.next()); - assertToken(")", TokenType.CLOSE_PAREN, i.next()); - assertFalse(i.hasNext()); - } - - @Test - public void testSpacesFunctionsVariablesOperators() { - Expression e; - Iterator i; - - e = new Expression(" sin ( 30 + x ) "); - i = e.getExpressionTokenizer(); - assertToken("sin", TokenType.FUNCTION, i.next()); - assertToken("(", TokenType.OPEN_PAREN, i.next()); - assertToken("30", TokenType.LITERAL, i.next()); - assertToken("+", TokenType.OPERATOR, i.next()); - assertToken("x", TokenType.VARIABLE, i.next()); - assertToken(")", TokenType.CLOSE_PAREN, i.next()); - assertFalse(i.hasNext()); - } - - @Test - public void testNumbers() { - Expression e; - Iterator i; - - e = new Expression("1"); - i = e.getExpressionTokenizer(); - assertToken("1", TokenType.LITERAL, i.next()); - assertFalse(i.hasNext()); - assertNull(i.next()); - - e = new Expression("-1"); - i = e.getExpressionTokenizer(); - assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); - assertToken("1", TokenType.LITERAL, i.next()); - assertFalse(i.hasNext()); - assertNull(i.next()); - - e = new Expression("123"); - i = e.getExpressionTokenizer(); - assertToken("123", TokenType.LITERAL, i.next()); - assertFalse(i.hasNext()); - assertNull(i.next()); - - e = new Expression("-123"); - i = e.getExpressionTokenizer(); - assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); - assertToken("123", TokenType.LITERAL, i.next()); - assertFalse(i.hasNext()); - assertNull(i.next()); - - e = new Expression("123.4"); - i = e.getExpressionTokenizer(); - assertToken("123.4", TokenType.LITERAL, i.next()); - assertFalse(i.hasNext()); - assertNull(i.next()); - - e = new Expression("-123.456"); - i = e.getExpressionTokenizer(); - assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); - assertToken("123.456", TokenType.LITERAL, i.next()); - assertFalse(i.hasNext()); - assertNull(i.next()); - - e = new Expression(".1"); - i = e.getExpressionTokenizer(); - assertToken(".1", TokenType.LITERAL, i.next()); - assertFalse(i.hasNext()); - assertNull(i.next()); - - e = new Expression("-.1"); - i = e.getExpressionTokenizer(); - assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); - assertToken(".1", TokenType.LITERAL, i.next()); - assertFalse(i.hasNext()); - assertNull(i.next()); - } + private void assertToken(String surface, Expression.TokenType type, Expression.Token actual) { + assertEquals(surface, actual.surface); + assertEquals(type, actual.type); + } + + @Test + public void testSpacesFunctions() { + Expression e; + Iterator i; + + e = new Expression("sin (30)"); + i = e.getExpressionTokenizer(); + assertToken("sin", TokenType.FUNCTION, i.next()); + assertToken("(", TokenType.OPEN_PAREN, i.next()); + assertToken("30", TokenType.LITERAL, i.next()); + assertToken(")", TokenType.CLOSE_PAREN, i.next()); + assertFalse(i.hasNext()); + } + + @Test + public void testSpacesFunctionsVariablesOperators() { + Expression e; + Iterator i; + + e = new Expression(" sin ( 30 + x ) "); + i = e.getExpressionTokenizer(); + assertToken("sin", TokenType.FUNCTION, i.next()); + assertToken("(", TokenType.OPEN_PAREN, i.next()); + assertToken("30", TokenType.LITERAL, i.next()); + assertToken("+", TokenType.OPERATOR, i.next()); + assertToken("x", TokenType.VARIABLE, i.next()); + assertToken(")", TokenType.CLOSE_PAREN, i.next()); + assertFalse(i.hasNext()); + } + + @Test + public void testNumbers() { + Expression e; + Iterator i; + + e = new Expression("1"); + i = e.getExpressionTokenizer(); + assertToken("1", TokenType.LITERAL, i.next()); + assertFalse(i.hasNext()); + assertNull(i.next()); + + e = new Expression("-1"); + i = e.getExpressionTokenizer(); + assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); + assertToken("1", TokenType.LITERAL, i.next()); + assertFalse(i.hasNext()); + assertNull(i.next()); + + e = new Expression("123"); + i = e.getExpressionTokenizer(); + assertToken("123", TokenType.LITERAL, i.next()); + assertFalse(i.hasNext()); + assertNull(i.next()); + + e = new Expression("-123"); + i = e.getExpressionTokenizer(); + assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); + assertToken("123", TokenType.LITERAL, i.next()); + assertFalse(i.hasNext()); + assertNull(i.next()); + + e = new Expression("123.4"); + i = e.getExpressionTokenizer(); + assertToken("123.4", TokenType.LITERAL, i.next()); + assertFalse(i.hasNext()); + assertNull(i.next()); + + e = new Expression("-123.456"); + i = e.getExpressionTokenizer(); + assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); + assertToken("123.456", TokenType.LITERAL, i.next()); + assertFalse(i.hasNext()); + assertNull(i.next()); + + e = new Expression(".1"); + i = e.getExpressionTokenizer(); + assertToken(".1", TokenType.LITERAL, i.next()); + assertFalse(i.hasNext()); + assertNull(i.next()); + + e = new Expression("-.1"); + i = e.getExpressionTokenizer(); + assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); + assertToken(".1", TokenType.LITERAL, i.next()); + assertFalse(i.hasNext()); + assertNull(i.next()); + } @Test public void testTokenizerExtraSpaces() { Expression e = new Expression("1 "); Iterator i = e.getExpressionTokenizer(); assertTrue(i.hasNext()); - assertToken("1", TokenType.LITERAL, i.next()); + assertToken("1", TokenType.LITERAL, i.next()); assertFalse(i.hasNext()); assertNull(i.next()); @@ -121,225 +122,245 @@ public void testTokenizerExtraSpaces() { e = new Expression(" 1 "); i = e.getExpressionTokenizer(); assertTrue(i.hasNext()); - assertToken("1", TokenType.LITERAL, i.next()); + assertToken("1", TokenType.LITERAL, i.next()); assertFalse(i.hasNext()); assertNull(i.next()); e = new Expression(" 1 + 2 "); i = e.getExpressionTokenizer(); - assertToken("1", TokenType.LITERAL, i.next()); - assertToken("+", TokenType.OPERATOR, i.next()); - assertToken("2", TokenType.LITERAL, i.next()); + assertToken("1", TokenType.LITERAL, i.next()); + assertToken("+", TokenType.OPERATOR, i.next()); + assertToken("2", TokenType.LITERAL, i.next()); assertFalse(i.hasNext()); assertNull(i.next()); } @Test - public void testTokenizer1() { - Expression e = new Expression("1+2"); - Iterator i = e.getExpressionTokenizer(); - - assertToken("1", TokenType.LITERAL, i.next()); - assertToken("+", TokenType.OPERATOR, i.next()); - assertToken("2", TokenType.LITERAL, i.next()); - } - - @Test - public void testTokenizer2() { - Expression e = new Expression("1 + 2"); - Iterator i = e.getExpressionTokenizer(); - - assertToken("1", TokenType.LITERAL, i.next()); - assertToken("+", TokenType.OPERATOR, i.next()); - assertToken("2", TokenType.LITERAL, i.next()); - } - - @Test - public void testTokenizer3() { - Expression e = new Expression(" 1 + 2 "); - Iterator i = e.getExpressionTokenizer(); - - assertToken("1", TokenType.LITERAL, i.next()); - assertToken("+", TokenType.OPERATOR, i.next()); - assertToken("2", TokenType.LITERAL, i.next()); - } - - @Test - public void testTokenizer4() { - Expression e = new Expression("1+2-3/4*5"); - Iterator i = e.getExpressionTokenizer(); - - assertToken("1", TokenType.LITERAL, i.next()); - assertToken("+", TokenType.OPERATOR, i.next()); - assertToken("2", TokenType.LITERAL, i.next()); - assertToken("-", TokenType.OPERATOR, i.next()); - assertToken("3", TokenType.LITERAL, i.next()); - assertToken("/", TokenType.OPERATOR, i.next()); - assertToken("4", TokenType.LITERAL, i.next()); - assertToken("*", TokenType.OPERATOR, i.next()); - assertToken("5", TokenType.LITERAL, i.next()); - } - - @Test - public void testTokenizer5() { - Expression e = new Expression("1+2.1-3.45/4.982*5.0"); - Iterator i = e.getExpressionTokenizer(); - - assertToken("1", TokenType.LITERAL, i.next()); - assertToken("+", TokenType.OPERATOR, i.next()); - assertToken("2.1", TokenType.LITERAL, i.next()); - assertToken("-", TokenType.OPERATOR, i.next()); - assertToken("3.45", TokenType.LITERAL, i.next()); - assertToken("/", TokenType.OPERATOR, i.next()); - assertToken("4.982", TokenType.LITERAL, i.next()); - assertToken("*", TokenType.OPERATOR, i.next()); - assertToken("5.0", TokenType.LITERAL, i.next()); - - } - - @Test - public void testTokenizer6() { - Expression e = new Expression("-3+4*-1"); - Iterator i = e.getExpressionTokenizer(); - - assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); - assertToken("3", TokenType.LITERAL, i.next()); - assertToken("+", TokenType.OPERATOR, i.next()); - assertToken("4", TokenType.LITERAL, i.next()); - assertToken("*", TokenType.OPERATOR, i.next()); - assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); - assertToken("1", TokenType.LITERAL, i.next()); - } - - @Test - public void testTokenizer7() { - Expression e = new Expression("(-3+4)*-1/(7-(5*-8))"); - Iterator i = e.getExpressionTokenizer(); - - assertToken("(", TokenType.OPEN_PAREN, i.next()); - assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); - assertToken("3", TokenType.LITERAL, i.next()); - assertToken("+", TokenType.OPERATOR, i.next()); - assertToken("4", TokenType.LITERAL, i.next()); - assertToken(")", TokenType.CLOSE_PAREN, i.next()); - - assertToken("*", TokenType.OPERATOR, i.next()); - assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); - assertToken("1", TokenType.LITERAL, i.next()); - assertToken("/", TokenType.OPERATOR, i.next()); - assertToken("(", TokenType.OPEN_PAREN, i.next()); - assertToken("7", TokenType.LITERAL, i.next()); - assertToken("-", TokenType.OPERATOR, i.next()); - assertToken("(", TokenType.OPEN_PAREN, i.next()); - assertToken("5", TokenType.LITERAL, i.next()); - assertToken("*", TokenType.OPERATOR, i.next()); - assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); - assertToken("8", TokenType.LITERAL, i.next()); - assertToken(")", TokenType.CLOSE_PAREN, i.next()); - assertToken(")", TokenType.CLOSE_PAREN, i.next()); - } - - @Test - public void testTokenizer8() { - Expression e = new Expression("(1.9+2.8)/4.7"); - Iterator i = e.getExpressionTokenizer(); - - assertToken("(", TokenType.OPEN_PAREN, i.next()); - assertToken("1.9", TokenType.LITERAL, i.next()); - assertToken("+", TokenType.OPERATOR, i.next()); - assertToken("2.8", TokenType.LITERAL, i.next()); - assertToken(")", TokenType.CLOSE_PAREN, i.next()); - assertToken("/", TokenType.OPERATOR, i.next()); - assertToken("4.7", TokenType.LITERAL, i.next()); - - } - - @Test - public void testTokenizerFunction1() { - Expression e = new Expression("ABS(3.5)"); - Iterator i = e.getExpressionTokenizer(); - - assertToken("ABS", TokenType.FUNCTION, i.next()); - assertToken("(", TokenType.OPEN_PAREN, i.next()); - assertToken("3.5", TokenType.LITERAL, i.next()); - assertToken(")", TokenType.CLOSE_PAREN, i.next()); - } - - @Test - public void testTokenizerFunction2() { - Expression e = new Expression("3-ABS(3.5)/9"); - Iterator i = e.getExpressionTokenizer(); - - assertToken("3", TokenType.LITERAL, i.next()); - assertToken("-", TokenType.OPERATOR, i.next()); - assertToken("ABS", TokenType.FUNCTION, i.next()); - assertToken("(", TokenType.OPEN_PAREN, i.next()); - assertToken("3.5", TokenType.LITERAL, i.next()); - assertToken(")", TokenType.CLOSE_PAREN, i.next()); - assertToken("/", TokenType.OPERATOR, i.next()); - assertToken("9", TokenType.LITERAL, i.next()); - - } - @Test - - public void testTokenizerFunction3() { - Expression e = new Expression("MAX(3.5,5.2)"); - Iterator i = e.getExpressionTokenizer(); - - assertToken("MAX", TokenType.FUNCTION, i.next()); - assertToken("(", TokenType.OPEN_PAREN, i.next()); - assertToken("3.5", TokenType.LITERAL, i.next()); - assertToken(",", TokenType.COMMA, i.next()); - assertToken("5.2", TokenType.LITERAL, i.next()); - assertToken(")", TokenType.CLOSE_PAREN, i.next()); - } - - @Test - public void testTokenizerFunction4() { - Expression e = new Expression("3-MAX(3.5,5.2)/9"); - Iterator i = e.getExpressionTokenizer(); - - assertToken("3", TokenType.LITERAL, i.next()); - assertToken("-", TokenType.OPERATOR, i.next()); - assertToken("MAX", TokenType.FUNCTION, i.next()); - assertToken("(", TokenType.OPEN_PAREN, i.next()); - assertToken("3.5", TokenType.LITERAL, i.next()); - assertToken(",", TokenType.COMMA, i.next()); - assertToken("5.2", TokenType.LITERAL, i.next()); - assertToken(")", TokenType.CLOSE_PAREN, i.next()); - assertToken("/", TokenType.OPERATOR, i.next()); - assertToken("9", TokenType.LITERAL, i.next()); - } - - @Test - public void testTokenizerFunction5() { - Expression e = new Expression("3/MAX(-3.5,-5.2)/9"); - Iterator i = e.getExpressionTokenizer(); - - assertToken("3", TokenType.LITERAL, i.next()); - assertToken("/", TokenType.OPERATOR, i.next()); - assertToken("MAX", TokenType.FUNCTION, i.next()); - assertToken("(", TokenType.OPEN_PAREN, i.next()); - assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); - assertToken("3.5", TokenType.LITERAL, i.next()); - assertToken(",", TokenType.COMMA, i.next()); - assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); - assertToken("5.2", TokenType.LITERAL, i.next()); - assertToken(")", TokenType.CLOSE_PAREN, i.next()); - assertToken("/", TokenType.OPERATOR, i.next()); - assertToken("9", TokenType.LITERAL, i.next()); - } - - @Test - public void testInsertImplizitMultiplication() { - Expression e = new Expression("22(3+1)"); - Iterator i = e.getExpressionTokenizer(); - - assertToken("22", TokenType.LITERAL, i.next()); - assertToken("(", TokenType.OPEN_PAREN, i.next()); - assertToken("3", TokenType.LITERAL, i.next()); - assertToken("+", TokenType.OPERATOR, i.next()); - assertToken("1", TokenType.LITERAL, i.next()); - assertToken(")", TokenType.CLOSE_PAREN, i.next()); - } + public void testTokenizer1() { + Expression e = new Expression("1+2"); + Iterator i = e.getExpressionTokenizer(); + + assertToken("1", TokenType.LITERAL, i.next()); + assertToken("+", TokenType.OPERATOR, i.next()); + assertToken("2", TokenType.LITERAL, i.next()); + } + + @Test + public void testTokenizer2() { + Expression e = new Expression("1 + 2"); + Iterator i = e.getExpressionTokenizer(); + + assertToken("1", TokenType.LITERAL, i.next()); + assertToken("+", TokenType.OPERATOR, i.next()); + assertToken("2", TokenType.LITERAL, i.next()); + } + + @Test + public void testTokenizer3() { + Expression e = new Expression(" 1 + 2 "); + Iterator i = e.getExpressionTokenizer(); + + assertToken("1", TokenType.LITERAL, i.next()); + assertToken("+", TokenType.OPERATOR, i.next()); + assertToken("2", TokenType.LITERAL, i.next()); + } + + @Test + public void testTokenizer4() { + Expression e = new Expression("1+2-3/4*5"); + Iterator i = e.getExpressionTokenizer(); + + assertToken("1", TokenType.LITERAL, i.next()); + assertToken("+", TokenType.OPERATOR, i.next()); + assertToken("2", TokenType.LITERAL, i.next()); + assertToken("-", TokenType.OPERATOR, i.next()); + assertToken("3", TokenType.LITERAL, i.next()); + assertToken("/", TokenType.OPERATOR, i.next()); + assertToken("4", TokenType.LITERAL, i.next()); + assertToken("*", TokenType.OPERATOR, i.next()); + assertToken("5", TokenType.LITERAL, i.next()); + } + + @Test + public void testTokenizer5() { + Expression e = new Expression("1+2.1-3.45/4.982*5.0"); + Iterator i = e.getExpressionTokenizer(); + + assertToken("1", TokenType.LITERAL, i.next()); + assertToken("+", TokenType.OPERATOR, i.next()); + assertToken("2.1", TokenType.LITERAL, i.next()); + assertToken("-", TokenType.OPERATOR, i.next()); + assertToken("3.45", TokenType.LITERAL, i.next()); + assertToken("/", TokenType.OPERATOR, i.next()); + assertToken("4.982", TokenType.LITERAL, i.next()); + assertToken("*", TokenType.OPERATOR, i.next()); + assertToken("5.0", TokenType.LITERAL, i.next()); + + } + + @Test + public void testTokenizer6() { + Expression e = new Expression("-3+4*-1"); + Iterator i = e.getExpressionTokenizer(); + + assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); + assertToken("3", TokenType.LITERAL, i.next()); + assertToken("+", TokenType.OPERATOR, i.next()); + assertToken("4", TokenType.LITERAL, i.next()); + assertToken("*", TokenType.OPERATOR, i.next()); + assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); + assertToken("1", TokenType.LITERAL, i.next()); + } + + @Test + public void testTokenizer7() { + Expression e = new Expression("(-3+4)*-1/(7-(5*-8))"); + Iterator i = e.getExpressionTokenizer(); + + assertToken("(", TokenType.OPEN_PAREN, i.next()); + assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); + assertToken("3", TokenType.LITERAL, i.next()); + assertToken("+", TokenType.OPERATOR, i.next()); + assertToken("4", TokenType.LITERAL, i.next()); + assertToken(")", TokenType.CLOSE_PAREN, i.next()); + + assertToken("*", TokenType.OPERATOR, i.next()); + assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); + assertToken("1", TokenType.LITERAL, i.next()); + assertToken("/", TokenType.OPERATOR, i.next()); + assertToken("(", TokenType.OPEN_PAREN, i.next()); + assertToken("7", TokenType.LITERAL, i.next()); + assertToken("-", TokenType.OPERATOR, i.next()); + assertToken("(", TokenType.OPEN_PAREN, i.next()); + assertToken("5", TokenType.LITERAL, i.next()); + assertToken("*", TokenType.OPERATOR, i.next()); + assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); + assertToken("8", TokenType.LITERAL, i.next()); + assertToken(")", TokenType.CLOSE_PAREN, i.next()); + assertToken(")", TokenType.CLOSE_PAREN, i.next()); + } + + @Test + public void testTokenizer8() { + Expression e = new Expression("(1.9+2.8)/4.7"); + Iterator i = e.getExpressionTokenizer(); + + assertToken("(", TokenType.OPEN_PAREN, i.next()); + assertToken("1.9", TokenType.LITERAL, i.next()); + assertToken("+", TokenType.OPERATOR, i.next()); + assertToken("2.8", TokenType.LITERAL, i.next()); + assertToken(")", TokenType.CLOSE_PAREN, i.next()); + assertToken("/", TokenType.OPERATOR, i.next()); + assertToken("4.7", TokenType.LITERAL, i.next()); + + } + + @Test + public void testTokenizerFunction1() { + Expression e = new Expression("ABS(3.5)"); + Iterator i = e.getExpressionTokenizer(); + + assertToken("ABS", TokenType.FUNCTION, i.next()); + assertToken("(", TokenType.OPEN_PAREN, i.next()); + assertToken("3.5", TokenType.LITERAL, i.next()); + assertToken(")", TokenType.CLOSE_PAREN, i.next()); + } + + @Test + public void testTokenizerFunction2() { + Expression e = new Expression("3-ABS(3.5)/9"); + Iterator i = e.getExpressionTokenizer(); + + assertToken("3", TokenType.LITERAL, i.next()); + assertToken("-", TokenType.OPERATOR, i.next()); + assertToken("ABS", TokenType.FUNCTION, i.next()); + assertToken("(", TokenType.OPEN_PAREN, i.next()); + assertToken("3.5", TokenType.LITERAL, i.next()); + assertToken(")", TokenType.CLOSE_PAREN, i.next()); + assertToken("/", TokenType.OPERATOR, i.next()); + assertToken("9", TokenType.LITERAL, i.next()); + + } + + @Test + + public void testTokenizerFunction3() { + Expression e = new Expression("MAX(3.5,5.2)"); + Iterator i = e.getExpressionTokenizer(); + + assertToken("MAX", TokenType.FUNCTION, i.next()); + assertToken("(", TokenType.OPEN_PAREN, i.next()); + assertToken("3.5", TokenType.LITERAL, i.next()); + assertToken(",", TokenType.COMMA, i.next()); + assertToken("5.2", TokenType.LITERAL, i.next()); + assertToken(")", TokenType.CLOSE_PAREN, i.next()); + } + + @Test + public void testTokenizerFunction4() { + Expression e = new Expression("3-MAX(3.5,5.2)/9"); + Iterator i = e.getExpressionTokenizer(); + + assertToken("3", TokenType.LITERAL, i.next()); + assertToken("-", TokenType.OPERATOR, i.next()); + assertToken("MAX", TokenType.FUNCTION, i.next()); + assertToken("(", TokenType.OPEN_PAREN, i.next()); + assertToken("3.5", TokenType.LITERAL, i.next()); + assertToken(",", TokenType.COMMA, i.next()); + assertToken("5.2", TokenType.LITERAL, i.next()); + assertToken(")", TokenType.CLOSE_PAREN, i.next()); + assertToken("/", TokenType.OPERATOR, i.next()); + assertToken("9", TokenType.LITERAL, i.next()); + } + + @Test + public void testTokenizerFunction5() { + Expression e = new Expression("3/MAX(-3.5,-5.2)/9"); + Iterator i = e.getExpressionTokenizer(); + + assertToken("3", TokenType.LITERAL, i.next()); + assertToken("/", TokenType.OPERATOR, i.next()); + assertToken("MAX", TokenType.FUNCTION, i.next()); + assertToken("(", TokenType.OPEN_PAREN, i.next()); + assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); + assertToken("3.5", TokenType.LITERAL, i.next()); + assertToken(",", TokenType.COMMA, i.next()); + assertToken("-u", TokenType.UNARY_OPERATOR, i.next()); + assertToken("5.2", TokenType.LITERAL, i.next()); + assertToken(")", TokenType.CLOSE_PAREN, i.next()); + assertToken("/", TokenType.OPERATOR, i.next()); + assertToken("9", TokenType.LITERAL, i.next()); + } + + @Test + public void testInsertImplicitMultiplication() { + Expression e = new Expression("22(3+1)"); + Iterator i = e.getExpressionTokenizer(); + + assertToken("22", TokenType.LITERAL, i.next()); + assertToken("(", TokenType.OPEN_PAREN, i.next()); + assertToken("3", TokenType.LITERAL, i.next()); + assertToken("+", TokenType.OPERATOR, i.next()); + assertToken("1", TokenType.LITERAL, i.next()); + assertToken(")", TokenType.CLOSE_PAREN, i.next()); + } + + @Test + public void testBracesCustomOperatorAndInIf() { + Expression e = new Expression("if( (a=0) and (b=0), 0, 1)"); + e.addOperator(new AbstractOperator("AND", Expression.OPERATOR_PRECEDENCE_AND, false, true) { + @Override + public BigDecimal eval(BigDecimal v1, BigDecimal v2) { + boolean b1 = v1.compareTo(BigDecimal.ZERO) != 0; + if (!b1) { + return BigDecimal.ZERO; + } + boolean b2 = v2.compareTo(BigDecimal.ZERO) != 0; + return b2 ? BigDecimal.ONE : BigDecimal.ZERO; + } + }); + + BigDecimal result = e.with("a", "0").and("b", "0").eval(); + assertEquals("0", result.toPlainString()); + } }