]> granicus.if.org Git - re2c/commitdiff
libre2c_posix: handle empty group () in parser; added more tests.
authorUlya Trofimovich <skvadrik@gmail.com>
Wed, 16 Jan 2019 21:49:38 +0000 (21:49 +0000)
committerUlya Trofimovich <skvadrik@gmail.com>
Wed, 16 Jan 2019 22:56:02 +0000 (22:56 +0000)
re2c/bootstrap/libre2c_posix/lex.cc
re2c/bootstrap/libre2c_posix/parse.cc
re2c/libre2c_posix/parse.ypp
re2c/libre2c_posix/test.cpp

index c8df8efec47e6f9f18df645afee8828185adc60f..c8c3531b8b16c7aebc575bf7d528af7f1c806c96 100644 (file)
@@ -1,4 +1,4 @@
-/* Generated by re2c 1.1.1 on Tue Jan 15 00:23:54 2019 */
+/* Generated by re2c 1.1.1 on Wed Jan 16 21:53:43 2019 */
 #line 1 "../libre2c_posix/lex.re"
 #include <stdio.h>
 
index 3ee8ee40461a215f27e8f3e27080e4a651e06695..5b7efd5972403958c34fc38fc2fa066b97987768 100644 (file)
@@ -389,18 +389,18 @@ union yyalloc
 #endif /* !YYCOPY_NEEDED */
 
 /* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  9
+#define YYFINAL  10
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   13
+#define YYLAST   16
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  12
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  6
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  13
+#define YYNRULES  14
 /* YYNSTATES -- Number of states.  */
-#define YYNSTATES  18
+#define YYNSTATES  19
 
 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
    by yylex, with out-of-bounds checking.  */
@@ -448,7 +448,7 @@ static const yytype_uint8 yytranslate[] =
 static const yytype_uint8 yyrline[] =
 {
        0,    39,    39,    42,    43,    47,    48,    52,    53,    54,
-      55,    56,    60,    61
+      55,    56,    60,    61,    62
 };
 #endif
 
@@ -487,8 +487,8 @@ static const yytype_uint16 yytoknum[] =
      STATE-NUM.  */
 static const yytype_int8 yypact[] =
 {
-      -2,    -5,    -2,     1,     4,    -5,    -2,    -3,    -4,    -5,
-      -2,    -5,    -5,    -5,    -5,    -5,    -5,    -5
+       2,    -5,    -2,     1,    -4,    -5,     2,    -3,    -5,     4,
+      -5,     2,    -5,    -5,    -5,    -5,    -5,    -5,    -5
 };
 
   /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -496,14 +496,14 @@ static const yytype_int8 yypact[] =
      means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       0,    12,     0,     0,     2,     3,     5,     7,     0,     1,
-       0,     6,    11,     8,     9,    10,    13,     4
+       0,    12,     0,     0,     2,     3,     5,     7,    13,     0,
+       1,     0,     6,    11,     8,     9,    10,    14,     4
 };
 
   /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-      -5,    -5,     9,     3,    -5,    -5
+      -5,    -5,    11,     5,    -5,    -5
 };
 
   /* YYDEFGOTO[NTERM-NUM].  */
@@ -517,36 +517,36 @@ static const yytype_int8 yydefgoto[] =
      number is the opposite.  If YYTABLE_NINF, syntax error.  */
 static const yytype_uint8 yytable[] =
 {
-      12,     9,    10,     1,    13,    14,    15,    16,     2,    11,
-      10,     8,     0,    17
+      13,    10,    11,     1,    14,    15,    16,     1,     2,     8,
+      11,    12,     2,     9,     0,    17,    18
 };
 
 static const yytype_int8 yycheck[] =
 {
-       3,     0,     6,     5,     7,     8,     9,    11,    10,     6,
-       6,     2,    -1,    10
+       3,     0,     6,     5,     7,     8,     9,     5,    10,    11,
+       6,     6,    10,     2,    -1,    11,    11
 };
 
   /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
      symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,     5,    10,    13,    14,    15,    16,    17,    14,     0,
-       6,    15,     3,     7,     8,     9,    11,    15
+       0,     5,    10,    13,    14,    15,    16,    17,    11,    14,
+       0,     6,    15,     3,     7,     8,     9,    11,    15
 };
 
   /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
        0,    12,    13,    14,    14,    15,    15,    16,    16,    16,
-      16,    16,    17,    17
+      16,    16,    17,    17,    17
 };
 
   /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
        0,     2,     1,     1,     3,     1,     2,     1,     2,     2,
-       2,     2,     1,     3
+       2,     2,     1,     2,     3
 };
 
 
@@ -1268,12 +1268,18 @@ yyreduce:
 
   case 13:
 #line 61 "../libre2c_posix/parse.ypp" /* yacc.c:1646  */
-    { (yyval.regexp) = ast_cap((yyvsp[-1].regexp)); }
+    { (yyval.regexp) = ast_cap(ast_nil(0, 0)); }
 #line 1273 "libre2c_posix/parse.cc" /* yacc.c:1646  */
     break;
 
+  case 14:
+#line 62 "../libre2c_posix/parse.ypp" /* yacc.c:1646  */
+    { (yyval.regexp) = ast_cap((yyvsp[-1].regexp)); }
+#line 1279 "libre2c_posix/parse.cc" /* yacc.c:1646  */
+    break;
+
 
