10
10
//
11
11
//===----------------------------------------------------------------------===//
12
12
13
+ /// The kind of token a node can contain. Either a token of a specific kind or a
14
+ /// keyword with the given text.
15
+ public enum TokenChoice {
16
+ case keyword( text: String )
17
+ case token( tokenKind: String )
18
+
19
+ public var isKeyword : Bool {
20
+ switch self {
21
+ case . keyword: return true
22
+ case . token: return false
23
+ }
24
+ }
25
+ }
26
+
27
+ public enum ChildKind {
28
+ /// The child always contains a node of the given `kind`.
29
+ case node( kind: String )
30
+ /// The child always contains a node that matches one of the `choices`.
31
+ case nodeChoices( choices: [ Child ] )
32
+ /// The child is a collection of `kind`.
33
+ case collection( kind: String , collectionElementName: String )
34
+ /// The child is a token that matches one of the given `choices`.
35
+ case token( choices: [ TokenChoice ] )
36
+
37
+ public var isNodeChoices : Bool {
38
+ if case . nodeChoices = self {
39
+ return true
40
+ } else {
41
+ return false
42
+ }
43
+ }
44
+ }
45
+
13
46
/// A child of a node, that may be declared optional or a token with a
14
47
/// restricted subset of acceptable kinds or texts.
15
48
public class Child {
16
49
public let name : String
17
- public let syntaxKind : String
50
+ public let kind : ChildKind
18
51
public let description : String ?
19
- public let collectionElementName : String ?
20
52
public let forceClassification : Bool
21
53
public let isIndented : Bool
22
54
public let requiresLeadingNewline : Bool
23
55
public let isOptional : Bool
24
- public let textChoices : [ String ]
25
- public let nodeChoices : [ Child ]
26
56
public let classification : SyntaxClassification ?
27
- /// A restricted set of token kinds that will be accepted for this child.
28
- public let tokenChoices : [ TokenSpec ]
29
- public let tokenCanContainArbitraryText : Bool
30
57
31
58
public var swiftName : String {
32
59
return lowercaseFirstWord ( name: name)
33
60
}
34
61
62
+ public var syntaxKind : String {
63
+ switch kind {
64
+ case . node( kind: let kind) :
65
+ return kind
66
+ case . nodeChoices:
67
+ return " syntax "
68
+ case . collection( kind: let kind, collectionElementName: _) :
69
+ return kind
70
+ case . token( choices: let choices) :
71
+ if choices. count == 1 {
72
+ switch choices. first! {
73
+ case . keyword: return " KeywordToken "
74
+ case . token( tokenKind: let tokenKind) : return tokenKind
75
+ }
76
+ } else {
77
+ if choices. allSatisfy ( { $0. isKeyword } ) {
78
+ return " KeywordToken "
79
+ } else {
80
+ return " Token "
81
+ }
82
+ }
83
+ }
84
+ }
85
+
35
86
public var swiftSyntaxKind : String {
36
87
return lowercaseFirstWord ( name: syntaxKind)
37
88
}
@@ -59,11 +110,6 @@ public class Child {
59
110
return SYNTAX_TOKEN_MAP [ tokenKind]
60
111
}
61
112
62
- /// Returns the first choice from the `tokenChoices` if there are any, otherwise returns `nil`.
63
- public var mainToken : TokenSpec ? {
64
- return tokenChoices. first
65
- }
66
-
67
113
/// Whether this child has syntax kind `UnexpectedNodes`.
68
114
public var isUnexpectedNodes : Bool {
69
115
syntaxKind == " UnexpectedNodes "
@@ -75,47 +121,20 @@ public class Child {
75
121
/// If force_classification is also set to true, all child nodes (not only
76
122
/// identifiers) inherit the syntax classification.
77
123
init ( name: String ,
78
- kind: String ,
124
+ kind: ChildKind ,
79
125
description: String ? = nil ,
80
126
isOptional: Bool = false ,
81
- tokenChoices: [ String ] = [ ] ,
82
- textChoices: [ String ] = [ ] ,
83
- nodeChoices: [ Child ] = [ ] ,
84
- collectionElementName: String ? = nil ,
85
127
classification: String ? = nil ,
86
128
forceClassification: Bool = false ,
87
129
isIndented: Bool = false ,
88
130
requiresLeadingNewline: Bool = false ) {
89
131
self . name = name
90
- self . syntaxKind = kind
132
+ self . kind = kind
91
133
self . description = description
92
- self . collectionElementName = collectionElementName
93
134
self . classification = classificationByName ( classification)
94
135
self . forceClassification = forceClassification
95
136
self . isIndented = isIndented
96
137
self . requiresLeadingNewline = requiresLeadingNewline
97
138
self . isOptional = isOptional
98
-
99
- self . tokenChoices = tokenChoices. compactMap { SYNTAX_TOKEN_MAP [ " \( $0) Token " ] }
100
-
101
- // If mappedTokenChoices contains `nil`, the token can contain arbitrary text
102
- self . tokenCanContainArbitraryText = self . tokenChoices. contains { $0. text == nil }
103
-
104
- // A list of valid text for tokens, if specified.
105
- // This will force validation logic to check the text passed into the
106
- // token against the choices.
107
- self . textChoices = textChoices
108
-
109
- // A list of valid choices for a child
110
- self . nodeChoices = nodeChoices
111
-
112
- // Check the choices are either empty or multiple
113
- assert ( nodeChoices. count != 1 )
114
-
115
- // Check node choices are well-formed
116
- for choice in self . nodeChoices {
117
- assert ( !choice. isOptional, " node choice \( choice. name) cannot be optional " )
118
- assert ( choice. nodeChoices. isEmpty, " node choice \( choice. name) cannot have further choices " )
119
- }
120
139
}
121
140
}
0 commit comments