Skip to content

Commit a38ffbc

Browse files
committed
wip: introduce capture list
1 parent 435090d commit a38ffbc

File tree

15 files changed

+265
-404
lines changed

15 files changed

+265
-404
lines changed

Sources/PatternConverter/PatternConverter.swift

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@ struct PatternConverter: ParsableCommand {
3030
@Flag(help: "Whether to show canonical regex literal")
3131
var showCanonical: Bool = false
3232

33-
@Flag(help: "Whether to show capture structure")
34-
var showCaptureStructure: Bool = false
35-
3633
@Flag(help: "Whether to skip result builder DSL")
3734
var skipDSL: Bool = false
3835

@@ -71,13 +68,6 @@ struct PatternConverter: ParsableCommand {
7168
print()
7269
}
7370

74-
if showCaptureStructure {
75-
print("Capture structure:")
76-
print()
77-
print(ast.captureStructure)
78-
print()
79-
}
80-
8171
print()
8272
if !skipDSL {
8373
let render = ast.renderAsBuilderDSL(

Sources/_RegexParser/Regex/AST/AST.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,6 @@ public struct AST: Hashable {
2424
extension AST {
2525
/// Whether this AST tree has nested somewhere inside it a capture.
2626
public var hasCapture: Bool { root.hasCapture }
27-
28-
/// The capture structure of this AST tree.
29-
public var captureStructure: CaptureStructure {
30-
var constructor = CaptureStructure.Constructor(.flatten)
31-
return root._captureStructure(&constructor)
32-
}
3327
}
3428

3529
extension AST {
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2021-2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
public struct CaptureList {
13+
public var captures: [Capture]
14+
15+
public init() {
16+
captures = []
17+
}
18+
19+
public mutating func append(_ c: Capture) {
20+
captures.append(c)
21+
}
22+
}
23+
24+
extension CaptureList {
25+
public struct Capture {
26+
public var name: String?
27+
public var type: Any.Type?
28+
public var optionalDepth: Int
29+
30+
public init(
31+
name: String? = nil,
32+
type: Any.Type? = nil,
33+
optionalDepth: Int
34+
) {
35+
self.name = name
36+
self.type = type
37+
self.optionalDepth = optionalDepth
38+
}
39+
}
40+
}
41+
42+
extension AST.Node {
43+
44+
public func _addCaptures(
45+
to list: inout CaptureList,
46+
optionalNesting nesting: Int
47+
) {
48+
let addOptional = nesting+1
49+
switch self {
50+
case let .alternation(a):
51+
for child in a.children {
52+
child._addCaptures(to: &list, optionalNesting: addOptional)
53+
}
54+
55+
case let .concatenation(c):
56+
for child in c.children {
57+
child._addCaptures(to: &list, optionalNesting: nesting)
58+
}
59+
60+
case let .group(g):
61+
switch g.kind.value {
62+
case .capture:
63+
list.append(.init(optionalDepth: nesting))
64+
65+
case .namedCapture(let name):
66+
list.append(.init(name: name.value, optionalDepth: nesting))
67+
68+
case .balancedCapture(let b):
69+
list.append(.init(name: b.name?.value, optionalDepth: nesting))
70+
71+
default: break
72+
}
73+
g.child._addCaptures(to: &list, optionalNesting: nesting)
74+
75+
case .conditional(let c):
76+
switch c.condition.kind {
77+
case .group(let g):
78+
AST.Node.group(g)._addCaptures(to: &list, optionalNesting: nesting)
79+
default:
80+
break
81+
}
82+
83+
c.trueBranch._addCaptures(to: &list, optionalNesting: addOptional)
84+
c.falseBranch._addCaptures(to: &list, optionalNesting: addOptional)
85+
86+
case .quantification(let q):
87+
var optNesting = nesting
88+
if q.amount.value.bounds.atLeast == 0 {
89+
optNesting += 1
90+
}
91+
q.child._addCaptures(to: &list, optionalNesting: optNesting)
92+
93+
case .absentFunction(let abs):
94+
switch abs.kind {
95+
case .expression(_, _, let child):
96+
child._addCaptures(to: &list, optionalNesting: nesting)
97+
case .clearer, .repeater, .stopper:
98+
break
99+
}
100+
101+
case .quote, .trivia, .atom, .customCharacterClass, .empty:
102+
break
103+
}
104+
}
105+
106+
public var _captureList: CaptureList {
107+
var caps = CaptureList()
108+
self._addCaptures(to: &caps, optionalNesting: 0)
109+
return caps
110+
}
111+
}
112+
113+
extension CaptureList {
114+
func _captureStructure(nestOptionals: Bool) -> CaptureStructure {
115+
if captures.isEmpty { return .empty }
116+
if captures.count == 1 {
117+
return captures.first!._captureStructure(nestOptionals: nestOptionals)
118+
}
119+
return .tuple(captures.map {
120+
$0._captureStructure(nestOptionals: nestOptionals)
121+
})
122+
}
123+
}
124+
125+
extension CaptureList.Capture {
126+
func _captureStructure(nestOptionals: Bool) -> CaptureStructure {
127+
if optionalDepth == 0 {
128+
if let ty = type {
129+
return .atom(name: name, type: .init(ty))
130+
}
131+
return .atom(name: name)
132+
}
133+
var copy = self
134+
copy.optionalDepth = 0
135+
var base = copy._captureStructure(nestOptionals: false)
136+
for _ in 0..<(nestOptionals ? optionalDepth : 1) {
137+
base = .optional(base)
138+
}
139+
return base
140+
}
141+
}

0 commit comments

Comments
 (0)