Skip to content

Commit 67769e0

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 066eaef commit 67769e0

File tree

2 files changed

+66
-8
lines changed

2 files changed

+66
-8
lines changed

Package.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,9 @@ let package = Package(
126126
),
127127
.executableTarget(
128128
name: "swift-parser-test",
129-
dependencies: ["SwiftDiagnostics", "SwiftSyntax", "SwiftParser", .product(name: "ArgumentParser", package: "swift-argument-parser")]
129+
dependencies: ["SwiftDiagnostics", "SwiftSyntax", "SwiftParser",
130+
"SwiftOperators",
131+
.product(name: "ArgumentParser", package: "swift-argument-parser")]
130132
),
131133
.executableTarget(
132134
name: "generate-swift-syntax-builder",
@@ -173,7 +175,8 @@ let package = Package(
173175
),
174176
.testTarget(
175177
name: "SwiftParserTest",
176-
dependencies: ["SwiftDiagnostics", "SwiftParser", "_SwiftSyntaxTestSupport"]
178+
dependencies: ["SwiftDiagnostics", "SwiftOperators", "SwiftParser",
179+
"_SwiftSyntaxTestSupport"]
177180
),
178181
.testTarget(
179182
name: "SwiftOperatorsTest",

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

Lines changed: 61 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)
@@ -64,6 +65,19 @@ class SwiftParserTest: ParsableCommand {
6465
)
6566
}
6667

68+
/// Fold all of the sequences in the given source file.
69+
func foldAllSequences(_ tree: SourceFileSyntax) -> (Syntax, [Diagnostic]) {
70+
var diags: [Diagnostic] = []
71+
72+
let recordOperatorError: (OperatorError) -> Void = { error in
73+
diags.append(error.asDiagnostic)
74+
}
75+
var operatorTable = OperatorTable.standardOperators
76+
operatorTable.addSourceFile(tree, errorHandler: recordOperatorError)
77+
let resultTree = operatorTable.foldAll(tree, errorHandler: recordOperatorError)
78+
return (Syntax(resultTree), diags)
79+
}
80+
6781
class VerifyRoundTrip: ParsableCommand {
6882
required init() {}
6983

@@ -82,6 +96,10 @@ class VerifyRoundTrip: ParsableCommand {
8296
@Option(name: .long, help: "Enable or disable the use of forward slash regular-expression literal syntax")
8397
var enableBareSlashRegex: Bool?
8498

99+
@Flag(name: .long,
100+
help: "Perform sequence folding with the standard operators")
101+
var foldSequences: Bool = false
102+
85103
enum Error: Swift.Error, CustomStringConvertible {
86104
case roundTripFailed
87105

@@ -96,16 +114,24 @@ class VerifyRoundTrip: ParsableCommand {
96114
func run() throws {
97115
let source = try getContentsOfSourceFile(at: sourceFile)
98116

99-
try Self.run(source: source, swiftVersion: swiftVersion, enableBareSlashRegex: enableBareSlashRegex)
117+
try Self.run(source: source, swiftVersion: swiftVersion, enableBareSlashRegex: enableBareSlashRegex, foldSequences: foldSequences)
100118
}
101119

102-
static func run(source: String, swiftVersion: String?, enableBareSlashRegex: Bool?) throws {
120+
static func run(source: String, swiftVersion: String?, enableBareSlashRegex: Bool?, foldSequences: Bool) throws {
103121
let tree = try Parser.parse(
104122
source: source,
105123
languageVersion: swiftVersion,
106124
enableBareSlashRegexLiteral: enableBareSlashRegex
107125
)
108-
if tree.description != source {
126+
127+
let resultTree: Syntax
128+
if foldSequences {
129+
resultTree = foldAllSequences(tree).0
130+
} else {
131+
resultTree = Syntax(tree)
132+
}
133+
134+
if resultTree.description != source {
109135
throw Error.roundTripFailed
110136
}
111137
}
@@ -123,6 +149,10 @@ class PrintDiags: ParsableCommand {
123149
@Option(name: .long, help: "Enable or disable the use of forward slash regular-expression literal syntax")
124150
var enableBareSlashRegex: Bool?
125151

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

@@ -131,7 +161,12 @@ class PrintDiags: ParsableCommand {
131161
languageVersion: swiftVersion,
132162
enableBareSlashRegexLiteral: enableBareSlashRegex
133163
)
134-
let diags = ParseDiagnosticsGenerator.diagnostics(for: tree)
164+
var diags = ParseDiagnosticsGenerator.diagnostics(for: tree)
165+
166+
if foldSequences {
167+
diags += foldAllSequences(tree).1
168+
}
169+
135170
if diags.isEmpty {
136171
print("No diagnostics produced")
137172
}
@@ -153,6 +188,10 @@ class DumpTree: ParsableCommand {
153188
@Option(name: .long, help: "Enable or disable the use of forward slash regular-expression literal syntax")
154189
var enableBareSlashRegex: Bool?
155190

191+
@Flag(name: .long,
192+
help: "Perform sequence folding with the standard operators")
193+
var foldSequences: Bool = false
194+
156195
func run() throws {
157196
let source = try getContentsOfSourceFile(at: sourceFile)
158197

@@ -161,7 +200,14 @@ class DumpTree: ParsableCommand {
161200
languageVersion: swiftVersion,
162201
enableBareSlashRegexLiteral: enableBareSlashRegex
163202
)
164-
print(tree.recursiveDescription)
203+
204+
let resultTree: Syntax
205+
if foldSequences {
206+
resultTree = foldAllSequences(tree).0
207+
} else {
208+
resultTree = Syntax(tree)
209+
}
210+
print(resultTree.recursiveDescription)
165211
}
166212
}
167213

@@ -177,6 +223,10 @@ class Reduce: ParsableCommand {
177223
@Option(name: .long, help: "Enable or disable the use of forward slash regular-expression literal syntax")
178224
var enableBareSlashRegex: Bool?
179225

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

@@ -221,6 +271,10 @@ class Reduce: ParsableCommand {
221271
"--swift-version", swiftVersion
222272
]
223273
}
274+
if foldSequences {
275+
process.arguments! += [ "--fold-sequences" ]
276+
}
277+
224278
let sema = DispatchSemaphore(value: 0)
225279
process.standardOutput = FileHandle.nullDevice
226280
process.standardError = FileHandle.nullDevice
@@ -252,7 +306,8 @@ class Reduce: ParsableCommand {
252306
/// Returns `true` if `source` round-tripped successfully, `false` otherwise.
253307
private func runVerifyRoundTripInCurrentProcess(source: String) throws -> Bool {
254308
do {
255-
try VerifyRoundTrip.run(source: source, swiftVersion: self.swiftVersion, enableBareSlashRegex: self.enableBareSlashRegex)
309+
try VerifyRoundTrip.run(source: source, swiftVersion: self.swiftVersion, enableBareSlashRegex: self.enableBareSlashRegex,
310+
foldSequences: self.foldSequences)
256311
} catch {
257312
return false
258313
}

0 commit comments

Comments
 (0)