-#line 1277 "libre2c_posix/parse.cc" /* yacc.c:1646  */
+#line 1283 "libre2c_posix/parse.cc" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -1501,7 +1507,7 @@ yyreturn:
 #endif
   return yyresult;
 }
-#line 64 "../libre2c_posix/parse.ypp" /* yacc.c:1906  */
+#line 65 "../libre2c_posix/parse.ypp" /* yacc.c:1906  */
 
 
 extern "C" {
index cc7d0e8f4f4f60e02b3973b3bdab9294b2f86f7b..da193af12ead8850a9aee310ee4d559c719667b9 100644 (file)
@@ -58,6 +58,7 @@ factor
 
 primary
 : REGEXP
+| '(' ')'      { $$ = ast_cap(ast_nil(0, 0)); }
 | '(' expr ')' { $$ = ast_cap($2); }
 ;
 
index a249e2490c467be534cecb0329187ad04be1cdb7..4f4dbdce71eec605f09e0b7ca2ea619464213c55 100644 (file)
@@ -68,16 +68,19 @@ end:
 // 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)                           e |= test(r,s,sizeof(gs)/sizeof(gs[0])/2,gs);
-#define T0(r,s)                             e |= test(r,s,0,NULL);
-#define T1(r,s,a,b)                         { GS = {a,b};                         T(r,s,gs); }
-#define T2(r,s,a,b,c,d)                     { GS = {a,b,c,d};                     T(r,s,gs); }
-#define T3(r,s,a,b,c,d,e,f)                 { GS = {a,b,c,d,e,f};                 T(r,s,gs); }
-#define T4(r,s,a,b,c,d,e,f,g,h)             { GS = {a,b,c,d,e,f,g,h};             T(r,s,gs); }
-#define T5(r,s,a,b,c,d,e,f,g,h,i,j)         { GS = {a,b,c,d,e,f,g,h,i,j};         T(r,s,gs); }
-#define T6(r,s,a,b,c,d,e,f,g,h,i,j,k,l)     { GS = {a,b,c,d,e,f,g,h,i,j,k,l};     T(r,s,gs); }
-#define T7(r,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n) { GS = {a,b,c,d,e,f,g,h,i,j,k,l,m,n}; T(r,s,gs); }
+#define  GS                                              static const regoff_t gs[]
+#define  T(R,S,gs)                                       e |= test(R,S,sizeof(gs)/sizeof(gs[0])/2,gs);
+#define  T0(R,S)                                         e |= test(R,S,0,NULL);
+#define  T1(R,S,a,b)                                     { GS = {a,b};                                     T(R,S,gs); }
+#define  T2(R,S,a,b,c,d)                                 { GS = {a,b,c,d};                                 T(R,S,gs); }
+#define  T3(R,S,a,b,c,d,e,f)                             { GS = {a,b,c,d,e,f};                             T(R,S,gs); }
+#define  T4(R,S,a,b,c,d,e,f,g,h)                         { GS = {a,b,c,d,e,f,g,h};                         T(R,S,gs); }
+#define  T5(R,S,a,b,c,d,e,f,g,h,i,j)                     { GS = {a,b,c,d,e,f,g,h,i,j};                     T(R,S,gs); }
+#define  T6(R,S,a,b,c,d,e,f,g,h,i,j,k,l)                 { GS = {a,b,c,d,e,f,g,h,i,j,k,l};                 T(R,S,gs); }
+#define  T7(R,S,a,b,c,d,e,f,g,h,i,j,k,l,m,n)             { GS = {a,b,c,d,e,f,g,h,i,j,k,l,m,n};             T(R,S,gs); }
+#define  T8(R,S,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)         { GS = {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p};         T(R,S,gs); }
+#define  T9(R,S,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r)     { GS = {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r};     T(R,S,gs); }
+#define T10(R,S,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t) { 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); }
 
 int main()
 {
@@ -107,6 +110,65 @@ int main()
     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);
@@ -197,6 +259,241 @@ int main()
     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}",                             "NULL");
+    T0("(y){2}",                             "y");
+    T2("(y){2}",                             "yy",          0,2, 1,2);
+    T2("(y){0,2}",                           "NULL",        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}",                           "NULL");
+    T2("(y){1,2}",                           "y",           0,1, 0,1);
+    T2("(y){1,2}",                           "yy",          0,2, 1,2);
+    T0("(y){1,2}y",                          "NULL");
+    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?",                         "NULL");
+    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,}",                            "NULL");
+    T0("(y){2,}",                            "y");
+    T2("(y){2,}",                            "yy",          0,2, 1,2);
+    T2("(y){2,}",                            "yyy",         0,3, 2,3);
+    T2("(y?){2}",                            "NULL",        0,0, 0,0);
+    T2("(y?){2}",                            "y",           0,1, 1,1);
+    T2("(y?){2}",                            "yy",          0,2, 1,2);
+    T2("(y?){0,2}",                          "NULL",        0,0, 0,0);
+    T2("(y?){0,2}",                          "y",           0,1, 0,1);
+    T2("(y?){0,2}",                          "yy",          0,2, 1,2);
+    T2("(y?){1,2}",                          "NULL",        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",                         "NULL");
+    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?",                        "NULL",        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,}",                           "NULL",        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);
+
     return e;
 }