apple / swift-experimental-string-processing

An early experimental general-purpose pattern matching engine for Swift.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Runtime crash when accessing DSL-composed Regex Match with named capture groups

sstadelman opened this issue · comments

Description
Composing a Regex with the DSL using RegexLiterals with named capture groups works, and matching works, but accessing the matches crashes at runtime.

Using the same patterns in RegexLiteral & DSL without the names works fine.

forum.swift.org: runtime-crash-regexbuilding-with-regex-literals-containing-named-capture-groups/62539

Steps to reproduce
Define one or more patterns with named capture groups, and use the DSL to compose a Regex. Match (whole, prefix, etc.) to a string. The the pattern matches correctly, but accessing the Output causes a runtime crash.

enum FrameComponentRegex {
    static let number = /frame \#(?<frame_number>\d+):/
    static let address = /(?<frame_address>\dx\w{16})/
    static let module = /(?<frame_module>\w+\.{0,1}\w+)/
    static let function = /(?<frame_function>.+)/
}

let frame = Regex {
    FrameComponentRegex.number
    One(.whitespace)
    FrameComponentRegex.address
    One(.whitespace)
    FrameComponentRegex.module
    One("`")
    FrameComponentRegex.function
}

let frameString = """
frame apple/swift#10: 0x00007fff2011383a libdispatch.dylib`_dispatch_client_callout + 8
"""

if let match = frameString.wholeMatch(of: frame) {
    print(match) 
/**
Match(anyRegexOutput: _StringProcessing.AnyRegexOutput(
  input: "frame apple/swift#10: 0x00007fff2011383a libdispatch.dylib`_dispatch_client_callout + 8", 
  _elements: [
    _StringProcessing.AnyRegexOutput.ElementRepresentation(optionalDepth: 0, content: Optional((range: Range(Swift.String.Index(_rawBits: 15)..<Swift.String.Index(_rawBits: 4980743)), value: nil)), name: nil, referenceID: nil), 
    _StringProcessing.AnyRegexOutput.ElementRepresentation(optionalDepth: 0, content: Optional((range: Range(Swift.String.Index(_rawBits: 458757)..<Swift.String.Index(_rawBits: 590087)), value: nil)), name: Optional("frame_number"), referenceID: nil), 
    _StringProcessing.AnyRegexOutput.ElementRepresentation(optionalDepth: 0, content: Optional((range: Range(Swift.String.Index(_rawBits: 721159)..<Swift.String.Index(_rawBits: 1900807)), value: nil)), name: Optional("frame_address"), referenceID: nil), 
    _StringProcessing.AnyRegexOutput.ElementRepresentation(optionalDepth: 0, content: Optional((range: Range(Swift.String.Index(_rawBits: 1966343)..<Swift.String.Index(_rawBits: 3080455)), value: nil)), name: Optional("frame_module"), referenceID: nil), 
    _StringProcessing.AnyRegexOutput.ElementRepresentation(optionalDepth: 0, content: Optional((range: Range(Swift.String.Index(_rawBits: 3145733)..<Swift.String.Index(_rawBits: 4980743)), value: nil)), name: Optional("frame_function"), referenceID: nil)
  ]), 
  range: Range(Swift.String.Index(_rawBits: 15)..<Swift.String.Index(_rawBits: 4980743)))
**/
  
let _ = match.output /** Runtime crash
Could not cast value of type 
'(Swift.Substring, Swift.Substring, Swift.Substring, Swift.Substring, Swift.Substring)' (0x7ff848f83d00) 
to 'Swift.Substring' (0x7ff848af00c8).
**/

let (_, number, address, module, function) = match.output /** Compiler exception
Type of expression is ambiguous without more context 
**/

Expected behavior
It should be possible to access the captures via tuple. It would be nice to also have subscript-based access, but that's a separate issue.

enum FrameComponentRegex_Unnamed {
    static let number = /frame \#(\d+):/
    static let address = /(\dx\w{16})/
    static let module = /(\w+\.{0,1}\w+)/
    static let function = /(.+)/
}
if let match = frameString.wholeMatch(of: frame) {
    let (_, number, address, module, function) = match.output
    print("""
    number:     \(number)
    address:    \(address)
    module:     \(module)
    function:   \(function)
    """)
}
/**
number:     10
address:    0x00007fff2011383a
module:     libdispatch.dylib
function:   _dispatch_client_callout + 8
**/

Environment

  • Swift compiler version info swift-driver version: 1.62.15 Apple Swift version 5.7.1 (swiftlang-5.7.1.135.3 clang-1400.0.29.51)
  • Xcode version info Version 14.1 (14B47b)
  • Deployment target: macOS 13.0