@@ -391,3 +391,88 @@ func TestReverseSuffix_EdgeCases(t *testing.T) {
391391 })
392392 }
393393}
394+
395+ // TestIssue116_AlternationWithoutWildcard tests that alternation patterns without
396+ // wildcard prefix (like `[cgt]gggtaaa|tttaccc[acg]`) are NOT routed to
397+ // UseReverseSuffixSet, which would produce wrong match positions.
398+ // See: https://github.com/coregx/coregex/issues/116
399+ func TestIssue116_AlternationWithoutWildcard (t * testing.T ) {
400+ tests := []struct {
401+ name string
402+ pattern string
403+ input string
404+ want []string
405+ }{
406+ {
407+ name : "original bug report pattern" ,
408+ pattern : `[cgt]gggtaaa|tttaccc[acg]` ,
409+ input : "xxxcgggtaaaxxx" ,
410+ want : []string {"cgggtaaa" },
411+ },
412+ {
413+ name : "original bug report pattern - second alt" ,
414+ pattern : `[cgt]gggtaaa|tttaccc[acg]` ,
415+ input : "xxxtttacccaxxx" ,
416+ want : []string {"tttaccca" },
417+ },
418+ {
419+ name : "multiple matches" ,
420+ pattern : `[cgt]gggtaaa|tttaccc[acg]` ,
421+ input : "cgggtaaa tttaccca ggggtaaa tttacccg" ,
422+ want : []string {"cgggtaaa" , "tttaccca" , "ggggtaaa" , "tttacccg" },
423+ },
424+ {
425+ name : "no match" ,
426+ pattern : `[cgt]gggtaaa|tttaccc[acg]` ,
427+ input : "agggtaaa tttacccd" ,
428+ want : nil ,
429+ },
430+ {
431+ name : "simple alternation without char class" ,
432+ pattern : `foo|bar` ,
433+ input : "xxxfooxxxbarxxx" ,
434+ want : []string {"foo" , "bar" },
435+ },
436+ }
437+
438+ for _ , tt := range tests {
439+ t .Run (tt .name , func (t * testing.T ) {
440+ e , err := Compile (tt .pattern )
441+ if err != nil {
442+ t .Fatalf ("Compile(%q) failed: %v" , tt .pattern , err )
443+ }
444+
445+ // Verify strategy is NOT UseReverseSuffixSet for these patterns
446+ strategy := e .Strategy ()
447+ if strategy == UseReverseSuffixSet {
448+ t .Errorf ("pattern %q should NOT use UseReverseSuffixSet strategy" , tt .pattern )
449+ }
450+
451+ var got []string
452+ haystack := []byte (tt .input )
453+ at := 0
454+ for at < len (haystack ) {
455+ start , end , found := e .FindIndicesAt (haystack , at )
456+ if ! found {
457+ break
458+ }
459+ got = append (got , string (haystack [start :end ]))
460+ if end > at {
461+ at = end
462+ } else {
463+ at ++
464+ }
465+ }
466+
467+ if len (got ) != len (tt .want ) {
468+ t .Fatalf ("FindAll(%q) = %v (%d matches), want %v (%d matches)" ,
469+ tt .input , got , len (got ), tt .want , len (tt .want ))
470+ }
471+ for i := range got {
472+ if got [i ] != tt .want [i ] {
473+ t .Errorf ("match[%d] = %q, want %q" , i , got [i ], tt .want [i ])
474+ }
475+ }
476+ })
477+ }
478+ }
0 commit comments