@@ -57,63 +57,105 @@ extension CaptureList {
5757 }
5858}
5959
60+ extension CaptureList {
61+ public struct Builder {
62+ public var captures = CaptureList ( )
63+
64+ public init ( ) { }
65+
66+ public struct OptionalNesting {
67+ // We maintain two depths, inner and outer. These allow e.g the nesting
68+ // of a regex literal in a DSL, where outside of the scope of the literal,
69+ // nesting is allowed, but inside the literal at most one extra layer of
70+ // optionality may be added.
71+ public var outerDepth : Int
72+ public var canNest : Bool
73+ public var innerDepth : Int
74+
75+ internal init ( outerDepth: Int , canNest: Bool ) {
76+ self . outerDepth = outerDepth
77+ self . canNest = canNest
78+ self . innerDepth = 0
79+ }
80+
81+ public init ( canNest: Bool ) {
82+ self . init ( outerDepth: 0 , canNest: canNest)
83+ }
84+
85+ public var depth : Int { outerDepth + innerDepth }
86+
87+ public var disablingNesting : Self {
88+ // If we are currently able to nest, store the current depth as the
89+ // outer depth, and disable nesting for an inner scope.
90+ guard canNest else { return self }
91+ return . init( outerDepth: depth, canNest: false )
92+ }
93+
94+ public var addingOptional : Self {
95+ var result = self
96+ result. innerDepth = canNest ? innerDepth + 1 : 1
97+ return result
98+ }
99+ }
100+ }
101+ }
102+
60103// MARK: Generating from AST
61104
62- extension AST . Node {
63- public func _addCaptures(
64- to list: inout CaptureList ,
65- optionalNesting nesting: Int
105+ extension CaptureList . Builder {
106+ public mutating func addCaptures(
107+ of node: AST . Node , optionalNesting nesting: OptionalNesting
66108 ) {
67- let addOptional = nesting+ 1
68- switch self {
109+ switch node {
69110 case let . alternation( a) :
70111 for child in a. children {
71- child . _addCaptures ( to : & list , optionalNesting: addOptional )
112+ addCaptures ( of : child , optionalNesting: nesting . addingOptional )
72113 }
73114
74115 case let . concatenation( c) :
75116 for child in c. children {
76- child . _addCaptures ( to : & list , optionalNesting: nesting)
117+ addCaptures ( of : child , optionalNesting: nesting)
77118 }
78119
79120 case let . group( g) :
80121 switch g. kind. value {
81122 case . capture:
82- list . append ( . init( optionalDepth: nesting, g. location) )
123+ captures . append ( . init( optionalDepth: nesting. depth , g. location) )
83124
84125 case . namedCapture( let name) :
85- list. append ( . init( name: name. value, optionalDepth: nesting, g. location) )
126+ captures. append ( . init(
127+ name: name. value, optionalDepth: nesting. depth, g. location) )
86128
87129 case . balancedCapture( let b) :
88- list . append ( . init( name : b . name ? . value , optionalDepth : nesting ,
89- g. location) )
130+ captures . append ( . init(
131+ name : b . name ? . value , optionalDepth : nesting . depth , g. location) )
90132
91133 default : break
92134 }
93- g . child . _addCaptures ( to : & list , optionalNesting: nesting)
135+ addCaptures ( of : g . child , optionalNesting: nesting)
94136
95137 case . conditional( let c) :
96138 switch c. condition. kind {
97139 case . group( let g) :
98- AST . Node . group ( g) . _addCaptures ( to : & list , optionalNesting: nesting)
140+ addCaptures ( of : . group( g) , optionalNesting: nesting)
99141 default :
100142 break
101143 }
102144
103- c . trueBranch . _addCaptures ( to : & list , optionalNesting: addOptional )
104- c . falseBranch . _addCaptures ( to : & list , optionalNesting: addOptional )
145+ addCaptures ( of : c . trueBranch , optionalNesting: nesting . addingOptional )
146+ addCaptures ( of : c . falseBranch , optionalNesting: nesting . addingOptional )
105147
106148 case . quantification( let q) :
107149 var optNesting = nesting
108150 if q. amount. value. bounds. atLeast == 0 {
109- optNesting += 1
151+ optNesting = optNesting . addingOptional
110152 }
111- q . child . _addCaptures ( to : & list , optionalNesting: optNesting)
153+ addCaptures ( of : q . child , optionalNesting: optNesting)
112154
113155 case . absentFunction( let abs) :
114156 switch abs. kind {
115157 case . expression( _, _, let child) :
116- child . _addCaptures ( to : & list , optionalNesting: nesting)
158+ addCaptures ( of : child , optionalNesting: nesting)
117159 case . clearer, . repeater, . stopper:
118160 break
119161 }
@@ -122,16 +164,17 @@ extension AST.Node {
122164 break
123165 }
124166 }
167+ public static func build( _ ast: AST ) -> CaptureList {
168+ var builder = Self ( )
169+ builder. captures. append ( . init( optionalDepth: 0 , . fake) )
170+ builder. addCaptures ( of: ast. root, optionalNesting: . init( canNest: false ) )
171+ return builder. captures
172+ }
125173}
126174
127175extension AST {
128176 /// The capture list (including the whole match) of this AST.
129- public var captureList : CaptureList {
130- var caps = CaptureList ( )
131- caps. append ( . init( optionalDepth: 0 , . fake) )
132- root. _addCaptures ( to: & caps, optionalNesting: 0 )
133- return caps
134- }
177+ public var captureList : CaptureList { . Builder. build ( self ) }
135178}
136179
137180// MARK: Convenience for testing and inspection
0 commit comments