Skip to content

Commit 1903170

Browse files
committed
Refactor AST construction for upcoming overhaul
1 parent 1986624 commit 1903170

File tree

16 files changed

+3189
-853
lines changed

16 files changed

+3189
-853
lines changed

Sources/VariadicsGenerator/VariadicsGenerator.swift

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,23 @@ func output(_ content: String) {
6363
}
6464

6565
func outputForEach<C: Collection>(
66-
_ elements: C, separator: String, _ content: (C.Element) -> String
66+
_ elements: C,
67+
separator: String,
68+
lineTerminator: String? = nil,
69+
_ content: (C.Element) -> String
6770
) {
6871
for i in elements.indices {
6972
output(content(elements[i]))
70-
if elements.index(after: i) != elements.endIndex {
73+
let needsSep = elements.index(after: i) != elements.endIndex
74+
if needsSep {
7175
output(separator)
7276
}
77+
if let lt = lineTerminator {
78+
let indent = needsSep ? " " : " "
79+
output("\(lt)\n\(indent)")
80+
} else if needsSep {
81+
output(" ")
82+
}
7383
}
7484
}
7585

@@ -97,7 +107,12 @@ struct VariadicsGenerator: ParsableCommand {
97107
precondition(maxArity > 1)
98108
precondition(maxArity < Counter.bitWidth)
99109

100-
output("// BEGIN AUTO-GENERATED CONTENT\n\n\n")
110+
output("""
111+
// BEGIN AUTO-GENERATED CONTENT
112+
113+
import _MatchingEngine
114+
115+
""")
101116

102117
for arity in minArity...maxArity {
103118
for permutation in Permutations(arity: arity) {
@@ -118,12 +133,12 @@ struct VariadicsGenerator: ParsableCommand {
118133
// public init(...) { ... }
119134
// }
120135
let typeName = "\(concatenationStructTypeBaseName)\(arity)_\(permutation.identifier)"
121-
output("public struct \(typeName)<")
122-
outputForEach(0..<arity, separator: ", ") { "T\($0): \(patternProtocolName)" }
123-
output(">: \(patternProtocolName)")
136+
output("public struct \(typeName)<\n ")
137+
outputForEach(0..<arity, separator: ",") { "T\($0): \(patternProtocolName)" }
138+
output("\n>: \(patternProtocolName)")
124139
if permutation.hasCaptureless {
125140
output(" where ")
126-
outputForEach(permutation.capturelessIndices, separator: ", ") {
141+
outputForEach(permutation.capturelessIndices, separator: ",") {
127142
"T\($0).\(captureAssociatedTypeName): \(emptyProtocolName)"
128143
}
129144
}
@@ -140,26 +155,28 @@ struct VariadicsGenerator: ParsableCommand {
140155
output("\n")
141156
output(" public let \(patternProtocolRequirementName): \(PatternTypeBaseName)<\(captureAssociatedTypeName)>\n")
142157
output(" init(")
143-
outputForEach(0..<arity, separator: ", ") { "_ x\($0): T\($0)" }
158+
outputForEach(0..<arity, separator: ",") { "_ x\($0): T\($0)" }
144159
output(") {\n")
145-
output(" \(patternProtocolRequirementName) = .init(ast: .concatenation([")
146-
outputForEach(0..<arity, separator: ", ") { i in
160+
output(" \(patternProtocolRequirementName) = .init(ast: concat(\n ")
161+
outputForEach(
162+
0..<arity, separator: ",", lineTerminator: ""
163+
) { i in
147164
"x\(i).\(patternProtocolRequirementName).ast"
148165
}
149-
output("]))\n")
166+
output("))\n")
150167
output(" }\n}\n\n")
151168

152169
// Emit concatenation builders.
153170
output("extension \(patternBuilderTypeName) {\n")
154171
output(" public static func buildBlock<")
155-
outputForEach(0..<arity, separator: ", ") { "T\($0)" }
172+
outputForEach(0..<arity, separator: ",") { "T\($0)" }
156173
output(">(\n ")
157-
outputForEach(0..<arity, separator: ", ") { "_ x\($0): T\($0)" }
174+
outputForEach(0..<arity, separator: ",") { "_ x\($0): T\($0)" }
158175
output("\n ) -> \(typeName)<")
159-
outputForEach(0..<arity, separator: ", ") { "T\($0)" }
176+
outputForEach(0..<arity, separator: ",") { "T\($0)" }
160177
output("> {\n")
161178
output(" \(typeName)(")
162-
outputForEach(0..<arity, separator: ", ") { "x\($0)" }
179+
outputForEach(0..<arity, separator: ",") { "x\($0)" }
163180
output(")\n }\n}\n\n")
164181
}
165182
}

Sources/_MatchingEngine/Regex/AST/AST.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/// A regex abstract syntax tree
2-
public enum AST: ASTValue, ASTAction {
2+
public enum AST: ASTValue/*, ASTAction*/ {
33
public typealias Product = Self
44

55
/// ... | ... | ...
@@ -11,10 +11,6 @@ public enum AST: ASTValue, ASTAction {
1111
/// (...)
1212
indirect case group(Group, AST)
1313

14-
/// Group with a registered transform
15-
indirect case groupTransform(
16-
Group, AST, transform: CaptureTransform)
17-
1814
indirect case quantification(Quantifier, AST)
1915

2016
case quote(String)
@@ -26,6 +22,11 @@ public enum AST: ASTValue, ASTAction {
2622
case customCharacterClass(CustomCharacterClass)
2723

2824
case empty
25+
26+
27+
// FIXME: Move off the regex literal AST
28+
indirect case groupTransform(
29+
Group, AST, transform: CaptureTransform)
2930
}
3031

3132
extension AST {
Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
1-
public protocol ASTAction {
2-
// TODO: associated types, or just make them produce AST nodes?
1+
// TODO: This might be interesting in the future, but for now
2+
// we make trees
33

4-
// MARK: Group
5-
static func capture(_ a: AST, _ sr: SourceRange?) -> AST
6-
7-
static func nonCapture(_ a: AST, _ sr: SourceRange?) -> AST
8-
9-
// MARK: Quantification
10-
11-
static func zeroOrMore(
12-
_ kind: Quantifier.Kind, _ a: AST, _ r: SourceRange?
13-
) -> AST
14-
static func oneOrMore(
15-
_ kind: Quantifier.Kind, _ a: AST, _ r: SourceRange?
16-
) -> AST
17-
static func zeroOrOne(
18-
_ kind: Quantifier.Kind, _ a: AST, _ r: SourceRange?
19-
) -> AST
20-
}
4+
//public protocol ASTAction {
5+
// // TODO: associated types, or just make them produce AST nodes?
6+
//
7+
// // MARK: Group
8+
// static func capture(_ a: AST, _ sr: SourceRange?) -> AST
9+
//
10+
// static func nonCapture(_ a: AST, _ sr: SourceRange?) -> AST
11+
//
12+
// // MARK: Quantification
13+
//
14+
// static func zeroOrMore(
15+
// _ kind: Quantifier.Kind, _ a: AST, _ r: SourceRange?
16+
// ) -> AST
17+
// static func oneOrMore(
18+
// _ kind: Quantifier.Kind, _ a: AST, _ r: SourceRange?
19+
// ) -> AST
20+
// static func zeroOrOne(
21+
// _ kind: Quantifier.Kind, _ a: AST, _ r: SourceRange?
22+
// ) -> AST
23+
//}
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
3+
These functions are temporary AST construction helpers. As
4+
the AST gets more and more source-location tracking, we'll
5+
want easier migration paths for our parser tests (which
6+
construct and compare location-less AST nodes) as well as the
7+
result builder DSL (which has a different notion of location).
8+
9+
Without real namespaces and `using`, attempts at
10+
pseudo-namespaces tie the use site to being nested inside a
11+
type. So for now, these are global, but they will likely be
12+
namespaced in the future if/when clients are weaned off the
13+
AST.
14+
15+
*/
16+
17+
public let _fakeLoc = "".startIndex
18+
public let _fakeRange = _fakeLoc ..< _fakeLoc
19+
20+
public func alt(_ asts: [AST]) -> AST {
21+
.alternation(asts)
22+
}
23+
public func alt(_ asts: AST...) -> AST {
24+
alt(asts)
25+
}
26+
27+
public func concat(_ asts: [AST]) -> AST {
28+
.concatenation(asts)
29+
}
30+
public func concat(_ asts: AST...) -> AST {
31+
concat(asts)
32+
}
33+
34+
public func group(
35+
_ kind: Group.Kind, _ child: AST
36+
) -> AST {
37+
.group(Group(kind, _fakeRange), child)
38+
}
39+
public func capture(
40+
_ child: AST
41+
) -> AST {
42+
group(.capture, child)
43+
}
44+
public func nonCapture(
45+
_ child: AST
46+
) -> AST {
47+
group(.nonCapture, child)
48+
}
49+
public func namedCapture(
50+
_ name: String,
51+
_ child: AST
52+
) -> AST {
53+
group(.namedCapture(name), child)
54+
}
55+
public func nonCaptureReset(
56+
_ child: AST
57+
) -> AST {
58+
group(.nonCaptureReset, child)
59+
}
60+
public func atomicNonCapturing(
61+
_ child: AST
62+
) -> AST {
63+
group(.atomicNonCapturing, child)
64+
}
65+
public func lookahead(_ child: AST) -> AST {
66+
group(.lookahead, child)
67+
}
68+
public func lookbehind(_ child: AST) -> AST {
69+
group(.lookbehind, child)
70+
}
71+
public func negativeLookahead(_ child: AST) -> AST {
72+
group(.negativeLookahead, child)
73+
}
74+
public func negativeLookbehind(_ child: AST) -> AST {
75+
group(.negativeLookbehind, child)
76+
}
77+
78+
public var any: AST { .atom(.any) }
79+
80+
public func quant(
81+
_ amount: Quantifier.Amount,
82+
_ kind: Quantifier.Kind = .greedy,
83+
_ child: AST
84+
) -> AST {
85+
.quantification(Quantifier(amount, kind, _fakeRange), child)
86+
}
87+
public func zeroOrMore(
88+
_ kind: Quantifier.Kind = .greedy,
89+
_ child: AST
90+
) -> AST {
91+
quant(.zeroOrMore, kind, child)
92+
}
93+
public func zeroOrOne(
94+
_ kind: Quantifier.Kind = .greedy,
95+
_ child: AST
96+
) -> AST {
97+
quant(.zeroOrOne, kind, child)
98+
}
99+
public func oneOrMore(
100+
_ kind: Quantifier.Kind = .greedy,
101+
_ child: AST
102+
) -> AST {
103+
quant(.oneOrMore, kind, child)
104+
}
105+
public func exactly(
106+
_ kind: Quantifier.Kind = .greedy,
107+
_ i: Int,
108+
child: AST
109+
) -> AST {
110+
quant(.exactly(i), kind, child)
111+
}
112+
public func nOrMore(
113+
_ kind: Quantifier.Kind = .greedy,
114+
_ i: Int,
115+
child: AST
116+
) -> AST {
117+
quant(.nOrMore(i), kind, child)
118+
}
119+
public func upToN(
120+
_ kind: Quantifier.Kind = .greedy,
121+
_ i: Int,
122+
child: AST
123+
) -> AST {
124+
quant(.upToN(i), kind, child)
125+
}
126+
public func quantRange(
127+
_ kind: Quantifier.Kind = .greedy,
128+
_ r: ClosedRange<Int>,
129+
child: AST
130+
) -> AST {
131+
quant(.range(r), kind, child)
132+
}
133+
134+
public func charClass(
135+
_ members: CustomCharacterClass.Member...,
136+
inverted: Bool = false
137+
) -> AST {
138+
let cc = CustomCharacterClass(
139+
inverted ? .inverted : .normal, members
140+
)
141+
return .customCharacterClass(cc)
142+
}
143+
public func charClass(
144+
_ members: CustomCharacterClass.Member...,
145+
inverted: Bool = false
146+
) -> CustomCharacterClass.Member {
147+
let cc = CustomCharacterClass(
148+
inverted ? .inverted : .normal, members
149+
)
150+
return .custom(cc)
151+
}
152+
public func posixSet(
153+
_ set: Unicode.POSIXCharacterSet, inverted: Bool = false
154+
) -> Atom {
155+
return .named(.init(inverted: inverted, set: set))
156+
}

Sources/_MatchingEngine/Regex/AST/ASTEntity.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public protocol ASTValue: _ASTPrintable, Hashable {
1010
///
1111
/// Tracks source location information
1212
public protocol ASTEntity: ASTValue {
13-
var sourceRange: SourceRange? { get }
13+
var sourceRange: SourceRange { get }
1414
}
1515

1616
public protocol ASTParentEntity: ASTEntity, _ASTPrintableNested {

0 commit comments

Comments
 (0)