@@ -852,6 +852,54 @@ class RegexDSLTests: XCTestCase {
852852 }
853853 }
854854 }
855+
856+ // Post-hoc captured reference w/ attempted match before capture
857+ // #"(?:\w\1|(\w):)+"#
858+ //
859+ // This tests that the reference `a` simply fails to match instead of
860+ // erroring when encountered before a match is captured into `a`. The
861+ // matching process here goes like this:
862+ // - the first time through, the first alternation is taken
863+ // - `.word` matches on "a"
864+ // - the `a` backreference fails on ":", because `a` hasn't matched yet
865+ // - backtrack to the beginning of the input
866+ // - now the second alternation is taken
867+ // - `.word` matches on "a" and is captured as `a`
868+ // - the literal ":" matches
869+ // - proceeding from the position of the first "b" in the first alternation
870+ // - `.word` matches on "b"
871+ // - the `a` backreference now contains "a", and matches on "a"
872+ // - proceeding from the position of the first "c" in the first alternation
873+ // - `.word` matches on "c"
874+ // - the `a` backreference still contains "a", and matches on "a"
875+ // - proceeding from the position of the first "o" in the first alternation
876+ // - `.word` matches on "o"
877+ // - the `a` backreference still contains "a", so it fails on ":"
878+ // - now the second alternation is taken
879+ // - `.word` matches on "o" and is captured as `a`
880+ // - the literal ":" matches
881+ // - continuing as above from the second "b"...
882+ try _testDSLCaptures (
883+ ( " a:bacao:boco " , ( " a:bacao:boco " , " o " ) ) ,
884+ matchType: ( Substring, Substring? ) . self,
885+ ==
886+ ) {
887+ // NOTE: "expression too complex to type check" when inferring the generic
888+ // parameter.
889+ OneOrMore {
890+ let a = Reference ( Substring . self)
891+ ChoiceOf< ( Substring, Substring? ) > {
892+ Regex {
893+ . word
894+ a
895+ }
896+ Regex {
897+ Capture ( . word, as: a)
898+ " : "
899+ }
900+ }
901+ }
902+ }
855903 }
856904
857905 func testSemanticVersionExample( ) {
0 commit comments