@@ -33,10 +33,18 @@ extension MEProgram {
3333
3434 // Registers
3535 var nextIntRegister = IntRegister ( 0 )
36- var nextCaptureRegister = CaptureRegister ( 0 )
3736 var nextValueRegister = ValueRegister ( 0 )
3837 var nextPositionRegister = PositionRegister ( 0 )
3938
39+ // Set to non-nil when a value register holds the whole-match
40+ // value (i.e. when a regex consists entirely of a custom matcher)
41+ var wholeMatchValue : ValueRegister ? = nil
42+
43+ // Note: Capture 0 (i.e. whole-match) is handled specially
44+ // by the engine, so `n` here refers to the regex AST's `n+1`
45+ // capture
46+ var nextCaptureRegister = CaptureRegister ( 0 )
47+
4048 // Special addresses or instructions
4149 var failAddressToken : AddressToken ? = nil
4250
@@ -70,6 +78,24 @@ extension MEProgram.Builder {
7078 self . second = b
7179 }
7280 }
81+
82+ // Maps the AST's named capture offset to a capture register
83+ func captureRegister( named name: String ) throws -> CaptureRegister {
84+ guard let index = captureList. indexOfCapture ( named: name) else {
85+ throw RegexCompilationError . uncapturedReference
86+ }
87+ return . init( index - 1 )
88+ }
89+
90+ // Map an AST's backreference number to a capture register
91+ func captureRegister( forBackreference i: Int ) -> CaptureRegister {
92+ . init( i - 1 )
93+ }
94+
95+ mutating func denoteCurrentValueIsWholeMatchValue( ) {
96+ assert ( wholeMatchValue == nil )
97+ wholeMatchValue = nextValueRegister
98+ }
7399}
74100
75101extension MEProgram . Builder {
@@ -337,10 +363,8 @@ extension MEProgram.Builder {
337363 }
338364
339365 mutating func buildNamedReference( _ name: String , isScalarMode: Bool ) throws {
340- guard let index = captureList. indexOfCapture ( named: name) else {
341- throw RegexCompilationError . uncapturedReference
342- }
343- buildBackreference ( . init( index) , isScalarMode: isScalarMode)
366+ let cap = try captureRegister ( named: name)
367+ buildBackreference ( cap, isScalarMode: isScalarMode)
344368 }
345369
346370 // TODO: Mutating because of fail address fixup, drop when
@@ -401,6 +425,7 @@ extension MEProgram.Builder {
401425 regInfo. transformFunctions = transformFunctions. count
402426 regInfo. matcherFunctions = matcherFunctions. count
403427 regInfo. captures = nextCaptureRegister. rawValue
428+ regInfo. wholeMatchValue = wholeMatchValue? . rawValue
404429
405430 return MEProgram (
406431 instructions: InstructionList ( instructions) ,
@@ -514,8 +539,8 @@ extension MEProgram.Builder {
514539 assert ( preexistingValue == nil )
515540 }
516541 if let name = name {
517- let index = captureList . indexOfCapture ( named: name)
518- assert ( index == nextCaptureRegister. rawValue )
542+ let cap = try ? captureRegister ( named: name)
543+ assert ( cap == nextCaptureRegister)
519544 }
520545 assert ( nextCaptureRegister. rawValue < captureList. captures. count)
521546 return nextCaptureRegister
0 commit comments