From 1c230933c1763a0792141377d7cb45734b8abfbb Mon Sep 17 00:00:00 2001 From: Srajan Garg Date: Wed, 20 Jan 2016 23:07:55 +0530 Subject: [PATCH] added support for symbols, and respective tests --- symengine/parser.cpp | 43 +++++++++++++++++++++------ symengine/tests/basic/test_parser.cpp | 41 ++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 10 deletions(-) diff --git a/symengine/parser.cpp b/symengine/parser.cpp index 559d2687ec..ce0cd35e45 100644 --- a/symengine/parser.cpp +++ b/symengine/parser.cpp @@ -39,16 +39,24 @@ class expressionParser { RCP result; bool result_set = false; + bool expr_is_symbol = false; std::string expr; for (uint iter = l; iter < h; ++iter) { - if (OPERATORS.find(s[iter]) != OPERATORS.end()) + if (is_operator(s, iter)) { if (s[iter] != '(') + { if (!result_set) - result = integer(std::stoi(expr)); - + { + if (expr_is_symbol) + result = symbol(expr); + else + result = integer(std::stoi(expr)); + } + } + switch(s[iter]) { case '+': @@ -79,13 +87,23 @@ class expressionParser continue; } result_set = true; + expr_is_symbol = false; } else { expr += s[iter]; + int ascii = s[iter] - '0'; + if (ascii < 0 or ascii > 9) + expr_is_symbol = true; + if (iter == h-1) - result = integer(std::stoi(expr)); + { + if (expr_is_symbol) + result = symbol(expr); + else + result = integer(std::stoi(expr)); + } } } @@ -95,7 +113,6 @@ class expressionParser RCP parse(std::string &s) { std::string copy; - char x; std::stack rBracket; std::stack > opStack; @@ -113,9 +130,9 @@ class expressionParser for (int i = newLength-1; i >= 0; i--) { - x = copy[i]; - if (OPERATORS.find(x) != OPERATORS.end()) - { + if (is_operator(copy, i)) + { + char x = copy[i]; if(x == '(') { while(opStack.top().second != rBracket.top()) @@ -127,7 +144,7 @@ class expressionParser else if(x == ')') { opStack.push(std::make_pair(opPrecedence[x], i)); - rBracket.push(i); + rBracket.push(i); } else { @@ -141,6 +158,14 @@ class expressionParser } return parse_string(copy, 0, newLength); } + + bool is_operator(std::string& s, int iter) + { + if (iter >= 0 and iter < (int)s.length()) + if (OPERATORS.find(s[iter]) != OPERATORS.end()) + return true; + return false; + } }; } // SymEngine diff --git a/symengine/tests/basic/test_parser.cpp b/symengine/tests/basic/test_parser.cpp index 257b52e2c5..cc468cca48 100644 --- a/symengine/tests/basic/test_parser.cpp +++ b/symengine/tests/basic/test_parser.cpp @@ -42,7 +42,7 @@ TEST_CASE("Parsing: integers, basic operations", "[parser]") s = "((3)+(1*0))"; res = p.parse(s); REQUIRE(eq(*res, *integer(3))); - + s = "((2))*(1+(2*3))"; res = p.parse(s); REQUIRE(eq(*res, *integer(14))); @@ -83,3 +83,42 @@ TEST_CASE("Parsing: integers, basic operations", "[parser]") res = p.parse(s); REQUIRE(eq(*res, *add(integer(9), div(integer(-5), integer(4))))); } + +TEST_CASE("Parsing: symbols", "[parser]") +{ + std::string s; + expressionParser p; + RCP res; + RCP x = symbol("x"); + RCP y = symbol("y"); + RCP w = symbol("w1"); + RCP l = symbol("l0ngn4me"); + + s = "x + 2*y"; + res = p.parse(s); + REQUIRE(eq(*res, *add(x, mul(integer(2), y)))); + + s = "w1*y"; + res = p.parse(s); + REQUIRE(eq(*res, *mul(w ,y))); + + s = "x^(3+w1)-2/y"; + res = p.parse(s); + REQUIRE(eq(*res, *add(pow(x, add(integer(3), w)), div(integer(-2), y)))); + + s = "l0ngn4me - w1*y + 2^(x)"; + res = p.parse(s); + REQUIRE(eq(*res, *add(add(l, neg(mul(w, y))), pow(integer(2), x)))); + + s = "4*x/8 - (w1*y)"; + res = p.parse(s); + REQUIRE(eq(*res, *add(neg(mul(w, y)), div(x, integer(2))))); + + s = "3*y + (2*y)"; + res = p.parse(s); + REQUIRE(eq(*res, *mul(y, integer(5)))); + + s = "3*y/(1+x)"; + res = p.parse(s); + REQUIRE(eq(*res, *div(mul(y, integer(3)), add(x, integer(1))))); +}