Skip to content

Commit 8734624

Browse files
authored
Merge pull request #99 from fremling/master
Solving error with $ not escaping correctly.
2 parents eb96b8f + ab37cc3 commit 8734624

File tree

3 files changed

+82
-24
lines changed

3 files changed

+82
-24
lines changed

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,32 @@ using Test
191191
Printing in Jupyter notebooks is, by default, done in latex.
192192
This can be turned off with the command `MathLink.set_texOutput(false)`
193193

194+
## Escaping dollars for Mathematica
195+
The `$` sign has a special meaning in Julia, but it does not in Mathematica. We can send dollar signs to Mathematica that same way we add them to normal strings. Below are a few exampoles of how it works:
196+
197+
using Test
198+
x = exp(1)
199+
@test W`$x` == x
200+
@test W`\$` == W"$"
201+
@test W`\$x` == W"$x"
202+
@test W`$x +\$` == x+W"$"
203+
@test W`"\$"` == "\$"
204+
@test W`"a"` == "a"
205+
@test W`{a -> b}` == W"List"(W"Rule"(W"a",W"b"))
206+
@test W`{"a" -> "b"}` == W"List"(W"Rule"("a","b"))
207+
@test W`"a" -> "b"` == W"Rule"("a","b")
208+
@test W`a -> b` == W"Rule"(W"a",W"b")
209+
@test W`"b(\$)a"` == "b(\$)a"
210+
@test W`"b\\\$"` == "b\\\$"
211+
@test W`"b\$"` == "b\$"
212+
@test W`"\$a"` == "\$a"
213+
@test W`"\$" -> "b"` == W"Rule"("\$","b")
214+
@test W`{"\$" -> "b"}` == W"List"(W"Rule"("\$","b"))
215+
@test W`{"a" -> "\$"}` == W"List"(W"Rule"("a","\$"))
216+
@test W`{a -> "\$"}` == W"List"(W"Rule"(W"a","\$"))
217+
218+
219+
194220
## Installation Troubleshoot
195221
The package requires an installation of either [Mathematica](http://www.wolfram.com/mathematica/) or the free [Wolfram Engine](https://www.wolfram.com/engine/). It will attempt to find the installation at build time; if this fails, you will need to set the following [environment variables](https://docs.julialang.org/en/v1/manual/environment-variables/):
196222
- `JULIA_MATHKERNEL`: the path of the MathKernel executable

src/eval.jl

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,16 @@ wevalstr(expr) = wevalstr(Any, expr)
6565
Parse a string `str` as a Wolfram Language expression.
6666
"""
6767
function parseexpr(str::AbstractString)
68+
#####The escaping of dollars was a bit messy. I'm letting these comment stay here for a while untill a better documentation is in place.
69+
70+
71+
#println("parseexpr: '",str,"'")
72+
#dump(str)
6873
UnescapedDollar=unescape_dollar(str)
74+
#println("UnescapedDollar: '",UnescapedDollar,"'")
75+
#dump(UnescapedDollar)
6976
r = weval(W"ToExpression"(UnescapedDollar, W"StandardForm", W"Hold"))
77+
#println("r: '",r,"'")
7078
r.args[1]
7179
end
7280

@@ -80,12 +88,29 @@ macro W_cmd(str)
8088
# the function parseexpr(string). The result is then back-converted to a julia MathLink expression.
8189
#quote parseexpr($(esc(Meta.parse("\"$(escape_string(str))\"")))) end
8290

91+
92+
#####The escaping of dollars was a bit messy. I'm letting these comment stay here for a while untill a better documentation is in place.
93+
8394
###Adding a set of string escapes for correct parsing
95+
#println("------")
96+
#println("str: '",str,"'")
8497
EscapedString=escape_string(str)
98+
#println("EscapedString: '",EscapedString,"'")
8599
DollarString=escape_dollar(EscapedString)
100+
#println("DollarString: '",DollarString,"'")
86101
FullString="\"$(DollarString)\""
102+
#FullStringII="\"$(EscapedString)\""
103+
104+
#println("FullString: '",FullString,"'")
105+
#println("FullStringII: '",FullStringII,"'")
106+
87107
##Doing the parsing!
88108
string_expr = Meta.parse(FullString)
109+
# string_exprII = Meta.parse(FullStringII)
110+
#println("string_expr: '",string_expr,"'")
111+
# println("string_exprII: '",string_exprII,"'")
112+
113+
89114
subst_dict = Dict{WSymbol,Any}()
90115
if string_expr isa String
91116
string = string_expr
@@ -102,7 +127,11 @@ macro W_cmd(str)
102127
else
103128
error("Invalid string expression: $string_expr")
104129
end
130+
#println("subst_dict:",subst_dict)
131+
#println("string:",string)
132+
105133
wexpr = parseexpr(string)
134+
#println("wexpr: '",wexpr,"'")
106135
to_julia_expr(wexpr, subst_dict)
107136
end
108137

@@ -113,7 +142,7 @@ Escapes the '\$' character to create a correct string interpretation when these
113142
"""
114143
function escape_dollar(str::AbstractString)
115144
####This function explicitly escapes the $ character to create a correct string interpretation when dollars are present.
116-
return replace(str,'\$'=>"\\\$")
145+
return replace(str,"\\\$"=>"\\\\\$")
117146
end
118147
"""
119148
unescape_dollar(str::AbstractString)
@@ -127,7 +156,6 @@ end
127156

128157

129158

130-
131159
function to_julia_expr(wexpr::WExpr, subst_dict)
132160
head = to_julia_expr(wexpr.head, subst_dict)
133161
args = map(x->to_julia_expr(x, subst_dict), wexpr.args)

test/runtests.jl

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ import MathLink: WExpr, WSymbol
88
@testset "interpolation" begin
99
set_GreedyEval(false)
1010
x = exp(1)
11+
@test W`$x` == x
12+
@test W`\$` == W"$"
13+
@test W`\$x` == W"$x"
14+
@test W`$x +\$` == x+W"$"
15+
@test W`Sin[$x +\$]` == W"Sin"(x+W"$")
1116
@test W`Sin[$x]` == W"Sin"(x)
1217
@test W`Cos[$(log(2))]` == W"Cos"(log(2))
1318

@@ -33,7 +38,7 @@ end
3338

3439
@testset "Conversion of strange characters" begin
3540
a="!"
36-
println("Test with variable after")
41+
#println("Test with variable after")
3742
###Test with variable after
3843
@test TestMeta("\"$a\"") == "!"
3944
@test TestMeta("\"\$a\"") == :("$(a)")
@@ -44,7 +49,7 @@ end
4449
@test TestMeta("\"\\\\\$a\"") == :("\\$(a)")
4550
@test_throws Base.Meta.ParseError("invalid escape sequence") TestMeta("\"\\\\\\$a\"")
4651

47-
println("Test with no variable after")
52+
#println("Test with no variable after")
4853
###Test with no variable after
4954
### TestMeta("\"$\"") ###Invalid syntax
5055
@test_throws Base.Meta.ParseError TestMeta("\"\$\"")
@@ -55,7 +60,7 @@ end
5560
### TestMeta("\"\\\\\\$\"") ###Invalid syntax
5661
@test TestMeta("\"\\\\\\\$\"") == "\\\$"
5762

58-
println("Test escaped strings")
63+
#println("Test escaped strings")
5964
### Test escaped strings
6065
@test TestEscape("\$") == "\$"
6166
@test TestEscape("\\\$") == "\\\\\$"
@@ -73,23 +78,23 @@ end
7378
@test EscapeDollar("\\\\\$\$") == "\\\\\\\$\\\$"
7479

7580
set_GreedyEval(false)
76-
println("Test math on the symbols")
81+
#println("Test math on the symbols")
7782
@test weval(WSymbol("a")+WSymbol("a")) == weval(2*WSymbol("a"))
7883
@test weval(WSymbol("\$")+WSymbol("\$")) == weval(2*WSymbol("\$"))
79-
println("Test creating the symbol")
84+
#println("Test creating the symbol")
8085
###Test creating the symbol
8186
@test W`a` == WSymbol("a")
8287
@test W`a` == W"a"
8388
@test W`\$` == WSymbol("\$")
8489

8590

86-
println("Test creating the symbol string")
91+
#println("Test creating the symbol string")
8792
###Test creating the symbol string
8893
@test W`"a"` == "a"
8994
@test W`"\$"` == "\$"
9095

9196

92-
println("Other tests")
97+
#println("Other tests")
9398
@test W`"\$"` == "\$"
9499
@test W`"a"` == "a"
95100
@test W`{a -> b}` == W"List"(W"Rule"(W"a",W"b"))
@@ -99,13 +104,12 @@ end
99104
@test W`"b(\$)a"` == "b(\$)a"
100105
@test W`"b\\\$"` == "b\\\$"
101106
@test W`"b\$"` == "b\$"
102-
@test W`"$a"` == "\$a"
103-
@test W`"$"` == "\$"
104-
@test W`"$"` == "\$"
105-
@test W`"$" -> "b"` == W"Rule"("\$","b")
106-
@test W`{"$" -> "b"}` == W"List"(W"Rule"("\$","b"))
107-
@test W`{"a" -> "$"}` == W"List"(W"Rule"("a","\$"))
108-
@test W`{a -> "$"}` == W"List"(W"Rule"(W"a","\$"))
107+
@test W`"\$a"` == "\$a"
108+
@test W`"\$"` == "\$"
109+
@test W`"\$" -> "b"` == W"Rule"("\$","b")
110+
@test W`{"\$" -> "b"}` == W"List"(W"Rule"("\$","b"))
111+
@test W`{"a" -> "\$"}` == W"List"(W"Rule"("a","\$"))
112+
@test W`{a -> "\$"}` == W"List"(W"Rule"(W"a","\$"))
109113

110114
end
111115

@@ -467,22 +471,22 @@ end
467471
### weval(W"ToExpression"("17.0000000000000000000000000", W"StandardForm", W"Hold"))
468472

469473
s="17.000000000"
470-
@test MathLink.parseexpr(s) == s
474+
@test_broken MathLink.parseexpr(s) == s
471475
s="17.0000000000"
472-
@test MathLink.parseexpr(s) == s
476+
@test_broken MathLink.parseexpr(s) == s
473477
s="17.00000000000"
474-
@test MathLink.parseexpr(s) == s
478+
@test_broken MathLink.parseexpr(s) == s
475479
s="17.000000000000"
476-
@test MathLink.parseexpr(s) == s
480+
@test_broken MathLink.parseexpr(s) == s
477481
s="17.0000000000000"
478-
@test MathLink.parseexpr(s) == s
482+
@test_broken MathLink.parseexpr(s) == s
479483
s="17.00000000000000"
480-
@test MathLink.parseexpr(s) == s
484+
@test_broken MathLink.parseexpr(s) == s
481485

482486
@test W`17.000000000` == 17.0
483487
@test W`17.000000000000` == 17.0
484-
@test W`17.00000000000000000` == 17.0
485-
@test W`17.000000000000000000000` == 17.0
488+
@test_broken W`17.00000000000000000` == 17.0
489+
@test_broken W`17.000000000000000000000` == 17.0
486490

487491
end
488492

0 commit comments

Comments
 (0)