diff --git a/io/src/FromString.cpp b/io/src/FromString.cpp index 11351d7c..459c25e5 100644 --- a/io/src/FromString.cpp +++ b/io/src/FromString.cpp @@ -208,12 +208,23 @@ auto ImplicitMultiplication(std::stringstream&& sstr) -> std::string while (sstr >> token) { if (is_function(token) || is_operator(token)) { + if (is_function(token) && lastToken == ")") { + secondPassResult << "*"; + } secondPassResult << token; lastToken = token; continue; } - if (lastToken == ")" && token == "(") { + // only "," out of nonfunc or operators should ignore implicit mult. + // (a+b)c -> (a+b)*c + if (lastToken == ")" && token != ",") { + secondPassResult << '*' << token; + lastToken = token; + continue; + } + // a(b+c) -> a*(b+c) + else if (lastToken != "" && !is_function(lastToken) && !is_operator(lastToken) && token == "(") { secondPassResult << '*' << token; lastToken = token; continue; diff --git a/io/tests/InFixTests.cpp b/io/tests/InFixTests.cpp index 2b06723c..9d931798 100644 --- a/io/tests/InFixTests.cpp +++ b/io/tests/InFixTests.cpp @@ -11,6 +11,8 @@ #include "Oasis/Multiply.hpp" #include "Oasis/FromString.hpp" #include "Oasis/Variable.hpp" +#include "Oasis/Exponent.hpp" +#include "Oasis/Derivative.hpp" template auto operator|(const std::string& str, FnT fn) -> boost::callable_traits::return_type_t @@ -116,4 +118,55 @@ TEST_CASE("In-Fix Works With Parenthesis", "[Parsing]") const auto result = std::string{ "(4+3)" } | Oasis::PreProcessInFix | InFixWithDefaultArgs; REQUIRE(result.has_value()); REQUIRE(result.value()->Equals(expected)); +} + +TEST_CASE("In-Fix Works With Trivial Implicit Multiplication", "[Parsing]") +{ + const Oasis::Multiply<> mult { + Oasis::Variable { "y" }, + Oasis::Add { + Oasis::Variable { "x" }, + Oasis::Real { 1 } }, + Oasis::Log { + Oasis::Variable { "a" }, + Oasis::Variable { "x" } } + }; + + auto InFixWithDefaultArgs = [](const std::string& in) { return Oasis::FromInFix(in); }; + const auto multresult = std::string { "y(x+1)log(a,x)" } | Oasis::PreProcessInFix | InFixWithDefaultArgs; + REQUIRE(multresult.has_value()); + REQUIRE(multresult.value()->Equals(mult)); + + const Oasis::Add<> add { + Oasis::Multiply { + Oasis::Variable { "a" }, + Oasis::Add { + Oasis::Variable { "b" }, + Oasis::Variable { "c" } } }, + Oasis::Multiply { + Oasis::Variable { "a" }, + Oasis::Add { + Oasis::Variable { "b" }, + Oasis::Variable { "c" } } } + }; + + const auto addresult = std::string { "a(b+c)+a(b+c)" } | Oasis::PreProcessInFix | InFixWithDefaultArgs; + REQUIRE(addresult.has_value()); + REQUIRE(addresult.value()->Equals(add)); + + const Oasis::Multiply ddexp { + Oasis::Variable { "a" }, + Oasis::Add { + Oasis::Variable { "x" }, + Oasis::Exponent { + Oasis::Add { + Oasis::Variable { "x" }, + Oasis::Real { 1 } }, + Oasis::Real { 2 } } } + }; + const Oasis::Derivative dd {ddexp, Oasis::Variable { "x" } }; + + const auto ddresult = std::string { "dd(a(x+(x+1)^2),x)" } | Oasis::PreProcessInFix | InFixWithDefaultArgs; + REQUIRE(ddresult.has_value()); + REQUIRE(ddresult.value()->Equals(dd)); } \ No newline at end of file