summaryrefslogtreecommitdiff
path: root/tcl/tests/parseExpr.test
blob: 9d0e034bbb7bed3e85c253aff90c796c3ffbc506 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
# This file contains a collection of tests for the procedures in the
# file tclParseExpr.c.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id$

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

# Note that the Tcl expression parser (tclParseExpr.c) does not check
# the semantic validity of the expressions it parses. It does not check,
# for example, that a math function actually exists, or that the operands
# of "<<" are integers.

if {[info commands testexprparser] == {}} {
    puts "This application hasn't been compiled with the \"testexprparser\""
    puts "command, so I can't test the Tcl expression parser."
    ::tcltest::cleanupTests
    return 
}

# Some tests only work if wide integers (>32bit) are not found to be
# integers at all.
set ::tcltest::testConstraints(wideIntegerUnparsed) \
	[expr {-1 == 0xffffffff}]

test parseExpr-1.1 {Tcl_ParseExpr procedure, computing string length} {
    testexprparser [bytestring "1+2\0 +3"] -1
} {- {} 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
test parseExpr-1.2 {Tcl_ParseExpr procedure, computing string length} {
    testexprparser "1  + 2" -1
} {- {} 0 subexpr {1  + 2} 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
test parseExpr-1.3 {Tcl_ParseExpr procedure, error getting initial lexeme} {wideIntegerUnparsed} {
    list [catch {testexprparser {12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-1.4 {Tcl_ParseExpr procedure, error in conditional expression} {
    list [catch {testexprparser {foo+} -1} msg] $msg
} {1 {syntax error in expression "foo+": variable references require preceding $}}
test parseExpr-1.5 {Tcl_ParseExpr procedure, lexemes after the expression} {
    list [catch {testexprparser {1+2 345} -1} msg] $msg
} {1 {syntax error in expression "1+2 345": extra tokens at end of expression}}

test parseExpr-2.1 {ParseCondExpr procedure, valid test subexpr} {
    testexprparser {2>3? 1 : 0} -1
} {- {} 0 subexpr {2>3? 1 : 0} 11 operator ? 0 subexpr 2>3 5 operator > 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-2.2 {ParseCondExpr procedure, error in test subexpr} {
    list [catch {testexprparser {0 || foo} -1} msg] $msg
} {1 {syntax error in expression "0 || foo": variable references require preceding $}}
test parseExpr-2.3 {ParseCondExpr procedure, next lexeme isn't "?"} {
    testexprparser {1+2} -1
} {- {} 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
test parseExpr-2.4 {ParseCondExpr procedure, next lexeme is "?"} {
    testexprparser {1+2 ? 3 : 4} -1
} {- {} 0 subexpr {1+2 ? 3 : 4} 11 operator ? 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-2.5 {ParseCondExpr procedure, bad lexeme after "?"} {wideIntegerUnparsed} {
    list [catch {testexprparser {1+2 ? 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-2.6 {ParseCondExpr procedure, valid "then" subexpression} {
    testexprparser {1? 3 : 4} -1
} {- {} 0 subexpr {1? 3 : 4} 7 operator ? 0 subexpr 1 1 text 1 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-2.7 {ParseCondExpr procedure, error in "then" subexpression} {
    list [catch {testexprparser {1? fred : martha} -1} msg] $msg
} {1 {syntax error in expression "1? fred : martha": variable references require preceding $}}
test parseExpr-2.8 {ParseCondExpr procedure, lexeme after "then" subexpr isn't ":"} {
    list [catch {testexprparser {1? 2 martha 3} -1} msg] $msg
} {1 {syntax error in expression "1? 2 martha 3": missing colon from ternary conditional}}
test parseExpr-2.9 {ParseCondExpr procedure, valid "else" subexpression} {
    testexprparser {27||3? 3 : 4&&9} -1
} {- {} 0 subexpr {27||3? 3 : 4&&9} 15 operator ? 0 subexpr 27||3 5 operator || 0 subexpr 27 1 text 27 0 subexpr 3 1 text 3 0 subexpr 3 1 text 3 0 subexpr 4&&9 5 operator && 0 subexpr 4 1 text 4 0 subexpr 9 1 text 9 0 {}}
test parseExpr-2.10 {ParseCondExpr procedure, error in "else" subexpression} {
    list [catch {testexprparser {1? 2 : martha} -1} msg] $msg
} {1 {syntax error in expression "1? 2 : martha": variable references require preceding $}}

test parseExpr-3.1 {ParseLorExpr procedure, valid logical and subexpr} {
    testexprparser {1&&2 || 3} -1
} {- {} 0 subexpr {1&&2 || 3} 9 operator || 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-3.2 {ParseLorExpr procedure, error in logical and subexpr} {
    list [catch {testexprparser {1&&foo || 3} -1} msg] $msg
} {1 {syntax error in expression "1&&foo || 3": variable references require preceding $}}
test parseExpr-3.3 {ParseLorExpr procedure, next lexeme isn't "||"} {
    testexprparser {1&&2? 1 : 0} -1
} {- {} 0 subexpr {1&&2? 1 : 0} 11 operator ? 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-3.4 {ParseLorExpr procedure, next lexeme is "||"} {
    testexprparser {1&&2 || 3} -1
} {- {} 0 subexpr {1&&2 || 3} 9 operator || 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-3.5 {ParseLorExpr procedure, bad lexeme after "||"} {wideIntegerUnparsed} {
    list [catch {testexprparser {1&&2 || 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-3.6 {ParseLorExpr procedure, valid RHS subexpression} {
    testexprparser {1&&2 || 3 || 4} -1
} {- {} 0 subexpr {1&&2 || 3 || 4} 13 operator || 0 subexpr {1&&2 || 3} 9 operator || 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-3.7 {ParseLorExpr procedure, error in RHS subexpression} {
    list [catch {testexprparser {1&&2 || 3 || martha} -1} msg] $msg
} {1 {syntax error in expression "1&&2 || 3 || martha": variable references require preceding $}}

test parseExpr-4.1 {ParseLandExpr procedure, valid LHS "|" subexpr} {
    testexprparser {1|2 && 3} -1
} {- {} 0 subexpr {1|2 && 3} 9 operator && 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-4.2 {ParseLandExpr procedure, error in LHS "|" subexpr} {
    list [catch {testexprparser {1&&foo && 3} -1} msg] $msg
} {1 {syntax error in expression "1&&foo && 3": variable references require preceding $}}
test parseExpr-4.3 {ParseLandExpr procedure, next lexeme isn't "&&"} {
    testexprparser {1|2? 1 : 0} -1
} {- {} 0 subexpr {1|2? 1 : 0} 11 operator ? 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-4.4 {ParseLandExpr procedure, next lexeme is "&&"} {
    testexprparser {1|2 && 3} -1
} {- {} 0 subexpr {1|2 && 3} 9 operator && 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-4.5 {ParseLandExpr procedure, bad lexeme after "&&"} {wideIntegerUnparsed} {
    list [catch {testexprparser {1|2 && 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-4.6 {ParseLandExpr procedure, valid RHS subexpression} {
    testexprparser {1|2 && 3 && 4} -1
} {- {} 0 subexpr {1|2 && 3 && 4} 13 operator && 0 subexpr {1|2 && 3} 9 operator && 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-4.7 {ParseLandExpr procedure, error in RHS subexpression} {
    list [catch {testexprparser {1|2 && 3 && martha} -1} msg] $msg
} {1 {syntax error in expression "1|2 && 3 && martha": variable references require preceding $}}

test parseExpr-5.1 {ParseBitOrExpr procedure, valid LHS "^" subexpr} {
    testexprparser {1^2 | 3} -1
} {- {} 0 subexpr {1^2 | 3} 9 operator | 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-5.2 {ParseBitOrExpr procedure, error in LHS "^" subexpr} {
    list [catch {testexprparser {1|foo | 3} -1} msg] $msg
} {1 {syntax error in expression "1|foo | 3": variable references require preceding $}}
test parseExpr-5.3 {ParseBitOrExpr procedure, next lexeme isn't "|"} {
    testexprparser {1^2? 1 : 0} -1
} {- {} 0 subexpr {1^2? 1 : 0} 11 operator ? 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-5.4 {ParseBitOrExpr procedure, next lexeme is "|"} {
    testexprparser {1^2 | 3} -1
} {- {} 0 subexpr {1^2 | 3} 9 operator | 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-5.5 {ParseBitOrExpr procedure, bad lexeme after "|"} {wideIntegerUnparsed} {
    list [catch {testexprparser {1^2 | 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-5.6 {ParseBitOrExpr procedure, valid RHS subexpression} {
    testexprparser {1^2 | 3 | 4} -1
} {- {} 0 subexpr {1^2 | 3 | 4} 13 operator | 0 subexpr {1^2 | 3} 9 operator | 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-5.7 {ParseBitOrExpr procedure, error in RHS subexpression} {
    list [catch {testexprparser {1^2 | 3 | martha} -1} msg] $msg
} {1 {syntax error in expression "1^2 | 3 | martha": variable references require preceding $}}

test parseExpr-6.1 {ParseBitXorExpr procedure, valid LHS "&" subexpr} {
    testexprparser {1&2 ^ 3} -1
} {- {} 0 subexpr {1&2 ^ 3} 9 operator ^ 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-6.2 {ParseBitXorExpr procedure, error in LHS "&" subexpr} {
    list [catch {testexprparser {1^foo ^ 3} -1} msg] $msg
} {1 {syntax error in expression "1^foo ^ 3": variable references require preceding $}}
test parseExpr-6.3 {ParseBitXorExpr procedure, next lexeme isn't "^"} {
    testexprparser {1&2? 1 : 0} -1
} {- {} 0 subexpr {1&2? 1 : 0} 11 operator ? 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-6.4 {ParseBitXorExpr procedure, next lexeme is "^"} {
    testexprparser {1&2 ^ 3} -1
} {- {} 0 subexpr {1&2 ^ 3} 9 operator ^ 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-6.5 {ParseBitXorExpr procedure, bad lexeme after "^"} {wideIntegerUnparsed} {
    list [catch {testexprparser {1&2 ^ 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-6.6 {ParseBitXorExpr procedure, valid RHS subexpression} {
    testexprparser {1&2 ^ 3 ^ 4} -1
} {- {} 0 subexpr {1&2 ^ 3 ^ 4} 13 operator ^ 0 subexpr {1&2 ^ 3} 9 operator ^ 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-6.7 {ParseBitXorExpr procedure, error in RHS subexpression} {
    list [catch {testexprparser {1&2 ^ 3 ^ martha} -1} msg] $msg
} {1 {syntax error in expression "1&2 ^ 3 ^ martha": variable references require preceding $}}

test parseExpr-7.1 {ParseBitAndExpr procedure, valid LHS equality subexpr} {
    testexprparser {1==2 & 3} -1
} {- {} 0 subexpr {1==2 & 3} 9 operator & 0 subexpr 1==2 5 operator == 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-7.2 {ParseBitAndExpr procedure, error in LHS equality subexpr} {
    list [catch {testexprparser {1!=foo & 3} -1} msg] $msg
} {1 {syntax error in expression "1!=foo & 3": variable references require preceding $}}
test parseExpr-7.3 {ParseBitAndExpr procedure, next lexeme isn't "&"} {
    testexprparser {1==2? 1 : 0} -1
} {- {} 0 subexpr {1==2? 1 : 0} 11 operator ? 0 subexpr 1==2 5 operator == 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-7.4 {ParseBitAndExpr procedure, next lexeme is "&"} {
    testexprparser {1>2 & 3} -1
} {- {} 0 subexpr {1>2 & 3} 9 operator & 0 subexpr 1>2 5 operator > 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-7.5 {ParseBitAndExpr procedure, bad lexeme after "&"} {wideIntegerUnparsed} {
    list [catch {testexprparser {1==2 & 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-7.6 {ParseBitAndExpr procedure, valid RHS subexpression} {
    testexprparser {1<2 & 3 & 4} -1
} {- {} 0 subexpr {1<2 & 3 & 4} 13 operator & 0 subexpr {1<2 & 3} 9 operator & 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-7.7 {ParseBitAndExpr procedure, error in RHS subexpression} {
    list [catch {testexprparser {1==2 & 3>2 & martha} -1} msg] $msg
} {1 {syntax error in expression "1==2 & 3>2 & martha": variable references require preceding $}}

test parseExpr-8.1 {ParseEqualityExpr procedure, valid LHS relational subexpr} {
    testexprparser {1<2 == 3} -1
} {- {} 0 subexpr {1<2 == 3} 9 operator == 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-8.2 {ParseEqualityExpr procedure, error in LHS relational subexpr} {
    list [catch {testexprparser {1>=foo == 3} -1} msg] $msg
} {1 {syntax error in expression "1>=foo == 3": variable references require preceding $}}
test parseExpr-8.3 {ParseEqualityExpr procedure, next lexeme isn't "==" or "!="} {
    testexprparser {1<2? 1 : 0} -1
} {- {} 0 subexpr {1<2? 1 : 0} 11 operator ? 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-8.4 {ParseEqualityExpr procedure, next lexeme is "==" or "!="} {
    testexprparser {1<2 == 3} -1
} {- {} 0 subexpr {1<2 == 3} 9 operator == 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-8.5 {ParseEqualityExpr procedure, next lexeme is "==" or "!="} {
    testexprparser {1<2 != 3} -1
} {- {} 0 subexpr {1<2 != 3} 9 operator != 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-8.6 {ParseEqualityExpr procedure, bad lexeme after "==" or "!="} {wideIntegerUnparsed} {
    list [catch {testexprparser {1<2 == 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-8.7 {ParseEqualityExpr procedure, valid RHS subexpression} {
    testexprparser {1<2 == 3 == 4} -1
} {- {} 0 subexpr {1<2 == 3 == 4} 13 operator == 0 subexpr {1<2 == 3} 9 operator == 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-8.8 {ParseEqualityExpr procedure, error in RHS subexpression} {
    list [catch {testexprparser {1<2 == 3 != martha} -1} msg] $msg
} {1 {syntax error in expression "1<2 == 3 != martha": variable references require preceding $}}

test parseExpr-9.1 {ParseRelationalExpr procedure, valid LHS shift subexpr} {
    testexprparser {1<<2 < 3} -1
} {- {} 0 subexpr {1<<2 < 3} 9 operator < 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-9.2 {ParseRelationalExpr procedure, error in LHS shift subexpr} {
    list [catch {testexprparser {1>=foo < 3} -1} msg] $msg
} {1 {syntax error in expression "1>=foo < 3": variable references require preceding $}}
test parseExpr-9.3 {ParseRelationalExpr procedure, next lexeme isn't relational op} {
    testexprparser {1<<2? 1 : 0} -1
} {- {} 0 subexpr {1<<2? 1 : 0} 11 operator ? 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-9.4 {ParseRelationalExpr procedure, next lexeme is relational op} {
    testexprparser {1<<2 < 3} -1
} {- {} 0 subexpr {1<<2 < 3} 9 operator < 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-9.5 {ParseRelationalExpr procedure, next lexeme is relational op} {
    testexprparser {1>>2 > 3} -1
} {- {} 0 subexpr {1>>2 > 3} 9 operator > 0 subexpr 1>>2 5 operator >> 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-9.6 {ParseRelationalExpr procedure, next lexeme is relational op} {
    testexprparser {1<<2 <= 3} -1
} {- {} 0 subexpr {1<<2 <= 3} 9 operator <= 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-9.7 {ParseRelationalExpr procedure, next lexeme is relational op} {
    testexprparser {1<<2 >= 3} -1
} {- {} 0 subexpr {1<<2 >= 3} 9 operator >= 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-9.8 {ParseRelationalExpr procedure, bad lexeme after relational op} {wideIntegerUnparsed} {
    list [catch {testexprparser {1<<2 < 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-9.9 {ParseRelationalExpr procedure, valid RHS subexpression} {
    testexprparser {1<<2 < 3 < 4} -1
} {- {} 0 subexpr {1<<2 < 3 < 4} 13 operator < 0 subexpr {1<<2 < 3} 9 operator < 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-9.10 {ParseRelationalExpr procedure, error in RHS subexpression} {
    list [catch {testexprparser {1<<2 < 3 > martha} -1} msg] $msg
} {1 {syntax error in expression "1<<2 < 3 > martha": variable references require preceding $}}

test parseExpr-10.1 {ParseShiftExpr procedure, valid LHS add subexpr} {
    testexprparser {1+2 << 3} -1
} {- {} 0 subexpr {1+2 << 3} 9 operator << 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-10.2 {ParseShiftExpr procedure, error in LHS add subexpr} {
    list [catch {testexprparser {1-foo << 3} -1} msg] $msg
} {1 {syntax error in expression "1-foo << 3": variable references require preceding $}}
test parseExpr-10.3 {ParseShiftExpr procedure, next lexeme isn't "<<" or ">>"} {
    testexprparser {1+2? 1 : 0} -1
} {- {} 0 subexpr {1+2? 1 : 0} 11 operator ? 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-10.4 {ParseShiftExpr procedure, next lexeme is "<<" or ">>"} {
    testexprparser {1+2 << 3} -1
} {- {} 0 subexpr {1+2 << 3} 9 operator << 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-10.5 {ParseShiftExpr procedure, next lexeme is "<<" or ">>"} {
    testexprparser {1+2 >> 3} -1
} {- {} 0 subexpr {1+2 >> 3} 9 operator >> 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-10.6 {ParseShiftExpr procedure, bad lexeme after "<<" or ">>"} {wideIntegerUnparsed} {
    list [catch {testexprparser {1+2 << 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-10.7 {ParseShiftExpr procedure, valid RHS subexpression} {
    testexprparser {1+2 << 3 << 4} -1
} {- {} 0 subexpr {1+2 << 3 << 4} 13 operator << 0 subexpr {1+2 << 3} 9 operator << 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-10.8 {ParseShiftExpr procedure, error in RHS subexpression} {
    list [catch {testexprparser {1+2 << 3 >> martha} -1} msg] $msg
} {1 {syntax error in expression "1+2 << 3 >> martha": variable references require preceding $}}

test parseExpr-11.1 {ParseAddExpr procedure, valid LHS multiply subexpr} {
    testexprparser {1*2 + 3} -1
} {- {} 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-11.2 {ParseAddExpr procedure, error in LHS multiply subexpr} {
    list [catch {testexprparser {1/foo + 3} -1} msg] $msg
} {1 {syntax error in expression "1/foo + 3": variable references require preceding $}}
test parseExpr-11.3 {ParseAddExpr procedure, next lexeme isn't "+" or "-"} {
    testexprparser {1*2? 1 : 0} -1
} {- {} 0 subexpr {1*2? 1 : 0} 11 operator ? 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-11.4 {ParseAddExpr procedure, next lexeme is "+" or "-"} {
    testexprparser {1*2 + 3} -1
} {- {} 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-11.5 {ParseAddExpr procedure, next lexeme is "+" or "-"} {
    testexprparser {1*2 - 3} -1
} {- {} 0 subexpr {1*2 - 3} 9 operator - 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-11.6 {ParseAddExpr procedure, bad lexeme after "+" or "-"} {wideIntegerUnparsed} {
    list [catch {testexprparser {1*2 + 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-11.7 {ParseAddExpr procedure, valid RHS subexpression} {
    testexprparser {1*2 + 3 + 4} -1
} {- {} 0 subexpr {1*2 + 3 + 4} 13 operator + 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-11.8 {ParseAddExpr procedure, error in RHS subexpression} {
    list [catch {testexprparser {1*2 + 3 - martha} -1} msg] $msg
} {1 {syntax error in expression "1*2 + 3 - martha": variable references require preceding $}}

test parseExpr-12.1 {ParseAddExpr procedure, valid LHS multiply subexpr} {
    testexprparser {1*2 + 3} -1
} {- {} 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-12.2 {ParseAddExpr procedure, error in LHS multiply subexpr} {
    list [catch {testexprparser {1/foo + 3} -1} msg] $msg
} {1 {syntax error in expression "1/foo + 3": variable references require preceding $}}
test parseExpr-12.3 {ParseAddExpr procedure, next lexeme isn't "+" or "-"} {
    testexprparser {1*2? 1 : 0} -1
} {- {} 0 subexpr {1*2? 1 : 0} 11 operator ? 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-12.4 {ParseAddExpr procedure, next lexeme is "+" or "-"} {
    testexprparser {1*2 + 3} -1
} {- {} 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-12.5 {ParseAddExpr procedure, next lexeme is "+" or "-"} {
    testexprparser {1*2 - 3} -1
} {- {} 0 subexpr {1*2 - 3} 9 operator - 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-12.6 {ParseAddExpr procedure, bad lexeme after "+" or "-"} {wideIntegerUnparsed} {
    list [catch {testexprparser {1*2 + 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-12.7 {ParseAddExpr procedure, valid RHS subexpression} {
    testexprparser {1*2 + 3 + 4} -1
} {- {} 0 subexpr {1*2 + 3 + 4} 13 operator + 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-12.8 {ParseAddExpr procedure, error in RHS subexpression} {
    list [catch {testexprparser {1*2 + 3 - martha} -1} msg] $msg
} {1 {syntax error in expression "1*2 + 3 - martha": variable references require preceding $}}

test parseExpr-13.1 {ParseMultiplyExpr procedure, valid LHS unary subexpr} {
    testexprparser {+2 * 3} -1
} {- {} 0 subexpr {+2 * 3} 7 operator * 0 subexpr +2 3 operator + 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-13.2 {ParseMultiplyExpr procedure, error in LHS unary subexpr} {wideIntegerUnparsed} {
    list [catch {testexprparser {-12345678901234567890 * 3} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-13.3 {ParseMultiplyExpr procedure, next lexeme isn't "*", "/", or "%"} {
    testexprparser {+2? 1 : 0} -1
} {- {} 0 subexpr {+2? 1 : 0} 9 operator ? 0 subexpr +2 3 operator + 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-13.4 {ParseMultiplyExpr procedure, next lexeme is "*", "/", or "%"} {
    testexprparser {-123 * 3} -1
} {- {} 0 subexpr {-123 * 3} 7 operator * 0 subexpr -123 3 operator - 0 subexpr 123 1 text 123 0 subexpr 3 1 text 3 0 {}}
test parseExpr-13.5 {ParseMultiplyExpr procedure, next lexeme is "*", "/", or "%"} {
    testexprparser {+-456 / 3} -1
} {- {} 0 subexpr {+-456 / 3} 9 operator / 0 subexpr +-456 5 operator + 0 subexpr -456 3 operator - 0 subexpr 456 1 text 456 0 subexpr 3 1 text 3 0 {}}
test parseExpr-13.6 {ParseMultiplyExpr procedure, next lexeme is "*", "/", or "%"} {
    testexprparser {+-456 % 3} -1
} {- {} 0 subexpr {+-456 % 3} 9 operator % 0 subexpr +-456 5 operator + 0 subexpr -456 3 operator - 0 subexpr 456 1 text 456 0 subexpr 3 1 text 3 0 {}}
test parseExpr-13.7 {ParseMultiplyExpr procedure, bad lexeme after "*", "/", or "%"} {wideIntegerUnparsed} {
    list [catch {testexprparser {--++5 / 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-13.8 {ParseMultiplyExpr procedure, valid RHS subexpression} {
    testexprparser {-2 / 3 % 4} -1
} {- {} 0 subexpr {-2 / 3 % 4} 11 operator % 0 subexpr {-2 / 3} 7 operator / 0 subexpr -2 3 operator - 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-13.9 {ParseMultiplyExpr procedure, error in RHS subexpression} {
    list [catch {testexprparser {++2 / 3 * martha} -1} msg] $msg
} {1 {syntax error in expression "++2 / 3 * martha": variable references require preceding $}}

test parseExpr-14.1 {ParseUnaryExpr procedure, first token is unary operator} {
    testexprparser {+2} -1
} {- {} 0 subexpr +2 3 operator + 0 subexpr 2 1 text 2 0 {}}
test parseExpr-14.2 {ParseUnaryExpr procedure, first token is unary operator} {
    testexprparser {-2} -1
} {- {} 0 subexpr -2 3 operator - 0 subexpr 2 1 text 2 0 {}}
test parseExpr-14.3 {ParseUnaryExpr procedure, first token is unary operator} {
    testexprparser {~2} -1
} {- {} 0 subexpr ~2 3 operator ~ 0 subexpr 2 1 text 2 0 {}}
test parseExpr-14.4 {ParseUnaryExpr procedure, first token is unary operator} {
    testexprparser {!2} -1
} {- {} 0 subexpr !2 3 operator ! 0 subexpr 2 1 text 2 0 {}}
test parseExpr-14.5 {ParseUnaryExpr procedure, error in lexeme after unary op} {wideIntegerUnparsed} {
    list [catch {testexprparser {-12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-14.6 {ParseUnaryExpr procedure, simple unary expr after unary op} {
    testexprparser {+"1234"} -1
} {- {} 0 subexpr +\"1234\" 3 operator + 0 subexpr {"1234"} 1 text 1234 0 {}}
test parseExpr-14.7 {ParseUnaryExpr procedure, another unary expr after unary op} {
    testexprparser {~!{fred}} -1
} {- {} 0 subexpr ~!{fred} 5 operator ~ 0 subexpr !{fred} 3 operator ! 0 subexpr {{fred}} 1 text fred 0 {}}
test parseExpr-14.8 {ParseUnaryExpr procedure, error in unary expr after unary op} {
    list [catch {testexprparser {+-||27} -1} msg] $msg
} {1 {syntax error in expression "+-||27": unexpected operator ||}}
test parseExpr-14.9 {ParseUnaryExpr procedure, error in unary expr after unary op} {
    list [catch {testexprparser {+-||27} -1} msg] $msg
} {1 {syntax error in expression "+-||27": unexpected operator ||}}
test parseExpr-14.10 {ParseUnaryExpr procedure, first token is not unary op} {
    testexprparser {123} -1
} {- {} 0 subexpr 123 1 text 123 0 {}}
test parseExpr-14.11 {ParseUnaryExpr procedure, not unary expr, complex primary expr} {
    testexprparser {(1+2)} -1
} {- {} 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
test parseExpr-14.12 {ParseUnaryExpr procedure, not unary expr, error in primary expr} {wideIntegerUnparsed} {
    list [catch {testexprparser {(12345678901234567890)} -1} msg] $msg
} {1 {integer value too large to represent}}

test parseExpr-15.1 {ParsePrimaryExpr procedure, just parenthesized subexpr} {
    testexprparser {({abc}/{def})} -1
} {- {} 0 subexpr {{abc}/{def}} 5 operator / 0 subexpr {{abc}} 1 text abc 0 subexpr {{def}} 1 text def 0 {}}
test parseExpr-15.2 {ParsePrimaryExpr procedure, bad lexeme after "("} {wideIntegerUnparsed} {
    list [catch {testexprparser {(12345678901234567890)} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-15.3 {ParsePrimaryExpr procedure, valid parenthesized subexpr} {
    testexprparser {({abc}? 2*4 : -6)} -1
} {- {} 0 subexpr {{abc}? 2*4 : -6} 13 operator ? 0 subexpr {{abc}} 1 text abc 0 subexpr 2*4 5 operator * 0 subexpr 2 1 text 2 0 subexpr 4 1 text 4 0 subexpr -6 3 operator - 0 subexpr 6 1 text 6 0 {}}
test parseExpr-15.4 {ParsePrimaryExpr procedure, error in parenthesized subexpr} {
    list [catch {testexprparser {(? 123 : 456)} -1} msg] $msg
} {1 {syntax error in expression "(? 123 : 456)": unexpected ternary 'then' separator}}
test parseExpr-15.5 {ParsePrimaryExpr procedure, missing ")" after in parenthesized subexpr} {
    list [catch {testexprparser {({abc}/{def}} -1} msg] $msg
} {1 {syntax error in expression "({abc}/{def}": looking for close parenthesis}}
test parseExpr-15.6 {ParsePrimaryExpr procedure, primary is literal} {
    testexprparser {12345} -1
} {- {} 0 subexpr 12345 1 text 12345 0 {}}
test parseExpr-15.7 {ParsePrimaryExpr procedure, primary is literal} {
    testexprparser {12345.6789} -1
} {- {} 0 subexpr 12345.6789 1 text 12345.6789 0 {}}
test parseExpr-15.8 {ParsePrimaryExpr procedure, primary is var reference} {
    testexprparser {$a} -1
} {- {} 0 subexpr {$a} 2 variable {$a} 1 text a 0 {}}
test parseExpr-15.9 {ParsePrimaryExpr procedure, primary is var reference} {
    testexprparser {$a(hello$there)} -1
} {- {} 0 subexpr {$a(hello$there)} 5 variable {$a(hello$there)} 4 text a 0 text hello 0 variable {$there} 1 text there 0 {}}
test parseExpr-15.10 {ParsePrimaryExpr procedure, primary is var reference} {
    testexprparser {$a()} -1
} {- {} 0 subexpr {$a()} 3 variable {$a()} 2 text a 0 text {} 0 {}}
test parseExpr-15.11 {ParsePrimaryExpr procedure, error in var reference} {
    list [catch {testexprparser {$a(} -1} msg] $msg
} {1 {missing )}}
test parseExpr-15.12 {ParsePrimaryExpr procedure, primary is quoted string} {
    testexprparser {"abc $xyz def"} -1
} {- {} 0 subexpr {"abc $xyz def"} 5 word {"abc $xyz def"} 4 text {abc } 0 variable {$xyz} 1 text xyz 0 text { def} 0 {}}
test parseExpr-15.13 {ParsePrimaryExpr procedure, error in quoted string} {
    list [catch {testexprparser {"$a(12"} -1} msg] $msg
} {1 {missing )}}
test parseExpr-15.14 {ParsePrimaryExpr procedure, quoted string has multiple tokens} {
    testexprparser {"abc [xyz] $def"} -1
} {- {} 0 subexpr {"abc [xyz] $def"} 6 word {"abc [xyz] $def"} 5 text {abc } 0 command {[xyz]} 0 text { } 0 variable {$def} 1 text def 0 {}}
test parseExpr-15.15 {ParsePrimaryExpr procedure, primary is command} {
    testexprparser {[def]} -1
} {- {} 0 subexpr {[def]} 1 command {[def]} 0 {}}
test parseExpr-15.16 {ParsePrimaryExpr procedure, primary is multiple commands} {
    testexprparser {[one; two; three; four;]} -1
} {- {} 0 subexpr {[one; two; three; four;]} 1 command {[one; two; three; four;]} 0 {}}
test parseExpr-15.17 {ParsePrimaryExpr procedure, primary is multiple commands} {
    testexprparser {[one; two; three; four;]} -1
} {- {} 0 subexpr {[one; two; three; four;]} 1 command {[one; two; three; four;]} 0 {}}
test parseExpr-15.18 {ParsePrimaryExpr procedure, missing close bracket} {
    list [catch {testexprparser {[one} -1} msg] $msg
} {1 {missing close-bracket}}
test parseExpr-15.19 {ParsePrimaryExpr procedure, primary is braced string} {
    testexprparser {{hello world}} -1
} {- {} 0 subexpr {{hello world}} 1 text {hello world} 0 {}}
test parseExpr-15.20 {ParsePrimaryExpr procedure, error in primary, which is braced string} {
    list [catch {testexprparser "\{abc\\\n" -1} msg] $msg
} {1 {missing close-brace}}
test parseExpr-15.21 {ParsePrimaryExpr procedure, primary is braced string with multiple tokens} {
    testexprparser "\{  \\
 +123 \}" -1
} {- {} 0 subexpr \{\ \ \\\n\ +123\ \} 4 word \{\ \ \\\n\ +123\ \} 3 text {  } 0 backslash \\\n\  0 text {+123 } 0 {}}
test parseExpr-15.22 {ParsePrimaryExpr procedure, primary is function call} {
    testexprparser {foo(123)} -1
} {- {} 0 subexpr foo(123) 3 operator foo 0 subexpr 123 1 text 123 0 {}}
test parseExpr-15.23 {ParsePrimaryExpr procedure, bad lexeme after function name} {wideIntegerUnparsed} {
    list [catch {testexprparser {foo 12345678901234567890 123)} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-15.24 {ParsePrimaryExpr procedure, lexeme after function name isn't "("} {
    list [catch {testexprparser {foo 27.4 123)} -1} msg] $msg
} {1 {syntax error in expression "foo 27.4 123)": variable references require preceding $}}
test parseExpr-15.25 {ParsePrimaryExpr procedure, bad lexeme after "("} {wideIntegerUnparsed} {
    list [catch {testexprparser {foo(12345678901234567890)} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-15.26 {ParsePrimaryExpr procedure, function call, one arg} {
    testexprparser {foo(27*4)} -1
} {- {} 0 subexpr foo(27*4) 7 operator foo 0 subexpr 27*4 5 operator * 0 subexpr 27 1 text 27 0 subexpr 4 1 text 4 0 {}}
test parseExpr-15.27 {ParsePrimaryExpr procedure, error in function arg} {
    list [catch {testexprparser {foo(*1-2)} -1} msg] $msg
} {1 {syntax error in expression "foo(*1-2)": unexpected operator *}}
test parseExpr-15.28 {ParsePrimaryExpr procedure, error in function arg} {
    list [catch {testexprparser {foo(*1-2)} -1} msg] $msg
} {1 {syntax error in expression "foo(*1-2)": unexpected operator *}}
test parseExpr-15.29 {ParsePrimaryExpr procedure, function call, comma after arg} {
    testexprparser {foo(27-2, (-2*[foo]))} -1
} {- {} 0 subexpr {foo(27-2, (-2*[foo]))} 15 operator foo 0 subexpr 27-2 5 operator - 0 subexpr 27 1 text 27 0 subexpr 2 1 text 2 0 subexpr {-2*[foo]} 7 operator * 0 subexpr -2 3 operator - 0 subexpr 2 1 text 2 0 subexpr {[foo]} 1 command {[foo]} 0 {}}
test parseExpr-15.30 {ParsePrimaryExpr procedure, bad lexeme after comma} {wideIntegerUnparsed} {
    list [catch {testexprparser {foo(123, 12345678901234567890)} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-15.31 {ParsePrimaryExpr procedure, lexeme not "," or ")" after arg} {
    list [catch {testexprparser {foo(123 [foo])} -1} msg] $msg
} {1 {syntax error in expression "foo(123 [foo])": missing close parenthesis at end of function call}}
test parseExpr-15.32 {ParsePrimaryExpr procedure, bad lexeme after primary} {wideIntegerUnparsed} {
    list [catch {testexprparser {123 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-15.33 {ParsePrimaryExpr procedure, comma-specific message} {
    list [catch {testexprparser {123+,456} -1} msg] $msg
} {1 {syntax error in expression "123+,456": commas can only separate function arguments}}
test parseExpr-15.34 {ParsePrimaryExpr procedure, single equal-specific message} {
    list [catch {testexprparser {123+=456} -1} msg] $msg
} {1 {syntax error in expression "123+=456": single equality character not legal in expressions}}
test parseExpr-15.35 {ParsePrimaryExpr procedure, error in parenthesized subexpr} {
    list [catch {testexprparser {(: 123 : 456)} -1} msg] $msg
} {1 {syntax error in expression "(: 123 : 456)": unexpected ternary 'else' separator}}

test parseExpr-16.1 {GetLexeme procedure, whitespace before lexeme} {
    testexprparser {   123} -1
} {- {} 0 subexpr 123 1 text 123 0 {}}
test parseExpr-16.2 {GetLexeme procedure, whitespace before lexeme} {
    testexprparser {  \
456} -1
} {- {} 0 subexpr 456 1 text 456 0 {}}
test parseExpr-16.3 {GetLexeme procedure, no lexeme after whitespace} {
    testexprparser { 123 \
   } -1
} {- {} 0 subexpr 123 1 text 123 0 {}}
test parseExpr-16.4 {GetLexeme procedure, integer lexeme} {
    testexprparser {000} -1
} {- {} 0 subexpr 000 1 text 000 0 {}}
test parseExpr-16.5 {GetLexeme procedure, integer lexeme too big} {wideIntegerUnparsed} {
    list [catch {testexprparser {12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}

test parseExpr-16.6 {GetLexeme procedure, bad integer lexeme} -body {
    testexprparser {0999} -1
} -returnCodes error -match glob -result {*invalid octal number*}

test parseExpr-16.7 {GetLexeme procedure, double lexeme} {
    testexprparser {0.999} -1
} {- {} 0 subexpr 0.999 1 text 0.999 0 {}}
test parseExpr-16.8 {GetLexeme procedure, double lexeme} {
    testexprparser {.123} -1
} {- {} 0 subexpr .123 1 text .123 0 {}}
test parseExpr-16.9 {GetLexeme procedure, double lexeme} {nonPortable unixOnly} {
    testexprparser {nan} -1
} {- {} 0 subexpr nan 1 text nan 0 {}}
test parseExpr-16.10 {GetLexeme procedure, double lexeme} {nonPortable unixOnly} {
    testexprparser {NaN} -1
} {- {} 0 subexpr NaN 1 text NaN 0 {}}
test parseExpr-16.11 {GetLexeme procedure, bad double lexeme too big} {
    list [catch {testexprparser {123.e+99999999999999} -1} msg] $msg
} {1 {floating-point value too large to represent}}
test parseExpr-16.12 {GetLexeme procedure, bad double lexeme} {
    list [catch {testexprparser {123.4x56} -1} msg] $msg
} {1 {syntax error in expression "123.4x56": extra tokens at end of expression}}
test parseExpr-16.13 {GetLexeme procedure, lexeme is "["} {
    testexprparser {[foo]} -1
} {- {} 0 subexpr {[foo]} 1 command {[foo]} 0 {}}
test parseExpr-16.14 {GetLexeme procedure, lexeme is open brace} {
    testexprparser {{bar}} -1
} {- {} 0 subexpr {{bar}} 1 text bar 0 {}}
test parseExpr-16.15 {GetLexeme procedure, lexeme is "("} {
    testexprparser {(123)} -1
} {- {} 0 subexpr 123 1 text 123 0 {}}
test parseExpr-16.16 {GetLexeme procedure, lexeme is ")"} {
    testexprparser {(2*3)} -1
} {- {} 0 subexpr 2*3 5 operator * 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-16.17 {GetLexeme procedure, lexeme is "$"} {
    testexprparser {$wombat} -1
} {- {} 0 subexpr {$wombat} 2 variable {$wombat} 1 text wombat 0 {}}
test parseExpr-16.18 "GetLexeme procedure, lexeme is '\"'" {
    testexprparser {"fred"} -1
} {- {} 0 subexpr {"fred"} 1 text fred 0 {}}
test parseExpr-16.19 {GetLexeme procedure, lexeme is ","} {
    testexprparser {foo(1,2)} -1
} {- {} 0 subexpr foo(1,2) 5 operator foo 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
test parseExpr-16.20 {GetLexeme procedure, lexeme is "*"} {
    testexprparser {$a*$b} -1
} {- {} 0 subexpr {$a*$b} 7 operator * 0 subexpr {$a} 2 variable {$a} 1 text a 0 subexpr {$b} 2 variable {$b} 1 text b 0 {}}
test parseExpr-16.21 {GetLexeme procedure, lexeme is "/"} {
    testexprparser {5/6} -1
} {- {} 0 subexpr 5/6 5 operator / 0 subexpr 5 1 text 5 0 subexpr 6 1 text 6 0 {}}
test parseExpr-16.22 {GetLexeme procedure, lexeme is "%"} {
    testexprparser {5%[xxx]} -1
} {- {} 0 subexpr {5%[xxx]} 5 operator % 0 subexpr 5 1 text 5 0 subexpr {[xxx]} 1 command {[xxx]} 0 {}}
test parseExpr-16.23 {GetLexeme procedure, lexeme is "+"} {
    testexprparser {1+2} -1
} {- {} 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
test parseExpr-16.24 {GetLexeme procedure, lexeme is "-"} {
    testexprparser {.12-0e27} -1
} {- {} 0 subexpr .12-0e27 5 operator - 0 subexpr .12 1 text .12 0 subexpr 0e27 1 text 0e27 0 {}}
test parseExpr-16.25 {GetLexeme procedure, lexeme is "?" or ":"} {
    testexprparser {$b? 1 : 0} -1
} {- {} 0 subexpr {$b? 1 : 0} 8 operator ? 0 subexpr {$b} 2 variable {$b} 1 text b 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-16.26 {GetLexeme procedure, lexeme is "<"} {
    testexprparser {2<3} -1
} {- {} 0 subexpr 2<3 5 operator < 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-16.27 {GetLexeme procedure, lexeme is "<<"} {
    testexprparser {2<<3} -1
} {- {} 0 subexpr 2<<3 5 operator << 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-16.28 {GetLexeme procedure, lexeme is "<="} {
    testexprparser {2<=3} -1
} {- {} 0 subexpr 2<=3 5 operator <= 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-16.29 {GetLexeme procedure, lexeme is ">"} {
    testexprparser {2>3} -1
} {- {} 0 subexpr 2>3 5 operator > 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-16.30 {GetLexeme procedure, lexeme is ">>"} {
    testexprparser {2>>3} -1
} {- {} 0 subexpr 2>>3 5 operator >> 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-16.31 {GetLexeme procedure, lexeme is ">="} {
    testexprparser {2>=3} -1
} {- {} 0 subexpr 2>=3 5 operator >= 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-16.32 {GetLexeme procedure, lexeme is "=="} {
    testexprparser {2==3} -1
} {- {} 0 subexpr 2==3 5 operator == 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-16.33 {GetLexeme procedure, bad lexeme starting with "="} {
    list [catch {testexprparser {2=+3} -1} msg] $msg
} {1 {syntax error in expression "2=+3": extra tokens at end of expression}}
test parseExpr-16.34 {GetLexeme procedure, lexeme is "!="} {
    testexprparser {2!=3} -1
} {- {} 0 subexpr 2!=3 5 operator != 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-16.35 {GetLexeme procedure, lexeme is "!"} {
    testexprparser {!2} -1
} {- {} 0 subexpr !2 3 operator ! 0 subexpr 2 1 text 2 0 {}}
test parseExpr-16.36 {GetLexeme procedure, lexeme is "&&"} {
    testexprparser {2&&3} -1
} {- {} 0 subexpr 2&&3 5 operator && 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-16.37 {GetLexeme procedure, lexeme is "&"} {
    testexprparser {1&2} -1
} {- {} 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
test parseExpr-16.38 {GetLexeme procedure, lexeme is "^"} {
    testexprparser {1^2} -1
} {- {} 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
test parseExpr-16.39 {GetLexeme procedure, lexeme is "||"} {
    testexprparser {2||3} -1
} {- {} 0 subexpr 2||3 5 operator || 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-16.40 {GetLexeme procedure, lexeme is "|"} {
    testexprparser {1|2} -1
} {- {} 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
test parseExpr-16.41 {GetLexeme procedure, lexeme is "~"} {
    testexprparser {~2} -1
} {- {} 0 subexpr ~2 3 operator ~ 0 subexpr 2 1 text 2 0 {}}
test parseExpr-16.42 {GetLexeme procedure, lexeme is func name} {
    testexprparser {george()} -1
} {- {} 0 subexpr george() 1 operator george 0 {}}
test parseExpr-16.43 {GetLexeme procedure, lexeme is func name} {
    testexprparser {harmonic_ratio(2,3)} -1
} {- {} 0 subexpr harmonic_ratio(2,3) 5 operator harmonic_ratio 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-16.44 {GetLexeme procedure, unknown lexeme} {
    list [catch {testexprparser {@27} -1} msg] $msg
} {1 {syntax error in expression "@27": character not legal in expressions}}

test parseExpr-17.1 {PrependSubExprTokens procedure, expand token array} {
    testexprparser {[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]} -1
} {- {} 0 subexpr {[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]} 13 operator && 0 subexpr {[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]} 9 operator && 0 subexpr {[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]} 5 operator && 0 subexpr {[string compare [format %c $i] [string index $a $i]]} 1 command {[string compare [format %c $i] [string index $a $i]]} 0 subexpr {[string compare [format %c $i] [string index $a $i]]} 1 command {[string compare [format %c $i] [string index $a $i]]} 0 subexpr {[string compare [format %c $i] [string index $a $i]]} 1 command {[string compare [format %c $i] [string index $a $i]]} 0 subexpr {[string compare [format %c $i] [string index $a $i]]} 1 command {[string compare [format %c $i] [string index $a $i]]} 0 {}}

test parseExpr-18.1 {LogSyntaxError procedure, error in expr longer than 60 chars} {
    list [catch {testexprparser {(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)/} -1} msg] $msg
} {1 {syntax error in expression "(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+012...": premature end of expression}}

# cleanup
::tcltest::cleanupTests
return