Skip to content

Commit 6c7a361

Browse files
committed
Add --fold-sequences operation to swift-parser-test
Use the `SwiftOperators` library to add support for sequence folding into `swift-parser-test`. Each of the subcommands now supports the `--fold-sequences` operation, which applies sequence folding using the standard library operators and any additional precedence groups and operators defines within the provided source file. The resulting behavior for each of the subcommands is: * `verify-round-trip`: ensure that, after folding, the resulting tree still reproduces the input source. * `print-diags`: also prints any diagnostics from sequence folding, e.g., a ** b ** c where ** is non-associative will produce an error. * `dump-tree`: prints the folded tree, which (for example) will no longer have any SequenceExprSyntax nodes. * `reduce`: passes `--fold-sequences` down for reduction.
1 parent be427f5 commit 6c7a361

File tree

2 files changed

+68
-8
lines changed

2 files changed

+68
-8
lines changed

Package.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,9 @@ let package = Package(
130130
),
131131
.executableTarget(
132132
name: "swift-parser-test",
133-
dependencies: ["SwiftDiagnostics", "SwiftSyntax", "SwiftParser", .product(name: "ArgumentParser", package: "swift-argument-parser")]
133+
dependencies: ["SwiftDiagnostics", "SwiftSyntax", "SwiftParser",
134+
"SwiftOperators",
135+
.product(name: "ArgumentParser", package: "swift-argument-parser")]
134136
),
135137
.executableTarget(
136138
name: "generate-swift-syntax-builder",
@@ -177,7 +179,8 @@ let package = Package(
177179
),
178180
.testTarget(
179181
name: "SwiftParserTest",
180-
dependencies: ["SwiftDiagnostics", "SwiftParser", "_SwiftSyntaxTestSupport"]
182+
dependencies: ["SwiftDiagnostics", "SwiftOperators", "SwiftParser",
183+
"_SwiftSyntaxTestSupport"]
181184
),
182185
.testTarget(
183186
name: "SwiftOperatorsTest",

Sources/swift-parser-test/swift-parser-test.swift

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import SwiftDiagnostics
1515
import SwiftSyntax
1616
import SwiftParser
17+
import SwiftOperators
1718
import Foundation
1819
import ArgumentParser
1920
#if os(Windows)
@@ -51,6 +52,19 @@ class SwiftParserTest: ParsableCommand {
5152
)
5253
}
5354

55+
/// Fold all of the sequences in the given source file.
56+
func foldAllSequences(_ tree: SourceFileSyntax) -> (Syntax, [Diagnostic]) {
57+
var diags: [Diagnostic] = []
58+
59+
let recordOperatorError: (OperatorError) -> Void = { error in
60+
diags.append(error.asDiagnostic)
61+
}
62+
var operatorTable = OperatorTable.standardOperators
63+
operatorTable.addSourceFile(tree, errorHandler: recordOperatorError)
64+
let resultTree = operatorTable.foldAll(tree, errorHandler: recordOperatorError)
65+
return (Syntax(resultTree), diags)
66+
}
67+
5468
class VerifyRoundTrip: ParsableCommand {
5569
required init() {}
5670

@@ -69,6 +83,10 @@ class VerifyRoundTrip: ParsableCommand {
6983
@Option(name: .long, help: "Enable or disable the use of forward slash regular-expression literal syntax")
7084
var enableBareSlashRegex: Bool?
7185

86+
@Flag(name: .long,
87+
help: "Perform sequence folding with the standard operators")
88+
var foldSequences: Bool = false
89+
7290
enum Error: Swift.Error, CustomStringConvertible {
7391
case roundTripFailed
7492

@@ -86,21 +104,30 @@ class VerifyRoundTrip: ParsableCommand {
86104
try source.withUnsafeBufferPointer { sourceBuffer in
87105
try Self.run(
88106
source: sourceBuffer, swiftVersion: swiftVersion,
89-
enableBareSlashRegex: enableBareSlashRegex
107+
enableBareSlashRegex: enableBareSlashRegex,
108+
foldSequences: foldSequences
90109
)
91110
}
92111
}
93112

94113
static func run(
95114
source: UnsafeBufferPointer<UInt8>, swiftVersion: String?,
96-
enableBareSlashRegex: Bool?
115+
enableBareSlashRegex: Bool?, foldSequences: Bool
97116
) throws {
98117
let tree = try Parser.parse(
99118
source: source,
100119
languageVersion: swiftVersion,
101120
enableBareSlashRegexLiteral: enableBareSlashRegex
102121
)
103-
if tree.syntaxTextBytes != [UInt8](source) {
122+
123+
let resultTree: Syntax
124+
if foldSequences {
125+
resultTree = foldAllSequences(tree).0
126+
} else {
127+
resultTree = Syntax(tree)
128+
}
129+
130+
if resultTree.syntaxTextBytes != [UInt8](source) {
104131
throw Error.roundTripFailed
105132
}
106133
}
@@ -118,6 +145,10 @@ class PrintDiags: ParsableCommand {
118145
@Option(name: .long, help: "Enable or disable the use of forward slash regular-expression literal syntax")
119146
var enableBareSlashRegex: Bool?
120147

148+
@Flag(name: .long,
149+
help: "Perform sequence folding with the standard operators")
150+
var foldSequences: Bool = false
151+
121152
func run() throws {
122153
let source = try getContentsOfSourceFile(at: sourceFile)
123154

@@ -127,7 +158,12 @@ class PrintDiags: ParsableCommand {
127158
languageVersion: swiftVersion,
128159
enableBareSlashRegexLiteral: enableBareSlashRegex
129160
)
130-
let diags = ParseDiagnosticsGenerator.diagnostics(for: tree)
161+
var diags = ParseDiagnosticsGenerator.diagnostics(for: tree)
162+
163+
if foldSequences {
164+
diags += foldAllSequences(tree).1
165+
}
166+
131167
if diags.isEmpty {
132168
print("No diagnostics produced")
133169
}
@@ -150,6 +186,10 @@ class DumpTree: ParsableCommand {
150186
@Option(name: .long, help: "Enable or disable the use of forward slash regular-expression literal syntax")
151187
var enableBareSlashRegex: Bool?
152188

189+
@Flag(name: .long,
190+
help: "Perform sequence folding with the standard operators")
191+
var foldSequences: Bool = false
192+
153193
func run() throws {
154194
let source = try getContentsOfSourceFile(at: sourceFile)
155195

@@ -159,7 +199,15 @@ class DumpTree: ParsableCommand {
159199
languageVersion: swiftVersion,
160200
enableBareSlashRegexLiteral: enableBareSlashRegex
161201
)
162-
print(tree.recursiveDescription)
202+
203+
let resultTree: Syntax
204+
if foldSequences {
205+
resultTree = foldAllSequences(tree).0
206+
} else {
207+
resultTree = Syntax(tree)
208+
}
209+
210+
print(resultTree.recursiveDescription)
163211
}
164212
}
165213
}
@@ -176,6 +224,10 @@ class Reduce: ParsableCommand {
176224
@Option(name: .long, help: "Enable or disable the use of forward slash regular-expression literal syntax")
177225
var enableBareSlashRegex: Bool?
178226

227+
@Flag(name: .long,
228+
help: "Perform sequence folding with the standard operators")
229+
var foldSequences: Bool = false
230+
179231
@Flag(help: "Print status updates while reducing the test case")
180232
var verbose: Bool = false
181233

@@ -220,6 +272,10 @@ class Reduce: ParsableCommand {
220272
"--swift-version", swiftVersion
221273
]
222274
}
275+
if foldSequences {
276+
process.arguments! += [ "--fold-sequences" ]
277+
}
278+
223279
let sema = DispatchSemaphore(value: 0)
224280
process.standardOutput = FileHandle.nullDevice
225281
process.standardError = FileHandle.nullDevice
@@ -252,7 +308,8 @@ class Reduce: ParsableCommand {
252308
private func runVerifyRoundTripInCurrentProcess(source: [UInt8]) throws -> Bool {
253309
do {
254310
try source.withUnsafeBufferPointer { sourceBuffer in
255-
try VerifyRoundTrip.run(source: sourceBuffer, swiftVersion: self.swiftVersion, enableBareSlashRegex: self.enableBareSlashRegex)
311+
try VerifyRoundTrip.run(source: sourceBuffer, swiftVersion: self.swiftVersion, enableBareSlashRegex: self.enableBareSlashRegex,
312+
foldSequences: foldSequences)
256313
}
257314
} catch {
258315
return false

0 commit comments

Comments
 (0)