Skip to content

Commit 8851421

Browse files
committed
(fix) Exponentiation precedence and adds test
1 parent 9e8d132 commit 8851421

12 files changed

+106
-27
lines changed

src/main/java/com/googlecode/aviator/parser/ExpressionParser.java

+9-9
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ public void expr() {
460460
}
461461

462462
public void exponent() {
463-
unary();
463+
factor();
464464
while (true) {
465465
if (expectChar('*')) {
466466
move(true);
@@ -480,19 +480,19 @@ public void exponent() {
480480

481481

482482
public void term() {
483-
exponent();
483+
unary();
484484
while (true) {
485485
if (expectChar('*')) {
486486
move(true);
487-
exponent();
487+
unary();
488488
getCodeGeneratorWithTimes().onMult(this.lookhead);
489489
} else if (expectChar('/')) {
490490
move(true);
491-
exponent();
491+
unary();
492492
getCodeGeneratorWithTimes().onDiv(this.lookhead);
493493
} else if (expectChar('%')) {
494494
move(true);
495-
exponent();
495+
unary();
496496
getCodeGeneratorWithTimes().onMod(this.lookhead);
497497
} else {
498498
break;
@@ -507,7 +507,7 @@ public void unary() {
507507
// check if it is a seq function call,"!" as variable
508508
if (expectChar(',') || expectChar(')')) {
509509
back();
510-
factor();
510+
exponent();
511511
} else {
512512
unary();
513513
getCodeGeneratorWithTimes().onNot(this.lookhead);
@@ -517,7 +517,7 @@ public void unary() {
517517
// check if it is a seq function call,"!" as variable
518518
if (expectChar(',') || expectChar(')')) {
519519
back();
520-
factor();
520+
exponent();
521521
} else {
522522
unary();
523523
getCodeGeneratorWithTimes().onNeg(this.lookhead);
@@ -527,13 +527,13 @@ public void unary() {
527527
// check if it is a seq function call,"~" as variable
528528
if (expectChar(',') || expectChar(')')) {
529529
back();
530-
factor();
530+
exponent();
531531
} else {
532532
unary();
533533
getCodeGeneratorWithTimes().onBitNot(this.lookhead);
534534
}
535535
} else {
536-
factor();
536+
exponent();
537537
}
538538

539539

src/main/java/com/googlecode/aviator/runtime/function/math/MathRoundFunction.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
import java.util.Map;
44
import com.googlecode.aviator.runtime.function.AbstractFunction;
55
import com.googlecode.aviator.runtime.function.FunctionUtils;
6-
import com.googlecode.aviator.runtime.type.AviatorDouble;
6+
import com.googlecode.aviator.runtime.type.AviatorLong;
77
import com.googlecode.aviator.runtime.type.AviatorObject;
88

99

1010
/**
1111
* math.round(d) function
12-
*
12+
*
1313
* @author dennis
14-
*
14+
*
1515
*/
1616
public class MathRoundFunction extends AbstractFunction {
1717

@@ -20,8 +20,8 @@ public class MathRoundFunction extends AbstractFunction {
2020

2121

2222
@Override
23-
public AviatorObject call(Map<String, Object> env, AviatorObject arg) {
24-
return AviatorDouble.valueOf(Math.round(FunctionUtils.getNumberValue(arg, env).doubleValue()));
23+
public AviatorObject call(final Map<String, Object> env, final AviatorObject arg) {
24+
return AviatorLong.valueOf(Math.round(FunctionUtils.getNumberValue(arg, env).doubleValue()));
2525
}
2626

2727

src/test/java/com/googlecode/aviator/AviatorEvaluatorInstanceCompatibleUnitTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.googlecode.aviator;
22

3-
import static org.junit.Assert.assertEquals;
3+
import static com.googlecode.aviator.TestUtils.assertEquals;
44
import static org.junit.Assert.fail;
55
import java.math.MathContext;
66
import org.junit.Before;

src/test/java/com/googlecode/aviator/AviatorEvaluatorInstanceUnitTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
**/
1616
package com.googlecode.aviator;
1717

18-
import static org.junit.Assert.assertEquals;
18+
import static com.googlecode.aviator.TestUtils.assertEquals;
1919
import static org.junit.Assert.assertFalse;
2020
import static org.junit.Assert.assertNotNull;
2121
import static org.junit.Assert.assertNotSame;

src/test/java/com/googlecode/aviator/AviatorEvaluatorUnitTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
**/
1616
package com.googlecode.aviator;
1717

18-
import static org.junit.Assert.assertEquals;
18+
import static com.googlecode.aviator.TestUtils.assertEquals;
1919
import static org.junit.Assert.assertNotNull;
2020
import static org.junit.Assert.assertNotSame;
2121
import static org.junit.Assert.assertSame;

src/test/java/com/googlecode/aviator/LambdaUnitTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.googlecode.aviator;
22

3-
import static org.junit.Assert.assertEquals;
3+
import static com.googlecode.aviator.TestUtils.assertEquals;
44
import static org.junit.Assert.assertNotNull;
55
import static org.junit.Assert.assertSame;
66
import static org.junit.Assert.assertTrue;

src/test/java/com/googlecode/aviator/ScriptEngineTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.googlecode.aviator;
22

3-
import static org.junit.Assert.assertEquals;
3+
import static com.googlecode.aviator.TestUtils.assertEquals;
44
import static org.junit.Assert.assertNotNull;
55
import static org.junit.Assert.assertNull;
66
import java.io.FileReader;

src/test/java/com/googlecode/aviator/TestUtils.java

+40
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package com.googlecode.aviator;
22

3+
import java.util.Objects;
34
import com.googlecode.aviator.utils.Env;
5+
import com.googlecode.aviator.utils.TypeUtils;
6+
import junit.framework.AssertionFailedError;
47

58
/**
69
* Test helper
@@ -15,4 +18,41 @@ public static Env getTestEnv() {
1518
env.setInstance(AviatorEvaluator.getInstance());
1619
return env;
1720
}
21+
22+
static public void assertEquals(final double expected, final double actual, final double delta) {
23+
assertEquals(null, expected, actual, delta);
24+
}
25+
26+
static public void assertEquals(final String message, final double expected, final double actual,
27+
final double delta) {
28+
if (Double.compare(expected, actual) == 0) {
29+
return;
30+
}
31+
if (!(Math.abs(expected - actual) <= delta)) {
32+
throw new AssertionFailedError("Expect " + expected + ", but was " + actual);
33+
}
34+
}
35+
36+
public static void assertEquals(final Object expected, final Object real) {
37+
if (expected instanceof Number && real instanceof Number) {
38+
if (TypeUtils.isDouble(expected) && TypeUtils.isDouble(real)) {
39+
double delta = ((Number) expected).doubleValue() - ((Number) real).doubleValue();
40+
if (delta < 0.00001) {
41+
return;
42+
}
43+
}
44+
45+
if (TypeUtils.isLong(expected) && TypeUtils.isLong(real)) {
46+
if (((Number) expected).longValue() == ((Number) real).longValue()) {
47+
return;
48+
}
49+
}
50+
}
51+
52+
if (Objects.equals(expected, real)) {
53+
return;
54+
}
55+
throw new AssertionFailedError("Expect " + expected + "(" + expected.getClass()
56+
+ "), but actual was " + real + "(" + real.getClass() + ")");
57+
}
1858
}

src/test/java/com/googlecode/aviator/scripts/TestScripts.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.googlecode.aviator.scripts;
22

3-
import static org.junit.Assert.assertEquals;
3+
import static com.googlecode.aviator.TestUtils.assertEquals;
44
import static org.junit.Assert.assertNotNull;
55
import static org.junit.Assert.assertTrue;
66
import static org.junit.Assert.fail;

src/test/java/com/googlecode/aviator/test/function/FunctionTest.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
**/
1515
package com.googlecode.aviator.test.function;
1616

17+
import static com.googlecode.aviator.TestUtils.assertEquals;
1718
import static org.junit.Assert.assertArrayEquals;
18-
import static org.junit.Assert.assertEquals;
1919
import static org.junit.Assert.assertFalse;
2020
import static org.junit.Assert.assertNotNull;
2121
import static org.junit.Assert.assertNotSame;
@@ -822,19 +822,19 @@ public void testBigNumber() {
822822
// big int + decimal
823823
assertEquals(new BigDecimal("4.1"),
824824
AviatorEvaluator.exec("a+b", new BigDecimal("1.1"), new BigInteger("3")));
825-
assertEquals(new BigDecimal("4.1"), AviatorEvaluator.exec("a+3N", new BigDecimal("1")));
825+
assertEquals(new BigDecimal("4"), AviatorEvaluator.exec("a+3N", new BigDecimal("1")));
826826
assertEquals(new BigDecimal("4.1"), AviatorEvaluator.exec("1.1M+b", new BigInteger("3")));
827827
assertEquals(new BigDecimal("4.1"), AviatorEvaluator.exec("3N+1.1M"));
828-
assertEquals(new BigDecimal("301"), AviatorEvaluator.exec("3.01M*100N"));
828+
assertEquals(new BigDecimal("301.00"), AviatorEvaluator.exec("3.01M*100N"));
829829
assertEquals(new BigDecimal("100"), AviatorEvaluator.exec("400M/4N"));
830830
assertEquals(new BigDecimal("-2.9"), AviatorEvaluator.exec("a-4N", new BigDecimal("1.1")));
831831

832832
// decimal + long
833833
assertEquals(new BigDecimal("4.1"), AviatorEvaluator.exec("a+b", new BigDecimal("1.1"), 3));
834-
assertEquals(new BigDecimal("4.1"), AviatorEvaluator.exec("a+3", new BigDecimal("1")));
834+
assertEquals(new BigDecimal("4"), AviatorEvaluator.exec("a+3", new BigDecimal("1")));
835835
assertEquals(new BigDecimal("4.1"), AviatorEvaluator.exec("1.1M+b", 3));
836836
assertEquals(new BigDecimal("4.1"), AviatorEvaluator.exec("3+1.1M"));
837-
assertEquals(new BigDecimal("301"), AviatorEvaluator.exec("3.01M*100"));
837+
assertEquals(new BigDecimal("301.00"), AviatorEvaluator.exec("3.01M*100"));
838838
assertEquals(new BigDecimal("100"), AviatorEvaluator.exec("400M/4"));
839839
assertEquals(new BigDecimal("-2.9"), AviatorEvaluator.exec("a-4", new BigDecimal("1.1")));
840840
// decimal + double

src/test/java/com/googlecode/aviator/test/function/GrammarUnitTest.java

+40-1
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
**/
1515
package com.googlecode.aviator.test.function;
1616

17+
import static com.googlecode.aviator.TestUtils.assertEquals;
1718
import static org.junit.Assert.assertArrayEquals;
18-
import static org.junit.Assert.assertEquals;
1919
import static org.junit.Assert.assertFalse;
2020
import static org.junit.Assert.assertNull;
2121
import static org.junit.Assert.assertTrue;
@@ -38,6 +38,7 @@
3838
import com.googlecode.aviator.exception.CompileExpressionErrorException;
3939
import com.googlecode.aviator.exception.ExpressionRuntimeException;
4040
import com.googlecode.aviator.exception.ExpressionSyntaxErrorException;
41+
import com.googlecode.aviator.runtime.RuntimeUtils;
4142
import com.googlecode.aviator.runtime.function.AbstractFunction;
4243
import com.googlecode.aviator.runtime.function.FunctionUtils;
4344
import com.googlecode.aviator.runtime.type.AviatorLong;
@@ -64,6 +65,44 @@ public void testMultilineExpressions() {
6465
}
6566
}
6667

68+
@Test
69+
public void testExponent() {
70+
assertEquals(1, exec("0**0"));
71+
assertEquals(1, exec("1**0"));
72+
assertEquals(1.0, exec("1.2**0"));
73+
assertEquals(-9, exec("-3**2"));
74+
assertEquals(-1.0, exec("-1.2**0"));
75+
assertEquals(-1, exec("-1**0"));
76+
assertEquals(new BigDecimal("1"), exec("3M**0"));
77+
assertEquals(new BigInteger("-1"), exec("-2N**0"));
78+
assertEquals(1, exec("1 + 4/2**3"));
79+
80+
assertEquals(1, exec("1 + 4/-2**3"));
81+
assertEquals(33.0, exec("1 + 4/2**-3"));
82+
assertEquals(5, exec("1 + 4/2**0"));
83+
assertEquals(-2.2, exec("1-4**2*5**-1"));
84+
assertEquals(-2.2, exec("1-(4**2)*(5**-1)"));
85+
86+
assertEquals(Math.pow(2, 1000), exec("2**1000.0"));
87+
assertEquals(Math.pow(2, 1000), exec("2.0**1000.0"));
88+
assertEquals(Math.pow(2, 1000), exec("2.0**1000"));
89+
90+
assertEquals(new BigDecimal("2.0").pow(1000, RuntimeUtils.getMathContext(null)),
91+
exec("2.0M**1000"));
92+
assertEquals(new BigDecimal("2.0").pow(1000, RuntimeUtils.getMathContext(null)),
93+
exec("2.0M**1000.001"));
94+
assertEquals(new BigInteger("2").pow(1000), exec("2N**1000.001"));
95+
assertEquals(new BigInteger("2").pow(1000), exec("2N**1000.001"));
96+
97+
Expression exp = AviatorEvaluator.compile("a-b/c**2.0*1000");
98+
99+
assertEquals(-221.2222222222222, exp.execute(exp.newEnv("a", 1, "b", 2, "c", 3)));
100+
assertEquals(-221.2222222222222, exp.execute(exp.newEnv("a", 1, "b", -2, "c", -3)));
101+
assertEquals(322.2222222222222, exec("100-2/-3**2.0*1000"));
102+
assertEquals(-122.2222222222222, exec("100-2/(-3)**2.0*1000"));
103+
assertEquals(-122.2222222222222, exp.execute(exp.newEnv("a", 100, "b", 2, "c", -3)));
104+
}
105+
67106
@Test
68107
public void testCompareWithVariableSyntaxSuger() {
69108
try {

src/test/java/com/googlecode/aviator/test/function/OperatorFunctionTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.googlecode.aviator.test.function;
22

3-
import static org.junit.Assert.assertEquals;
3+
import static com.googlecode.aviator.TestUtils.assertEquals;
44
import static org.junit.Assert.fail;
55
import java.util.Arrays;
66
import java.util.HashMap;

0 commit comments

Comments
 (0)