package example;
import parser.RecursiveDescentParser;
import parser.Value;
import valueTypes.BooleanValue;
import valueTypes.DecimalValue;
/**
* A unit test for the RecursiveDescentParser. An exception is thrown and
* printed to the console if an error is found (if the result from the
* evaluation does not match the expected one)
*
* @author Curran Kelleher
*
*/
public class RecursiveDescentParserTest {
// create the single parser we will use
static RecursiveDescentParser parser = new RecursiveDescentParser();
/**
* Tests the parser with many expressions.
*
* @param args
*/
public static void main(String[] args) {
// test expressions
assertParseResultEquals("2+2", 4.0);
assertParseResultEquals("2+(2+(2+2))", 2 + (2 + (2 + 2)));
assertParseResultEquals("2*(2+(2+2))", 2 * (2 + (2 + 2)));
assertParseResultEquals("2+(2*(2+2))", 2 + (2 * (2 + 2)));
assertParseResultEquals("-2", -2.0);
assertParseResultEquals("-(5^-2)", -Math.pow(5, -2));
assertParseResultEquals("5^5", Math.pow(5, 5));
assertParseResultEquals("5+5*5^5", 5 + 5 * Math.pow(5, 5));
assertParseResultEquals("5+(5*5)^5", 5 + Math.pow(5 * 5, 5));
assertParseResultEquals("(5+5)*5^5", (5 + 5) * Math.pow(5, 5));
assertParseResultEquals("5E3", 5000);
assertParseResultEquals("2+5E3", 5002);
assertParseResultEquals("sin(3)", Math.sin(3));
assertParseResultEquals("3Esin(-3+(7^3-400*(6*-3)))", 3 * Math.pow(10,
Math.sin(-3 + (Math.pow(7, 3) - 400 * (6 * -3)))));
double a, b, c, d, f;
assertParseResultEquals("a = -(b = 6^(c = 8+(d = 6-9^(f=99^-2))*5))",
a = -(b = Math.pow(6, (c = 8 + (d = 6 - Math.pow(9, (f = Math
.pow(99, -2)))) * 5))));
assertParseResultEquals("a/b", a / b);
assertParseResultEquals("c%d", c % d);
assertParseResultEquals("f%a/d*c", f % a / d * c);
assertParseResultEquals("cos(5)", Math.cos(5));
assertParseResultEquals("tan(5)", Math.tan(5));
assertParseResultEquals("cot(.5)", Math.tan(Math.PI / 2 - 0.5));
assertParseResultEquals("sec(.5)", 1 / Math.cos(0.5));
assertParseResultEquals("csc(.5)", 1 / Math.sin(0.5));
assertParseResultEquals("asin(0.5)", Math.asin(0.5));
assertParseResultEquals("acos(.5)", Math.acos(0.5));
assertParseResultEquals("atan(.5)", Math.atan(0.5));
// sin(3)+cos(5)+tan(5)+cot(.5)+sec(.5)+csc(.5)+asin(0.5)+acos(.5)+atan(.5)
assertParseResultEquals("ln(5)", Math.log(5));
assertParseResultEquals("log(1000)", 3);
assertParseResultEquals("abs(-5)", 5);
assertParseResultEquals("3!", 6);
assertParseResultEquals("(2+1)!+4", 10);
// all mathematical binary operators
assertParseResultEquals("1+2-3*4/5^6E-7%8!", 1
+ 2
- 3
* 4
/ Math.pow(5, (6 * Math.pow(10,
(-7 % (8 * 7 * 6 * 5 * 4 * 3 * 2))))));
assertParseResultEquals("sqrt(25)", 5);
assertParseResultEquals("round(6.5)", 7);
assertParseResultEquals("round(6.4)", 6);
assertParseResultEquals("floor(6.6)", 6);
assertParseResultEquals("floor(6.4)", 6);
assertParseResultEquals("ceil(6.6)", 7);
assertParseResultEquals("ceil(6.4)", 7);
// ln(5)+log(1000)+abs(-5)+sqrt(25)+round(6.5)+floor(6.6)+ceil(6.4)
assertParseResultEquals("pi", Math.PI);
assertParseResultEquals("e", Math.E);
assertParseResultEquals("Infinity", Double.POSITIVE_INFINITY);
assertParseResultEquals("true", true);
assertParseResultEquals("false", false);
assertParseResultEquals("1<2", true);
assertParseResultEquals("2<1", false);
assertParseResultEquals("2<2", false);
assertParseResultEquals("10^2-50*2<2E2", true);
assertParseResultEquals("1<=2", true);
assertParseResultEquals("2<=1", false);
assertParseResultEquals("2<=2", true);
assertParseResultEquals("1>2", false);
assertParseResultEquals("2>1", true);
assertParseResultEquals("2>2", false);
assertParseResultEquals("10^2-50*2>2E2", false);
assertParseResultEquals("1>=2", false);
assertParseResultEquals("2>=1", true);
assertParseResultEquals("2>=2", true);
assertParseResultEquals("2 == 2", true);
assertParseResultEquals("2 == 6", false);
assertParseResultEquals("2 != 2", false);
assertParseResultEquals("2 != 6", true);
assertParseResultEquals("true && true", true);
assertParseResultEquals("true && false", false);
assertParseResultEquals("false && true", false);
assertParseResultEquals("true || true", true);
assertParseResultEquals("true || false", true);
assertParseResultEquals("false || true", true);
assertParseResultEquals("false || false", false);
assertParseResultEquals("4!>=5^2-1&&2*2==2^2&&3!!=4!*2", true);
assertParseResultEquals("a = 3", 3);
assertParseResultEquals("b = 4", 4);
evaluate("f = createFunction(a+b)");
evaluate("executeFunction(f)");
assertParseResultEquals("b = 7", 7);
evaluate("executeFunction(f)");
evaluate("g = {c = (a*b)}");// same as "g = createFunction(c = (a+b))"
evaluate("executeFunction(g)");
assertParseResultEquals("c", 21);
evaluate("f = {a = 0;b = 1; c = 2; d = false}");
evaluate("executeFunction(f)");
assertParseResultEquals("a", 0);
assertParseResultEquals("b", 1);
assertParseResultEquals("c", 2);
assertParseResultEquals("d", false);
// if
evaluate("if(0<1){a = 5}");
assertParseResultEquals("a", 5);
// our first recursive progam!!
assertParseResultEquals("a = 5.0", 5);
assertParseResultEquals("a", 5);
evaluate("sum = {if((a = a+1)<500){executeFunction(sum)}}");
evaluate("executeFunction(sum)");
assertParseResultEquals("a", 500);
// the turnary ? : operator
assertParseResultEquals("true?5:4", 5);
assertParseResultEquals("4!>=5^2-1&&2*2==2^2&&3!!=4!*2?5:4", 5);
assertParseResultEquals("false?5:4", 4);
evaluate("f={d=(a=0)<1;b=1;c =4!>=5^2-1&&2*2==2^2&&3!!=4!*2?(a==0&&b==1&&d?567:568):678;d=false}");
evaluate("executeFunction(f)");
assertParseResultEquals("c", 567);
// the while loop
// assertParseResultEquals("a = 1", 1);
assertParseResultEquals("b = 10", 10);
evaluate("f = {while(b < 100){b = b+1}}");
evaluate("executeFunction(f)");
assertParseResultEquals("b", 100);
assertParseResultEquals("a = 1", 1);
evaluate("f = {for(i = 1;i<20;i = i+1){a = a*i}}");
evaluate("executeFunction(f)");
int i;
a = 1;
for (i = 1; i < 20; i = i + 1) {
a = a * i;
}
assertParseResultEquals("i", i);
assertParseResultEquals("a", a);
//testing lists
assertParseResultEquals("[1,2,3]","[1.0, 2.0, 3.0]");
assertParseResultEquals("createErrorValue(\"test error value\")","test error value");
}
/**
* Parses and executes the specified expression string. Prints out the
* result.
*
* @param expression
* the expression string
*/
private static void evaluate(String expression) {
Value result = parser.parse(expression).evaluate();
System.out.println("executed " + expression);
System.out.println(" result is " + result);
}
/**
* Evaluates the specified expression string, and throws an exception if the
* result does not equal the specified value.
*
* @param expression
* the expression to evaluate
* @param b
* the value to test against
*/
private static void assertParseResultEquals(String expression, boolean b) {
Value aVal = parser.parse(expression).evaluate();
if (aVal instanceof BooleanValue)
if (((BooleanValue) aVal).value == b) {
System.out.println("success! " + expression + " == " + b);
return;
}
(new Exception(aVal + " != " + b)).printStackTrace();
}
/**
* Evaluates the specified expression string, and throws an exception if the
* result does not equal the specified value.
*
* @param expression
* the expression to evaluate
* @param b
* the value to test against
*/
private static void assertParseResultEquals(String expression, double b) {
Value aVal = parser.parse(expression).evaluate();
if (aVal instanceof DecimalValue)
if (((DecimalValue) aVal).value == b) {
System.out.println("success! " + expression + " == " + b);
return;
}
(new Exception(aVal + " != " + b)).printStackTrace();
}
/**
* Evaluates the specified expression string, and throws an exception if the
* result does not equal the specified value.
*
* @param expression
* the expression to evaluate
* @param b
* the value to test against
*/
private static void assertParseResultEquals(String expression, String result) {
Value aVal = parser.parse(expression).evaluate();
if (aVal.toString().equals(result)) {
System.out.println("success! " + expression + " == " + result);
return;
}
(new Exception(aVal + " != " + result)).printStackTrace();
}
}