Skip to content

Commit 094089b

Browse files
committed
Implement auto-possessification
This optimization recognizes quantifications followed by an atom that can't be matched at the start of the quantification, and converts them to possessive, eliminating any backtracking at that position. This change includes an accessor for the first "required" atom (which will be used in other optimizations), and converts DSL.QuantificationKind to a struct to support the possessification changes.
1 parent 4cdb58a commit 094089b

File tree

8 files changed

+564
-38
lines changed

8 files changed

+564
-38
lines changed

Sources/_StringProcessing/ByteCodeGen+DSLList.swift

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
internal import _RegexParser
1313

1414
extension Compiler.ByteCodeGen {
15-
mutating func emitRoot(_ root: DSLList) throws -> MEProgram {
15+
mutating func emitRoot(_ root: inout DSLList) throws -> MEProgram {
1616
// If the whole regex is a matcher, then the whole-match value
1717
// is the constructed value. Denote that the current value
1818
// register is the processor's value output.
@@ -22,7 +22,11 @@ extension Compiler.ByteCodeGen {
2222
default:
2323
break
2424
}
25-
25+
26+
if optimizationsEnabled {
27+
root.autoPossessify()
28+
}
29+
2630
var list = root.nodes[...]
2731
try emitNode(&list)
2832

@@ -352,15 +356,7 @@ fileprivate extension Compiler.ByteCodeGen {
352356
_ kind: DSLTree.QuantificationKind,
353357
_ list: inout ArraySlice<DSLTree.Node>
354358
) throws {
355-
let updatedKind: AST.Quantification.Kind
356-
switch kind {
357-
case .explicit(let kind):
358-
updatedKind = kind.ast
359-
case .syntax(let kind):
360-
updatedKind = kind.ast.applying(options)
361-
case .default:
362-
updatedKind = options.defaultQuantificationKind
363-
}
359+
let updatedKind = kind.applying(options: options)
364360

365361
let (low, high) = amount.bounds
366362
guard let low = low else {

Sources/_StringProcessing/ByteCodeGen.swift

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -506,15 +506,7 @@ extension Compiler.ByteCodeGen {
506506
_ kind: DSLTree.QuantificationKind,
507507
_ child: DSLTree.Node
508508
) throws {
509-
let updatedKind: AST.Quantification.Kind
510-
switch kind {
511-
case .explicit(let kind):
512-
updatedKind = kind.ast
513-
case .syntax(let kind):
514-
updatedKind = kind.ast.applying(options)
515-
case .default:
516-
updatedKind = options.defaultQuantificationKind
517-
}
509+
let updatedKind = kind.applying(options: options)
518510

519511
let (low, high) = amount.bounds
520512
guard let low = low else {

Sources/_StringProcessing/Compiler.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,13 @@ class Compiler {
4747

4848
__consuming func emitViaList() throws -> MEProgram {
4949
// TODO: Handle global options
50-
let dslList = DSLList(tree: tree)
50+
var dslList = DSLList(tree: tree)
5151
var codegen = ByteCodeGen(
5252
options: options,
5353
compileOptions:
5454
compileOptions,
5555
captureList: tree.captureList)
56-
return try codegen.emitRoot(dslList)
56+
return try codegen.emitRoot(&dslList)
5757
}
5858
}
5959

Sources/_StringProcessing/LiteralPrinter.swift

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,16 @@ extension LiteralPrinter {
224224
}
225225

226226
mutating func outputQuantificationKind(_ kind: DSLTree.QuantificationKind) {
227-
switch kind {
228-
case .`default`:
227+
guard let astKind = kind.quantificationKind?.ast else {
229228
// We can treat this as if the current default had been given explicity.
230229
outputQuantificationKind(
231230
.explicit(.init(ast: options.defaultQuantificationKind)))
232-
case let .explicit(kind):
233-
switch kind.ast {
231+
return
232+
}
233+
234+
if kind.isExplicit {
235+
// Explicitly provided modifiers need to match the current option state.
236+
switch astKind {
234237
case .eager:
235238
output(options.isReluctantByDefault ? "?" : "")
236239
case .reluctant:
@@ -242,9 +245,9 @@ extension LiteralPrinter {
242245
fatalError()
243246
#endif
244247
}
245-
case let .syntax(kind):
248+
} else {
246249
// Syntactically-specified quantification modifiers can stay as-is.
247-
switch kind.ast {
250+
switch astKind {
248251
case .eager:
249252
output("")
250253
case .reluctant:

0 commit comments

Comments
 (0)