Add files with expressions, parser, Nikuradse dataset and a new test case.

This commit is contained in:
Gabriel Kronberger 2025-04-18 08:19:22 +02:00
parent 6ab826cc42
commit 293c5f13a4
14 changed files with 689 additions and 0 deletions

View File

@ -5,12 +5,16 @@ version = "1.0.0-DEV"
[deps]
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"
GZip = "92fee26a-97fe-5a0c-ad85-20a5f3185b63"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
[compat]
DelimitedFiles = "1.9.1"
GZip = "0.6.2"
LinearAlgebra = "1.11.0"
Printf = "1.11.0"
Random = "1.11.0"

View File

@ -1,5 +1,9 @@
using LinearAlgebra
using BenchmarkTools
using DelimitedFiles
using GZip
include("parser.jl") # to parse expressions from a file
function test_cpu_interpreter(nrows; parallel = false)
exprs = [
@ -45,3 +49,27 @@ end
@test test_cpu_interpreter(1000, parallel=true) # start julia -t 6 for six threads
@test test_cpu_interpreter(10000)
@test test_cpu_interpreter(10000, parallel=true)
function test_cpu_interpreter_nikuradse()
data,varnames = readdlm("data/nikuradse_1.csv", ',', header=true);
X = convert(Matrix{Float32}, data)
exprs = Expr[]
parameters = Vector{Vector{Float32}}()
varnames = ["x$i" for i in 1:10]
paramnames = ["p$i" for i in 1:20]
# data/esr_nvar2_len10.txt.gz_9.txt.gz has ~250_000 exprs
# data/esr_nvar2_len10.txt.gz_10.txt.gz has ~800_000 exrps
GZip.open("data/esr_nvar2_len10.txt.gz_9.txt.gz") do io
for line in eachline(io)
expr, p = parse_infix(line, varnames, paramnames)
push!(exprs, expr)
push!(parameters, randn(Float32, length(p)))
end
end
interpret_cpu(exprs, X, parameters) # TODO: sufficient to do up to 10 repetitions per expression,
end

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,363 @@
r_k,log_Re,target
507,4.114,0.456
507,4.23,0.438
507,4.322,0.417
507,4.362,0.407
507,4.362,0.403
507,4.462,0.381
507,4.491,0.38
507,4.532,0.366
507,4.568,0.365
507,4.591,0.356
507,4.623,0.347
507,4.672,0.333
507,4.69,0.324
507,4.716,0.32
507,4.763,0.307
507,4.806,0.303
507,4.851,0.292
507,4.898,0.286
507,4.94,0.278
507,4.973,0.274
507,5.009,0.274
507,5.025,0.272
507,5.049,0.27
507,5.1,0.262
507,5.143,0.26
507,5.199,0.255
507,5.236,0.253
507,5.27,0.255
507,5.281,0.253
507,5.303,0.25
507,5.326,0.252
507,5.377,0.255
507,5.43,0.253
507,5.493,0.258
507,5.534,0.26
507,5.574,0.262
507,5.608,0.29
507,5.63,0.272
507,5.668,0.272
507,5.709,0.272
507,5.756,0.278
507,5.792,0.279
507,5.833,0.283
507,5.94,0.286
507,5.965,0.288
507,5.929,0.289
507,5.954,0.288
507,5.987,0.286
252,4.21,0.4506
252,4.279,0.4349
252,4.465,0.3808
252,4.507,0.3636
252,4.549,0.3579
252,4.597,0.3562
252,4.644,0.3434
252,4.778,0.3257
252,4.82,0.3282
252,4.916,0.3222
252,4.987,0.3197
252,5.057,0.321
252,5.1,0.3228
252,5.173,0.3197
252,5.21,0.3276
252,5.283,0.3322
252,5.366,0.3416
252,5.494,0.3504
252,5.58,0.3562
252,5.623,0.3602
252,5.702,0.3636
252,4.708,0.3371
252,5.305,0.3328
252,5.544,0.3562
252,5.787,0.3661
252,4.748,0.3335
252,4.869,0.3228
252,4.954,0.321
252,5.134,0.321
252,5.255,0.3294
252,5.415,0.3434
252,5.58,0.3551
252,5.748,0.3608
252,5.845,0.3666
252,5.881,0.3688
252,5.924,0.3727
252,5.967,0.3705
252,5.991,0.3716
60,3.653,0.593
60,3.7,0.577
60,3.74,0.571
60,3.785,0.56
60,3.851,0.544
60,3.869,0.531
60,3.909,0.512
60,3.949,0.512
60,3.996,0.507
60,4.057,0.494
60,4.09,0.49
60,4.161,0.494
60,4.236,0.487
60,4.29,0.487
60,4.391,0.481
60,4.412,0.489
60,4.512,0.49
60,4.54,0.487
60,4.553,0.498
60,4.58,0.493
60,4.609,0.507
60,4.654,0.504
60,4.665,0.507
60,4.699,0.509
60,4.74,0.517
60,4.769,0.52
60,4.813,0.528
60,4.849,0.526
60,4.93,0.543
60,4.954,0.534
60,5.034,0.543
60,5.155,0.543
60,5.083,0.545
60,5.185,0.55
60,5.231,0.537
60,4.875,0.535
60,4.924,0.534
60,4.954,0.542
60,5.052,0.535
60,5.033,0.54
60,5.13,0.545
60,5.17,0.55
60,5.196,0.547
60,5.23,0.568
60,5.258,0.551
60,5.283,0.555
60,5.312,0.551
60,5.35,0.555
60,5.408,0.55
60,5.47,0.555
60,5.497,0.543
60,5.515,0.551
60,5.549,0.55
60,5.554,0.558
60,5.575,0.551
60,5.6,0.55
60,5.621,0.56
60,5.625,0.543
60,5.641,0.543
60,5.655,0.55
60,5.659,0.551
60,5.668,0.56
60,5.691,0.553
60,5.714,0.551
60,5.748,0.558
60,5.757,0.55
60,5.789,0.551
60,5.836,0.547
60,5.865,0.555
60,5.914,0.553
60,5.916,0.55
60,5.945,0.551
60,5.962,0.555
15,3.77,0.696
15,3.82,0.699
15,3.855,0.707
15,3.905,0.712
15,3.955,0.717
15,4,0.73
15,4.041,0.734
15,4.076,0.736
15,4.079,0.744
15,4.114,0.751
15,4.133,0.74
15,4.179,0.744
15,4.196,0.754
15,4.27,0.76
15,4.29,0.756
15,4.314,0.769
15,4.34,0.763
15,4.366,0.778
15,4.386,0.772
15,4.41,0.772
15,4.425,0.782
15,4.466,0.785
15,4.52,0.78
15,4.59,0.781
15,4.63,0.777
15,4.725,0.78
15,4.811,0.781
15,4.865,0.777
15,4.885,0.776
15,4.965,0.779
15,5,0.781
15,5.042,0.78
15,5.098,0.781
15,5.155,0.778
15,5.179,0.781
15,5.285,0.779
15,4.44,0.775
15,4.5,0.777
15,4.54,0.778
15,4.596,0.78
15,4.685,0.781
15,4.722,0.777
15,4.845,0.775
15,4.869,0.778
15,4.929,0.78
15,4.949,0.779
15,5.002,0.777
15,5.005,0.775
15,5.097,0.778
15,5.139,0.783
15,5.156,0.784
15,5.22,0.777
15,5.236,0.78
15,5.31,0.778
15,5.36,0.775
15,5.41,0.78
15,5.446,0.78
15,5.455,0.777
15,5.515,0.781
15,5.567,0.778
15,5.613,0.78
15,5.69,0.784
15,5.834,0.781
15,5.882,0.777
15,5.959,0.778
15,6.008,0.78
15,5.793,0.78
15,5.857,0.777
15,5.93,0.778
15,5.987,0.78
126,3.63,0.594
126,3.675,0.588
126,3.715,0.576
126,3.76,0.566
126,3.81,0.552
126,3.833,0.564
126,3.895,0.532
126,3.925,0.515
126,3.95,0.503
126,3.965,0.498
126,4.015,0.491
126,4.111,0.471
126,4.196,0.451
126,4.265,0.435
126,4.33,0.424
126,4.386,0.415
126,4.425,0.412
126,4.47,0.4
126,4.496,0.396
126,4.511,0.4
126,4.55,0.393
126,4.62,0.392
126,4.697,0.391
126,4.76,0.4
126,4.82,0.403
126,4.91,0.408
126,4.985,0.414
126,5.057,0.422
126,5.121,0.424
126,5.164,0.43
126,5.591,0.45
126,5.616,0.453
126,5.655,0.447
126,5.675,0.45
126,5.708,0.445
126,5.736,0.452
126,5.756,0.445
126,5.775,0.445
126,5.798,0.45
126,5.831,0.45
126,5.835,0.446
126,5.874,0.45
126,5.894,0.447
126,5.935,0.45
126,5.961,0.444
126,5.97,0.449
126,5.987,0.447
126,4.95,0.43
126,5.049,0.432
126,5.021,0.415
126,5.1,0.422
126,5.13,0.422
126,5.179,0.43
126,5.196,0.43
126,5.225,0.435
126,5.225,0.43
126,5.25,0.436
126,5.274,0.438
126,5.29,0.438
126,5.31,0.436
126,5.33,0.439
126,5.35,0.439
126,5.366,0.444
126,5.393,0.444
126,5.423,0.446
126,5.432,0.447
126,5.455,0.45
126,5.476,0.452
126,5.501,0.447
126,5.525,0.447
126,5.56,0.45
30.6,3.672,0.592
30.6,3.708,0.59
30.6,3.748,0.592
30.6,3.763,0.597
30.6,3.785,0.583
30.6,3.826,0.585
30.6,3.869,0.596
30.6,3.881,0.578
30.6,3.929,0.578
30.6,3.935,0.583
30.6,3.978,0.578
30.6,4.009,0.585
30.6,4.049,0.583
30.6,4.079,0.592
30.6,4.124,0.59
30.6,4.13,0.599
30.6,4.19,0.599
30.6,4.27,0.609
30.6,4.29,0.618
30.6,4.309,0.612
30.6,4.584,0.639
30.6,4.653,0.644
30.6,4.799,0.647
30.6,4.9,0.656
30.6,4.965,0.656
30.6,5.029,0.652
30.6,5.068,0.65
30.6,5.134,0.65
30.6,5.176,0.65
30.6,4.425,0.637
30.6,4.44,0.63
30.6,4.56,0.637
30.6,4.636,0.647
30.6,4.74,0.654
30.6,4.83,0.654
30.6,4.855,0.661
30.6,4.99,0.657
30.6,5.1,0.652
30.6,5.24,0.657
30.6,5.275,0.657
30.6,5.323,0.647
30.6,5.473,0.657
30.6,5.655,0.652
30.6,4.934,0.656
30.6,5.068,0.657
30.6,5.17,0.659
30.6,5.223,0.656
30.6,5.255,0.652
30.6,5.342,0.657
30.6,5.344,0.657
30.6,5.394,0.659
30.6,5.428,0.659
30.6,5.444,0.661
30.6,5.516,0.657
30.6,5.541,0.659
30.6,5.559,0.657
30.6,5.776,0.659
30.6,5.81,0.659
30.6,5.863,0.657
30.6,5.916,0.659
30.6,5.962,0.65
30.6,6,0.659
1 r_k log_Re target
2 507 4.114 0.456
3 507 4.23 0.438
4 507 4.322 0.417
5 507 4.362 0.407
6 507 4.362 0.403
7 507 4.462 0.381
8 507 4.491 0.38
9 507 4.532 0.366
10 507 4.568 0.365
11 507 4.591 0.356
12 507 4.623 0.347
13 507 4.672 0.333
14 507 4.69 0.324
15 507 4.716 0.32
16 507 4.763 0.307
17 507 4.806 0.303
18 507 4.851 0.292
19 507 4.898 0.286
20 507 4.94 0.278
21 507 4.973 0.274
22 507 5.009 0.274
23 507 5.025 0.272
24 507 5.049 0.27
25 507 5.1 0.262
26 507 5.143 0.26
27 507 5.199 0.255
28 507 5.236 0.253
29 507 5.27 0.255
30 507 5.281 0.253
31 507 5.303 0.25
32 507 5.326 0.252
33 507 5.377 0.255
34 507 5.43 0.253
35 507 5.493 0.258
36 507 5.534 0.26
37 507 5.574 0.262
38 507 5.608 0.29
39 507 5.63 0.272
40 507 5.668 0.272
41 507 5.709 0.272
42 507 5.756 0.278
43 507 5.792 0.279
44 507 5.833 0.283
45 507 5.94 0.286
46 507 5.965 0.288
47 507 5.929 0.289
48 507 5.954 0.288
49 507 5.987 0.286
50 252 4.21 0.4506
51 252 4.279 0.4349
52 252 4.465 0.3808
53 252 4.507 0.3636
54 252 4.549 0.3579
55 252 4.597 0.3562
56 252 4.644 0.3434
57 252 4.778 0.3257
58 252 4.82 0.3282
59 252 4.916 0.3222
60 252 4.987 0.3197
61 252 5.057 0.321
62 252 5.1 0.3228
63 252 5.173 0.3197
64 252 5.21 0.3276
65 252 5.283 0.3322
66 252 5.366 0.3416
67 252 5.494 0.3504
68 252 5.58 0.3562
69 252 5.623 0.3602
70 252 5.702 0.3636
71 252 4.708 0.3371
72 252 5.305 0.3328
73 252 5.544 0.3562
74 252 5.787 0.3661
75 252 4.748 0.3335
76 252 4.869 0.3228
77 252 4.954 0.321
78 252 5.134 0.321
79 252 5.255 0.3294
80 252 5.415 0.3434
81 252 5.58 0.3551
82 252 5.748 0.3608
83 252 5.845 0.3666
84 252 5.881 0.3688
85 252 5.924 0.3727
86 252 5.967 0.3705
87 252 5.991 0.3716
88 60 3.653 0.593
89 60 3.7 0.577
90 60 3.74 0.571
91 60 3.785 0.56
92 60 3.851 0.544
93 60 3.869 0.531
94 60 3.909 0.512
95 60 3.949 0.512
96 60 3.996 0.507
97 60 4.057 0.494
98 60 4.09 0.49
99 60 4.161 0.494
100 60 4.236 0.487
101 60 4.29 0.487
102 60 4.391 0.481
103 60 4.412 0.489
104 60 4.512 0.49
105 60 4.54 0.487
106 60 4.553 0.498
107 60 4.58 0.493
108 60 4.609 0.507
109 60 4.654 0.504
110 60 4.665 0.507
111 60 4.699 0.509
112 60 4.74 0.517
113 60 4.769 0.52
114 60 4.813 0.528
115 60 4.849 0.526
116 60 4.93 0.543
117 60 4.954 0.534
118 60 5.034 0.543
119 60 5.155 0.543
120 60 5.083 0.545
121 60 5.185 0.55
122 60 5.231 0.537
123 60 4.875 0.535
124 60 4.924 0.534
125 60 4.954 0.542
126 60 5.052 0.535
127 60 5.033 0.54
128 60 5.13 0.545
129 60 5.17 0.55
130 60 5.196 0.547
131 60 5.23 0.568
132 60 5.258 0.551
133 60 5.283 0.555
134 60 5.312 0.551
135 60 5.35 0.555
136 60 5.408 0.55
137 60 5.47 0.555
138 60 5.497 0.543
139 60 5.515 0.551
140 60 5.549 0.55
141 60 5.554 0.558
142 60 5.575 0.551
143 60 5.6 0.55
144 60 5.621 0.56
145 60 5.625 0.543
146 60 5.641 0.543
147 60 5.655 0.55
148 60 5.659 0.551
149 60 5.668 0.56
150 60 5.691 0.553
151 60 5.714 0.551
152 60 5.748 0.558
153 60 5.757 0.55
154 60 5.789 0.551
155 60 5.836 0.547
156 60 5.865 0.555
157 60 5.914 0.553
158 60 5.916 0.55
159 60 5.945 0.551
160 60 5.962 0.555
161 15 3.77 0.696
162 15 3.82 0.699
163 15 3.855 0.707
164 15 3.905 0.712
165 15 3.955 0.717
166 15 4 0.73
167 15 4.041 0.734
168 15 4.076 0.736
169 15 4.079 0.744
170 15 4.114 0.751
171 15 4.133 0.74
172 15 4.179 0.744
173 15 4.196 0.754
174 15 4.27 0.76
175 15 4.29 0.756
176 15 4.314 0.769
177 15 4.34 0.763
178 15 4.366 0.778
179 15 4.386 0.772
180 15 4.41 0.772
181 15 4.425 0.782
182 15 4.466 0.785
183 15 4.52 0.78
184 15 4.59 0.781
185 15 4.63 0.777
186 15 4.725 0.78
187 15 4.811 0.781
188 15 4.865 0.777
189 15 4.885 0.776
190 15 4.965 0.779
191 15 5 0.781
192 15 5.042 0.78
193 15 5.098 0.781
194 15 5.155 0.778
195 15 5.179 0.781
196 15 5.285 0.779
197 15 4.44 0.775
198 15 4.5 0.777
199 15 4.54 0.778
200 15 4.596 0.78
201 15 4.685 0.781
202 15 4.722 0.777
203 15 4.845 0.775
204 15 4.869 0.778
205 15 4.929 0.78
206 15 4.949 0.779
207 15 5.002 0.777
208 15 5.005 0.775
209 15 5.097 0.778
210 15 5.139 0.783
211 15 5.156 0.784
212 15 5.22 0.777
213 15 5.236 0.78
214 15 5.31 0.778
215 15 5.36 0.775
216 15 5.41 0.78
217 15 5.446 0.78
218 15 5.455 0.777
219 15 5.515 0.781
220 15 5.567 0.778
221 15 5.613 0.78
222 15 5.69 0.784
223 15 5.834 0.781
224 15 5.882 0.777
225 15 5.959 0.778
226 15 6.008 0.78
227 15 5.793 0.78
228 15 5.857 0.777
229 15 5.93 0.778
230 15 5.987 0.78
231 126 3.63 0.594
232 126 3.675 0.588
233 126 3.715 0.576
234 126 3.76 0.566
235 126 3.81 0.552
236 126 3.833 0.564
237 126 3.895 0.532
238 126 3.925 0.515
239 126 3.95 0.503
240 126 3.965 0.498
241 126 4.015 0.491
242 126 4.111 0.471
243 126 4.196 0.451
244 126 4.265 0.435
245 126 4.33 0.424
246 126 4.386 0.415
247 126 4.425 0.412
248 126 4.47 0.4
249 126 4.496 0.396
250 126 4.511 0.4
251 126 4.55 0.393
252 126 4.62 0.392
253 126 4.697 0.391
254 126 4.76 0.4
255 126 4.82 0.403
256 126 4.91 0.408
257 126 4.985 0.414
258 126 5.057 0.422
259 126 5.121 0.424
260 126 5.164 0.43
261 126 5.591 0.45
262 126 5.616 0.453
263 126 5.655 0.447
264 126 5.675 0.45
265 126 5.708 0.445
266 126 5.736 0.452
267 126 5.756 0.445
268 126 5.775 0.445
269 126 5.798 0.45
270 126 5.831 0.45
271 126 5.835 0.446
272 126 5.874 0.45
273 126 5.894 0.447
274 126 5.935 0.45
275 126 5.961 0.444
276 126 5.97 0.449
277 126 5.987 0.447
278 126 4.95 0.43
279 126 5.049 0.432
280 126 5.021 0.415
281 126 5.1 0.422
282 126 5.13 0.422
283 126 5.179 0.43
284 126 5.196 0.43
285 126 5.225 0.435
286 126 5.225 0.43
287 126 5.25 0.436
288 126 5.274 0.438
289 126 5.29 0.438
290 126 5.31 0.436
291 126 5.33 0.439
292 126 5.35 0.439
293 126 5.366 0.444
294 126 5.393 0.444
295 126 5.423 0.446
296 126 5.432 0.447
297 126 5.455 0.45
298 126 5.476 0.452
299 126 5.501 0.447
300 126 5.525 0.447
301 126 5.56 0.45
302 30.6 3.672 0.592
303 30.6 3.708 0.59
304 30.6 3.748 0.592
305 30.6 3.763 0.597
306 30.6 3.785 0.583
307 30.6 3.826 0.585
308 30.6 3.869 0.596
309 30.6 3.881 0.578
310 30.6 3.929 0.578
311 30.6 3.935 0.583
312 30.6 3.978 0.578
313 30.6 4.009 0.585
314 30.6 4.049 0.583
315 30.6 4.079 0.592
316 30.6 4.124 0.59
317 30.6 4.13 0.599
318 30.6 4.19 0.599
319 30.6 4.27 0.609
320 30.6 4.29 0.618
321 30.6 4.309 0.612
322 30.6 4.584 0.639
323 30.6 4.653 0.644
324 30.6 4.799 0.647
325 30.6 4.9 0.656
326 30.6 4.965 0.656
327 30.6 5.029 0.652
328 30.6 5.068 0.65
329 30.6 5.134 0.65
330 30.6 5.176 0.65
331 30.6 4.425 0.637
332 30.6 4.44 0.63
333 30.6 4.56 0.637
334 30.6 4.636 0.647
335 30.6 4.74 0.654
336 30.6 4.83 0.654
337 30.6 4.855 0.661
338 30.6 4.99 0.657
339 30.6 5.1 0.652
340 30.6 5.24 0.657
341 30.6 5.275 0.657
342 30.6 5.323 0.647
343 30.6 5.473 0.657
344 30.6 5.655 0.652
345 30.6 4.934 0.656
346 30.6 5.068 0.657
347 30.6 5.17 0.659
348 30.6 5.223 0.656
349 30.6 5.255 0.652
350 30.6 5.342 0.657
351 30.6 5.344 0.657
352 30.6 5.394 0.659
353 30.6 5.428 0.659
354 30.6 5.444 0.661
355 30.6 5.516 0.657
356 30.6 5.541 0.659
357 30.6 5.559 0.657
358 30.6 5.776 0.659
359 30.6 5.81 0.659
360 30.6 5.863 0.657
361 30.6 5.916 0.659
362 30.6 5.962 0.65
363 30.6 6 0.659

294
package/test/parser.jl Normal file
View File

@ -0,0 +1,294 @@
## Parser for (ESR) expressions in infix format
mutable struct Parser
const str::AbstractString # string to be parsed
pos::Int64 # current position in string
sy::Union{AbstractString,Nothing} # current lookahead symbol
const pSy::Symbol
const xSy::Symbol
const varnames::Vector{<:AbstractString}
const paramnames::Vector{<:AbstractString}
const coeff::Vector{Float64}
const numbers_as_parameters::Bool
const integers_as_constants::Bool # TODO rename and implement as rationals_as_constants
# The kwparam numbers_as_parameters allows to include coefficient values directly in the expression and the values are parsed as parameters
# In this mode the suffix 'f' allows to mark constants. E.g. 3 * x ^ 2f would create the parameterized expression a0*x^2 with 2 a constant value.
function Parser(str::AbstractString, varnames::Vector{<:AbstractString}, paramnames::Vector{<:AbstractString}; numbers_as_parameters=false, integers_as_constants=false)
if numbers_as_parameters && length(paramnames) > 0
error("the parser does not support paramnames when numbers_as_parameters=true")
end
if !numbers_as_parameters && integers_as_constants
error("Set numbers_as_parameters=true to parse integers_as_constants")
end
p = new(lowercase(str), 1, nothing, :p, :x, varnames, paramnames, Vector{Float64}(), numbers_as_parameters, integers_as_constants)
next_symbol!(p)
return p;
end
end
# recursive descent parser
# scanner is also defined in this file
# LL(1) grammar:
# G(Expr):
# Expr = Term { ('+' | '-') Term }
# Term = Fact { ('*' | '/') Fact }
# Fact = { '+' | '-' }
# (ident | number | parameter
# | '(' Expr ')'
# | ident ParamList // function call
# ) [ ('**' | '^') Fact ]
# ParamList = '(' Expr { ',' Expr } ')'
# scanner
function parse_infix(exprStr::AbstractString, varnames::Vector{<:AbstractString}, paramnames::Vector{<:AbstractString};
numbers_as_parameters = false, integers_as_constants = false)::Tuple{Expr, Vector{Float64}}
parser = Parser(exprStr, varnames, paramnames;
numbers_as_parameters = numbers_as_parameters, integers_as_constants = integers_as_constants)
body = parse_expr!(parser)
expr = Expr(:->, Expr(:tuple, :x, :p), body) # :((x,p) -> $body)
(expr, parser.coeff)
end
function parse_expr!(p::Parser)
t1 = parse_term!(p)
while p.sy == "+" || p.sy == "-"
if p.sy == "+"
next_symbol!(p)
t2 = parse_term!(p)
t1 = :($t1 + $t2) # add_simpl(t1, t2)
else
next_symbol!(p)
t2 = parse_term!(p)
t1 = :($t1 - $t2) # sub_simpl(t1, t2)
end
end
return t1
end
function parse_term!(p::Parser)
f1 = parse_factor!(p)
while p.sy == "*" || p.sy == "/"
if p.sy == "*"
next_symbol!(p)
f2 = parse_factor!(p)
f1 = :($f1 * $f2) # mul_simpl(f1, f2)
else
next_symbol!(p)
f2 = parse_factor!(p)
f1 = :($f1 / $f2) # div_simpl(f1, f2)
end
end
return f1
end
# Fact = { '+' | '-' }
# (constant | parameter
# | '(' Expr ')'
# | ident [ ParamList ] variable or function call
# ) [ ('**' | '^') Fact ]
# ParamList = '(' Expr { ',' Expr } ')'
function parse_factor!(p::Parser)
sign = 1.0
while p.sy == "+" || p.sy == "-"
if p.sy == "-"
sign = sign * -1.0
end
next_symbol!(p)
end
factor = 1.0
if isident(p.sy)
ident = p.sy
next_symbol!(p)
if p.sy == "("
parameters = parse_paramlist!(p)
if ident == "sqr"
# convert sqr(x) call to x**2 (so that we don't have to update the interpreters)
factor = Expr(:call, func_symbol("pow"), parameters..., 2.0)
else
factor = Expr(:call, func_symbol(ident), parameters...)
end
else
idx = findfirst(p -> p==ident, p.varnames)
if !isnothing(idx)
factor = Expr(:ref, p.xSy, idx)
elseif !p.numbers_as_parameters # only if paramnames are given
idx = findfirst(p -> p==ident, p.paramnames)
# replace parameter variables with access to coefficient vector (initialized to zero)
if !isnothing(idx)
factor = Expr(:ref, p.pSy, idx)
push!(p.coeff, 0.0)
else
error("undefined symbol $ident")
end
else
error("undefined variable $ident")
end
end
elseif isnumber(p.sy)
if p.numbers_as_parameters
numStr = p.sy
val = parse(Float64, numStr)
next_symbol!(p)
if p.sy == "f"
# constant
factor = sign * val # numbers are parsed without sign (if we parsed a sign above then we can include this in the constant here)
sign = 1.0
next_symbol!(p)
elseif p.integers_as_constants && isinteger(val)
# integers are parsed as constants
factor = sign * val # numbers are parsed without sign (if we parsed a sign above then we can include this in the constant here)
sign = 1.0
else
# parameter
factor = new_param!(p, sign * val)
sign = 1.0
end
else
# otherwise all numbers are parsed as constants
numStr = p.sy
next_symbol!(p)
if p.sy == "//"
num = parse(Int64, numStr)
next_symbol!(p)
denom = parse(Int64, p.sy)
val = num // denom
next_symbol!(p)
else
val = parse(Float64, numStr)
end
factor = sign * val
sign = 1.0
end
elseif p.sy == "("
next_symbol!(p)
factor = parse_expr!(p)
expect_and_next!(p, ")")
else
error("cannot parse expression")
end
if p.sy == "**" || p.sy == "^"
next_symbol!(p)
exponent = parse_factor!(p)
factor = :($factor ^ $exponent) # pow_simpl(factor, exponent)
end
if sign == -1
neg_simpl(factor)
else
factor
end
end
function parse_paramlist!(p::Parser)::Vector
parameters = Vector()
expect_and_next!(p, "(")
push!(parameters, parse_expr!(p))
while p.sy == ","
next_symbol!(p)
push!(parameters, parse_expr!(p))
end
expect_and_next!(p, ")")
return parameters
end
function expect_and_next!(p::Parser, expectedSy::AbstractString)
if p.sy != expectedSy
error("expected: $(expectedSy) at column $(p.pos)")
else
next_symbol!(p)
end
end
function new_param!(p::Parser, val::Float64)::Expr
push!(p.coeff, val)
return Expr(:ref, p.pSy, length(p.coeff))
end
function isident(s::AbstractString)::Bool
return s != "nan" && s != "inf" && !isnothing(match(r"^[_a-zA-Z][_a-zA-Z0-9]*$", s))
end
function isnumber(s::AbstractString)::Bool
return !isnothing(tryparse(Float64, s))
end
function variable_index(p::Parser, str::AbstractString)
return findfirst(s->s==str, p.varNames)
end
function func_symbol(id::AbstractString)
if id == "pow"
return :^;
else
return Symbol(id)
end
end
function next_symbol!(p::Parser)
s = p.str
pos = p.pos
# skip whitespace
while pos <= length(s) && isspace(s[pos])
pos += 1
end
if pos > length(s)
p.sy = nothing
p.pos = pos
return
end
if isdigit(s[pos]) # numbers
m = match(r"(\d+([.]\d*)?([eE][+-]?\d+)?|[.]\d+([eE][+-]?\d+)?)", s, pos) # match floating point number
pos += length(m[1]) # get the whole match
p.sy = m[1]
elseif isletter(s[pos]) # identifiers
idStr = string(s[pos])
pos += 1
while pos <= length(s) && (isdigit(s[pos]) || isletter(s[pos]) || s[pos] == '_')
idStr = idStr * s[pos]
pos += 1
end
p.sy = idStr
elseif s[pos] == '*'
pos += 1
p.sy = "*"
if s[pos] == '*'
p.sy = "**"
pos += 1
end
elseif s[pos] == '/'
pos += 1
p.sy = "/"
if s[pos] == '/'
p.sy = "//"
pos += 1
end
else
p.sy = string(s[pos]) # single character symbol
pos += 1
end
p.pos = pos
# println((p.sy, pos)) # for debugging
end