16
16
#include " swift/Basic/Debug.h"
17
17
#include " swift/Basic/SourceLoc.h"
18
18
#include " swift/Parse/ParsedTrivia.h"
19
+ #include " swift/Parse/SyntaxParseActions.h"
19
20
#include " swift/Parse/Token.h"
20
21
#include " swift/Syntax/SyntaxKind.h"
21
22
#include " llvm/Support/Debug.h"
@@ -41,76 +42,40 @@ class SyntaxParsingContext;
41
42
// / in the current parsing context.
42
43
class ParsedRawSyntaxNode {
43
44
friend class ParsedRawSyntaxRecorder ;
44
- enum class DataKind : uint8_t {
45
- Null,
46
- Recorded,
47
- DeferredLayout,
48
- DeferredToken,
49
- };
50
-
51
- struct RecordedSyntaxNode {
52
- OpaqueSyntaxNode OpaqueNode;
53
- };
54
- struct DeferredLayoutNode {
55
- MutableArrayRef<ParsedRawSyntaxNode> Children;
56
- };
57
- struct DeferredTokenNode {
58
- SourceLoc TokLoc;
59
- unsigned TokLength;
60
- StringRef LeadingTrivia;
61
- StringRef TrailingTrivia;
62
- };
63
-
64
- union {
65
- RecordedSyntaxNode RecordedData;
66
- DeferredLayoutNode DeferredLayout;
67
- DeferredTokenNode DeferredToken;
68
- };
45
+ using DataKind = RecordedOrDeferredNode::Kind;
46
+
47
+ // / The opaque data of this node. Needs to be interpreted by the \c
48
+ // / SyntaxParseActions, which created it.
49
+ RecordedOrDeferredNode Data;
50
+
69
51
// / The range of this node, including trivia.
70
52
CharSourceRange Range;
71
53
uint16_t SynKind;
72
54
uint16_t TokKind;
73
- DataKind DK;
74
55
// / Primary used for capturing a deferred missing token.
75
56
bool IsMissing = false ;
76
57
77
- ParsedRawSyntaxNode (syntax::SyntaxKind k, CharSourceRange r,
78
- MutableArrayRef<ParsedRawSyntaxNode> deferredNodes)
79
- : DeferredLayout({deferredNodes}), Range(r), SynKind(uint16_t (k)),
80
- TokKind (uint16_t (tok::unknown)), DK(DataKind::DeferredLayout) {
81
- assert (getKind () == k && " Syntax kind with too large value!" );
82
- }
83
-
84
- ParsedRawSyntaxNode (tok tokKind, SourceLoc tokLoc, unsigned tokLength,
85
- StringRef leadingTrivia, StringRef trailingTrivia)
86
- : DeferredToken{tokLoc, tokLength, leadingTrivia, trailingTrivia},
87
- Range{tokLoc.getAdvancedLoc (-leadingTrivia.size ()),
88
- (unsigned )leadingTrivia.size () + tokLength +
89
- (unsigned )trailingTrivia.size ()},
90
- SynKind (uint16_t (syntax::SyntaxKind::Token)),
91
- TokKind (uint16_t (tokKind)), DK(DataKind::DeferredToken) {
92
- assert (getTokenKind () == tokKind && " Token kind is too large value!" );
93
- }
94
58
ParsedRawSyntaxNode (const ParsedRawSyntaxNode &other) = delete ;
95
59
ParsedRawSyntaxNode &operator =(const ParsedRawSyntaxNode &other) = delete ;
96
60
97
61
public:
98
62
ParsedRawSyntaxNode ()
99
- : RecordedData{}, Range(), SynKind(uint16_t (syntax::SyntaxKind::Unknown)),
100
- TokKind (uint16_t (tok::unknown)), DK(DataKind::Null) {}
101
-
102
- ParsedRawSyntaxNode (syntax::SyntaxKind k, tok tokKind, CharSourceRange r,
103
- OpaqueSyntaxNode n, bool IsMissing = false )
104
- : RecordedData{n}, Range(r), SynKind(uint16_t (k)),
105
- TokKind (uint16_t (tokKind)), DK(DataKind::Recorded),
106
- IsMissing (IsMissing) {
107
- assert (getKind () == k && " Syntax kind with too large value!" );
108
- assert (getTokenKind () == tokKind && " Token kind with too large value!" );
63
+ : Data(nullptr , DataKind::Null), Range(),
64
+ SynKind (uint16_t (syntax::SyntaxKind::Unknown)),
65
+ TokKind(uint16_t (tok::unknown)) {}
66
+
67
+ ParsedRawSyntaxNode (OpaqueSyntaxNode Opaque, CharSourceRange Range,
68
+ syntax::SyntaxKind SynKind, tok TokKind, DataKind DK,
69
+ bool IsMissing)
70
+ : Data(Opaque, DK), Range(Range), SynKind(uint16_t (SynKind)),
71
+ TokKind(uint16_t (TokKind)), IsMissing(IsMissing) {
72
+ assert (getKind () == SynKind && " Syntax kind with too large value!" );
73
+ assert (getTokenKind () == TokKind && " Token kind with too large value!" );
109
74
}
110
75
111
76
#ifndef NDEBUG
112
77
bool ensureDataIsNotRecorded () {
113
- if (DK != DataKind::Recorded)
78
+ if (getDataKind () != DataKind::Recorded)
114
79
return true ;
115
80
llvm::dbgs () << " Leaking node: " ;
116
81
dump (llvm::dbgs ());
@@ -122,23 +87,10 @@ class ParsedRawSyntaxNode {
122
87
ParsedRawSyntaxNode &operator =(ParsedRawSyntaxNode &&other) {
123
88
assert (ensureDataIsNotRecorded () &&
124
89
" recorded data is being destroyed by assignment" );
125
- switch (other.DK ) {
126
- case DataKind::Null:
127
- break ;
128
- case DataKind::Recorded:
129
- RecordedData = std::move (other.RecordedData );
130
- break ;
131
- case DataKind::DeferredLayout:
132
- DeferredLayout = std::move (other.DeferredLayout );
133
- break ;
134
- case DataKind::DeferredToken:
135
- DeferredToken = std::move (other.DeferredToken );
136
- break ;
137
- }
90
+ Data = std::move (other.Data );
138
91
Range = std::move (other.Range );
139
92
SynKind = std::move (other.SynKind );
140
93
TokKind = std::move (other.TokKind );
141
- DK = std::move (other.DK );
142
94
IsMissing = std::move (other.IsMissing );
143
95
other.reset ();
144
96
return *this ;
@@ -150,6 +102,33 @@ class ParsedRawSyntaxNode {
150
102
assert (ensureDataIsNotRecorded () && " recorded data is being destructed" );
151
103
}
152
104
105
+ // / Returns the type of this node (recorded, deferred layout, deferred token,
106
+ // / null).
107
+ DataKind getDataKind () const { return Data.getKind (); }
108
+
109
+ // / Returns the opaque data of this node, assuming that it is deferred. This
110
+ // / must be interpreted by the \c SyntaxParseAction, which likely also needs
111
+ // / the node type (layout or token) to interpret the data.
112
+ // / The data opaque data returned by this function *must not* be used to
113
+ // / record the node, only to insepect it.
114
+ OpaqueSyntaxNode getUnsafeDeferredOpaqueData () const {
115
+ assert (isDeferredLayout () || isDeferredToken ());
116
+ return Data.getOpaque ();
117
+ }
118
+
119
+ RecordedOrDeferredNode takeRecordedOrDeferredNode () {
120
+ RecordedOrDeferredNode Data = this ->Data ;
121
+ reset ();
122
+ return Data;
123
+ }
124
+
125
+ // / Return the opaque data of this node and reset it.
126
+ OpaqueSyntaxNode takeData () {
127
+ OpaqueSyntaxNode Data = this ->Data .getOpaque ();
128
+ reset ();
129
+ return Data;
130
+ }
131
+
153
132
syntax::SyntaxKind getKind () const { return syntax::SyntaxKind (SynKind); }
154
133
tok getTokenKind () const { return tok (TokKind); }
155
134
@@ -160,118 +139,73 @@ class ParsedRawSyntaxNode {
160
139
return getTokenKind () == tokKind;
161
140
}
162
141
163
- bool isNull () const {
164
- return DK == DataKind::Null;
165
- }
142
+ bool isNull () const { return getDataKind () == DataKind::Null; }
166
143
167
- bool isRecorded () const { return DK == DataKind::Recorded; }
168
- bool isDeferredLayout () const { return DK == DataKind::DeferredLayout; }
169
- bool isDeferredToken () const { return DK == DataKind::DeferredToken; }
144
+ bool isRecorded () const { return getDataKind () == DataKind::Recorded; }
145
+ bool isDeferredLayout () const {
146
+ return getDataKind () == DataKind::DeferredLayout;
147
+ }
148
+ bool isDeferredToken () const {
149
+ return getDataKind () == DataKind::DeferredToken;
150
+ }
170
151
171
152
// / Primary used for a deferred missing token.
172
153
bool isMissing () const { return IsMissing; }
173
154
174
155
void reset () {
175
- RecordedData = {} ;
156
+ Data = RecordedOrDeferredNode ( nullptr , DataKind::Null) ;
176
157
SynKind = uint16_t (syntax::SyntaxKind::Unknown);
177
158
TokKind = uint16_t (tok::unknown);
178
- DK = DataKind::Null;
179
159
IsMissing = false ;
180
160
}
181
161
182
162
ParsedRawSyntaxNode unsafeCopy () const {
183
163
ParsedRawSyntaxNode copy;
184
- switch (DK) {
185
- case DataKind::DeferredLayout:
186
- copy.DeferredLayout = DeferredLayout;
187
- break ;
188
- case DataKind::DeferredToken:
189
- copy.DeferredToken = DeferredToken;
190
- break ;
191
- case DataKind::Recorded:
192
- copy.RecordedData = RecordedData;
193
- break ;
194
- case DataKind::Null:
195
- break ;
196
- }
164
+ copy.Data = Data;
197
165
copy.Range = Range;
198
166
copy.SynKind = SynKind;
199
167
copy.TokKind = TokKind;
200
- copy.DK = DK;
201
168
copy.IsMissing = IsMissing;
202
169
return copy;
203
170
}
204
171
205
172
// / Returns the range of this node including leading and trailing trivia.
206
173
CharSourceRange getRange () const { return Range; }
207
174
208
- // Recorded Data ===========================================================//
209
-
210
- const OpaqueSyntaxNode &getOpaqueNode () const {
211
- assert (isRecorded ());
212
- return RecordedData.OpaqueNode ;
213
- }
214
- OpaqueSyntaxNode takeOpaqueNode () {
215
- assert (isRecorded ());
216
- auto opaque = RecordedData.OpaqueNode ;
217
- reset ();
218
- return opaque;
219
- }
220
-
221
175
// Deferred Layout Data ====================================================//
222
176
223
- ArrayRef<ParsedRawSyntaxNode> getDeferredChildren () const {
224
- assert (DK == DataKind::DeferredLayout);
225
- return DeferredLayout.Children ;
226
- }
177
+ // / If this node is a deferred layout node, return the child at index \p
178
+ // / ChildIndex.
179
+ // / Note that this may be an expensive operation since the \c
180
+ // / SyntaxParseAction, which created the node (implicitly passed via the
181
+ // / \p SyntaxContext) needs to be consulted to retrieve the child.
182
+ ParsedRawSyntaxNode
183
+ getDeferredChild (size_t ChildIndex,
184
+ const SyntaxParsingContext *SyntaxContext) const ;
227
185
228
- MutableArrayRef<ParsedRawSyntaxNode> getDeferredChildren () {
229
- assert (DK == DataKind::DeferredLayout);
230
- return DeferredLayout.Children ;
231
- }
186
+ size_t
187
+ getDeferredNumChildren (const SyntaxParsingContext *SyntaxContext) const ;
232
188
233
189
ParsedRawSyntaxNode copyDeferred () const {
190
+ assert (isDeferredLayout () || isDeferredToken () && " node not deferred" );
234
191
ParsedRawSyntaxNode copy;
235
- switch (DK) {
236
- case DataKind::DeferredLayout:
237
- copy.DeferredLayout = DeferredLayout;
238
- break ;
239
- case DataKind::DeferredToken:
240
- copy.DeferredToken = DeferredToken;
241
- break ;
242
- default :
243
- llvm_unreachable (" node not deferred" );
244
- }
192
+ copy.Data = Data;
245
193
copy.Range = Range;
246
194
copy.SynKind = SynKind;
247
195
copy.TokKind = TokKind;
248
- copy.DK = DK;
249
196
copy.IsMissing = IsMissing;
250
197
return copy;
251
198
}
252
199
253
- // Deferred Token Data =====================================================//
254
-
255
- CharSourceRange getDeferredTokenRange () const {
256
- assert (DK == DataKind::DeferredToken);
257
- return CharSourceRange{DeferredToken.TokLoc , DeferredToken.TokLength };
258
- }
259
- StringRef getDeferredLeadingTrivia () const {
260
- assert (DK == DataKind::DeferredToken);
261
- return DeferredToken.LeadingTrivia ;
262
- }
263
- StringRef getDeferredTrailingTrivia () const {
264
- assert (DK == DataKind::DeferredToken);
265
- return DeferredToken.TrailingTrivia ;
266
- }
267
-
268
200
// ==========================================================================//
269
201
270
202
// / Dump this piece of syntax recursively for debugging or testing.
271
203
SWIFT_DEBUG_DUMP;
272
204
273
- // / Dump this piece of syntax recursively.
274
- void dump (raw_ostream &OS, unsigned Indent = 0 ) const ;
205
+ // / Dump this piece of syntax recursively. If \p Context is passed, this
206
+ // / method is also able to traverse its children and dump them.
207
+ void dump (raw_ostream &OS, const SyntaxParsingContext *Context = nullptr ,
208
+ unsigned Indent = 0 ) const ;
275
209
276
210
static ParsedRawSyntaxNode null () {
277
211
return ParsedRawSyntaxNode{};
0 commit comments