1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
mod parsed_children;
mod raw_syntax;
use crate::SyntaxKind;
use std::fmt;
use std::iter::{FusedIterator, Peekable};
pub use self::parsed_children::{
ParsedChildren, ParsedChildrenIntoIterator, ParsedChildrenIterator,
};
pub use self::raw_syntax::{
RawSyntaxElement, RawSyntaxElementRef, RawSyntaxNode, RawSyntaxNodeRef, RawSyntaxToken,
RawSyntaxTokenRef,
};
/// Factory for creating syntax nodes of a particular kind.
pub trait SyntaxFactory: fmt::Debug {
/// The syntax kind used by the nodes constructed by this syntax factory.
type Kind: SyntaxKind;
/// Creates a new syntax node of the passed `kind` with the given children.
///
/// The `children` contains the parsed direct children of the node. There may be fewer children
/// in case there's a syntax error and a required child or an optional child isn't present in the source code.
/// The `make_syntax` implementation must then fill in empty slots to match the slots as they're defined in the grammar.
///
/// The implementation is free to change the `kind` of the node but that has the consequence that
/// such a node will not be cached. The reason for not caching these nodes is that the cache lookup is performed
/// before calling `make_syntax`, thus querying the cache with the old kind.
///
/// It's important that the factory function is idempotent, meaning, calling the function
/// multiple times with the same `kind` and `children` returns syntax nodes with the same structure.
/// This is important because the returned nodes may be cached by `kind` and what `children` are present.
fn make_syntax(
kind: Self::Kind,
children: ParsedChildren<Self::Kind>,
) -> RawSyntaxNode<Self::Kind>;
/// Crates a *node list* syntax node. Validates if all elements are valid and changes the node's kind to
/// [SyntaxKind::to_bogus] if that's not the case.
fn make_node_list_syntax<F>(
kind: Self::Kind,
children: ParsedChildren<Self::Kind>,
can_cast: F,
) -> RawSyntaxNode<Self::Kind>
where
F: Fn(Self::Kind) -> bool,
{
let valid = (&children)
.into_iter()
.all(|element| can_cast(element.kind()));
let kind = if valid { kind } else { kind.to_bogus() };
RawSyntaxNode::new(kind, children.into_iter().map(Some))
}
/// Creates a *separated list* syntax node. Validates if the elements are valid, are correctly
/// separated by the specified separator token.
///
/// It changes the kind of the node to [SyntaxKind::to_bogus] if an element isn't a valid list-node
/// nor separator.
///
/// It inserts empty slots for missing elements or missing markers
fn make_separated_list_syntax<F>(
kind: Self::Kind,
children: ParsedChildren<Self::Kind>,
can_cast: F,
separator: Self::Kind,
allow_trailing: bool,
) -> RawSyntaxNode<Self::Kind>
where
F: Fn(Self::Kind) -> bool,
{
let mut next_node = true;
let mut missing_count = 0;
let mut valid = true;
for child in &children {
let kind = child.kind();
if next_node {
if can_cast(kind) {
next_node = false;
} else if kind == separator {
// a missing element
missing_count += 1;
} else {
// an invalid element
valid = false;
break;
}
} else if kind == separator {
next_node = true;
} else if can_cast(kind) {
// a missing separator
missing_count += 1;
} else {
// something unexpected
valid = false;
}
}
if next_node && !allow_trailing && !children.is_empty() {
// a trailing comma in a list that doesn't support trailing commas
missing_count += 1;
}
if !valid {
RawSyntaxNode::new(kind.to_bogus(), children.into_iter().map(Some))
} else if missing_count > 0 {
RawSyntaxNode::new(
kind,
SeparatedListWithMissingNodesOrSeparatorSlotsIterator {
inner: children.into_iter().peekable(),
missing_count,
next_node: true,
separator,
},
)
} else {
RawSyntaxNode::new(kind, children.into_iter().map(Some))
}
}
}
/// Iterator that "fixes up" a separated list by inserting empty slots for any missing
/// separator or element.
struct SeparatedListWithMissingNodesOrSeparatorSlotsIterator<'a, K: SyntaxKind> {
inner: Peekable<ParsedChildrenIntoIterator<'a, K>>,
missing_count: usize,
next_node: bool,
separator: K,
}
impl<K: SyntaxKind> Iterator for SeparatedListWithMissingNodesOrSeparatorSlotsIterator<'_, K> {
type Item = Option<RawSyntaxElement<K>>;
#[cold]
fn next(&mut self) -> Option<Self::Item> {
let peeked = self.inner.peek();
if let Some(peeked) = peeked {
let is_separator = self.separator == peeked.kind();
if self.next_node {
self.next_node = false;
if !is_separator {
Some(self.inner.next())
} else {
self.missing_count -= 1;
Some(None) // Missing separator
}
} else if is_separator {
self.next_node = true;
Some(self.inner.next())
} else {
// Missing node
self.missing_count -= 1;
self.next_node = true;
Some(None)
}
} else if self.missing_count > 0 {
// at a trailing comma in a list that doesn't allow trailing commas.
self.missing_count -= 1;
Some(None)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
}
impl<K: SyntaxKind> FusedIterator for SeparatedListWithMissingNodesOrSeparatorSlotsIterator<'_, K> {}
impl<K: SyntaxKind> ExactSizeIterator
for SeparatedListWithMissingNodesOrSeparatorSlotsIterator<'_, K>
{
fn len(&self) -> usize {
self.inner.len() + self.missing_count
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum SlotContent {
Present,
Absent,
}
/// Description of the slots of a node in combination with [ParsedChildren].
/// It stores for each slot if the node is present in [ParsedChildren] or not, allowing
/// to generate a node with the right number of empty slots.
#[derive(Debug)]
pub struct RawNodeSlots<const COUNT: usize> {
slots: [SlotContent; COUNT],
current_slot: usize,
}
impl<const COUNT: usize> Default for RawNodeSlots<COUNT> {
fn default() -> Self {
Self {
slots: [SlotContent::Absent; COUNT],
current_slot: 0,
}
}
}
impl<const COUNT: usize> RawNodeSlots<COUNT> {
/// Progresses to the next slot
pub fn next_slot(&mut self) {
debug_assert!(self.current_slot < COUNT);
self.current_slot += 1;
}
/// Marks that the node for the current slot is *present* in the source code.
pub fn mark_present(&mut self) {
debug_assert!(self.current_slot < COUNT);
self.slots[self.current_slot] = SlotContent::Present;
}
/// Creates a node with the kind `kind`, filling in the nodes from the `children`.
pub fn into_node<K: SyntaxKind>(
self,
kind: K,
children: ParsedChildren<K>,
) -> RawSyntaxNode<K> {
debug_assert!(self.current_slot == COUNT, "Missing slots");
RawSyntaxNode::new(
kind,
RawNodeSlotIterator {
children: children.into_iter(),
slots: self.slots.as_slice().iter(),
},
)
}
}
struct RawNodeSlotIterator<'a, K: SyntaxKind> {
children: ParsedChildrenIntoIterator<'a, K>,
slots: std::slice::Iter<'a, SlotContent>,
}
impl<K: SyntaxKind> Iterator for RawNodeSlotIterator<'_, K> {
type Item = Option<RawSyntaxElement<K>>;
fn next(&mut self) -> Option<Self::Item> {
let slot = self.slots.next()?;
match slot {
SlotContent::Present => {
Some(Some(self.children.next().expect(
"Expected a present node according to the slot description",
)))
}
SlotContent::Absent => Some(None),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.slots.len(), Some(self.slots.len()))
}
}
impl<K: SyntaxKind> FusedIterator for RawNodeSlotIterator<'_, K> {}
impl<K: SyntaxKind> ExactSizeIterator for RawNodeSlotIterator<'_, K> {}