Skip to content

Commit cb134fa

Browse files
authored
Merge pull request #1943 from ahoppen/ahoppen/simplify-tokenspec
Simplify `TokenSpec` in CodeGeneration
2 parents 43c070f + 95328cc commit cb134fa

File tree

11 files changed

+180
-223
lines changed

11 files changed

+180
-223
lines changed

CodeGeneration/Sources/SyntaxSupport/GrammarGenerator.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ struct GrammarGenerator {
2323
if let tokenText = token.text {
2424
return "`'\(tokenText)'`"
2525
} else {
26-
return "`<\(token.swiftKind)>`"
26+
return "`<\(token.varOrCaseName)>`"
2727
}
2828
}
2929
}

CodeGeneration/Sources/SyntaxSupport/TokenSpec.swift

Lines changed: 81 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -10,157 +10,114 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
import SwiftSyntax
14+
1315
/// Represents the specification for a Token in the TokenSyntax file.
14-
public class TokenSpec {
15-
public let name: String
16+
public struct TokenSpec {
17+
public enum Kind {
18+
case punctuation
19+
/// The `keyword` TokenKind that contains the actual keyword as an associated value
20+
case keyword
21+
case other
22+
}
23+
24+
public let varOrCaseName: TokenSyntax
1625
public let nameForDiagnostics: String
1726
public let text: String?
18-
public let associatedValueClass: String?
19-
20-
public var swiftKind: String {
21-
return lowercaseFirstWord(name: self.name)
22-
}
27+
public let kind: Kind
2328

24-
init(
29+
fileprivate init(
2530
name: String,
2631
nameForDiagnostics: String,
2732
text: String? = nil,
28-
associatedValueClass: String? = nil
33+
kind: Kind
2934
) {
30-
self.name = name
35+
self.varOrCaseName = .identifier(name)
3136
self.nameForDiagnostics = nameForDiagnostics
3237
self.text = text
33-
self.associatedValueClass = associatedValueClass
34-
}
35-
}
36-
37-
public class PoundSpec: TokenSpec {
38-
init(
39-
name: String,
40-
nameForDiagnostics: String? = nil,
41-
text: String
42-
) {
43-
super.init(
44-
name: name,
45-
nameForDiagnostics: nameForDiagnostics ?? text,
46-
text: text
47-
)
48-
}
49-
}
50-
51-
public class PoundObjectLiteralSpec: PoundSpec {
52-
let `protocol`: String
53-
54-
init(
55-
name: String,
56-
text: String,
57-
nameForDiagnostics: String,
58-
`protocol`: String
59-
) {
60-
self.`protocol` = `protocol`
61-
super.init(
62-
name: name,
63-
nameForDiagnostics: nameForDiagnostics,
64-
text: text
65-
)
38+
self.kind = kind
6639
}
67-
}
68-
69-
public class PoundConfigSpec: PoundSpec {}
7040

71-
public class PoundDirectiveSpec: PoundSpec {
72-
init(
73-
name: String,
74-
text: String
75-
) {
76-
super.init(
41+
static func punctuator(name: String, text: String) -> TokenSpec {
42+
return TokenSpec(
7743
name: name,
78-
text: text
44+
nameForDiagnostics: text,
45+
text: text,
46+
kind: .punctuation
7947
)
8048
}
81-
}
8249

83-
public class PoundConditionalDirectiveSpec: PoundDirectiveSpec {
84-
override init(
85-
name: String,
86-
text: String
87-
) {
88-
super.init(
50+
static func poundKeyword(name: String, text: String) -> TokenSpec {
51+
return TokenSpec(
8952
name: name,
90-
text: text
53+
nameForDiagnostics: text,
54+
text: text,
55+
kind: .other
9156
)
9257
}
93-
}
9458

95-
public class PunctuatorSpec: TokenSpec {
96-
init(
97-
name: String,
98-
text: String
99-
) {
100-
super.init(
59+
static func other(name: String, nameForDiagnostics: String, text: String? = nil) -> TokenSpec {
60+
TokenSpec(
10161
name: name,
102-
nameForDiagnostics: text,
103-
text: text
62+
nameForDiagnostics: nameForDiagnostics,
63+
text: text,
64+
kind: .other
10465
)
10566
}
10667
}
10768

108-
public class LiteralSpec: TokenSpec {}
109-
110-
public class MiscSpec: TokenSpec {}
111-
11269
public let SYNTAX_TOKENS: [TokenSpec] = [
113-
PunctuatorSpec(name: "Arrow", text: "->"),
114-
PunctuatorSpec(name: "AtSign", text: "@"),
115-
PunctuatorSpec(name: "Backslash", text: "\\"),
116-
PunctuatorSpec(name: "Backtick", text: "`"),
117-
MiscSpec(name: "BinaryOperator", nameForDiagnostics: "binary operator"),
118-
PunctuatorSpec(name: "Colon", text: ":"),
119-
PunctuatorSpec(name: "Comma", text: ","),
120-
MiscSpec(name: "DollarIdentifier", nameForDiagnostics: "dollar identifier"),
121-
PunctuatorSpec(name: "Ellipsis", text: "..."),
122-
MiscSpec(name: "EndOfFile", nameForDiagnostics: "end of file", text: ""),
123-
PunctuatorSpec(name: "Equal", text: "="),
124-
PunctuatorSpec(name: "ExclamationMark", text: "!"),
125-
MiscSpec(name: "ExtendedRegexDelimiter", nameForDiagnostics: "extended delimiter"),
126-
LiteralSpec(name: "FloatingLiteral", nameForDiagnostics: "floating literal"),
127-
MiscSpec(name: "Identifier", nameForDiagnostics: "identifier"),
128-
PunctuatorSpec(name: "InfixQuestionMark", text: "?"),
129-
LiteralSpec(name: "IntegerLiteral", nameForDiagnostics: "integer literal"),
130-
MiscSpec(name: "Keyword", nameForDiagnostics: "keyword", associatedValueClass: "Keyword"),
131-
PunctuatorSpec(name: "LeftAngle", text: "<"),
132-
PunctuatorSpec(name: "LeftBrace", text: "{"),
133-
PunctuatorSpec(name: "LeftParen", text: "("),
134-
PunctuatorSpec(name: "LeftSquare", text: "["),
135-
PunctuatorSpec(name: "MultilineStringQuote", text: "\"\"\""),
136-
PunctuatorSpec(name: "Period", text: "."),
137-
MiscSpec(name: "PostfixOperator", nameForDiagnostics: "postfix operator"),
138-
PunctuatorSpec(name: "PostfixQuestionMark", text: "?"),
139-
PunctuatorSpec(name: "Pound", text: "#"),
140-
PoundConfigSpec(name: "PoundAvailable", text: "#available"),
141-
PoundConditionalDirectiveSpec(name: "PoundElse", text: "#else"),
142-
PoundConditionalDirectiveSpec(name: "PoundElseif", text: "#elseif"),
143-
PoundConditionalDirectiveSpec(name: "PoundEndif", text: "#endif"),
144-
PoundConditionalDirectiveSpec(name: "PoundIf", text: "#if"),
145-
PoundDirectiveSpec(name: "PoundSourceLocation", text: "#sourceLocation"),
146-
PoundConfigSpec(name: "PoundUnavailable", text: "#unavailable"),
147-
PunctuatorSpec(name: "PrefixAmpersand", text: "&"),
148-
MiscSpec(name: "PrefixOperator", nameForDiagnostics: "prefix operator"),
149-
MiscSpec(name: "RawStringDelimiter", nameForDiagnostics: "raw string delimiter"),
150-
MiscSpec(name: "RegexLiteralPattern", nameForDiagnostics: "regex pattern"),
151-
PunctuatorSpec(name: "RegexSlash", text: "/"),
152-
PunctuatorSpec(name: "RightAngle", text: ">"),
153-
PunctuatorSpec(name: "RightBrace", text: "}"),
154-
PunctuatorSpec(name: "RightParen", text: ")"),
155-
PunctuatorSpec(name: "RightSquare", text: "]"),
156-
PunctuatorSpec(name: "Semicolon", text: ";"),
157-
PunctuatorSpec(name: "SingleQuote", text: "\'"),
158-
PunctuatorSpec(name: "StringQuote", text: "\""),
159-
MiscSpec(name: "StringSegment", nameForDiagnostics: "string segment"),
160-
MiscSpec(name: "Unknown", nameForDiagnostics: "token"),
161-
MiscSpec(name: "Wildcard", nameForDiagnostics: "wildcard", text: "_"),
70+
.punctuator(name: "arrow", text: "->"),
71+
.punctuator(name: "atSign", text: "@"),
72+
.punctuator(name: "backslash", text: "\\"),
73+
.punctuator(name: "backtick", text: "`"),
74+
.other(name: "binaryOperator", nameForDiagnostics: "binary operator"),
75+
.punctuator(name: "colon", text: ":"),
76+
.punctuator(name: "comma", text: ","),
77+
.other(name: "dollarIdentifier", nameForDiagnostics: "dollar identifier"),
78+
.punctuator(name: "ellipsis", text: "..."),
79+
.other(name: "endOfFile", nameForDiagnostics: "end of file", text: ""),
80+
.punctuator(name: "equal", text: "="),
81+
.punctuator(name: "exclamationMark", text: "!"),
82+
.other(name: "extendedRegexDelimiter", nameForDiagnostics: "extended delimiter"),
83+
.other(name: "floatingLiteral", nameForDiagnostics: "floating literal"),
84+
.other(name: "identifier", nameForDiagnostics: "identifier"),
85+
.punctuator(name: "infixQuestionMark", text: "?"),
86+
.other(name: "integerLiteral", nameForDiagnostics: "integer literal"),
87+
TokenSpec(name: "keyword", nameForDiagnostics: "keyword", text: nil, kind: .keyword),
88+
.punctuator(name: "leftAngle", text: "<"),
89+
.punctuator(name: "leftBrace", text: "{"),
90+
.punctuator(name: "leftParen", text: "("),
91+
.punctuator(name: "leftSquare", text: "["),
92+
.punctuator(name: "multilineStringQuote", text: "\"\"\""),
93+
.punctuator(name: "period", text: "."),
94+
.other(name: "postfixOperator", nameForDiagnostics: "postfix operator"),
95+
.punctuator(name: "postfixQuestionMark", text: "?"),
96+
.punctuator(name: "pound", text: "#"),
97+
.poundKeyword(name: "poundAvailable", text: "#available"),
98+
.poundKeyword(name: "poundElse", text: "#else"),
99+
.poundKeyword(name: "poundElseif", text: "#elseif"),
100+
.poundKeyword(name: "poundEndif", text: "#endif"),
101+
.poundKeyword(name: "poundIf", text: "#if"),
102+
.poundKeyword(name: "poundSourceLocation", text: "#sourceLocation"),
103+
.poundKeyword(name: "poundUnavailable", text: "#unavailable"),
104+
.punctuator(name: "prefixAmpersand", text: "&"),
105+
.other(name: "prefixOperator", nameForDiagnostics: "prefix operator"),
106+
.other(name: "rawStringDelimiter", nameForDiagnostics: "raw string delimiter"),
107+
.other(name: "regexLiteralPattern", nameForDiagnostics: "regex pattern"),
108+
.punctuator(name: "regexSlash", text: "/"),
109+
.punctuator(name: "rightAngle", text: ">"),
110+
.punctuator(name: "rightBrace", text: "}"),
111+
.punctuator(name: "rightParen", text: ")"),
112+
.punctuator(name: "rightSquare", text: "]"),
113+
.punctuator(name: "semicolon", text: ";"),
114+
.punctuator(name: "singleQuote", text: "\'"),
115+
.punctuator(name: "stringQuote", text: "\""),
116+
.other(name: "stringSegment", nameForDiagnostics: "string segment"),
117+
.other(name: "unknown", nameForDiagnostics: "token"),
118+
.other(name: "wildcard", nameForDiagnostics: "wildcard", text: "_"),
162119
]
163120

164121
public let SYNTAX_TOKEN_MAP = Dictionary(
165-
uniqueKeysWithValues: SYNTAX_TOKENS.map { ("\($0.name)Token", $0) }
122+
uniqueKeysWithValues: SYNTAX_TOKENS.map { ("\($0.varOrCaseName.description.withFirstCharacterUppercased)Token", $0) }
166123
)

CodeGeneration/Sources/Utils/SyntaxBuildableChild.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ public extension Child {
6969
return type.defaultValue
7070
}
7171
if token.text != nil {
72-
return ExprSyntax(".\(raw: token.swiftKind)Token()")
72+
return ExprSyntax(".\(token.varOrCaseName)Token()")
7373
}
74-
guard case .token(let choices, _, _) = kind, choices.count == 1, token.associatedValueClass != nil else {
74+
guard case .token(let choices, _, _) = kind, choices.count == 1, token.kind == .keyword else {
7575
return nil
7676
}
7777
var textChoice: String
@@ -82,7 +82,7 @@ public extension Child {
8282
if textChoice == "init" {
8383
textChoice = "`init`"
8484
}
85-
return ExprSyntax(".\(raw: token.swiftKind)(.\(raw: textChoice))")
85+
return ExprSyntax(".\(token.varOrCaseName)(.\(raw: textChoice))")
8686
}
8787

8888
/// If the child node has a default value, return an expression of the form

CodeGeneration/Sources/Utils/SyntaxBuildableType.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public struct SyntaxBuildableType: Hashable {
6464
return ExprSyntax(NilLiteralExprSyntax())
6565
} else if let token = token {
6666
if token.text != nil {
67-
return ExprSyntax(".\(raw: lowercaseFirstWord(name: token.name))Token()")
67+
return ExprSyntax(".\(token.varOrCaseName)Token()")
6868
}
6969
}
7070
return nil

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftparser/ParserTokenSpecSetFile.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ let parserTokenSpecSetFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
3030
DeclSyntax("case \(raw: keyword.escapedName)")
3131
case .token(let tokenText):
3232
let token = SYNTAX_TOKEN_MAP[tokenText]!
33-
DeclSyntax("case \(raw: token.swiftKind)")
33+
DeclSyntax("case \(token.varOrCaseName)")
3434
}
3535
}
3636

@@ -44,7 +44,7 @@ let parserTokenSpecSetFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
4444
case .token(let tokenText):
4545
let token = SYNTAX_TOKEN_MAP[tokenText]!
4646
SwitchCaseSyntax(
47-
"case TokenSpec(.\(raw: token.swiftKind)): self = .\(raw: token.swiftKind)"
47+
"case TokenSpec(.\(token.varOrCaseName)): self = .\(token.varOrCaseName)"
4848
)
4949
}
5050
}
@@ -64,7 +64,7 @@ let parserTokenSpecSetFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
6464
case .token(let tokenText):
6565
let token = SYNTAX_TOKEN_MAP[tokenText]!
6666
SwitchCaseSyntax(
67-
"case .\(raw: token.swiftKind): return .\(raw: token.swiftKind)"
67+
"case .\(token.varOrCaseName): return .\(token.varOrCaseName)"
6868
)
6969
}
7070
}

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftparser/TokenSpecStaticMembersFile.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ let tokenSpecStaticMembersFile = SourceFileSyntax(leadingTrivia: copyrightHeader
1919
DeclSyntax("@_spi(RawSyntax) import SwiftSyntax")
2020

2121
try! ExtensionDeclSyntax("extension TokenSpec") {
22-
for token in SYNTAX_TOKENS where token.swiftKind != "keyword" {
23-
DeclSyntax("static var \(raw: token.swiftKind): TokenSpec { return TokenSpec(.\(raw: token.swiftKind)) }")
22+
for token in SYNTAX_TOKENS where token.kind != .keyword {
23+
DeclSyntax("static var \(token.varOrCaseName): TokenSpec { return TokenSpec(.\(token.varOrCaseName)) }")
2424
}
2525

2626
DeclSyntax("static func keyword(_ keyword: Keyword) -> TokenSpec { return TokenSpec(keyword) }")

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftparserdiagnostics/TokenNameForDiagnosticsFile.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ let tokenNameForDiagnosticFile = SourceFileSyntax(leadingTrivia: copyrightHeader
2121
try! ExtensionDeclSyntax("extension TokenKind") {
2222
try! VariableDeclSyntax("var nameForDiagnostics: String") {
2323
try! SwitchExprSyntax("switch self") {
24-
for token in SYNTAX_TOKENS where token.swiftKind != "keyword" {
25-
SwitchCaseSyntax("case .\(raw: token.swiftKind):") {
26-
StmtSyntax("return #\"\(raw: token.nameForDiagnostics)\"#")
24+
for token in SYNTAX_TOKENS where token.kind != .keyword {
25+
SwitchCaseSyntax("case .\(token.varOrCaseName):") {
26+
StmtSyntax("return \(literal: token.nameForDiagnostics)")
2727
}
2828
}
2929
SwitchCaseSyntax("case .keyword(let keyword):") {

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/RawSyntaxValidationFile.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ let rawSyntaxValidationFile = try! SourceFileSyntax(leadingTrivia: copyrightHead
216216
case .keyword(text: let text):
217217
ArrayElementSyntax(expression: ExprSyntax(#".keyword("\#(raw: text)")"#))
218218
case .token(tokenKind: let tokenKind):
219-
ArrayElementSyntax(expression: ExprSyntax(".tokenKind(.\(raw: SYNTAX_TOKEN_MAP[tokenKind]!.swiftKind))"))
219+
ArrayElementSyntax(expression: ExprSyntax(".tokenKind(.\(SYNTAX_TOKEN_MAP[tokenKind]!.varOrCaseName))"))
220220
}
221221
}
222222
}

0 commit comments

Comments
 (0)