diff --git a/Sources/_StringProcessing/ByteCodeGen.swift b/Sources/_StringProcessing/ByteCodeGen.swift index ae8a1c8b..6a00a0df 100644 --- a/Sources/_StringProcessing/ByteCodeGen.swift +++ b/Sources/_StringProcessing/ByteCodeGen.swift @@ -773,11 +773,19 @@ fileprivate extension Compiler.ByteCodeGen { case .atom(let atom): switch atom { case .char(let c): - // Single scalar ascii value character - guard let val = c._singleScalarAsciiValue else { - return false + if options.isCaseInsensitive && c.isCased { + // Cased character with case-insensitive matching; match only as an ASCII bitset + guard let bitset = DSLTree.CustomCharacterClass(members: [.atom(atom)]).asAsciiBitset(options) else { + return false + } + builder.buildQuantify(bitset: bitset, kind, minTrips, maxExtraTrips, isScalarSemantics: isScalarSemantics) + } else { + // Uncased character OR case-sensitive matching; match as a single scalar ascii value character + guard let val = c._singleScalarAsciiValue else { + return false + } + builder.buildQuantify(asciiChar: val, kind, minTrips, maxExtraTrips, isScalarSemantics: isScalarSemantics) } - builder.buildQuantify(asciiChar: val, kind, minTrips, maxExtraTrips, isScalarSemantics: isScalarSemantics) case .any: builder.buildQuantifyAny( diff --git a/Tests/RegexTests/MatchTests.swift b/Tests/RegexTests/MatchTests.swift index 1b5c67e0..c52560d6 100644 --- a/Tests/RegexTests/MatchTests.swift +++ b/Tests/RegexTests/MatchTests.swift @@ -2193,6 +2193,41 @@ extension RegexTests { ("cafe", true), ("CaFe", true), ("EfAc", true)) + + matchTest( + #"(?i)a+b"#, + ("ab", true), + ("Ab", true), + ("aB", true), + ("AB", true), + ("AaAab", true), + ("aaaAB", true)) + matchTest( + #"^(?i)a?b$"#, + ("ab", true), + ("Ab", true), + ("aB", true), + ("AB", true), + ("aaB", false), + ("b", true), + ("B", true)) + matchTest( + #"^(?i)[a]?b$"#, + ("ab", true), + ("Ab", true), + ("aB", true), + ("AB", true), + ("b", true), + ("B", true)) + matchTest( + #"^(?i)a{2,4}b$"#, + ("ab", false), + ("Ab", false), + ("AaB", true), + ("aAB", true), + ("aAaB", true), + ("aAaAB", true), + ("AaAaAB", false)) } func testNonSemanticWhitespace() {