# using StringReplace and StringPattern to convert exp(...) to Exp[....]

I am looking at a file generated by another CAS. I'd like to convert it to Mathematica syntax.

Only issue is how to convert exp(....) to Exp[....]. I am using StringReplace with pattern to do the replacement but it is not catching all possible cases. I am not good at regular expressions in Mathematica.

Here are 5 simple input examples to test with

ClearAll[z]
str1 = "exp(x)^2";
str2 = "exp((x+2))";
str3 = "exp( (x+2) * exp(exp(x)+2) )";
str4 = "(4*x)/exp((x-(2/5))/((3/(exp(x)+5))*4+(x-(2-x))*x))+4"
str5="(20*x^4+(-30)*x^3+12*x^2+4*x)*exp(x)^2+(200*x^4+(-300)*x^3+300*x^2+(-236)*x)*exp(x)+(500*x^4+(-750)*x^3+1500*x^2+(-1400)*x+720)"


These should become

str1 = "Exp[x]^2";
str2 = "Exp[(x+2)]";
str3 = "Exp[ (x+2) * Exp[Exp[x]+2]  ]";
str4 = "(4*x)/Exp[(x-(2/5))/((3/(Exp[x]+5))*4+(x-(2-x))*x)]+4"
str5 = "(20*x^4+(-30)*x^3+12*x^2+4*x)*Exp[x]^2+(200*x^4+(-300)*x^3+300*x^2+(-236)*x)*Exp[x]+(500*x^4+(-750)*x^3+1500*x^2+(-1400)*x+720)"


This is what I tried among many other things

StringReplace[str, "exp(" ~~ z__ ~~ ")" :> "Exp[" ~~ z ~~ "]"]


Only the first and second worked. The third one, it did not change any of the internal ones. it failed on str4 and str5 also.

Any suggestions how to do this conversion all in one command? Either using string patterns or regular expression in Mathematica.

I am using version 12.3.1

• As far as I understand StringReplace is indeed a wolframized version of extended regular expressions. In the case of nested parentheses it's noteworthy that extended regular expressions are simply not expressive enough construct to handle arbitrary counting and matching of nested parentheses, which is required here (unless you work around it with the @ trick). Sep 14, 2021 at 12:57

Update: We can convert the strings to expressions without any string processing:

ClearAll[sR0]

sR0 /@ {str1, str2, str3, str4, str5} // Column If you need to get strings as output wrap the expression with ToString[#, InputForm]& using the third argument of ToExpression:

ClearAll[sR01]
sR01 = ToExpression[#, TraditionalForm, ToString[#, InputForm] &] &;

sR01 /@ {str1, str2, str3, str4, str5}

{"E^(2*x)",
"E^(2 + x)",
"E^(E^(2 + E^x)*(2 + x))",
"4 + (4*x)/E^((-2/5 + x)/(12/(5 + E^x) + x*(-2 + 2*x)))",
"720 - 1400*x + 1500*x^2 - 750*x^3 + 500*x^4 +
E^(2*x)*(4*x + 12*x^2 - 30*x^3 + 20*x^4) +
E^x*(-236*x + 300*x^2 - 300*x^3 + 200*x^4)"}


ClearAll[sR]
sR = StringReplace[#, "exp(" ~~ Shortest[z__] ~~ ")" /;
Equal @@ (StringCount[z, #] & /@ {"(", ")"}) :>
"Exp[" <> sR @ z <> "]"] &;

sR /@ {str1, str2, str3, str4, str5}

{"Exp[x]^2",
"Exp[(x+2)]",
"Exp[ (x+2) * Exp[Exp[x]+2] ]",
"(4*x)/Exp[(x-(2/5))/((3/(Exp[x]+5))*4+(x-(2-x))*x)]+4",
"(20*x^4+(-30)*x^3+12*x^2+4*x)*Exp[x]^2+(200*x^4+(-300)*x^3+300*x^2+
(-236)*x)*Exp[x]+(500*x^4+(-750)*x^3+1500*x^2+(-1400)*x+720)"}


You can also use FixedPoint as follows:

ClearAll[sR2]
sR2 = FixedPoint[StringReplace[
"exp(" ~~ Shortest[z__] ~~ ")" /;
Equal @@ (StringCount[z, #] & /@ {"(", ")"}) :>
"Exp[" <> z <> "]"], #] &;

sR2 /@ {str1, str2, str3, str4, str5} == sR /@ {str1, str2, str3, str4, str5}

 True

• Thanks. I tried it on the main files, there are cases where it does not work. Here is one str4="(20*x^4+(-30)*x^3+12*x^2+4*x)*exp(x)^2+(200*x^4+(-300)*x^3+300*x^2+(-236)*x)*exp(x)+(500*x^4+(-750)*x^3+1500*x^2+(-1400)*x+720)" it gives "(20*x^4+(-30)*x^3+12*x^2+4*x)*Exp[x)^2+(200*x^4+(-300)*x^3+300*x^2+(- 236)*x)*Exp[x)+(500*x^4+(-750)*x^3+1500*x^2+(-1400]*x+720]" I will add this example to my question for completion. Sep 9, 2021 at 5:04
• Also please note that str4 test also did not pass. It generated Exp[x) there as well. Sep 9, 2021 at 5:12
• @Nasser, please see the updated version.
– kglr
Sep 9, 2021 at 5:20
• Thanks for the update. But for str5 it still gives Exp[x)^2 Sep 9, 2021 at 5:26
• @Nasser, updated version works for str1 thru str5 (will need another update for str6:)
– kglr
Sep 9, 2021 at 5:34

A simple trick is to notice that in Mathematica, Exp[x] can be written as Exp@(x) where the @ symbol has very high precedence. A replacement of the string "exp" by the string "Exp@" therefore does the necessary conversion without needing any bracket-matching logic:

convert[s_String] := ToExpression[StringReplace[s, "exp" -> "Exp@"]]

convert[str1]
(*    E^(2 x)    *)

convert[str2]
(*    E^(2 + x)    *)

convert[str3]
(*    E^(E^(2 + E^x) (2 + x))    *)

convert[str4]
(*    4 + 4 E^(-((-(2/5) + x)/(12/(5 + E^x) + x (-2 + 2 x)))) x    *)

convert[str5]
(*    720 - 1400 x + 1500 x^2 - 750 x^3 + 500 x^4 + E^(2 x) (4 x + 12 x^2 - 30 x^3 + 20 x^4) + E^x (-236 x + 300 x^2 - 300 x^3 + 200 x^4)    *)


If you want pretty string forms (instead of automatic evaluation with ToExpression as above), use an invisible application esc-@-esc to hide the @ symbols:

convert2[s_String] := StringReplace[s, "exp" -> "Exp\[InvisibleApplication]"]

convert2[str1]
(*    "Exp\[InvisibleApplication](x)^2"    *)
(*    actually looks like "Exp(x)^2" in the front-end but is
correct Mathematica syntax                                *)

ToExpression[%]
(*    E^(2 x)    *)