Skip to content

Commit 280bf24

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 95461b5 commit 280bf24

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)
@@ -56,6 +57,19 @@ class SwiftParserTest: ParsableCommand {
5657
)
5758
}
5859

60+
/// Fold all of the sequences in the given source file.
61+
func foldAllSequences(_ tree: SourceFileSyntax) -> (Syntax, [Diagnostic]) {
62+
var diags: [Diagnostic] = []
63+
64+
let recordOperatorError: (OperatorError) -> Void = { error in
65+
diags.append(error.asDiagnostic)
66+
}
67+
var operatorTable = OperatorTable.standardOperators
68+
operatorTable.addSourceFile(tree, errorHandler: recordOperatorError)
69+
let resultTree = operatorTable.foldAll(tree, errorHandler: recordOperatorError)
70+
return (Syntax(resultTree), diags)
71+
}
72+
5973
class VerifyRoundTrip: ParsableCommand {
6074
required init() {}
6175

@@ -74,6 +88,10 @@ class VerifyRoundTrip: ParsableCommand {
7488
@Option(name: .long, help: "Enable or disable the use of forward slash regular-expression literal syntax")
7589
var enableBareSlashRegex: Bool?
7690

91+
@Flag(name: .long,
92+
help: "Perform sequence folding with the standard operators")
93+
var foldSequences: Bool = false
94+
7795
enum Error: Swift.Error, CustomStringConvertible {
7896
case roundTripFailed
7997

@@ -91,21 +109,30 @@ class VerifyRoundTrip: ParsableCommand {
91109
try source.withUnsafeBufferPointer { sourceBuffer in
92110
try Self.run(
93111
source: sourceBuffer, swiftVersion: swiftVersion,
94-
enableBareSlashRegex: enableBareSlashRegex
112+
enableBareSlashRegex: enableBareSlashRegex,
113+
foldSequences: foldSequences
95114
)
96115
}
97116
}
98117

99118
static func run(
100119
source: UnsafeBufferPointer<UInt8>, swiftVersion: String?,
101-
enableBareSlashRegex: Bool?
120+
enableBareSlashRegex: Bool?, foldSequences: Bool
102121
) throws {
103122
let tree = try Parser.parse(
104123
source: source,
105124
languageVersion: swiftVersion,
106125
enableBareSlashRegexLiteral: enableBareSlashRegex
107126
)
108-
if tree.syntaxTextBytes != [UInt8](source) {
127+
128+
let resultTree: Syntax
129+
if foldSequences {
130+
resultTree = foldAllSequences(tree).0
131+
} else {
132+
resultTree = Syntax(tree)
133+
}
134+
135+
if resultTree.syntaxTextBytes != [UInt8](source) {
109136
throw Error.roundTripFailed
110137
}
111138
}
@@ -123,6 +150,10 @@ class PrintDiags: ParsableCommand {
123150
@Option(name: .long, help: "Enable or disable the use of forward slash regular-expression literal syntax")
124151
var enableBareSlashRegex: Bool?
125152

153+
@Flag(name: .long,
154+
help: "Perform sequence folding with the standard operators")
155+
var foldSequences: Bool = false
156+
126157
func run() throws {
127158
let source = try getContentsOfSourceFile(at: sourceFile)
128159

@@ -132,7 +163,12 @@ class PrintDiags: ParsableCommand {
132163
languageVersion: swiftVersion,
133164
enableBareSlashRegexLiteral: enableBareSlashRegex
134165
)
135-
let diags = ParseDiagnosticsGenerator.diagnostics(for: tree)
166+
var diags = ParseDiagnosticsGenerator.diagnostics(for: tree)
167+
168+
if foldSequences {
169+
diags += foldAllSequences(tree).1
170+
}
171+
136172
if diags.isEmpty {
137173
print("No diagnostics produced")
138174
}
@@ -155,6 +191,10 @@ class DumpTree: ParsableCommand {
155191
@Option(name: .long, help: "Enable or disable the use of forward slash regular-expression literal syntax")
156192
var enableBareSlashRegex: Bool?
157193

194+
@Flag(name: .long,
195+
help: "Perform sequence folding with the standard operators")
196+
var foldSequences: Bool = false
197+
158198
func run() throws {
159199
let source = try getContentsOfSourceFile(at: sourceFile)
160200

@@ -164,7 +204,15 @@ class DumpTree: ParsableCommand {
164204
languageVersion: swiftVersion,
165205
enableBareSlashRegexLiteral: enableBareSlashRegex
166206
)
167-
print(tree.recursiveDescription)
207+
208+
let resultTree: Syntax
209+
if foldSequences {
210+
resultTree = foldAllSequences(tree).0
211+
} else {
212+
resultTree = Syntax(tree)
213+
}
214+
215+
print(resultTree.recursiveDescription)
168216
}
169217
}
170218
}
@@ -181,6 +229,10 @@ class Reduce: ParsableCommand {
181229
@Option(name: .long, help: "Enable or disable the use of forward slash regular-expression literal syntax")
182230
var enableBareSlashRegex: Bool?
183231

232+
@Flag(name: .long,
233+
help: "Perform sequence folding with the standard operators")
234+
var foldSequences: Bool = false
235+
184236
@Flag(help: "Print status updates while reducing the test case")
185237
var verbose: Bool = false
186238

@@ -225,6 +277,10 @@ class Reduce: ParsableCommand {
225277
"--swift-version", swiftVersion
226278
]
227279
}
280+
if foldSequences {
281+
process.arguments! += [ "--fold-sequences" ]
282+
}
283+
228284
let sema = DispatchSemaphore(value: 0)
229285
process.standardOutput = FileHandle.nullDevice
230286
process.standardError = FileHandle.nullDevice
@@ -257,7 +313,8 @@ class Reduce: ParsableCommand {
257313
private func runVerifyRoundTripInCurrentProcess(source: [UInt8]) throws -> Bool {
258314
do {
259315
try source.withUnsafeBufferPointer { sourceBuffer in
260-
try VerifyRoundTrip.run(source: sourceBuffer, swiftVersion: self.swiftVersion, enableBareSlashRegex: self.enableBareSlashRegex)
316+
try VerifyRoundTrip.run(source: sourceBuffer, swiftVersion: self.swiftVersion, enableBareSlashRegex: self.enableBareSlashRegex,
317+
foldSequences: foldSequences)
261318
}
262319
} catch {
263320
return false

0 commit comments

Comments
 (0)