     performTest(regex: "a(b*)c(d+)ef", input: "abbcdef",
       expectedCaptureType: (Substring, Substring).self,
       expecting: .init(captures: ("bb", "d"), capturesEqual: ==))
-    performTest(regex: "a(.*)(c+)", input: "abbbbcccc",
-      expectedCaptureType: (Substring, Substring).self,
-      expecting: .init(captures: ("bbbbccc", "c"), capturesEqual: ==))
-    performTest(regex: "a(.+)(c+)", input: "abbbbcccc",
-      expectedCaptureType: (Substring, Substring).self,
-      expecting: .init(captures: ("bbbbccc", "c"), capturesEqual: ==))
-    performTest(regex: "a(.*?)(c+)", input: "abbbbcccc",
-      expectedCaptureType: (Substring, Substring).self,
-      expecting: .init(captures: ("bbbb", "cccc"), capturesEqual: ==))
-    performTest(regex: "a(.+?)(c+)", input: "abbbbcccc",
-      expectedCaptureType: (Substring, Substring).self,
-      expecting: .init(captures: ("bbbb", "cccc"), capturesEqual: ==))
+    
+    // Greedy vs lazy quantifiers
+    performTest(regex: "a(.*)(c+).*(e+)", input: "abbbbccccddddeeee",
+      expectedCaptureType: (Substring, Substring, Substring).self,
+      expecting: .init(captures: ("bbbbccc", "c", "e"), capturesEqual: ==))
+    performTest(regex: "a(.+)(c+).+(e+)", input: "abbbbccccddddeeee",
+      expectedCaptureType: (Substring, Substring, Substring).self,
+      expecting: .init(captures: ("bbbbccc", "c", "e"), capturesEqual: ==))
+    performTest(regex: "a(.?)(c+).?(e+)", input: "acccceeee",
+      expectedCaptureType: (Substring, Substring, Substring).self,
+      expecting: .init(captures: ("c", "ccc", "eee"), capturesEqual: ==))
+    performTest(regex: "a(.*?)(c+).*?(e+)", input: "abbbbccccddddeeee",
+      expectedCaptureType: (Substring, Substring, Substring).self,
+      expecting: .init(captures: ("bbbb", "cccc", "eeee"), capturesEqual: ==))
+    performTest(regex: "a(.+?)(c+).+?(e+)", input: "abbbbccccddddeeee",
+      expectedCaptureType: (Substring, Substring, Substring).self,
+      expecting: .init(captures: ("bbbb", "cccc", "eeee"), capturesEqual: ==))
+    performTest(regex: "a(.??)(c+).??(e+)", input: "acccceeee",
+      expectedCaptureType: (Substring, Substring, Substring).self,
+      expecting: .init(captures: ("", "cccc", "eeee"), capturesEqual: ==))
     // performTest(regex: "(?a*)*", input: "aaaa",
     //   expectedCaptureType: Substring.self,
     //   expecting: .init(captures: "aaaa", capturesEqual: ==))


    performTest("abc", concat("a", "b", "c"))
    performTest("abc\\+d*", concat("a", "b", "c", "+", .many("d")))
    performTest("abc\\+d*?", concat("a", "b", "c", "+", .lazyMany("d")))
    performTest("abc(?:de)+fghi*k|j",
                alt(concat("a", "b", "c",
                           .oneOrMore(.group(concat("d", "e"))),

                    "j"))
    performTest("a(?:b|c)?d", concat("a", .zeroOrOne(.group(alt("b", "c"))),
                                   "d"))
    performTest("a?b??c+d+?e*f*?", concat(
      .zeroOrOne("a"), .lazyZeroOrOne("b"),
      .oneOrMore("c"), .lazyOneOrMore("d"),
      .many("e"), .lazyMany("f")))
    performTest("a|b?c", alt("a", concat(.zeroOrOne("b"), "c")))
    performTest("(a|b)c", concat(.capturingGroup(alt("a", "b")), "c"))
    performTest("(.)*(.*)", concat(.many(.capturingGroup(.characterClass(.any))), .capturingGroup(.many(.characterClass(.any)))))
