#include "harness.h" #define CHECK_PARSE(var, expr) \ do { \ var = Expr::From(expr, false); \ CHECK_TRUE(var != NULL); \ } while(0) #define CHECK_PARSE_ERR(expr, msg) \ do { \ std::string err; \ Expr *e = Expr::Parse(expr, &err); \ CHECK_TRUE(e == NULL); \ CHECK_TRUE(err.find(msg) != std::string::npos); \ } while(0) TEST_CASE(constant) { Expr *e; CHECK_PARSE(e, "pi"); CHECK_EQ_EPS(e->Eval(), 3.1415926); } TEST_CASE(literal) { Expr *e; CHECK_PARSE(e, "42"); CHECK_TRUE(e->Eval() == 42); CHECK_PARSE(e, "42.5"); CHECK_TRUE(e->Eval() == 42.5); CHECK_PARSE(e, "1_000_000"); CHECK_TRUE(e->Eval() == 1000000); } TEST_CASE(unary_ops) { Expr *e; CHECK_PARSE(e, "-10"); CHECK_TRUE(e->Eval() == -10); } TEST_CASE(binary_ops) { Expr *e; CHECK_PARSE(e, "1 + 2"); CHECK_TRUE(e->Eval() == 3); CHECK_PARSE(e, "1 - 2"); CHECK_TRUE(e->Eval() == -1); CHECK_PARSE(e, "3 * 4"); CHECK_TRUE(e->Eval() == 12); CHECK_PARSE(e, "3 / 4"); CHECK_TRUE(e->Eval() == 0.75); } TEST_CASE(parentheses) { Expr *e; CHECK_PARSE(e, "(1 + 2) * 3"); CHECK_TRUE(e->Eval() == 9); CHECK_PARSE(e, "1 + (2 * 3)"); CHECK_TRUE(e->Eval() == 7); } TEST_CASE(functions) { Expr *e; CHECK_PARSE(e, "sqrt(2)"); CHECK_EQ_EPS(e->Eval(), 1.414213); CHECK_PARSE(e, "square(3)"); CHECK_EQ_EPS(e->Eval(), 9); CHECK_PARSE(e, "sin(180)"); CHECK_EQ_EPS(e->Eval(), 0); CHECK_PARSE(e, "sin(90)"); CHECK_EQ_EPS(e->Eval(), 1); CHECK_PARSE(e, "cos(180)"); CHECK_EQ_EPS(e->Eval(), -1); CHECK_PARSE(e, "asin(1)"); CHECK_EQ_EPS(e->Eval(), 90); CHECK_PARSE(e, "acos(0)"); CHECK_EQ_EPS(e->Eval(), 90); } TEST_CASE(variable) { Expr *e; CHECK_PARSE(e, "Var"); CHECK_TRUE(e->op == Expr::Op::VARIABLE); } TEST_CASE(precedence) { Expr *e; CHECK_PARSE(e, "2 + 3 * 4"); CHECK_TRUE(e->Eval() == 14); CHECK_PARSE(e, "2 - 3 / 4"); CHECK_TRUE(e->Eval() == 1.25); CHECK_PARSE(e, "-3 + 2"); CHECK_TRUE(e->Eval() == -1); CHECK_PARSE(e, "2 + 3 - 4"); CHECK_TRUE(e->Eval() == 1); } TEST_CASE(errors) { CHECK_PARSE_ERR("\x01", "Unexpected character"); CHECK_PARSE_ERR("notavar", "'notavar' is not a valid variable, function or constant"); CHECK_PARSE_ERR("1e2e3", "'1e2e3' is not a valid number"); CHECK_PARSE_ERR("_", "'_' is not a valid operator"); CHECK_PARSE_ERR("2 2", "Expected an operator"); CHECK_PARSE_ERR("2 + +", "Expected an operand"); CHECK_PARSE_ERR("( 2 + 2", "Expected ')'"); }