summaryrefslogtreecommitdiff
path: root/lib/test.cc
blob: 68dac77e2b903d38c971440a0afc3adcad3f6c7e (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
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#include "lib/regex.h"
#include "src/util/c99_stdint.h"


static int test(const char *pattern, const char *string
    , size_t nmatch, const regoff_t *submatch, int flags)
{
    static uint32_t total = 0;
    static uint32_t failed = 0;

    regex_t re;
    regmatch_t *pmatch = new regmatch_t[nmatch];
    const char *prefix = flags & REG_NFA ? "NFA" : "DFA";
    int result;

    result = regcomp(&re, pattern, flags);
    if (result != 0) {
        fprintf(stderr, "%s: regcomp() failed for RE %s\n", prefix, pattern);
        goto end;
    }

    // run multiple times to ensure everything gets cleaned up properly
    static const uint32_t NRUNS = 2;
    for (uint32_t i = 0; i < NRUNS; ++i) {
        result = regexec(&re, string, nmatch, pmatch, flags);
        if (result != 0) {
            if (nmatch == 0) {
                // failure was expected => it's a success
                result = 0;
            }
            else if (nmatch > 0) {
                fprintf(stderr, "%s: regexec() failed for RE %s and string %s\n"
                    , prefix, pattern, string);
                goto end;
            }
        }
        else if (nmatch == 0) {
            // regexed must have failed, something is wrong
            result = REG_NOMATCH;
            fprintf(stderr, "%s: regexec() didn't fail while it should"
                " for RE %s and string %s\n", prefix, pattern, string);
            goto end;
        }
    }

    assert(nmatch == 0 || nmatch == re.re_nsub);

    for (uint32_t i = 0; i < nmatch; ++i) {
        regoff_t so = submatch[2 * i];
        regoff_t eo = submatch[2 * i + 1];
        const regmatch_t &have = pmatch[i];

        if (so != have.rm_so || eo != have.rm_eo) {
            result = 1;
            fprintf(stderr, "%s: incorrect submatch for RE %s and string %s:\n"
                "\tpmatch[%u].rm_so = %ld (expected %ld)\n"
                "\tpmatch[%u].rm_eo = %ld (expected %ld)\n"
                , prefix, pattern, string
                , i, (long)have.rm_so, (long)so
                , i, (long)have.rm_eo, (long)eo);
            goto end;
        }
    }

end:
    regfree(&re);
    delete[] pmatch;

    ++total;
    if (result != 0) {
        ++failed;
        fprintf(stderr, "failed %u of %u\n", failed, total);
    }

    return result;
}

// Poor man's replacement for C++11 initializer lists. :)
// Variadic macros are non-standard in c++98. Variadic functions have
// subtle problems with types: literals are 'int' by default, so passing
// 'long' as vararg requres suffix 'L', which is easy to forget and hard
// to notice (the problem is platform/toolchain-specific).
#define  GS                                              static const regoff_t gs[]
#define  T(R,S,gs)                                       do { e |= test(R,S,sizeof(gs)/sizeof(gs[0])/2,gs,flags); } while(0)
#define  T0(R,S)                                         do { e |= test(R,S,0,NULL,flags); } while(0)
#define  T1(R,S,a,b)                                     do { GS = {a,b};                                     T(R,S,gs); } while(0)
#define  T2(R,S,a,b,c,d)                                 do { GS = {a,b,c,d};                                 T(R,S,gs); } while(0)
#define  T3(R,S,a,b,c,d,e,f)                             do { GS = {a,b,c,d,e,f};                             T(R,S,gs); } while(0)
#define  T4(R,S,a,b,c,d,e,f,g,h)                         do { GS = {a,b,c,d,e,f,g,h};                         T(R,S,gs); } while(0)
#define  T5(R,S,a,b,c,d,e,f,g,h,i,j)                     do { GS = {a,b,c,d,e,f,g,h,i,j};                     T(R,S,gs); } while(0)
#define  T6(R,S,a,b,c,d,e,f,g,h,i,j,k,l)                 do { GS = {a,b,c,d,e,f,g,h,i,j,k,l};                 T(R,S,gs); } while(0)
#define  T7(R,S,a,b,c,d,e,f,g,h,i,j,k,l,m,n)             do { GS = {a,b,c,d,e,f,g,h,i,j,k,l,m,n};             T(R,S,gs); } while(0)
#define  T8(R,S,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)         do { GS = {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p};         T(R,S,gs); } while(0)
#define  T9(R,S,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r)     do { GS = {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r};     T(R,S,gs); } while(0)
#define T10(R,S,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t) do { GS = {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t}; T(R,S,gs); } while(0)

static int test_all_posix(int flags)
{
    int e = 0;

    T5("(a+(c+))|(b+(d+))", "ac", 0,2, 0,2, 1,2, -1,-1, -1,-1);

    T2("(aaaa|aaa|a)+", "aaaaaaaaaa", 0,10, 9,10);
    T2("(aaaa|aaa|a){3,}", "aaaaaaaaaa", 0,10, 9,10);
    if (!(flags & REG_BACKWARD)) {
        // expected failures for Cox algorithm
        T2("(aaaa|aaa|a){3,4}", "aaaaaaaaaa", 0,10, 9,10);
        T2("(aaaaaa|aaaaa|aaaa|aa|a){3,4}", "aaaaaaaaaaaaaaa", 0,15, 14,15);
        T2("(aaaaa?a?|aa?){1,4}", "aaaaaaaaaaaaaaa", 0,15, 14,15);
        T5("(((a){3,4}a?)()a|aa?){1,4}", "aaaaaaaaaaaaaaa", 0,15, 14,15, -1,-1, -1,-1, -1,-1);
        T4("(((aaaa?|a?)){1,4})+", "aaaaaaaaaa", 0,10, 0,10, 9,10, 9,10);
        T9("((((a){2,3}(()|a)(()|a?)a|a?)){2,5})*", "aaaaaaaaaaaaaa", 0,14, 0,14, 13,14, 13,14, -1,-1, -1,-1, -1,-1, -1,-1, -1,-1);
    }
    if (!((flags & REG_BACKWARD) && (flags & REG_GTOP))) {
        // expected failures for Cox algorithm
        T6("(((((a){3,3}a?|a?)){0,4})?)*", "aaaaaaaaaa", 0,10, 0,10, 0,10, 9,10, 9,10, -1,-1);
        T10("(((((a){3,4}|a?)){1,4}|((a)+(a|())){1,2}))*", "aaaaaaaaaa", 0,10, 0,10, 0,10, 9,10, 9,10, -1,-1, -1,-1, -1,-1, -1,-1, -1,-1);
    }
    if (!((flags & REG_BACKWARD) && !(flags & REG_GTOP))) {
        // expected failures for Cox algorithm
        T7("((a?|a?(a?a?)((())+)+))*", "aaaaaa", 0,6, 3,6, 3,6, 4,6, 6,6, 6,6, 6,6);
    }
    T4("(((a?a)){2,3})*", "aaaa", 0,4, 0,4, 2,4, 2,4);

    T6("(((aa?a)((aaa)+))+)+",              "aaaaaaaaaa", 0,10, 0,10, 5,10, 5,7, 7,10, 7,10);
    T6("(((aaa?)((aaa)+))+)+",              "aaaaaaaaaa", 0,10, 0,10, 5,10, 5,7, 7,10, 7,10);
    T6("(((aaa?)((aaa){1,3})){1,2})*",      "aaaaaaaaaa", 0,10, 0,10, 5,10, 5,7, 7,10, 7,10);
    T6("((((aaa?)(aaa){1,3})){1,2})*",      "aaaaaaaaaa", 0,10, 0,10, 5,10, 5,10, 5,7, 7,10);
    T7("((((aaa?)((a){3,3}){1,3})){1,2})*", "aaaaaaaaaa", 0,10, 0,10, 5,10, 5,10, 5,7, 7,10, 9,10);

    T2("(a|aa)*", "",           0,0,  -1,-1);
    T2("(a|aa)*", "a",          0,1,  0,1);
    T2("(a|aa)*", "aa",         0,2,  0,2);
    T2("(a|aa)*", "aaa",        0,3,  2,3);
    T2("(a|aa)*", "aaaa",       0,4,  2,4);
    T2("(a|aa)*", "aaaaa",      0,5,  4,5);
    T2("(a|aa)*", "aaaaaa",     0,6,  4,6);
    T2("(a|aa)*", "aaaaaaa",    0,7,  6,7);
    T2("(a|aa)*", "aaaaaaaa",   0,8,  6,8);
    T2("(a|aa)*", "aaaaaaaaa",  0,9,  8,9);
    T2("(a|aa)*", "aaaaaaaaaa", 0,10, 8,10);
    T2("(aa|a)*", "",           0,0,  -1,-1);
    T2("(aa|a)*", "a",          0,1,  0,1);
    T2("(aa|a)*", "aa",         0,2,  0,2);
    T2("(aa|a)*", "aaa",        0,3,  2,3);
    T2("(aa|a)*", "aaaa",       0,4,  2,4);
    T2("(aa|a)*", "aaaaa",      0,5,  4,5);
    T2("(aa|a)*", "aaaaaa",     0,6,  4,6);
    T2("(aa|a)*", "aaaaaaa",    0,7,  6,7);
    T2("(aa|a)*", "aaaaaaaa",   0,8,  6,8);
    T2("(aa|a)*", "aaaaaaaaa",  0,9,  8,9);
    T2("(aa|a)*", "aaaaaaaaaa", 0,10, 8,10);

    T2("(aaa|aa)*", "aaaaaaaaaa",        0,10, 8,10);
    T2("(aa|aaa)*", "aaaaaaaaaa",        0,10, 8,10);

    T3("((a*)*)*",                           "",            0,0, 0,0, 0,0);

    T2("(y?){0,2}",                          "",            0,0, 0,0);
    T3("((y?){2,3}){2}",                     "yyyyy",       0,5, 3,5, 4,5);
    T3("((y?){2,3}){2,3}",                   "yyyyy",       0,5, 3,5, 4,5);
    T3("((y?){2,3})*",                       "yyyyy",       0,5, 3,5, 4,5);
    T3("((y?){3}){2}",                       "yyyyy",       0,5, 3,5, 5,5);
    T3("((y?){3}){2,3}",                     "yyyyy",       0,5, 3,5, 5,5);
    T3("((y?){3})*",                         "yyyyy",       0,5, 3,5, 5,5);
    T3("((y?)*){2}",                         "yyyyy",       0,5, 5,5, 5,5);
    T3("((y?)*){2,3}",                       "yyyyy",       0,5, 5,5, 5,5);
    T3("((y?)*)*",                           "yyyyy",       0,5, 0,5, 4,5);

    T4("((a)(b)?)*",                         "aba",         0,3, 2,3, 2,3, -1,-1);
    T4("((a)|(b))*",                         "ba",          0,2, 1,2, 1,2, -1,-1);
    T4("((a)|(b))*",                         "ab",          0,2, 1,2, -1,-1, 1,2);
    T4("((a?)|(b?))*",                       "ab",          0,2, 1,2, -1,-1, 1,2);
    T4("((a?)|(b?))*",                       "ba",          0,2, 1,2, 1,2, -1,-1);
    if (!((flags & REG_BACKWARD) && !(flags & REG_GTOP))) {
        T4("((a?)|(b?)){2,3}",               "ab",          0,2, 1,2, -1,-1, 1,2);
    }
    T4("((a?)|(b?)){3}",                     "ab",          0,2, 2,2, 2,2, -1,-1);
    T1("y{3}",                               "yyy",         0,3);
    T1("y{0,2}",                             "",            0,0);
    T1("y{0,2}",                             "y",           0,1);
    T1("y{0,2}",                             "yy",          0,2);
    T2("(y){3}",                             "yyy",         0,3, 2,3);
    T2("(y){0,2}",                           "",            0,0, -1,-1);
    T2("(y){0,2}",                           "y",           0,1, 0,1);
    T2("(y){0,2}",                           "yy",          0,2, 1,2);
    T2("()",                                 "",            0,0, 0,0);
    T2("(){2}",                              "",            0,0, 0,0);
    T2("(){0,2}",                            "",            0,0, 0,0);
    T4("(((){0,30}){0,30}){0,30}",           "",            0,0, 0,0, 0,0, 0,0);
    T2("(y?){2}",                            "y",           0,1, 1,1);

    T1("a",        "a",    0,1);
    T2("(a)",      "a",    0,1, 0,1);
    T2("(a*)",     "aaa",  0,3, 0,3);
    T3("(a*)(b*)", "aabb", 0,4, 0,2, 2,4);
    T3("(a*)(a*)", "aa",   0,2, 0,2, 2,2);
    T2("(a|aa)*",  "aa",   0,2, 0,2);
    T3("(a)|(a)",  "a",    0,1, 0,1, -1,-1);
    T3("(a)*(a)*", "a",    0,1, 0,1, -1,-1);

    T1("[a]",      "a",    0,1);
    T0("[a]",      "b");
    T0("[^a]",     "a");
    T1("[^a]",     "b",    0,1);
    T1("[ac]*",    "ac",   0,2);
    T1("[a-c]*",   "abc",  0,3);
    T1("[]]",      "]",    0,1);
    T0("[^]]",     "]");
    T1("[^]]",     "a",    0,1);
    T1("[-]",      "-",    0,1);
    T1("[]-]*",    "]-",   0,2);
    T1("[-a]*",    "-a",   0,2);
    T1("[a-]*",    "-a",   0,2);
    T1("[-a-]*",   "-a",   0,2);

    // basic
    T3("(..)*(...)*",              "a",           0,0, -1,-1, -1,-1);
    T3("(..)*(...)*",              "abcd",        0,4, 2,4, -1,-1);
    T3("(ab|a)(bc|c)",             "abc",         0,3, 0,2, 2,3);
    T2("(ab)c|abc",                "abc",         0,3, 0,2);
    T4("(a*)(b?)(b+)b{3}",         "aaabbbbbbb",  0,10, 0,3, 3,4, 4,7);
    T4("(a*)(b{0,1})(b{1,})b{3}",  "aaabbbbbbb",  0,10, 0,3, 3,4, 4,7);
    T3("((a|a)|a)",                "a",           0,1, 0,1, 0,1);
    T3("(a*)(a|aa)",               "aaaa",        0,4, 0,3, 3,4);
    T2("a*(a.|aa)",                "aaaa",        0,4, 2,4);
    T4("a(b)|c(d)|a(e)f",          "aef",         0,3, -1,-1, -1,-1, 1,2);
    T2("(a|b)?.*",                 "b",           0,1, 0,1);
    T3("(a|b)c|a(b|c)",            "ac",          0,2, 0,1, -1,-1);
    T3("(a|b)c|a(b|c)",            "ab",          0,2, -1,-1, 1,2);
    T3("(a|b)*c|(a|ab)*c",         "abc",         0,3, 1,2, -1,-1);
    T3("(.a|.b).*|.*(.a|.b)",      "xa",          0,2, 0,2, -1,-1);
    T2("a?(ab|ba)ab",              "abab",        0,4, 0,2);
    T2("a?(a[c]{0}b|ba)ab",        "abab",        0,4, 0,2);
    T1("ab|abab",                  "abbabab",     0,2);
    T3("(aa|aaa)*|(a|aaaaa)",      "aa",          0,2, 0,2, -1,-1);
    T3("(a.|.a.)*|(a|.a...)",      "aa",          0,2, 0,2, -1,-1);
    T4("(a)(b)(c)",                "abc",         0,3, 0,1, 1,2, 2,3);
    T7("((((((x))))))",            "x",           0,1, 0,1, 0,1, 0,1, 0,1, 0,1, 0,1);
    T7("((((((x))))))*",           "xx",          0,2, 1,2, 1,2, 1,2, 1,2, 1,2, 1,2);
    T2("a?(ab|ba)*",               "ababababababababababababababababababababababababababababababababababababababababa", 0,81, 79,81);
    T1("a*a*a*a*a*b",              "aaaaaaaaab",  0,10);
    T1("a[b]+bc",                  "abbc",        0,4);
    T1("a[b]+bc",                  "abbbbc",      0,6);
    T1("a[b]?bc",                  "abbc",        0,4);
    T1("a[b]?bc",                  "abc",         0,3);
    T1("a[b]?c",                   "abc",         0,3);
    T1("ab|cd",                    "abc",         0,2);
    T1("ab|cd",                    "abcd",        0,2);
    T3("((a))",                    "abc",         0,1, 0,1, 0,1);
    T3("(a)b(c)",                  "abc",         0,3, 0,1, 2,3);
    T1("a*",                       "aaa",         0,3);
    T2("(a*)*",                    "-",           0,0, 0,0);
    T2("(a*)+",                    "-",           0,0, 0,0);
    T2("(a*|b)*",                  "-",           0,0, 0,0);
    T2("(a+|b)*",                  "ab",          0,2, 1,2);
    T2("(a+|b)+",                  "ab",          0,2, 1,2);
    T2("(a+|b)?",                  "ab",          0,1, 0,1);
    T2("([abc])*d",                "abbbcd",      0,6, 4,5);
    T2("([abc])*bcd",              "abcd",        0,4, 0,1);
    T1("a|b|c|d|e",                "e",           0,1);
    T2("(a|b|c|d|e)f",             "ef",          0,2, 0,1);
    T3("((a*|b))*",                "-",           0,0, 0,0, 0,0);
    T2("(ab|a[b]*)bc",             "abc",         0,3, 0,1);
    T2("a([bc]*)c*",               "abc",         0,3, 1,3);
    T3("a([bc]*)(c*d)",            "abcd",        0,4, 1,3, 3,4);
    T3("a([bc]+)(c*d)",            "abcd",        0,4, 1,3, 3,4);
    T3("a([bc]*)(c+d)",            "abcd",        0,4, 1,2, 2,4);
    T1("a[bcd]*dcdcde",            "adcdcde",     0,7);
    T2("(ab|a)b*c",                "abc",         0,3, 0,2);
    T5("((a)(b)c)(d)",             "abcd",        0,4, 0,3, 0,1, 1,2, 3,4);
    T3("(.*)c(.*)",                "abcde",       0,5, 0,2, 3,5);
    T2("a(bc)d",                   "abcd",        0,4, 1,3);
    T2("a+(b|c)*d+",               "aabcdd",      0,6, 3,4);

    // categorize
    T4("(a*)(ab)*(b*)",            "abc",    0,2, 0,1, -1,-1, 1,2);
    T7("((a*)(ab)*)((b*)(a*))",    "aba",    0,3, 0,2, 0,0, 0,2, 2,3, 2,2, 2,3);
    T2("(...?.?)*",                "xxxxxx", 0,6, 4,6);
    T3("(a|ab)(bc|c)",             "abcabc", 0,3, 0,2, 2,3);
    T3("(aba|a*b)(aba|a*b)",       "ababa",  0,5, 0,2, 2,5);
    T2("(a*){2}",                  "xxxxx",  0,0, 0,0);
    T2("(a*)*",                    "a",      0,1, 0,1);
    T2("(aba|a*b)*",               "ababa",  0,5, 2,5);
    T3("(a(b)?)+",                 "aba",    0,3, 2,3, -1,-1);
    T2(".*(.*)",                   "ab",     0,2, 2,2);
    T6("(a?)((ab)?)(b?)a?(ab)?b?", "abab",   0,4, 0,1, 1,1, -1,-1, 1,2, -1,-1);

    // forcedassoc
    T3("(a|ab)(c|bcd)",       "abcd", 0,4, 0,1, 1,4);
    T3("(a|ab)(bcd|c)",       "abcd", 0,4, 0,1, 1,4);
    T3("(ab|a)(c|bcd)",       "abcd", 0,4, 0,1, 1,4);
    T3("(ab|a)(bcd|c)",       "abcd", 0,4, 0,1, 1,4);
    T5("((a|ab)(c|bcd))(d*)", "abcd", 0,4, 0,4, 0,1, 1,4, 4,4);
    T5("((a|ab)(bcd|c))(d*)", "abcd", 0,4, 0,4, 0,1, 1,4, 4,4);
    T5("((ab|a)(c|bcd))(d*)", "abcd", 0,4, 0,4, 0,1, 1,4, 4,4);
    T5("((ab|a)(bcd|c))(d*)", "abcd", 0,4, 0,4, 0,1, 1,4, 4,4);
    T5("(a|ab)((c|bcd)(d*))", "abcd", 0,4, 0,2, 2,4, 2,3, 3,4);
    T5("(a|ab)((bcd|c)(d*))", "abcd", 0,4, 0,2, 2,4, 2,3, 3,4);
    T5("(ab|a)((c|bcd)(d*))", "abcd", 0,4, 0,2, 2,4, 2,3, 3,4);
    T5("(ab|a)((bcd|c)(d*))", "abcd", 0,4, 0,2, 2,4, 2,3, 3,4);
    T3("(a*)(b|abc)",         "abc",  0,3, 0,0, 0,3);
    T3("(a*)(abc|b)",         "abc",  0,3, 0,0, 0,3);
    T5("((a*)(b|abc))(c*)",   "abc",  0,3, 0,3, 0,0, 0,3, 3,3);
    T5("((a*)(abc|b))(c*)",   "abc",  0,3, 0,3, 0,0, 0,3, 3,3);
    T5("(a*)((b|abc)(c*))",   "abc",  0,3, 0,1, 1,3, 1,2, 2,3);
    T5("(a*)((abc|b)(c*))",   "abc",  0,3, 0,1, 1,3, 1,2, 2,3);
    T3("(a*)(b|abc)",         "abc",  0,3, 0,0, 0,3);
    T3("(a*)(abc|b)",         "abc",  0,3, 0,0, 0,3);
    T5("((a*)(b|abc))(c*)",   "abc",  0,3, 0,3, 0,0, 0,3, 3,3);
    T5("((a*)(abc|b))(c*)",   "abc",  0,3, 0,3, 0,0, 0,3, 3,3);
    T5("(a*)((b|abc)(c*))",   "abc",  0,3, 0,1, 1,3, 1,2, 2,3);
    T5("(a*)((abc|b)(c*))",   "abc",  0,3, 0,1, 1,3, 1,2, 2,3);
    T2("(a|ab)",              "ab",   0,2, 0,2);
    T2("(ab|a)",              "ab",   0,2, 0,2);
    T3("(a|ab)(b*)",          "ab",   0,2, 0,2, 2,2);
    T3("(ab|a)(b*)",          "ab",   0,2, 0,2, 2,2);

    // glennfowler
    T4("(a?)((ab)?)",                    "ab",      0,2, 0,0, 0,2, 0,2);
    T5("(a?)((ab)?)(b?)",                "ab",      0,2, 0,1, 1,1, -1,-1, 1,2);
    T6("((a?)((ab)?))(b?)",              "ab",      0,2, 0,2, 0,0, 0,2, 0,2, 2,2);
    T6("(a?)(((ab)?)(b?))",              "ab",      0,2, 0,1, 1,2, 1,1, -1,-1, 1,2);
    T2("(.?)",                           "x",       0,1, 0,1);
    T2("(.?){1}",                        "x",       0,1, 0,1);
    T3("(.?)(.?)",                       "x",       0,1, 0,1, 1,1);
    T2("(.?){2}",                        "x",       0,1, 1,1);
    T2("(.?)*",                          "x",       0,1, 0,1);
    T2("(.?.?)",                         "xxx",     0,2, 0,2);
    T2("(.?.?){1}",                      "xxx",     0,2, 0,2);
    T3("(.?.?)(.?.?)",                   "xxx",     0,3, 0,2, 2,3);
    T2("(.?.?){2}",                      "xxx",     0,3, 2,3);
    T4("(.?.?)(.?.?)(.?.?)",             "xxx",     0,3, 0,2, 2,3, 3,3);
    T2("(.?.?){3}",                      "xxx",     0,3, 3,3);
    T2("(.?.?)*",                        "xx",      0,2, 0,2);
    T2("(.?.?)*",                        "xxx",     0,3, 2,3);
    T2("(.?.?)*",                        "xxxx",    0,4, 2,4);
    T4("a?((ab)?)(b?)",                  "ab",      0,2, 1,1, -1,-1, 1,2);
    T4("(a?)((ab)?)b?",                  "ab",      0,2, 0,1, 1,1, -1,-1);
    T3("a?((ab)?)b?",                    "ab",      0,2, 1,1, -1,-1);
    T2("(a*){2}",                        "xxxxx",   0,0, 0,0);
    T3("(ab?)(b?a)",                     "aba",     0,3, 0,2, 2,3);
    T3("(a|ab)(ba|a)",                   "aba",     0,3, 0,2, 2,3);
    T2("(a|ab|ba)",                      "aba",     0,2, 0,2);
    T3("(a|ab|ba)(a|ab|ba)",             "aba",     0,3, 0,2, 2,3);
    T2("(a|ab|ba)*",                     "aba",     0,3, 2,3);
    T2("(aba|a*b)",                      "ababa",   0,3, 0,3);
    T3("(aba|a*b)(aba|a*b)",             "ababa",   0,5, 0,2, 2,5);
    T0("(aba|a*b)(aba|a*b)(aba|a*b)",    "ababa");
    T2("(aba|a*b)*",                     "ababa",   0,5, 2,5);
    T2("(aba|ab|a)",                     "ababa",   0,3, 0,3);
    T3("(aba|ab|a)(aba|ab|a)",           "ababa",   0,5, 0,2, 2,5);
    T4("(aba|ab|a)(aba|ab|a)(aba|ab|a)", "ababa",   0,5, 0,2, 2,4, 4,5);
    T2("(aba|ab|a)*",                    "ababa",   0,5, 2,5);
    T3("(a(b)?)",                        "aba",     0,2, 0,2, 1,2);
    T5("(a(b)?)(a(b)?)",                 "aba",     0,3, 0,2, 1,2, 2,3, -1,-1);
    T3("(a(b)?)+",                       "aba",     0,3, 2,3, -1,-1);
    T3("(.*)(.*)",                       "xx",      0,2, 0,2, 2,2);
    T2(".*(.*)",                         "xx",      0,2, 2,2);
    T2("(a.*z|b.*y)",                    "azbazby", 0,5, 0,5);
    T3("(a.*z|b.*y)(a.*z|b.*y)",         "azbazby", 0,7, 0,5, 5,7);
    T2("(a.*z|b.*y)*",                   "azbazby", 0,7, 5,7);
    T3("(.|..)(.*)",                     "ab",      0,2, 0,2, 2,2);
    T4("((..)*(...)*)",                  "xxx",     0,3, 0,3, -1,-1, 0,3);
    T7("((..)*(...)*)((..)*(...)*)",     "xxx",     0,3, 0,3, -1,-1, 0,3, 3,3, -1,-1, -1,-1);
    T4("((..)*(...)*)*",                 "xxx",     0,3, 0,3, -1,-1, 0,3);

    // nullsubexpr
    T2("(a*)*",      "a",        0,1, 0,1);
    T2("(a*)*",      "x",        0,0, 0,0);
    T2("(a*)*",      "aaaaaa",   0,6, 0,6);
    T2("(a*)*",      "aaaaaax",  0,6, 0,6);
    T2("(a*)+",      "a",        0,1, 0,1);
    T2("(a*)+",      "x",        0,0, 0,0);
    T2("(a*)+",      "aaaaaa",   0,6, 0,6);
    T2("(a*)+",      "aaaaaax",  0,6, 0,6);
    T2("(a+)*",      "a",        0,1, 0,1);
    T2("(a+)*",      "x",        0,0, -1,-1);
    T2("(a+)*",      "aaaaaa",   0,6, 0,6);
    T2("(a+)*",      "aaaaaax",  0,6, 0,6);
    T2("(a+)+",      "a",        0,1, 0,1);
    T0("(a+)+",      "x");
    T2("(a+)+",      "aaaaaa",   0,6, 0,6);
    T2("(a+)+",      "aaaaaax",  0,6, 0,6);
    T2("([a]*)*",    "a",        0,1, 0,1);
    T2("([a]*)*",    "x",        0,0, 0,0);
    T2("([a]*)*",    "aaaaaa",   0,6, 0,6);
    T2("([a]*)*",    "aaaaaax",  0,6, 0,6);
    T2("([a]*)+",    "a",        0,1, 0,1);
    T2("([a]*)+",    "x",        0,0, 0,0);
    T2("([a]*)+",    "aaaaaa",   0,6, 0,6);
    T2("([a]*)+",    "aaaaaax",  0,6, 0,6);
    T2("([^b]*)*",   "a",        0,1, 0,1);
    T2("([^b]*)*",   "b",        0,0, 0,0);
    T2("([^b]*)*",   "aaaaaa",   0,6, 0,6);
    T2("([^b]*)*",   "aaaaaab",  0,6, 0,6);
    T2("([ab]*)*",   "a",        0,1, 0,1);
    T2("([ab]*)*",   "aaaaaa",   0,6, 0,6);
    T2("([ab]*)*",   "ababab",   0,6, 0,6);
    T2("([ab]*)*",   "bababa",   0,6, 0,6);
    T2("([ab]*)*",   "b",        0,1, 0,1);
    T2("([ab]*)*",   "bbbbbb",   0,6, 0,6);
    T2("([ab]*)*",   "aaaabcde", 0,5, 0,5);
    T2("([^a]*)*",   "b",        0,1, 0,1);
    T2("([^a]*)*",   "bbbbbb",   0,6, 0,6);
    T2("([^a]*)*",   "aaaaaa",   0,0, 0,0);
    T2("([^ab]*)*",  "ccccxx",   0,6, 0,6);
    T2("([^ab]*)*",  "ababab",   0,0, 0,0);
    T3("((z)+|a)*",  "zabcde",   0,2, 1,2, -1,-1);
    T2("(a)",        "aaa",      0,1, 0,1);
    T3("(a*)*(x)",   "x",        0,1, 0,0, 0,1);
    T3("(a*)*(x)",   "ax",       0,2, 0,1, 1,2);
    T3("(a*)*(x)",   "axa",      0,2, 0,1, 1,2);
    T3("(a*)+(x)",   "x",        0,1, 0,0, 0,1);
    T3("(a*)+(x)",   "ax",       0,2, 0,1, 1,2);
    T3("(a*)+(x)",   "axa",      0,2, 0,1, 1,2);
    T3("(a*){2}(x)", "x",        0,1, 0,0, 0,1);
    T3("(a*){2}(x)", "ax",       0,2, 1,1, 1,2);
    T3("(a*){2}(x)", "axa",      0,2, 1,1, 1,2);

    T4("(()|.)(b)",     "ab",    0,2, 0,1, -1,-1, 1,2);
    T4("(()|[ab])(b)",  "ab",    0,2, 0,1, -1,-1, 1,2);
    T3("(()|[ab])+b",   "aaab",  0,4, 2,3, -1,-1);
    T4("(.|())(b)",     "ab",    0,2, 0,1, -1,-1, 1,2);
    T4("([ab]|())(b)",  "ab",    0,2, 0,1, -1,-1, 1,2);
    T3("([ab]|())+b",   "aaab",  0,4, 2,3, -1,-1);
    T3("(.?)(b)",       "ab",    0,2, 0,1, 1,2);

    // other
    T2("(a|aa)*",                            "aaa",         0,3, 2,3);
    T2("(a|aa)*",                            "aaaa",        0,4, 2,4);
    T2("(aa|a)*",                            "aaa",         0,3, 2,3);
    T2("(aa|a)*",                            "aaaa",        0,4, 2,4);
    T2("a|(a)",                              "a",           0,1, -1,-1);
    T2("(a)|a",                              "a",           0,1, 0,1);
    T3("(b)a|b(a)",                          "ba",          0,2, 0,1, -1,-1);
    T3("b(a)|(b)a",                          "ba",          0,2, 1,2, -1,-1);
    T2("a*|(a|aa)*",                         "aa",          0,2, -1,-1);
    T2("(a|aa)*|a*",                         "aa",          0,2, 0,2);
    T2("(aa*|aaa*)*",                        "aaaaaa",      0,6, 0,6);
    T3("(aa*|aaa*)(aa*|aaa*)",               "aaaaaa",      0,6, 0,5, 5,6);
    T2("(aa*|aaa*){2}",                      "aaaaaa",      0,6, 5,6);
    T7("((aa)*|(aaa)*)((aa)*|(aaa)*)",       "aaaaaa",      0,6, 0,6, 4,6, -1,-1, 6,6, -1,-1, -1,-1);
    T4("((aa)*|(aaa)*){2}",                  "aaaaaa",      0,6, 6,6, -1,-1, -1,-1);
    T3("(aa)*|(aaa)*",                       "aaaaaa",      0,6, 4,6, -1,-1);
    T2("(X|Xa|Xab|Xaba|abab|baba|bY|Y)*",    "XY",          0,2, 1,2);
    T2("(X|Xa|Xab|Xaba|abab|baba|bY|Y)*",    "XabY",        0,4, 3,4);
    T2("(X|Xa|Xab|Xaba|abab|baba|bY|Y)*",    "XababY",      0,6, 4,6);
    T2("(X|Xa|Xab|Xaba|abab|baba|bY|Y)*",    "XabababY",    0,8, 7,8);
    T2("(X|Xa|Xab|Xaba|abab|baba|bY|Y)*",    "XababababY",  0,10, 8,10);
    T0("(y){2}",                             "");
    T0("(y){2}",                             "y");
    T2("(y){2}",                             "yy",          0,2, 1,2);
    T2("(y){0,2}",                           "",            0,0, -1,-1);
    T2("(y){0,2}",                           "y",           0,1, 0,1);
    T2("(y){0,2}",                           "yy",          0,2, 1,2);
    T0("(y){1,2}",                           "");
    T2("(y){1,2}",                           "y",           0,1, 0,1);
    T2("(y){1,2}",                           "yy",          0,2, 1,2);
    T0("(y){1,2}y",                          "");
    T0("(y){1,2}y",                          "y");
    T2("(y){1,2}y",                          "yy",          0,2, 0,1);
    T2("(y){1,2}y",                          "yyy",         0,3, 1,2);
    T0("(y){1,2}y?",                         "");
    T2("(y){1,2}y?",                         "y",           0,1, 0,1);
    T2("(y){1,2}y?",                         "yy",          0,2, 1,2);
    T2("(y){1,2}y?",                         "yyy",         0,3, 1,2);
    T0("(y){2,}",                            "");
    T0("(y){2,}",                            "y");
    T2("(y){2,}",                            "yy",          0,2, 1,2);
    T2("(y){2,}",                            "yyy",         0,3, 2,3);
    T2("(y?){2}",                            "",            0,0, 0,0);
    T2("(y?){2}",                            "y",           0,1, 1,1);
    T2("(y?){2}",                            "yy",          0,2, 1,2);
    T2("(y?){0,2}",                          "",            0,0, 0,0);
    T3("(y?){0,2}|(y?)",                     "y",           0,1, 0,1, -1,-1);
    T2("(y?){0,2}",                          "y",           0,1, 0,1);
    T2("(y?){0,2}",                          "yy",          0,2, 1,2);
    T2("(y?){1,2}",                          "",            0,0, 0,0);
    T2("(y?){1,2}",                          "y",           0,1, 0,1);
    T2("(y?){1,2}",                          "yy",          0,2, 1,2);
    T0("(y?){1,2}y",                         "");
    T2("(y?){1,2}y",                         "y",           0,1, 0,0);
    T2("(y?){1,2}y",                         "yy",          0,2, 0,1);
    T2("(y?){1,2}y",                         "yyy",         0,3, 1,2);
    T2("(y?){1,2}y?",                        "",            0,0, 0,0);
    T2("(y?){1,2}y?",                        "y",           0,1, 0,1);
    T2("(y?){1,2}y?",                        "yy",          0,2, 1,2);
    T2("(y?){1,2}y?",                        "yyy",         0,3, 1,2);
    T2("(y?){2,}",                           "",            0,0, 0,0);
    T2("(y?){2,}",                           "y",           0,1, 1,1);
    T2("(y?){2,}",                           "yy",          0,2, 1,2);
    T2("(y?){2,}",                           "yyy",         0,3, 2,3);
    T3("(y|(x?)){1,3}",                      "y",           0,1, 0,1, -1,-1);
    T2("(y[y]?){3}",                         "yyyy",        0,4, 3,4);

    // repetition
    T0("((..)|(.))",                         "");
    T0("((..)|(.))((..)|(.))",               "");
    T0("((..)|(.))((..)|(.))((..)|(.))",     "");
    T0("((..)|(.)){1}",                      "");
    T0("((..)|(.)){2}",                      "");
    T0("((..)|(.)){3}",                      "");
    T4("((..)|(.))*",                        "",            0,0, -1,-1, -1,-1, -1,-1);
    T4("((..)|(.))",                         "a",           0,1, 0,1, -1,-1, 0,1);
    T0("((..)|(.))((..)|(.))",               "a");
    T0("((..)|(.))((..)|(.))((..)|(.))",     "a");
    T4("((..)|(.)){1}",                      "a",           0,1, 0,1, -1,-1, 0,1);
    T0("((..)|(.)){2}",                      "a");
    T0("((..)|(.)){3}",                      "a");
    T4("((..)|(.))*",                        "a",           0,1, 0,1, -1,-1, 0,1);
    T4("((..)|(.))",                         "aa",          0,2, 0,2, 0,2, -1,-1);
    T7("((..)|(.))((..)|(.))",               "aa",          0,2, 0,1, -1,-1, 0,1, 1,2, -1,-1, 1,2);
    T0("((..)|(.))((..)|(.))((..)|(.))",     "aa");
    T4("((..)|(.)){1}",                      "aa",          0,2, 0,2, 0,2, -1,-1);
    T4("((..)|(.)){2}",                      "aa",          0,2, 1,2, -1,-1, 1,2);
    T0("((..)|(.)){3}",                      "aa");
    T4("((..)|(.))*",                        "aa",          0,2, 0,2, 0,2, -1,-1);
    T4("((..)|(.))",                         "aaa",         0,2, 0,2, 0,2, -1,-1);
    T7("((..)|(.))((..)|(.))",               "aaa",         0,3, 0,2, 0,2, -1,-1, 2,3, -1,-1, 2,3);
    T10("((..)|(.))((..)|(.))((..)|(.))",    "aaa",         0,3, 0,1, -1,-1, 0,1, 1,2, -1,-1, 1,2, 2,3, -1,-1, 2,3);
    T4("((..)|(.)){1}",                      "aaa",         0,2, 0,2, 0,2, -1,-1);
    T4("((..)|(.)){2}",                      "aaa",         0,3, 2,3, -1,-1, 2,3);
    T4("((..)|(.)){3}",                      "aaa",         0,3, 2,3, -1,-1, 2,3);
    T4("((..)|(.))*",                        "aaa",         0,3, 2,3, -1,-1, 2,3);
    T4("((..)|(.))",                         "aaaa",        0,2, 0,2, 0,2, -1,-1);
    T7("((..)|(.))((..)|(.))",               "aaaa",        0,4, 0,2, 0,2, -1,-1, 2,4, 2,4, -1,-1);
    T10("((..)|(.))((..)|(.))((..)|(.))",    "aaaa",        0,4, 0,2, 0,2, -1,-1, 2,3, -1,-1, 2,3, 3,4, -1,-1, 3,4);
    T4("((..)|(.)){1}",                      "aaaa",        0,2, 0,2, 0,2, -1,-1);
    T4("((..)|(.)){2}",                      "aaaa",        0,4, 2,4, 2,4, -1,-1);
    T4("((..)|(.)){3}",                      "aaaa",        0,4, 3,4, -1,-1, 3,4);
    T4("((..)|(.))*",                        "aaaa",        0,4, 2,4, 2,4, -1,-1);
    T4("((..)|(.))",                         "aaaaa",       0,2, 0,2, 0,2, -1,-1);
    T7("((..)|(.))((..)|(.))",               "aaaaa",       0,4, 0,2, 0,2, -1,-1, 2,4, 2,4, -1,-1);
    T10("((..)|(.))((..)|(.))((..)|(.))",    "aaaaa",       0,5, 0,2, 0,2, -1,-1, 2,4, 2,4, -1,-1, 4,5, -1,-1, 4,5);
    T4("((..)|(.)){1}",                      "aaaaa",       0,2, 0,2, 0,2, -1,-1);
    T4("((..)|(.)){2}",                      "aaaaa",       0,4, 2,4, 2,4, -1,-1);
    T4("((..)|(.)){3}",                      "aaaaa",       0,5, 4,5, -1,-1, 4,5);
    T4("((..)|(.))*",                        "aaaaa",       0,5, 4,5, -1,-1, 4,5);
    T4("((..)|(.))",                         "aaaaaa",      0,2, 0,2, 0,2, -1,-1);
    T7("((..)|(.))((..)|(.))",               "aaaaaa",      0,4, 0,2, 0,2, -1,-1, 2,4, 2,4, -1,-1);
    T10("((..)|(.))((..)|(.))((..)|(.))",    "aaaaaa",      0,6, 0,2, 0,2, -1,-1, 2,4, 2,4, -1,-1, 4,6, 4,6, -1,-1);
    T4("((..)|(.)){1}",                      "aaaaaa",      0,2, 0,2, 0,2, -1,-1);
    T4("((..)|(.)){2}",                      "aaaaaa",      0,4, 2,4, 2,4, -1,-1);
    T4("((..)|(.)){3}",                      "aaaaaa",      0,6, 4,6, 4,6, -1,-1);
    T4("((..)|(.))*",                        "aaaaaa",      0,6, 4,6, 4,6, -1,-1);
    T2("X(.?){0,}Y",                         "X1234567Y",   0,9, 7,8);
    T2("X(.?){1,}Y",                         "X1234567Y",   0,9, 7,8);
    T2("X(.?){2,}Y",                         "X1234567Y",   0,9, 7,8);
    T2("X(.?){3,}Y",                         "X1234567Y",   0,9, 7,8);
    T2("X(.?){4,}Y",                         "X1234567Y",   0,9, 7,8);
    T2("X(.?){5,}Y",                         "X1234567Y",   0,9, 7,8);
    T2("X(.?){6,}Y",                         "X1234567Y",   0,9, 7,8);
    T2("X(.?){7,}Y",                         "X1234567Y",   0,9, 7,8);
    T2("X(.?){8,}Y",                         "X1234567Y",   0,9, 8,8);
    T2("X(.?){0,8}Y",                        "X1234567Y",   0,9, 7,8);
    T2("X(.?){1,8}Y",                        "X1234567Y",   0,9, 7,8);
    T2("X(.?){2,8}Y",                        "X1234567Y",   0,9, 7,8);
    T2("X(.?){3,8}Y",                        "X1234567Y",   0,9, 7,8);
    T2("X(.?){4,8}Y",                        "X1234567Y",   0,9, 7,8);
    T2("X(.?){5,8}Y",                        "X1234567Y",   0,9, 7,8);
    T2("X(.?){6,8}Y",                        "X1234567Y",   0,9, 7,8);
    T2("X(.?){7,8}Y",                        "X1234567Y",   0,9, 7,8);
    T2("X(.?){8,8}Y",                        "X1234567Y",   0,9, 8,8);
    T3("(a|ab|c|bcd){0,}(d*)",               "ababcd",      0,6, 3,6, 6,6);
    T3("(a|ab|c|bcd){1,}(d*)",               "ababcd",      0,6, 3,6, 6,6);
    T3("(a|ab|c|bcd){2,}(d*)",               "ababcd",      0,6, 3,6, 6,6);
    T3("(a|ab|c|bcd){3,}(d*)",               "ababcd",      0,6, 3,6, 6,6);
    T0("(a|ab|c|bcd){4,}(d*)",               "ababcd");
    T3("(a|ab|c|bcd){0,10}(d*)",             "ababcd",      0,6, 3,6, 6,6);
    T3("(a|ab|c|bcd){1,10}(d*)",             "ababcd",      0,6, 3,6, 6,6);
    T3("(a|ab|c|bcd){2,10}(d*)",             "ababcd",      0,6, 3,6, 6,6);
    T3("(a|ab|c|bcd){3,10}(d*)",             "ababcd",      0,6, 3,6, 6,6);
    T0("(a|ab|c|bcd){4,10}(d*)",             "ababcd");
    T3("(a|ab|c|bcd)*(d*)",                  "ababcd",      0,6, 3,6, 6,6);
    T3("(a|ab|c|bcd)+(d*)",                  "ababcd",      0,6, 3,6, 6,6);
    T3("(ab|a|c|bcd){0,}(d*)",               "ababcd",      0,6, 3,6, 6,6);
    T3("(ab|a|c|bcd){1,}(d*)",               "ababcd",      0,6, 3,6, 6,6);
    T3("(ab|a|c|bcd){2,}(d*)",               "ababcd",      0,6, 3,6, 6,6);
    T3("(ab|a|c|bcd){3,}(d*)",               "ababcd",      0,6, 3,6, 6,6);
    T0("(ab|a|c|bcd){4,}(d*)",               "ababcd");
    T3("(ab|a|c|bcd){0,10}(d*)",             "ababcd",      0,6, 3,6, 6,6);
    T3("(ab|a|c|bcd){1,10}(d*)",             "ababcd",      0,6, 3,6, 6,6);
    T3("(ab|a|c|bcd){2,10}(d*)",             "ababcd",      0,6, 3,6, 6,6);
    T3("(ab|a|c|bcd){3,10}(d*)",             "ababcd",      0,6, 3,6, 6,6);
    T0("(ab|a|c|bcd){4,10}(d*)",             "ababcd");
    T3("(ab|a|c|bcd)*(d*)",                  "ababcd",      0,6, 3,6, 6,6);
    T3("(ab|a|c|bcd)+(d*)",                  "ababcd",      0,6, 3,6, 6,6);

    // rightassoc
    T4("(a|ab)(c|bcd)(d*)",                  "abcd",        0,4, 0,2, 2,3, 3,4);
    T4("(a|ab)(bcd|c)(d*)",                  "abcd",        0,4, 0,2, 2,3, 3,4);
    T4("(ab|a)(c|bcd)(d*)",                  "abcd",        0,4, 0,2, 2,3, 3,4);
    T4("(ab|a)(bcd|c)(d*)",                  "abcd",        0,4, 0,2, 2,3, 3,4);
    T4("(a*)(b|abc)(c*)",                    "abc",         0,3, 0,1, 1,2, 2,3);
    T4("(a*)(abc|b)(c*)",                    "abc",         0,3, 0,1, 1,2, 2,3);
    T4("(a*)(b|abc)(c*)",                    "abc",         0,3, 0,1, 1,2, 2,3);
    T4("(a*)(abc|b)(c*)",                    "abc",         0,3, 0,1, 1,2, 2,3);
    T4("(a|ab)(c|bcd)(d|.*)",                "abcd",        0,4, 0,2, 2,3, 3,4);
    T4("(a|ab)(bcd|c)(d|.*)",                "abcd",        0,4, 0,2, 2,3, 3,4);
    T4("(ab|a)(c|bcd)(d|.*)",                "abcd",        0,4, 0,2, 2,3, 3,4);
    T4("(ab|a)(bcd|c)(d|.*)",                "abcd",        0,4, 0,2, 2,3, 3,4);

    if (!(flags & REG_NFA)) {
        T3("((a?){1,300})*", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0,50, 0,50, 49,50);
    }
    else if (!(flags & (REG_SLOWPREC | REG_KUKLEWICZ))) {
        T3("((a?){1,1000})*", "aaaa", 0,4, 0,4, 3,4);

        T8("(((((aa)|((a?)*))*){0,10}){0,10}){0,10}", "", 0,0, 0,0, 0,0, 0,0, 0,0, -1,-1, 0,0, 0,0);
        if (!((flags & REG_BACKWARD) && !(flags & REG_GTOP))) {
            // expected failures for Cox algorithm
            T8("(((((aa)|((a?)*))*){0,10}){0,10}){0,10}", "aaa", 0,3, 0,3, 0,3, 0,3, 0,3, -1,-1, 0,3, 2,3);
            T8("(((((aa)|((a?)*))*){0,10}){0,10}){0,10}", "aaaaa", 0,5, 0,5, 0,5, 0,5, 0,5, -1,-1, 0,5, 4,5);
        }
    }

    T6("((((a?)+)|(aa))+)", "aaa", 0,3, 0,3, 0,3, 0,3, 2,3, -1,-1);
    T6("(((aa)|((a?)+))+)", "aaa", 0,3, 0,3, 0,3, -1,-1, 0,3, 2,3);
    T4("((a?){1,2}|(a)*)*", "aaaa", 0,4, 0,4, -1,-1, 3,4);
    T5("(((a?){2,3}|(a)*))*", "aaaaa", 0,5, 0,5, 0,5, -1,-1, 4,5);
    T5("(((a?)|(a?a?))+)", "aa", 0,2, 0,2, 0,2, -1,-1, 0,2);
    T9("((((a)*))*|((((a))*))+)*", "aa", 0,2, 0,2, 0,2, 0,2, 1,2, -1,-1, -1,-1, -1,-1, -1,-1);
    T6("(((a)*)*|((a)*)+)*", "aa", 0,2, 0,2, 0,2, 1,2, -1,-1, -1,-1);
    T7("(((a)+)|(((a)+)?))+", "aa", 0,2, 0,2, 0,2, 1,2, -1,-1, -1,-1, -1,-1);
    T3("(a*|(a)*)*", "aa", 0,2, 0,2, -1,-1);

    return e;
}

static int test_all_leftmost(int flags)
{
    int e = 0;

    T1("a",        "a",    0,1);
    T2("(a)",      "a",    0,1, 0,1);
    T2("(a*)",     "aaa",  0,3, 0,3);
    T3("(a*)(b*)", "aabb", 0,4, 0,2, 2,4);
    T3("(a*)(a*)", "aa",   0,2, 0,2, 2,2);
    T2("(a|aa)*",  "aa",   0,2, 1,2);
    T3("(a)|(a)",  "a",    0,1, 0,1, -1,-1);
    T3("(a)*(a)*", "a",    0,1, 0,1, -1,-1);

    T1("[a]",      "a",    0,1);
    T0("[a]",      "b");
    T0("[^a]",     "a");
    T1("[^a]",     "b",    0,1);
    T1("[ac]*",    "ac",   0,2);
    T1("[a-c]*",   "abc",  0,3);
    T1("[]]",      "]",    0,1);
    T0("[^]]",     "]");
    T1("[^]]",     "a",    0,1);
    T1("[-]",      "-",    0,1);
    T1("[]-]*",    "]-",   0,2);
    T1("[-a]*",    "-a",   0,2);
    T1("[a-]*",    "-a",   0,2);
    T1("[-a-]*",   "-a",   0,2);

    // basic
    T3("(..)*(...)*",              "a",           0,0, -1,-1, -1,-1);
    T3("(..)*(...)*",              "abcd",        0,4, 2,4, -1,-1);
    T3("(ab|a)(bc|c)",             "abc",         0,3, 0,2, 2,3);
    T2("(ab)c|abc",                "abc",         0,3, 0,2);
    T4("(a*)(b?)(b+)b{3}",         "aaabbbbbbb",  0,10, 0,3, 3,4, 4,7);
    T4("(a*)(b{0,1})(b{1,})b{3}",  "aaabbbbbbb",  0,10, 0,3, 3,4, 4,7);
    T3("((a|a)|a)",                "a",           0,1, 0,1, 0,1);
    T3("(a*)(a|aa)",               "aaaa",        0,4, 0,3, 3,4);
    T2("a*(a.|aa)",                "aaaa",        0,4, 2,4);
    T4("a(b)|c(d)|a(e)f",          "aef",         0,3, -1,-1, -1,-1, 1,2);
    T2("(a|b)?.*",                 "b",           0,1, 0,1);
    T3("(a|b)c|a(b|c)",            "ac",          0,2, 0,1, -1,-1);
    T3("(a|b)c|a(b|c)",            "ab",          0,2, -1,-1, 1,2);
    T3("(a|b)*c|(a|ab)*c",         "abc",         0,3, 1,2, -1,-1);
    T3("(.a|.b).*|.*(.a|.b)",      "xa",          0,2, 0,2, -1,-1);
    T2("a?(ab|ba)ab",              "abab",        0,4, 0,2);
    T2("a?(a[c]{0}b|ba)ab",        "abab",        0,4, 0,2);
    T1("ab|abab",                  "abbabab",     0,2);
    T3("(aa|aaa)*|(a|aaaaa)",      "aa",          0,2, 0,2, -1,-1);
    T3("(a.|.a.)*|(a|.a...)",      "aa",          0,2, 0,2, -1,-1);
    T4("(a)(b)(c)",                "abc",         0,3, 0,1, 1,2, 2,3);
    T7("((((((x))))))",            "x",           0,1, 0,1, 0,1, 0,1, 0,1, 0,1, 0,1);
    T7("((((((x))))))*",           "xx",          0,2, 1,2, 1,2, 1,2, 1,2, 1,2, 1,2);
    T2("a?(ab|ba)*",               "ababababababababababababababababababababababababababababababababababababababababa", 0,81, 79,81);
    T1("a*a*a*a*a*b",              "aaaaaaaaab",  0,10);
    T1("a[b]+bc",                  "abbc",        0,4);
    T1("a[b]+bc",                  "abbbbc",      0,6);
    T1("a[b]?bc",                  "abbc",        0,4);
    T1("a[b]?bc",                  "abc",         0,3);
    T1("a[b]?c",                   "abc",         0,3);
    T1("ab|cd",                    "abc",         0,2);
    T1("ab|cd",                    "abcd",        0,2);
    T3("((a))",                    "abc",         0,1, 0,1, 0,1);
    T3("(a)b(c)",                  "abc",         0,3, 0,1, 2,3);
    T1("a*",                       "aaa",         0,3);
    T2("(a*)*",                    "-",           0,0, 0,0);
    T2("(a*)+",                    "-",           0,0, 0,0);
    T2("(a*|b)*",                  "-",           0,0, 0,0);
    T2("(a+|b)*",                  "ab",          0,2, 1,2);
    T2("(a+|b)+",                  "ab",          0,2, 1,2);
    T2("(a+|b)?",                  "ab",          0,1, 0,1);
    T2("([abc])*d",                "abbbcd",      0,6, 4,5);
    T2("([abc])*bcd",              "abcd",        0,4, 0,1);
    T1("a|b|c|d|e",                "e",           0,1);
    T2("(a|b|c|d|e)f",             "ef",          0,2, 0,1);
    T3("((a*|b))*",                "-",           0,0, 0,0, 0,0);
    T2("(ab|a[b]*)bc",             "abc",         0,3, 0,1);
    T2("a([bc]*)c*",               "abc",         0,3, 1,3);
    T3("a([bc]*)(c*d)",            "abcd",        0,4, 1,3, 3,4);
    T3("a([bc]+)(c*d)",            "abcd",        0,4, 1,3, 3,4);
    T3("a([bc]*)(c+d)",            "abcd",        0,4, 1,2, 2,4);
    T1("a[bcd]*dcdcde",            "adcdcde",     0,7);
    T2("(ab|a)b*c",                "abc",         0,3, 0,2);
    T5("((a)(b)c)(d)",             "abcd",        0,4, 0,3, 0,1, 1,2, 3,4);
    T3("(.*)c(.*)",                "abcde",       0,5, 0,2, 3,5);
    T2("a(bc)d",                   "abcd",        0,4, 1,3);
    T2("a+(b|c)*d+",               "aabcdd",      0,6, 3,4);

    // categorize
    T4("(a*)(ab)*(b*)",            "abc",    0,2, 0,1, -1,-1, 1,2);
    T7("((a*)(ab)*)((b*)(a*))",    "aba",    0,3, 0,1, 0,1, -1,-1, 1,3, 1,2, 2,3);
    T2("(...?.?)*",                "xxxxxx", 0,6, 4,6);
    T3("(a|ab)(bc|c)",             "abcabc", 0,3, 0,1, 1,3);
    T3("(aba|a*b)(aba|a*b)",       "ababa",  0,5, 0,2, 2,5);
    T2("(a*){2}",                  "xxxxx",  0,0, 0,0);
    T2("(a*)*",                    "a",      0,1, 0,1);
    T2("(aba|a*b)*",               "ababa",  0,5, 2,5);
    T3("(a(b)?)+",                 "aba",    0,3, 2,3, -1,-1);
    T2(".*(.*)",                   "ab",     0,2, 2,2);
    T6("(a?)((ab)?)(b?)a?(ab)?b?", "abab",   0,4, 0,1, 1,1, -1,-1, 1,2, -1,-1);

    // forcedassoc
    T3("(a|ab)(c|bcd)",       "abcd", 0,4, 0,1, 1,4);
    T3("(a|ab)(bcd|c)",       "abcd", 0,4, 0,1, 1,4);
    T3("(ab|a)(c|bcd)",       "abcd", 0,4, 0,1, 1,4);
    T3("(ab|a)(bcd|c)",       "abcd", 0,4, 0,1, 1,4);
    T5("((a|ab)(c|bcd))(d*)", "abcd", 0,4, 0,4, 0,1, 1,4, 4,4);
    T5("((a|ab)(bcd|c))(d*)", "abcd", 0,4, 0,4, 0,1, 1,4, 4,4);
    T5("((ab|a)(c|bcd))(d*)", "abcd", 0,4, 0,3, 0,2, 2,3, 3,4);
    T5("((ab|a)(bcd|c))(d*)", "abcd", 0,4, 0,3, 0,2, 2,3, 3,4);
    T5("(a|ab)((c|bcd)(d*))", "abcd", 0,4, 0,1, 1,4, 1,4, 4,4);
    T5("(a|ab)((bcd|c)(d*))", "abcd", 0,4, 0,1, 1,4, 1,4, 4,4);
    T5("(ab|a)((c|bcd)(d*))", "abcd", 0,4, 0,2, 2,4, 2,3, 3,4);
    T5("(ab|a)((bcd|c)(d*))", "abcd", 0,4, 0,2, 2,4, 2,3, 3,4);
    T3("(a*)(b|abc)",         "abc",  0,3, 0,0, 0,3);
    T3("(a*)(abc|b)",         "abc",  0,3, 0,0, 0,3);
    T5("((a*)(b|abc))(c*)",   "abc",  0,3, 0,2, 0,1, 1,2, 2,3);
    T5("((a*)(abc|b))(c*)",   "abc",  0,3, 0,2, 0,1, 1,2, 2,3);
    T5("(a*)((b|abc)(c*))",   "abc",  0,3, 0,1, 1,3, 1,2, 2,3);
    T5("(a*)((abc|b)(c*))",   "abc",  0,3, 0,1, 1,3, 1,2, 2,3);
    T3("(a*)(b|abc)",         "abc",  0,3, 0,0, 0,3);
    T3("(a*)(abc|b)",         "abc",  0,3, 0,0, 0,3);
    T5("((a*)(b|abc))(c*)",   "abc",  0,3, 0,2, 0,1, 1,2, 2,3);
    T5("((a*)(abc|b))(c*)",   "abc",  0,3, 0,2, 0,1, 1,2, 2,3);
    T5("(a*)((b|abc)(c*))",   "abc",  0,3, 0,1, 1,3, 1,2, 2,3);
    T5("(a*)((abc|b)(c*))",   "abc",  0,3, 0,1, 1,3, 1,2, 2,3);
    T2("(a|ab)",              "ab",   0,2, 0,2);
    T2("(ab|a)",              "ab",   0,2, 0,2);
    T3("(a|ab)(b*)",          "ab",   0,2, 0,1, 1,2);
    T3("(ab|a)(b*)",          "ab",   0,2, 0,2, 2,2);

    // glennfowler
    T4("(a?)((ab)?)",                    "ab",      0,2, 0,0, 0,2, 0,2);
    T5("(a?)((ab)?)(b?)",                "ab",      0,2, 0,1, 1,1, -1,-1, 1,2);
    T6("((a?)((ab)?))(b?)",              "ab",      0,2, 0,1, 0,1, 1,1, -1,-1, 1,2);
    T6("(a?)(((ab)?)(b?))",              "ab",      0,2, 0,1, 1,2, 1,1, -1,-1, 1,2);
    T2("(.?)",                           "x",       0,1, 0,1);
    T2("(.?){1}",                        "x",       0,1, 0,1);
    T3("(.?)(.?)",                       "x",       0,1, 0,1, 1,1);
    T2("(.?){2}",                        "x",       0,1, 1,1);
    T2("(.?)*",                          "x",       0,1, 0,1);
    T2("(.?.?)",                         "xxx",     0,2, 0,2);
    T2("(.?.?){1}",                      "xxx",     0,2, 0,2);
    T3("(.?.?)(.?.?)",                   "xxx",     0,3, 0,2, 2,3);
    T2("(.?.?){2}",                      "xxx",     0,3, 2,3);
    T4("(.?.?)(.?.?)(.?.?)",             "xxx",     0,3, 0,2, 2,3, 3,3);
    T2("(.?.?){3}",                      "xxx",     0,3, 3,3);
    T2("(.?.?)*",                        "xxx",     0,3, 2,3);
    T4("a?((ab)?)(b?)",                  "ab",      0,2, 1,1, -1,-1, 1,2);
    T4("(a?)((ab)?)b?",                  "ab",      0,2, 0,1, 1,1, -1,-1);
    T3("a?((ab)?)b?",                    "ab",      0,2, 1,1, -1,-1);
    T2("(a*){2}",                        "xxxxx",   0,0, 0,0);
    T3("(ab?)(b?a)",                     "aba",     0,3, 0,2, 2,3);
    T3("(a|ab)(ba|a)",                   "aba",     0,3, 0,1, 1,3);
    T2("(a|ab|ba)",                      "aba",     0,2, 0,2);
    T3("(a|ab|ba)(a|ab|ba)",             "aba",     0,3, 0,1, 1,3);
    T2("(a|ab|ba)*",                     "aba",     0,3, 1,3);
    T2("(aba|a*b)",                      "ababa",   0,3, 0,3);
    T3("(aba|a*b)(aba|a*b)",             "ababa",   0,5, 0,2, 2,5);
    T0("(aba|a*b)(aba|a*b)(aba|a*b)",    "ababa");
    T2("(aba|a*b)*",                     "ababa",   0,5, 2,5);
    T2("(aba|ab|a)",                     "ababa",   0,3, 0,3);
    T3("(aba|ab|a)(aba|ab|a)",           "ababa",   0,5, 0,2, 2,5);
    T4("(aba|ab|a)(aba|ab|a)(aba|ab|a)", "ababa",   0,5, 0,2, 2,4, 4,5);
    T2("(aba|ab|a)*",                    "ababa",   0,5, 2,5);
    T3("(a(b)?)",                        "aba",     0,2, 0,2, 1,2);
    T5("(a(b)?)(a(b)?)",                 "aba",     0,3, 0,2, 1,2, 2,3, -1,-1);
    T3("(a(b)?)+",                       "aba",     0,3, 2,3, -1,-1);
    T3("(.*)(.*)",                       "xx",      0,2, 0,2, 2,2);
    T2(".*(.*)",                         "xx",      0,2, 2,2);
    T2("(a.*z|b.*y)",                    "azbazby", 0,5, 0,5);
    T3("(a.*z|b.*y)(a.*z|b.*y)",         "azbazby", 0,7, 0,5, 5,7);
    T2("(a.*z|b.*y)*",                   "azbazby", 0,7, 5,7);
    T3("(.|..)(.*)",                     "ab",      0,2, 0,1, 1,2);
    T4("((..)*(...)*)",                  "xxx",     0,3, 0,3, -1,-1, 0,3);
    T7("((..)*(...)*)((..)*(...)*)",     "xxx",     0,3, 0,3, -1,-1, 0,3, 3,3, -1,-1, -1,-1);
    T4("((..)*(...)*)*",                 "xxx",     0,3, 0,3, -1,-1, 0,3);

    // nullsubexpr
    T2("(a*)*",      "a",        0,1, 0,1);
    T2("(a*)*",      "x",        0,0, 0,0);
    T2("(a*)*",      "aaaaaa",   0,6, 0,6);
    T2("(a*)*",      "aaaaaax",  0,6, 0,6);
    T2("(a*)+",      "a",        0,1, 0,1);
    T2("(a*)+",      "x",        0,0, 0,0);
    T2("(a*)+",      "aaaaaa",   0,6, 0,6);
    T2("(a*)+",      "aaaaaax",  0,6, 0,6);
    T2("(a+)*",      "a",        0,1, 0,1);
    T2("(a+)*",      "x",        0,0, -1,-1);
    T2("(a+)*",      "aaaaaa",   0,6, 0,6);
    T2("(a+)*",      "aaaaaax",  0,6, 0,6);
    T2("(a+)+",      "a",        0,1, 0,1);
    T0("(a+)+",      "x");
    T2("(a+)+",      "aaaaaa",   0,6, 0,6);
    T2("(a+)+",      "aaaaaax",  0,6, 0,6);
    T2("([a]*)*",    "a",        0,1, 0,1);
    T2("([a]*)*",    "x",        0,0, 0,0);
    T2("([a]*)*",    "aaaaaa",   0,6, 0,6);
    T2("([a]*)*",    "aaaaaax",  0,6, 0,6);
    T2("([a]*)+",    "a",        0,1, 0,1);
    T2("([a]*)+",    "x",        0,0, 0,0);
    T2("([a]*)+",    "aaaaaa",   0,6, 0,6);
    T2("([a]*)+",    "aaaaaax",  0,6, 0,6);
    T2("([^b]*)*",   "a",        0,1, 0,1);
    T2("([^b]*)*",   "b",        0,0, 0,0);
    T2("([^b]*)*",   "aaaaaa",   0,6, 0,6);
    T2("([^b]*)*",   "aaaaaab",  0,6, 0,6);
    T2("([ab]*)*",   "a",        0,1, 0,1);
    T2("([ab]*)*",   "aaaaaa",   0,6, 0,6);
    T2("([ab]*)*",   "ababab",   0,6, 0,6);
    T2("([ab]*)*",   "bababa",   0,6, 0,6);
    T2("([ab]*)*",   "b",        0,1, 0,1);
    T2("([ab]*)*",   "bbbbbb",   0,6, 0,6);
    T2("([ab]*)*",   "aaaabcde", 0,5, 0,5);
    T2("([^a]*)*",   "b",        0,1, 0,1);
    T2("([^a]*)*",   "bbbbbb",   0,6, 0,6);
    T2("([^a]*)*",   "aaaaaa",   0,0, 0,0);
    T2("([^ab]*)*",  "ccccxx",   0,6, 0,6);
    T2("([^ab]*)*",  "ababab",   0,0, 0,0);
    T3("((z)+|a)*",  "zabcde",   0,2, 1,2, -1,-1);
    T2("(a)",        "aaa",      0,1, 0,1);
    T3("(a*)*(x)",   "x",        0,1, 0,0, 0,1);
    T3("(a*)*(x)",   "ax",       0,2, 0,1, 1,2);
    T3("(a*)*(x)",   "axa",      0,2, 0,1, 1,2);
    T3("(a*)+(x)",   "x",        0,1, 0,0, 0,1);
    T3("(a*)+(x)",   "ax",       0,2, 0,1, 1,2);
    T3("(a*)+(x)",   "axa",      0,2, 0,1, 1,2);
    T3("(a*){2}(x)", "x",        0,1, 0,0, 0,1);
    T3("(a*){2}(x)", "ax",       0,2, 1,1, 1,2);
    T3("(a*){2}(x)", "axa",      0,2, 1,1, 1,2);
    T4("(()|.)(b)",     "ab",    0,2, 0,1, -1,-1, 1,2);
    T4("(()|[ab])(b)",  "ab",    0,2, 0,1, -1,-1, 1,2);
    T3("(()|[ab])+b",   "aaab",  0,4, 2,3, -1,-1);
    T4("(.|())(b)",     "ab",    0,2, 0,1, -1,-1, 1,2);
    T4("([ab]|())(b)",  "ab",    0,2, 0,1, -1,-1, 1,2);
    T3("([ab]|())+b",   "aaab",  0,4, 2,3, -1,-1);
    T3("(.?)(b)",       "ab",    0,2, 0,1, 1,2);

    // other
    T2("(a|aa)*",                            "aaa",         0,3, 2,3);
    T2("(a|aa)*",                            "aaaa",        0,4, 3,4);
    T2("(aa|a)*",                            "aaa",         0,3, 2,3);
    T2("(aa|a)*",                            "aaaa",        0,4, 2,4);
    T2("a|(a)",                              "a",           0,1, -1,-1);
    T2("(a)|a",                              "a",           0,1, 0,1);
    T3("(b)a|b(a)",                          "ba",          0,2, 0,1, -1,-1);
    T3("b(a)|(b)a",                          "ba",          0,2, 1,2, -1,-1);
    T2("a*|(a|aa)*",                         "aa",          0,2, -1,-1);
    T2("(a|aa)*|a*",                         "aa",          0,2, 1,2);
    T2("(aa*|aaa*)*",                        "aaaaaa",      0,6, 0,6);
    T3("(aa*|aaa*)(aa*|aaa*)",               "aaaaaa",      0,6, 0,5, 5,6);
    T2("(aa*|aaa*){2}",                      "aaaaaa",      0,6, 5,6);
    T7("((aa)*|(aaa)*)((aa)*|(aaa)*)",       "aaaaaa",      0,6, 0,6, 4,6, -1,-1, 6,6, -1,-1, -1,-1);
    T4("((aa)*|(aaa)*){2}",                  "aaaaaa",      0,6, 6,6, -1,-1, -1,-1);
    T3("(aa)*|(aaa)*",                       "aaaaaa",      0,6, 4,6, -1,-1);
    T2("(X|Xa|Xab|Xaba|abab|baba|bY|Y)*",    "XY",          0,2, 1,2);
    T2("(X|Xa|Xab|Xaba|abab|baba|bY|Y)*",    "XabY",        0,4, 2,4);
    T2("(X|Xa|Xab|Xaba|abab|baba|bY|Y)*",    "XababY",      0,6, 5,6);
    T2("(X|Xa|Xab|Xaba|abab|baba|bY|Y)*",    "XabababY",    0,8, 6,8);
    T2("(X|Xa|Xab|Xaba|abab|baba|bY|Y)*",    "XababababY",  0,10, 9,10);
    T0("(y){2}",                             "");
    T0("(y){2}",                             "y");
    T2("(y){2}",                             "yy",          0,2, 1,2);
    T2("(y){0,2}",                           "",            0,0, -1,-1);
    T2("(y){0,2}",                           "y",           0,1, 0,1);
    T2("(y){0,2}",                           "yy",          0,2, 1,2);
    T0("(y){1,2}",                           "");
    T2("(y){1,2}",                           "y",           0,1, 0,1);
    T2("(y){1,2}",                           "yy",          0,2, 1,2);
    T0("(y){1,2}y",                          "");
    T0("(y){1,2}y",                          "y");
    T2("(y){1,2}y",                          "yy",          0,2, 0,1);
    T2("(y){1,2}y",                          "yyy",         0,3, 1,2);
    T0("(y){1,2}y?",                         "");
    T2("(y){1,2}y?",                         "y",           0,1, 0,1);
    T2("(y){1,2}y?",                         "yy",          0,2, 1,2);
    T2("(y){1,2}y?",                         "yyy",         0,3, 1,2);
    T0("(y){2,}",                            "");
    T0("(y){2,}",                            "y");
    T2("(y){2,}",                            "yy",          0,2, 1,2);
    T2("(y){2,}",                            "yyy",         0,3, 2,3);
    T2("(y?){2}",                            "",            0,0, 0,0);
    T2("(y?){2}",                            "y",           0,1, 1,1);
    T2("(y?){2}",                            "yy",          0,2, 1,2);
    T2("(y?){0,2}",                          "",            0,0, 0,0);
    T2("(y?){0,2}",                          "y",           0,1, 1,1);
    T2("(y?){0,2}",                          "yy",          0,2, 1,2);
    T2("(y?){1,2}",                          "",            0,0, 0,0);
    T2("(y?){1,2}",                          "y",           0,1, 1,1);
    T2("(y?){1,2}",                          "yy",          0,2, 1,2);
    T0("(y?){1,2}y",                         "");
    T2("(y?){1,2}y",                         "y",           0,1, 0,0);
    T2("(y?){1,2}y",                         "yy",          0,2, 1,1);
    T2("(y?){1,2}y",                         "yyy",         0,3, 1,2);
    T2("(y?){1,2}y?",                        "",            0,0, 0,0);
    T2("(y?){1,2}y?",                        "y",           0,1, 1,1);
    T2("(y?){1,2}y?",                        "yy",          0,2, 1,2);
    T2("(y?){1,2}y?",                        "yyy",         0,3, 1,2);
    T2("(y?){2,}",                           "",            0,0, 0,0);
    T2("(y?){2,}",                           "y",           0,1, 1,1);
    T2("(y?){2,}",                           "yy",          0,2, 1,2);
    T2("(y?){2,}",                           "yyy",         0,3, 2,3);
    T3("(y|(x?)){1,3}",                      "y",           0,1, 1,1, 1,1);
    T2("(y[y]?){3}",                         "yyyy",        0,4, 3,4);

    // repetition
    T0("((..)|(.))",                         "");
    T0("((..)|(.))((..)|(.))",               "");
    T0("((..)|(.))((..)|(.))((..)|(.))",     "");
    T0("((..)|(.)){1}",                      "");
    T0("((..)|(.)){2}",                      "");
    T0("((..)|(.)){3}",                      "");
    T4("((..)|(.))*",                        "",            0,0, -1,-1, -1,-1, -1,-1);
    T4("((..)|(.))",                         "a",           0,1, 0,1, -1,-1, 0,1);
    T0("((..)|(.))((..)|(.))",               "a");
    T0("((..)|(.))((..)|(.))((..)|(.))",     "a");
    T4("((..)|(.)){1}",                      "a",           0,1, 0,1, -1,-1, 0,1);
    T0("((..)|(.)){2}",                      "a");
    T0("((..)|(.)){3}",                      "a");
    T4("((..)|(.))*",                        "a",           0,1, 0,1, -1,-1, 0,1);
    T4("((..)|(.))",                         "aa",          0,2, 0,2, 0,2, -1,-1);
    T7("((..)|(.))((..)|(.))",               "aa",          0,2, 0,1, -1,-1, 0,1, 1,2, -1,-1, 1,2);
    T0("((..)|(.))((..)|(.))((..)|(.))",     "aa");
    T4("((..)|(.)){1}",                      "aa",          0,2, 0,2, 0,2, -1,-1);
    T4("((..)|(.)){2}",                      "aa",          0,2, 1,2, -1,-1, 1,2);
    T0("((..)|(.)){3}",                      "aa");
    T4("((..)|(.))*",                        "aa",          0,2, 0,2, 0,2, -1,-1);
    T4("((..)|(.))",                         "aaa",         0,2, 0,2, 0,2, -1,-1);
    T7("((..)|(.))((..)|(.))",               "aaa",         0,3, 0,2, 0,2, -1,-1, 2,3, -1,-1, 2,3);
    T10("((..)|(.))((..)|(.))((..)|(.))",    "aaa",         0,3, 0,1, -1,-1, 0,1, 1,2, -1,-1, 1,2, 2,3, -1,-1, 2,3);
    T4("((..)|(.)){1}",                      "aaa",         0,2, 0,2, 0,2, -1,-1);
    T4("((..)|(.)){2}",                      "aaa",         0,3, 2,3, -1,-1, 2,3);
    T4("((..)|(.)){3}",                      "aaa",         0,3, 2,3, -1,-1, 2,3);
    T4("((..)|(.))*",                        "aaa",         0,3, 2,3, -1,-1, 2,3);
    T4("((..)|(.))",                         "aaaa",        0,2, 0,2, 0,2, -1,-1);
    T7("((..)|(.))((..)|(.))",               "aaaa",        0,4, 0,2, 0,2, -1,-1, 2,4, 2,4, -1,-1);
    T10("((..)|(.))((..)|(.))((..)|(.))",    "aaaa",        0,4, 0,2, 0,2, -1,-1, 2,3, -1,-1, 2,3, 3,4, -1,-1, 3,4);
    T4("((..)|(.)){1}",                      "aaaa",        0,2, 0,2, 0,2, -1,-1);
    T4("((..)|(.)){2}",                      "aaaa",        0,4, 2,4, 2,4, -1,-1);
    T4("((..)|(.)){3}",                      "aaaa",        0,4, 3,4, -1,-1, 3,4);
    T4("((..)|(.))*",                        "aaaa",        0,4, 2,4, 2,4, -1,-1);
    T4("((..)|(.))",                         "aaaaa",       0,2, 0,2, 0,2, -1,-1);
    T7("((..)|(.))((..)|(.))",               "aaaaa",       0,4, 0,2, 0,2, -1,-1, 2,4, 2,4, -1,-1);
    T10("((..)|(.))((..)|(.))((..)|(.))",    "aaaaa",       0,5, 0,2, 0,2, -1,-1, 2,4, 2,4, -1,-1, 4,5, -1,-1, 4,5);
    T4("((..)|(.)){1}",                      "aaaaa",       0,2, 0,2, 0,2, -1,-1);
    T4("((..)|(.)){2}",                      "aaaaa",       0,4, 2,4, 2,4, -1,-1);
    T4("((..)|(.)){3}",                      "aaaaa",       0,5, 4,5, -1,-1, 4,5);
    T4("((..)|(.))*",                        "aaaaa",       0,5, 4,5, -1,-1, 4,5);
    T4("((..)|(.))",                         "aaaaaa",      0,2, 0,2, 0,2, -1,-1);
    T7("((..)|(.))((..)|(.))",               "aaaaaa",      0,4, 0,2, 0,2, -1,-1, 2,4, 2,4, -1,-1);
    T10("((..)|(.))((..)|(.))((..)|(.))",    "aaaaaa",      0,6, 0,2, 0,2, -1,-1, 2,4, 2,4, -1,-1, 4,6, 4,6, -1,-1);
    T4("((..)|(.)){1}",                      "aaaaaa",      0,2, 0,2, 0,2, -1,-1);
    T4("((..)|(.)){2}",                      "aaaaaa",      0,4, 2,4, 2,4, -1,-1);
    T4("((..)|(.)){3}",                      "aaaaaa",      0,6, 4,6, 4,6, -1,-1);
    T4("((..)|(.))*",                        "aaaaaa",      0,6, 4,6, 4,6, -1,-1);
    T2("X(.?){0,}Y",                         "X1234567Y",   0,9, 7,8);
    T2("X(.?){1,}Y",                         "X1234567Y",   0,9, 7,8);
    T2("X(.?){2,}Y",                         "X1234567Y",   0,9, 7,8);
    T2("X(.?){3,}Y",                         "X1234567Y",   0,9, 7,8);
    T2("X(.?){4,}Y",                         "X1234567Y",   0,9, 7,8);
    T2("X(.?){5,}Y",                         "X1234567Y",   0,9, 7,8);
    T2("X(.?){6,}Y",                         "X1234567Y",   0,9, 7,8);
    T2("X(.?){7,}Y",                         "X1234567Y",   0,9, 7,8);
    T2("X(.?){8,}Y",                         "X1234567Y",   0,9, 8,8);
    T2("X(.?){0,8}Y",                        "X1234567Y",   0,9, 8,8);
    T2("X(.?){1,8}Y",                        "X1234567Y",   0,9, 8,8);
    T2("X(.?){2,8}Y",                        "X1234567Y",   0,9, 8,8);
    T2("X(.?){3,8}Y",                        "X1234567Y",   0,9, 8,8);
    T2("X(.?){4,8}Y",                        "X1234567Y",   0,9, 8,8);
    T2("X(.?){5,8}Y",                        "X1234567Y",   0,9, 8,8);
    T2("X(.?){6,8}Y",                        "X1234567Y",   0,9, 8,8);
    T2("X(.?){7,8}Y",                        "X1234567Y",   0,9, 8,8);
    T2("X(.?){8,8}Y",                        "X1234567Y",   0,9, 8,8);
    T3("(a|ab|c|bcd){0,}(d*)",               "ababcd",      0,6, 3,6, 6,6);
    T3("(a|ab|c|bcd){1,}(d*)",               "ababcd",      0,6, 3,6, 6,6);
    T3("(a|ab|c|bcd){2,}(d*)",               "ababcd",      0,6, 3,6, 6,6);
    T3("(a|ab|c|bcd){3,}(d*)",               "ababcd",      0,6, 3,6, 6,6);
    T0("(a|ab|c|bcd){4,}(d*)",               "ababcd");
    T3("(a|ab|c|bcd){0,10}(d*)",             "ababcd",      0,6, 3,6, 6,6);
    T3("(a|ab|c|bcd){1,10}(d*)",             "ababcd",      0,6, 3,6, 6,6);
    T3("(a|ab|c|bcd){2,10}(d*)",             "ababcd",      0,6, 3,6, 6,6);
    T3("(a|ab|c|bcd){3,10}(d*)",             "ababcd",      0,6, 3,6, 6,6);
    T0("(a|ab|c|bcd){4,10}(d*)",             "ababcd");
    T3("(a|ab|c|bcd)*(d*)",                  "ababcd",      0,6, 3,6, 6,6);
    T3("(a|ab|c|bcd)+(d*)",                  "ababcd",      0,6, 3,6, 6,6);
    T3("(ab|a|c|bcd){0,}(d*)",               "ababcd",      0,6, 4,5, 5,6);
    T3("(ab|a|c|bcd){1,}(d*)",               "ababcd",      0,6, 4,5, 5,6);
    T3("(ab|a|c|bcd){2,}(d*)",               "ababcd",      0,6, 4,5, 5,6);
    T3("(ab|a|c|bcd){3,}(d*)",               "ababcd",      0,6, 4,5, 5,6);
    T0("(ab|a|c|bcd){4,}(d*)",               "ababcd");
    T3("(ab|a|c|bcd){0,10}(d*)",             "ababcd",      0,6, 4,5, 5,6);
    T3("(ab|a|c|bcd){1,10}(d*)",             "ababcd",      0,6, 4,5, 5,6);
    T3("(ab|a|c|bcd){2,10}(d*)",             "ababcd",      0,6, 4,5, 5,6);
    T3("(ab|a|c|bcd){3,10}(d*)",             "ababcd",      0,6, 4,5, 5,6);
    T0("(ab|a|c|bcd){4,10}(d*)",             "ababcd");
    T3("(ab|a|c|bcd)*(d*)",                  "ababcd",      0,6, 4,5, 5,6);
    T3("(ab|a|c|bcd)+(d*)",                  "ababcd",      0,6, 4,5, 5,6);

    // rightassoc
    T4("(a|ab)(c|bcd)(d*)",                  "abcd",        0,4, 0,1, 1,4, 4,4);
    T4("(a|ab)(bcd|c)(d*)",                  "abcd",        0,4, 0,1, 1,4, 4,4);
    T4("(ab|a)(c|bcd)(d*)",                  "abcd",        0,4, 0,2, 2,3, 3,4);
    T4("(ab|a)(bcd|c)(d*)",                  "abcd",        0,4, 0,2, 2,3, 3,4);
    T4("(a*)(b|abc)(c*)",                    "abc",         0,3, 0,1, 1,2, 2,3);
    T4("(a*)(abc|b)(c*)",                    "abc",         0,3, 0,1, 1,2, 2,3);
    T4("(a*)(b|abc)(c*)",                    "abc",         0,3, 0,1, 1,2, 2,3);
    T4("(a*)(abc|b)(c*)",                    "abc",         0,3, 0,1, 1,2, 2,3);
    T4("(a|ab)(c|bcd)(d|.*)",                "abcd",        0,4, 0,1, 1,4, 4,4);
    T4("(a|ab)(bcd|c)(d|.*)",                "abcd",        0,4, 0,1, 1,4, 4,4);
    T4("(ab|a)(c|bcd)(d|.*)",                "abcd",        0,4, 0,2, 2,3, 3,4);
    T4("(ab|a)(bcd|c)(d|.*)",                "abcd",        0,4, 0,2, 2,3, 3,4);

    // other
    T3("((a?){1,1000})*", "aaaa", 0,4, 0,4, 4,4);

    return e;
}

#undef GS
#undef T
#undef T0
#undef T1
#undef T2
#undef T3
#undef T4
#undef T5
#undef T6
#undef T7
#undef T8
#undef T9
#undef T10

int main()
{
    int e = 0;

    e |= test_all_posix(0);
    e |= test_all_posix(REG_STADFA);

    e |= test_all_posix(REG_NFA);
    e |= test_all_posix(REG_NFA | REG_GTOP);

    e |= test_all_posix(REG_NFA | REG_KUKLEWICZ);
    e |= test_all_posix(REG_NFA | REG_KUKLEWICZ | REG_GTOP);

    e |= test_all_posix(REG_NFA | REG_TRIE);
    e |= test_all_posix(REG_NFA | REG_TRIE | REG_GTOP);

    e |= test_all_posix(REG_NFA | REG_SLOWPREC);

    e |= test_all_leftmost(REG_NFA | REG_LEFTMOST);
    e |= test_all_leftmost(REG_NFA | REG_LEFTMOST | REG_TRIE);

    e |= test_all_posix(REG_NFA | REG_BACKWARD);
    e |= test_all_posix(REG_NFA | REG_BACKWARD | REG_GTOP);

    return e;
}