aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-09-16 10:54:24 +0100
committerAleksey Kladov <[email protected]>2018-09-16 11:07:39 +0100
commitb5021411a84822cb3f1e3aeffad9550dd15bdeb6 (patch)
tree9dca564f8e51b298dced01c4ce669c756dce3142 /crates/ra_syntax/src
parentba0bfeee12e19da40b5eabc8d0408639af10e96f (diff)
rename all things
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r--crates/ra_syntax/src/algo/mod.rs129
-rw-r--r--crates/ra_syntax/src/algo/visit.rs110
-rw-r--r--crates/ra_syntax/src/algo/walk.rs38
-rw-r--r--crates/ra_syntax/src/ast/generated.rs2142
-rw-r--r--crates/ra_syntax/src/ast/generated.rs.tera83
-rw-r--r--crates/ra_syntax/src/ast/mod.rs206
-rw-r--r--crates/ra_syntax/src/grammar.ron538
-rw-r--r--crates/ra_syntax/src/grammar/attributes.rs31
-rw-r--r--crates/ra_syntax/src/grammar/expressions/atom.rs400
-rw-r--r--crates/ra_syntax/src/grammar/expressions/mod.rs450
-rw-r--r--crates/ra_syntax/src/grammar/items/consts.rs21
-rw-r--r--crates/ra_syntax/src/grammar/items/mod.rs393
-rw-r--r--crates/ra_syntax/src/grammar/items/nominal.rs154
-rw-r--r--crates/ra_syntax/src/grammar/items/traits.rs117
-rw-r--r--crates/ra_syntax/src/grammar/items/use_item.rs68
-rw-r--r--crates/ra_syntax/src/grammar/mod.rs188
-rw-r--r--crates/ra_syntax/src/grammar/params.rs142
-rw-r--r--crates/ra_syntax/src/grammar/paths.rs101
-rw-r--r--crates/ra_syntax/src/grammar/patterns.rs224
-rw-r--r--crates/ra_syntax/src/grammar/type_args.rs48
-rw-r--r--crates/ra_syntax/src/grammar/type_params.rs136
-rw-r--r--crates/ra_syntax/src/grammar/types.rs247
-rw-r--r--crates/ra_syntax/src/lexer/classes.rs26
-rw-r--r--crates/ra_syntax/src/lexer/comments.rs57
-rw-r--r--crates/ra_syntax/src/lexer/mod.rs209
-rw-r--r--crates/ra_syntax/src/lexer/numbers.rs67
-rw-r--r--crates/ra_syntax/src/lexer/ptr.rs166
-rw-r--r--crates/ra_syntax/src/lexer/strings.rs123
-rw-r--r--crates/ra_syntax/src/lib.rs105
-rw-r--r--crates/ra_syntax/src/parser_api.rs178
-rw-r--r--crates/ra_syntax/src/parser_impl/event.rs154
-rw-r--r--crates/ra_syntax/src/parser_impl/input.rs86
-rw-r--r--crates/ra_syntax/src/parser_impl/mod.rs194
-rw-r--r--crates/ra_syntax/src/reparsing.rs343
-rw-r--r--crates/ra_syntax/src/syntax_kinds/generated.rs562
-rw-r--r--crates/ra_syntax/src/syntax_kinds/generated.rs.tera73
-rw-r--r--crates/ra_syntax/src/syntax_kinds/mod.rs26
-rw-r--r--crates/ra_syntax/src/text_utils.rs26
-rw-r--r--crates/ra_syntax/src/token_set.rs37
-rw-r--r--crates/ra_syntax/src/utils.rs85
-rw-r--r--crates/ra_syntax/src/yellow/builder.rs64
-rw-r--r--crates/ra_syntax/src/yellow/green.rs90
-rw-r--r--crates/ra_syntax/src/yellow/mod.rs100
-rw-r--r--crates/ra_syntax/src/yellow/red.rs113
-rw-r--r--crates/ra_syntax/src/yellow/syntax.rs215
-rw-r--r--crates/ra_syntax/src/yellow/syntax_text.rs122
46 files changed, 9187 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/algo/mod.rs b/crates/ra_syntax/src/algo/mod.rs
new file mode 100644
index 000000000..7287f5bb2
--- /dev/null
+++ b/crates/ra_syntax/src/algo/mod.rs
@@ -0,0 +1,129 @@
1pub mod walk;
2pub mod visit;
3
4use {
5 SyntaxNodeRef, TextUnit, TextRange,
6 text_utils::{contains_offset_nonstrict, is_subrange},
7};
8
9pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffset {
10 let range = node.range();
11 assert!(
12 contains_offset_nonstrict(range, offset),
13 "Bad offset: range {:?} offset {:?}", range, offset
14 );
15 if range.is_empty() {
16 return LeafAtOffset::None;
17 }
18
19 if node.is_leaf() {
20 return LeafAtOffset::Single(node);
21 }
22
23 let mut children = node.children()
24 .filter(|child| {
25 let child_range = child.range();
26 !child_range.is_empty() && contains_offset_nonstrict(child_range, offset)
27 });
28
29 let left = children.next().unwrap();
30 let right = children.next();
31 assert!(children.next().is_none());
32 return if let Some(right) = right {
33 match (find_leaf_at_offset(left, offset), find_leaf_at_offset(right, offset)) {
34 (LeafAtOffset::Single(left), LeafAtOffset::Single(right)) =>
35 LeafAtOffset::Between(left, right),
36 _ => unreachable!()
37 }
38 } else {
39 find_leaf_at_offset(left, offset)
40 };
41}
42
43#[derive(Clone, Copy, Debug)]
44pub enum LeafAtOffset<'a> {
45 None,
46 Single(SyntaxNodeRef<'a>),
47 Between(SyntaxNodeRef<'a>, SyntaxNodeRef<'a>)
48}
49
50impl<'a> LeafAtOffset<'a> {
51 pub fn right_biased(self) -> Option<SyntaxNodeRef<'a>> {
52 match self {
53 LeafAtOffset::None => None,
54 LeafAtOffset::Single(node) => Some(node),
55 LeafAtOffset::Between(_, right) => Some(right)
56 }
57 }
58
59 pub fn left_biased(self) -> Option<SyntaxNodeRef<'a>> {
60 match self {
61 LeafAtOffset::None => None,
62 LeafAtOffset::Single(node) => Some(node),
63 LeafAtOffset::Between(left, _) => Some(left)
64 }
65 }
66}
67
68impl<'f> Iterator for LeafAtOffset<'f> {
69 type Item = SyntaxNodeRef<'f>;
70
71 fn next(&mut self) -> Option<SyntaxNodeRef<'f>> {
72 match *self {
73 LeafAtOffset::None => None,
74 LeafAtOffset::Single(node) => { *self = LeafAtOffset::None; Some(node) }
75 LeafAtOffset::Between(left, right) => { *self = LeafAtOffset::Single(right); Some(left) }
76 }
77 }
78}
79
80pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRef {
81 assert!(is_subrange(root.range(), range));
82 let (left, right) = match (
83 find_leaf_at_offset(root, range.start()).right_biased(),
84 find_leaf_at_offset(root, range.end()).left_biased()
85 ) {
86 (Some(l), Some(r)) => (l, r),
87 _ => return root
88 };
89
90 common_ancestor(left, right)
91}
92
93pub fn ancestors<'a>(node: SyntaxNodeRef<'a>) -> impl Iterator<Item=SyntaxNodeRef<'a>> {
94 generate(Some(node), |&node| node.parent())
95}
96
97#[derive(Debug)]
98pub enum Direction {
99 Forward,
100 Backward,
101}
102
103pub fn siblings<'a>(
104 node: SyntaxNodeRef<'a>,
105 direction: Direction
106) -> impl Iterator<Item=SyntaxNodeRef<'a>> {
107 generate(Some(node), move |&node| match direction {
108 Direction::Forward => node.next_sibling(),
109 Direction::Backward => node.prev_sibling(),
110 })
111}
112
113fn common_ancestor<'a>(n1: SyntaxNodeRef<'a>, n2: SyntaxNodeRef<'a>) -> SyntaxNodeRef<'a> {
114 for p in ancestors(n1) {
115 if ancestors(n2).any(|a| a == p) {
116 return p;
117 }
118 }
119 panic!("Can't find common ancestor of {:?} and {:?}", n1, n2)
120}
121
122pub fn generate<T>(seed: Option<T>, step: impl Fn(&T) -> Option<T>) -> impl Iterator<Item=T> {
123 ::itertools::unfold(seed, move |slot| {
124 slot.take().map(|curr| {
125 *slot = step(&curr);
126 curr
127 })
128 })
129}
diff --git a/crates/ra_syntax/src/algo/visit.rs b/crates/ra_syntax/src/algo/visit.rs
new file mode 100644
index 000000000..9f1c127c7
--- /dev/null
+++ b/crates/ra_syntax/src/algo/visit.rs
@@ -0,0 +1,110 @@
1use std::marker::PhantomData;
2use {SyntaxNodeRef, AstNode};
3
4
5pub fn visitor<'a, T>() -> impl Visitor<'a, Output=T> {
6 EmptyVisitor { ph: PhantomData }
7}
8
9pub fn visitor_ctx<'a, T, C>(ctx: C) -> impl VisitorCtx<'a, Output=T, Ctx=C> {
10 EmptyVisitorCtx { ph: PhantomData, ctx }
11}
12
13pub trait Visitor<'a>: Sized {
14 type Output;
15 fn accept(self, node: SyntaxNodeRef<'a>) -> Option<Self::Output>;
16 fn visit<N, F>(self, f: F) -> Vis<Self, N, F>
17 where N: AstNode<'a>,
18 F: FnOnce(N) -> Self::Output,
19 {
20 Vis { inner: self, f, ph: PhantomData }
21 }
22}
23
24pub trait VisitorCtx<'a>: Sized {
25 type Output;
26 type Ctx;
27 fn accept(self, node: SyntaxNodeRef<'a>) -> Result<Self::Output, Self::Ctx>;
28 fn visit<N, F>(self, f: F) -> VisCtx<Self, N, F>
29 where N: AstNode<'a>,
30 F: FnOnce(N, Self::Ctx) -> Self::Output,
31 {
32 VisCtx { inner: self, f, ph: PhantomData }
33 }
34}
35
36#[derive(Debug)]
37struct EmptyVisitor<T> {
38 ph: PhantomData<fn() -> T>
39}
40
41impl<'a, T> Visitor<'a> for EmptyVisitor<T> {
42 type Output = T;
43
44 fn accept(self, _node: SyntaxNodeRef<'a>) -> Option<T> {
45 None
46 }
47}
48
49#[derive(Debug)]
50struct EmptyVisitorCtx<T, C> {
51 ctx: C,
52 ph: PhantomData<fn() -> T>,
53}
54
55impl<'a, T, C> VisitorCtx<'a> for EmptyVisitorCtx<T, C> {
56 type Output = T;
57 type Ctx = C;
58
59 fn accept(self, _node: SyntaxNodeRef<'a>) -> Result<T, C> {
60 Err(self.ctx)
61 }
62}
63
64#[derive(Debug)]
65pub struct Vis<V, N, F> {
66 inner: V,
67 f: F,
68 ph: PhantomData<fn(N)>,
69}
70
71impl<'a, V, N, F> Visitor<'a> for Vis<V, N, F>
72 where
73 V: Visitor<'a>,
74 N: AstNode<'a>,
75 F: FnOnce(N) -> <V as Visitor<'a>>::Output,
76{
77 type Output = <V as Visitor<'a>>::Output;
78
79 fn accept(self, node: SyntaxNodeRef<'a>) -> Option<Self::Output> {
80 let Vis { inner, f, .. } = self;
81 inner.accept(node).or_else(|| N::cast(node).map(f))
82 }
83}
84
85#[derive(Debug)]
86pub struct VisCtx<V, N, F> {
87 inner: V,
88 f: F,
89 ph: PhantomData<fn(N)>,
90}
91
92impl<'a, V, N, F> VisitorCtx<'a> for VisCtx<V, N, F>
93 where
94 V: VisitorCtx<'a>,
95 N: AstNode<'a>,
96 F: FnOnce(N, <V as VisitorCtx<'a>>::Ctx) -> <V as VisitorCtx<'a>>::Output,
97{
98 type Output = <V as VisitorCtx<'a>>::Output;
99 type Ctx = <V as VisitorCtx<'a>>::Ctx;
100
101 fn accept(self, node: SyntaxNodeRef<'a>) -> Result<Self::Output, Self::Ctx> {
102 let VisCtx { inner, f, .. } = self;
103 inner.accept(node).or_else(|ctx|
104 match N::cast(node) {
105 None => Err(ctx),
106 Some(node) => Ok(f(node, ctx))
107 }
108 )
109 }
110}
diff --git a/crates/ra_syntax/src/algo/walk.rs b/crates/ra_syntax/src/algo/walk.rs
new file mode 100644
index 000000000..536ee705f
--- /dev/null
+++ b/crates/ra_syntax/src/algo/walk.rs
@@ -0,0 +1,38 @@
1use {
2 SyntaxNodeRef,
3 algo::generate,
4};
5
6pub fn preorder<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = SyntaxNodeRef<'a>> {
7 walk(root).filter_map(|event| match event {
8 WalkEvent::Enter(node) => Some(node),
9 WalkEvent::Exit(_) => None,
10 })
11}
12
13#[derive(Debug, Copy, Clone)]
14pub enum WalkEvent<'a> {
15 Enter(SyntaxNodeRef<'a>),
16 Exit(SyntaxNodeRef<'a>),
17}
18
19pub fn walk<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = WalkEvent<'a>> {
20 generate(Some(WalkEvent::Enter(root)), move |pos| {
21 let next = match *pos {
22 WalkEvent::Enter(node) => match node.first_child() {
23 Some(child) => WalkEvent::Enter(child),
24 None => WalkEvent::Exit(node),
25 },
26 WalkEvent::Exit(node) => {
27 if node == root {
28 return None;
29 }
30 match node.next_sibling() {
31 Some(sibling) => WalkEvent::Enter(sibling),
32 None => WalkEvent::Exit(node.parent().unwrap()),
33 }
34 }
35 };
36 Some(next)
37 })
38}
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
new file mode 100644
index 000000000..c945c094a
--- /dev/null
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -0,0 +1,2142 @@
1use {
2 ast,
3 SyntaxNodeRef, AstNode,
4 SyntaxKind::*,
5};
6
7// ArgList
8#[derive(Debug, Clone, Copy)]
9pub struct ArgList<'a> {
10 syntax: SyntaxNodeRef<'a>,
11}
12
13impl<'a> AstNode<'a> for ArgList<'a> {
14 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
15 match syntax.kind() {
16 ARG_LIST => Some(ArgList { syntax }),
17 _ => None,
18 }
19 }
20 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
21}
22
23impl<'a> ArgList<'a> {
24 pub fn args(self) -> impl Iterator<Item = Expr<'a>> + 'a {
25 super::children(self)
26 }
27}
28
29// ArrayExpr
30#[derive(Debug, Clone, Copy)]
31pub struct ArrayExpr<'a> {
32 syntax: SyntaxNodeRef<'a>,
33}
34
35impl<'a> AstNode<'a> for ArrayExpr<'a> {
36 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
37 match syntax.kind() {
38 ARRAY_EXPR => Some(ArrayExpr { syntax }),
39 _ => None,
40 }
41 }
42 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
43}
44
45impl<'a> ArrayExpr<'a> {}
46
47// ArrayType
48#[derive(Debug, Clone, Copy)]
49pub struct ArrayType<'a> {
50 syntax: SyntaxNodeRef<'a>,
51}
52
53impl<'a> AstNode<'a> for ArrayType<'a> {
54 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
55 match syntax.kind() {
56 ARRAY_TYPE => Some(ArrayType { syntax }),
57 _ => None,
58 }
59 }
60 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
61}
62
63impl<'a> ArrayType<'a> {}
64
65// Attr
66#[derive(Debug, Clone, Copy)]
67pub struct Attr<'a> {
68 syntax: SyntaxNodeRef<'a>,
69}
70
71impl<'a> AstNode<'a> for Attr<'a> {
72 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
73 match syntax.kind() {
74 ATTR => Some(Attr { syntax }),
75 _ => None,
76 }
77 }
78 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
79}
80
81impl<'a> Attr<'a> {pub fn value(self) -> Option<TokenTree<'a>> {
82 super::child_opt(self)
83 }
84}
85
86// BinExpr
87#[derive(Debug, Clone, Copy)]
88pub struct BinExpr<'a> {
89 syntax: SyntaxNodeRef<'a>,
90}
91
92impl<'a> AstNode<'a> for BinExpr<'a> {
93 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
94 match syntax.kind() {
95 BIN_EXPR => Some(BinExpr { syntax }),
96 _ => None,
97 }
98 }
99 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
100}
101
102impl<'a> BinExpr<'a> {}
103
104// BindPat
105#[derive(Debug, Clone, Copy)]
106pub struct BindPat<'a> {
107 syntax: SyntaxNodeRef<'a>,
108}
109
110impl<'a> AstNode<'a> for BindPat<'a> {
111 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
112 match syntax.kind() {
113 BIND_PAT => Some(BindPat { syntax }),
114 _ => None,
115 }
116 }
117 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
118}
119
120impl<'a> ast::NameOwner<'a> for BindPat<'a> {}
121impl<'a> BindPat<'a> {}
122
123// Block
124#[derive(Debug, Clone, Copy)]
125pub struct Block<'a> {
126 syntax: SyntaxNodeRef<'a>,
127}
128
129impl<'a> AstNode<'a> for Block<'a> {
130 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
131 match syntax.kind() {
132 BLOCK => Some(Block { syntax }),
133 _ => None,
134 }
135 }
136 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
137}
138
139impl<'a> Block<'a> {
140 pub fn statements(self) -> impl Iterator<Item = Stmt<'a>> + 'a {
141 super::children(self)
142 }
143pub fn expr(self) -> Option<Expr<'a>> {
144 super::child_opt(self)
145 }
146}
147
148// BlockExpr
149#[derive(Debug, Clone, Copy)]
150pub struct BlockExpr<'a> {
151 syntax: SyntaxNodeRef<'a>,
152}
153
154impl<'a> AstNode<'a> for BlockExpr<'a> {
155 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
156 match syntax.kind() {
157 BLOCK_EXPR => Some(BlockExpr { syntax }),
158 _ => None,
159 }
160 }
161 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
162}
163
164impl<'a> BlockExpr<'a> {pub fn block(self) -> Option<Block<'a>> {
165 super::child_opt(self)
166 }
167}
168
169// BreakExpr
170#[derive(Debug, Clone, Copy)]
171pub struct BreakExpr<'a> {
172 syntax: SyntaxNodeRef<'a>,
173}
174
175impl<'a> AstNode<'a> for BreakExpr<'a> {
176 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
177 match syntax.kind() {
178 BREAK_EXPR => Some(BreakExpr { syntax }),
179 _ => None,
180 }
181 }
182 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
183}
184
185impl<'a> BreakExpr<'a> {}
186
187// CallExpr
188#[derive(Debug, Clone, Copy)]
189pub struct CallExpr<'a> {
190 syntax: SyntaxNodeRef<'a>,
191}
192
193impl<'a> AstNode<'a> for CallExpr<'a> {
194 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
195 match syntax.kind() {
196 CALL_EXPR => Some(CallExpr { syntax }),
197 _ => None,
198 }
199 }
200 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
201}
202
203impl<'a> ast::ArgListOwner<'a> for CallExpr<'a> {}
204impl<'a> CallExpr<'a> {pub fn expr(self) -> Option<Expr<'a>> {
205 super::child_opt(self)
206 }
207}
208
209// CastExpr
210#[derive(Debug, Clone, Copy)]
211pub struct CastExpr<'a> {
212 syntax: SyntaxNodeRef<'a>,
213}
214
215impl<'a> AstNode<'a> for CastExpr<'a> {
216 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
217 match syntax.kind() {
218 CAST_EXPR => Some(CastExpr { syntax }),
219 _ => None,
220 }
221 }
222 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
223}
224
225impl<'a> CastExpr<'a> {}
226
227// Condition
228#[derive(Debug, Clone, Copy)]
229pub struct Condition<'a> {
230 syntax: SyntaxNodeRef<'a>,
231}
232
233impl<'a> AstNode<'a> for Condition<'a> {
234 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
235 match syntax.kind() {
236 CONDITION => Some(Condition { syntax }),
237 _ => None,
238 }
239 }
240 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
241}
242
243impl<'a> Condition<'a> {pub fn pat(self) -> Option<Pat<'a>> {
244 super::child_opt(self)
245 }
246pub fn expr(self) -> Option<Expr<'a>> {
247 super::child_opt(self)
248 }
249}
250
251// ConstDef
252#[derive(Debug, Clone, Copy)]
253pub struct ConstDef<'a> {
254 syntax: SyntaxNodeRef<'a>,
255}
256
257impl<'a> AstNode<'a> for ConstDef<'a> {
258 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
259 match syntax.kind() {
260 CONST_DEF => Some(ConstDef { syntax }),
261 _ => None,
262 }
263 }
264 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
265}
266
267impl<'a> ast::NameOwner<'a> for ConstDef<'a> {}
268impl<'a> ast::TypeParamsOwner<'a> for ConstDef<'a> {}
269impl<'a> ast::AttrsOwner<'a> for ConstDef<'a> {}
270impl<'a> ConstDef<'a> {}
271
272// ContinueExpr
273#[derive(Debug, Clone, Copy)]
274pub struct ContinueExpr<'a> {
275 syntax: SyntaxNodeRef<'a>,
276}
277
278impl<'a> AstNode<'a> for ContinueExpr<'a> {
279 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
280 match syntax.kind() {
281 CONTINUE_EXPR => Some(ContinueExpr { syntax }),
282 _ => None,
283 }
284 }
285 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
286}
287
288impl<'a> ContinueExpr<'a> {}
289
290// DynTraitType
291#[derive(Debug, Clone, Copy)]
292pub struct DynTraitType<'a> {
293 syntax: SyntaxNodeRef<'a>,
294}
295
296impl<'a> AstNode<'a> for DynTraitType<'a> {
297 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
298 match syntax.kind() {
299 DYN_TRAIT_TYPE => Some(DynTraitType { syntax }),
300 _ => None,
301 }
302 }
303 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
304}
305
306impl<'a> DynTraitType<'a> {}
307
308// EnumDef
309#[derive(Debug, Clone, Copy)]
310pub struct EnumDef<'a> {
311 syntax: SyntaxNodeRef<'a>,
312}
313
314impl<'a> AstNode<'a> for EnumDef<'a> {
315 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
316 match syntax.kind() {
317 ENUM_DEF => Some(EnumDef { syntax }),
318 _ => None,
319 }
320 }
321 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
322}
323
324impl<'a> ast::NameOwner<'a> for EnumDef<'a> {}
325impl<'a> ast::TypeParamsOwner<'a> for EnumDef<'a> {}
326impl<'a> ast::AttrsOwner<'a> for EnumDef<'a> {}
327impl<'a> EnumDef<'a> {}
328
329// Expr
330#[derive(Debug, Clone, Copy)]
331pub enum Expr<'a> {
332 TupleExpr(TupleExpr<'a>),
333 ArrayExpr(ArrayExpr<'a>),
334 ParenExpr(ParenExpr<'a>),
335 PathExpr(PathExpr<'a>),
336 LambdaExpr(LambdaExpr<'a>),
337 IfExpr(IfExpr<'a>),
338 LoopExpr(LoopExpr<'a>),
339 ForExpr(ForExpr<'a>),
340 WhileExpr(WhileExpr<'a>),
341 ContinueExpr(ContinueExpr<'a>),
342 BreakExpr(BreakExpr<'a>),
343 Label(Label<'a>),
344 BlockExpr(BlockExpr<'a>),
345 ReturnExpr(ReturnExpr<'a>),
346 MatchExpr(MatchExpr<'a>),
347 MatchArmList(MatchArmList<'a>),
348 MatchArm(MatchArm<'a>),
349 MatchGuard(MatchGuard<'a>),
350 StructLit(StructLit<'a>),
351 NamedFieldList(NamedFieldList<'a>),
352 NamedField(NamedField<'a>),
353 CallExpr(CallExpr<'a>),
354 IndexExpr(IndexExpr<'a>),
355 MethodCallExpr(MethodCallExpr<'a>),
356 FieldExpr(FieldExpr<'a>),
357 TryExpr(TryExpr<'a>),
358 CastExpr(CastExpr<'a>),
359 RefExpr(RefExpr<'a>),
360 PrefixExpr(PrefixExpr<'a>),
361 RangeExpr(RangeExpr<'a>),
362 BinExpr(BinExpr<'a>),
363 Literal(Literal<'a>),
364}
365
366impl<'a> AstNode<'a> for Expr<'a> {
367 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
368 match syntax.kind() {
369 TUPLE_EXPR => Some(Expr::TupleExpr(TupleExpr { syntax })),
370 ARRAY_EXPR => Some(Expr::ArrayExpr(ArrayExpr { syntax })),
371 PAREN_EXPR => Some(Expr::ParenExpr(ParenExpr { syntax })),
372 PATH_EXPR => Some(Expr::PathExpr(PathExpr { syntax })),
373 LAMBDA_EXPR => Some(Expr::LambdaExpr(LambdaExpr { syntax })),
374 IF_EXPR => Some(Expr::IfExpr(IfExpr { syntax })),
375 LOOP_EXPR => Some(Expr::LoopExpr(LoopExpr { syntax })),
376 FOR_EXPR => Some(Expr::ForExpr(ForExpr { syntax })),
377 WHILE_EXPR => Some(Expr::WhileExpr(WhileExpr { syntax })),
378 CONTINUE_EXPR => Some(Expr::ContinueExpr(ContinueExpr { syntax })),
379 BREAK_EXPR => Some(Expr::BreakExpr(BreakExpr { syntax })),
380 LABEL => Some(Expr::Label(Label { syntax })),
381 BLOCK_EXPR => Some(Expr::BlockExpr(BlockExpr { syntax })),
382 RETURN_EXPR => Some(Expr::ReturnExpr(ReturnExpr { syntax })),
383 MATCH_EXPR => Some(Expr::MatchExpr(MatchExpr { syntax })),
384 MATCH_ARM_LIST => Some(Expr::MatchArmList(MatchArmList { syntax })),
385 MATCH_ARM => Some(Expr::MatchArm(MatchArm { syntax })),
386 MATCH_GUARD => Some(Expr::MatchGuard(MatchGuard { syntax })),
387 STRUCT_LIT => Some(Expr::StructLit(StructLit { syntax })),
388 NAMED_FIELD_LIST => Some(Expr::NamedFieldList(NamedFieldList { syntax })),
389 NAMED_FIELD => Some(Expr::NamedField(NamedField { syntax })),
390 CALL_EXPR => Some(Expr::CallExpr(CallExpr { syntax })),
391 INDEX_EXPR => Some(Expr::IndexExpr(IndexExpr { syntax })),
392 METHOD_CALL_EXPR => Some(Expr::MethodCallExpr(MethodCallExpr { syntax })),
393 FIELD_EXPR => Some(Expr::FieldExpr(FieldExpr { syntax })),
394 TRY_EXPR => Some(Expr::TryExpr(TryExpr { syntax })),
395 CAST_EXPR => Some(Expr::CastExpr(CastExpr { syntax })),
396 REF_EXPR => Some(Expr::RefExpr(RefExpr { syntax })),
397 PREFIX_EXPR => Some(Expr::PrefixExpr(PrefixExpr { syntax })),
398 RANGE_EXPR => Some(Expr::RangeExpr(RangeExpr { syntax })),
399 BIN_EXPR => Some(Expr::BinExpr(BinExpr { syntax })),
400 LITERAL => Some(Expr::Literal(Literal { syntax })),
401 _ => None,
402 }
403 }
404 fn syntax(self) -> SyntaxNodeRef<'a> {
405 match self {
406 Expr::TupleExpr(inner) => inner.syntax(),
407 Expr::ArrayExpr(inner) => inner.syntax(),
408 Expr::ParenExpr(inner) => inner.syntax(),
409 Expr::PathExpr(inner) => inner.syntax(),
410 Expr::LambdaExpr(inner) => inner.syntax(),
411 Expr::IfExpr(inner) => inner.syntax(),
412 Expr::LoopExpr(inner) => inner.syntax(),
413 Expr::ForExpr(inner) => inner.syntax(),
414 Expr::WhileExpr(inner) => inner.syntax(),
415 Expr::ContinueExpr(inner) => inner.syntax(),
416 Expr::BreakExpr(inner) => inner.syntax(),
417 Expr::Label(inner) => inner.syntax(),
418 Expr::BlockExpr(inner) => inner.syntax(),
419 Expr::ReturnExpr(inner) => inner.syntax(),
420 Expr::MatchExpr(inner) => inner.syntax(),
421 Expr::MatchArmList(inner) => inner.syntax(),
422 Expr::MatchArm(inner) => inner.syntax(),
423 Expr::MatchGuard(inner) => inner.syntax(),
424 Expr::StructLit(inner) => inner.syntax(),
425 Expr::NamedFieldList(inner) => inner.syntax(),
426 Expr::NamedField(inner) => inner.syntax(),
427 Expr::CallExpr(inner) => inner.syntax(),
428 Expr::IndexExpr(inner) => inner.syntax(),
429 Expr::MethodCallExpr(inner) => inner.syntax(),
430 Expr::FieldExpr(inner) => inner.syntax(),
431 Expr::TryExpr(inner) => inner.syntax(),
432 Expr::CastExpr(inner) => inner.syntax(),
433 Expr::RefExpr(inner) => inner.syntax(),
434 Expr::PrefixExpr(inner) => inner.syntax(),
435 Expr::RangeExpr(inner) => inner.syntax(),
436 Expr::BinExpr(inner) => inner.syntax(),
437 Expr::Literal(inner) => inner.syntax(),
438 }
439 }
440}
441
442impl<'a> Expr<'a> {}
443
444// ExprStmt
445#[derive(Debug, Clone, Copy)]
446pub struct ExprStmt<'a> {
447 syntax: SyntaxNodeRef<'a>,
448}
449
450impl<'a> AstNode<'a> for ExprStmt<'a> {
451 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
452 match syntax.kind() {
453 EXPR_STMT => Some(ExprStmt { syntax }),
454 _ => None,
455 }
456 }
457 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
458}
459
460impl<'a> ExprStmt<'a> {pub fn expr(self) -> Option<Expr<'a>> {
461 super::child_opt(self)
462 }
463}
464
465// ExternCrateItem
466#[derive(Debug, Clone, Copy)]
467pub struct ExternCrateItem<'a> {
468 syntax: SyntaxNodeRef<'a>,
469}
470
471impl<'a> AstNode<'a> for ExternCrateItem<'a> {
472 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
473 match syntax.kind() {
474 EXTERN_CRATE_ITEM => Some(ExternCrateItem { syntax }),
475 _ => None,
476 }
477 }
478 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
479}
480
481impl<'a> ExternCrateItem<'a> {}
482
483// FieldExpr
484#[derive(Debug, Clone, Copy)]
485pub struct FieldExpr<'a> {
486 syntax: SyntaxNodeRef<'a>,
487}
488
489impl<'a> AstNode<'a> for FieldExpr<'a> {
490 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
491 match syntax.kind() {
492 FIELD_EXPR => Some(FieldExpr { syntax }),
493 _ => None,
494 }
495 }
496 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
497}
498
499impl<'a> FieldExpr<'a> {}
500
501// FieldPatList
502#[derive(Debug, Clone, Copy)]
503pub struct FieldPatList<'a> {
504 syntax: SyntaxNodeRef<'a>,
505}
506
507impl<'a> AstNode<'a> for FieldPatList<'a> {
508 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
509 match syntax.kind() {
510 FIELD_PAT_LIST => Some(FieldPatList { syntax }),
511 _ => None,
512 }
513 }
514 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
515}
516
517impl<'a> FieldPatList<'a> {}
518
519// FnDef
520#[derive(Debug, Clone, Copy)]
521pub struct FnDef<'a> {
522 syntax: SyntaxNodeRef<'a>,
523}
524
525impl<'a> AstNode<'a> for FnDef<'a> {
526 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
527 match syntax.kind() {
528 FN_DEF => Some(FnDef { syntax }),
529 _ => None,
530 }
531 }
532 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
533}
534
535impl<'a> ast::NameOwner<'a> for FnDef<'a> {}
536impl<'a> ast::TypeParamsOwner<'a> for FnDef<'a> {}
537impl<'a> ast::AttrsOwner<'a> for FnDef<'a> {}
538impl<'a> FnDef<'a> {pub fn param_list(self) -> Option<ParamList<'a>> {
539 super::child_opt(self)
540 }
541pub fn body(self) -> Option<Block<'a>> {
542 super::child_opt(self)
543 }
544pub fn ret_type(self) -> Option<RetType<'a>> {
545 super::child_opt(self)
546 }
547}
548
549// FnPointerType
550#[derive(Debug, Clone, Copy)]
551pub struct FnPointerType<'a> {
552 syntax: SyntaxNodeRef<'a>,
553}
554
555impl<'a> AstNode<'a> for FnPointerType<'a> {
556 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
557 match syntax.kind() {
558 FN_POINTER_TYPE => Some(FnPointerType { syntax }),
559 _ => None,
560 }
561 }
562 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
563}
564
565impl<'a> FnPointerType<'a> {}
566
567// ForExpr
568#[derive(Debug, Clone, Copy)]
569pub struct ForExpr<'a> {
570 syntax: SyntaxNodeRef<'a>,
571}
572
573impl<'a> AstNode<'a> for ForExpr<'a> {
574 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
575 match syntax.kind() {
576 FOR_EXPR => Some(ForExpr { syntax }),
577 _ => None,
578 }
579 }
580 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
581}
582
583impl<'a> ast::LoopBodyOwner<'a> for ForExpr<'a> {}
584impl<'a> ForExpr<'a> {pub fn pat(self) -> Option<Pat<'a>> {
585 super::child_opt(self)
586 }
587pub fn iterable(self) -> Option<Expr<'a>> {
588 super::child_opt(self)
589 }
590}
591
592// ForType
593#[derive(Debug, Clone, Copy)]
594pub struct ForType<'a> {
595 syntax: SyntaxNodeRef<'a>,
596}
597
598impl<'a> AstNode<'a> for ForType<'a> {
599 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
600 match syntax.kind() {
601 FOR_TYPE => Some(ForType { syntax }),
602 _ => None,
603 }
604 }
605 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
606}
607
608impl<'a> ForType<'a> {}
609
610// IfExpr
611#[derive(Debug, Clone, Copy)]
612pub struct IfExpr<'a> {
613 syntax: SyntaxNodeRef<'a>,
614}
615
616impl<'a> AstNode<'a> for IfExpr<'a> {
617 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
618 match syntax.kind() {
619 IF_EXPR => Some(IfExpr { syntax }),
620 _ => None,
621 }
622 }
623 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
624}
625
626impl<'a> IfExpr<'a> {pub fn condition(self) -> Option<Condition<'a>> {
627 super::child_opt(self)
628 }
629}
630
631// ImplItem
632#[derive(Debug, Clone, Copy)]
633pub struct ImplItem<'a> {
634 syntax: SyntaxNodeRef<'a>,
635}
636
637impl<'a> AstNode<'a> for ImplItem<'a> {
638 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
639 match syntax.kind() {
640 IMPL_ITEM => Some(ImplItem { syntax }),
641 _ => None,
642 }
643 }
644 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
645}
646
647impl<'a> ImplItem<'a> {}
648
649// ImplTraitType
650#[derive(Debug, Clone, Copy)]
651pub struct ImplTraitType<'a> {
652 syntax: SyntaxNodeRef<'a>,
653}
654
655impl<'a> AstNode<'a> for ImplTraitType<'a> {
656 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
657 match syntax.kind() {
658 IMPL_TRAIT_TYPE => Some(ImplTraitType { syntax }),
659 _ => None,
660 }
661 }
662 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
663}
664
665impl<'a> ImplTraitType<'a> {}
666
667// IndexExpr
668#[derive(Debug, Clone, Copy)]
669pub struct IndexExpr<'a> {
670 syntax: SyntaxNodeRef<'a>,
671}
672
673impl<'a> AstNode<'a> for IndexExpr<'a> {
674 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
675 match syntax.kind() {
676 INDEX_EXPR => Some(IndexExpr { syntax }),
677 _ => None,
678 }
679 }
680 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
681}
682
683impl<'a> IndexExpr<'a> {}
684
685// ItemList
686#[derive(Debug, Clone, Copy)]
687pub struct ItemList<'a> {
688 syntax: SyntaxNodeRef<'a>,
689}
690
691impl<'a> AstNode<'a> for ItemList<'a> {
692 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
693 match syntax.kind() {
694 ITEM_LIST => Some(ItemList { syntax }),
695 _ => None,
696 }
697 }
698 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
699}
700
701impl<'a> ast::FnDefOwner<'a> for ItemList<'a> {}
702impl<'a> ast::ModuleItemOwner<'a> for ItemList<'a> {}
703impl<'a> ItemList<'a> {}
704
705// Label
706#[derive(Debug, Clone, Copy)]
707pub struct Label<'a> {
708 syntax: SyntaxNodeRef<'a>,
709}
710
711impl<'a> AstNode<'a> for Label<'a> {
712 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
713 match syntax.kind() {
714 LABEL => Some(Label { syntax }),
715 _ => None,
716 }
717 }
718 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
719}
720
721impl<'a> Label<'a> {}
722
723// LambdaExpr
724#[derive(Debug, Clone, Copy)]
725pub struct LambdaExpr<'a> {
726 syntax: SyntaxNodeRef<'a>,
727}
728
729impl<'a> AstNode<'a> for LambdaExpr<'a> {
730 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
731 match syntax.kind() {
732 LAMBDA_EXPR => Some(LambdaExpr { syntax }),
733 _ => None,
734 }
735 }
736 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
737}
738
739impl<'a> LambdaExpr<'a> {pub fn param_list(self) -> Option<ParamList<'a>> {
740 super::child_opt(self)
741 }
742pub fn body(self) -> Option<Expr<'a>> {
743 super::child_opt(self)
744 }
745}
746
747// LetStmt
748#[derive(Debug, Clone, Copy)]
749pub struct LetStmt<'a> {
750 syntax: SyntaxNodeRef<'a>,
751}
752
753impl<'a> AstNode<'a> for LetStmt<'a> {
754 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
755 match syntax.kind() {
756 LET_STMT => Some(LetStmt { syntax }),
757 _ => None,
758 }
759 }
760 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
761}
762
763impl<'a> LetStmt<'a> {pub fn pat(self) -> Option<Pat<'a>> {
764 super::child_opt(self)
765 }
766pub fn initializer(self) -> Option<Expr<'a>> {
767 super::child_opt(self)
768 }
769}
770
771// Lifetime
772#[derive(Debug, Clone, Copy)]
773pub struct Lifetime<'a> {
774 syntax: SyntaxNodeRef<'a>,
775}
776
777impl<'a> AstNode<'a> for Lifetime<'a> {
778 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
779 match syntax.kind() {
780 LIFETIME => Some(Lifetime { syntax }),
781 _ => None,
782 }
783 }
784 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
785}
786
787impl<'a> Lifetime<'a> {}
788
789// LifetimeParam
790#[derive(Debug, Clone, Copy)]
791pub struct LifetimeParam<'a> {
792 syntax: SyntaxNodeRef<'a>,
793}
794
795impl<'a> AstNode<'a> for LifetimeParam<'a> {
796 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
797 match syntax.kind() {
798 LIFETIME_PARAM => Some(LifetimeParam { syntax }),
799 _ => None,
800 }
801 }
802 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
803}
804
805impl<'a> LifetimeParam<'a> {pub fn lifetime(self) -> Option<Lifetime<'a>> {
806 super::child_opt(self)
807 }
808}
809
810// Literal
811#[derive(Debug, Clone, Copy)]
812pub struct Literal<'a> {
813 syntax: SyntaxNodeRef<'a>,
814}
815
816impl<'a> AstNode<'a> for Literal<'a> {
817 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
818 match syntax.kind() {
819 LITERAL => Some(Literal { syntax }),
820 _ => None,
821 }
822 }
823 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
824}
825
826impl<'a> Literal<'a> {}
827
828// LoopExpr
829#[derive(Debug, Clone, Copy)]
830pub struct LoopExpr<'a> {
831 syntax: SyntaxNodeRef<'a>,
832}
833
834impl<'a> AstNode<'a> for LoopExpr<'a> {
835 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
836 match syntax.kind() {
837 LOOP_EXPR => Some(LoopExpr { syntax }),
838 _ => None,
839 }
840 }
841 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
842}
843
844impl<'a> ast::LoopBodyOwner<'a> for LoopExpr<'a> {}
845impl<'a> LoopExpr<'a> {}
846
847// MatchArm
848#[derive(Debug, Clone, Copy)]
849pub struct MatchArm<'a> {
850 syntax: SyntaxNodeRef<'a>,
851}
852
853impl<'a> AstNode<'a> for MatchArm<'a> {
854 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
855 match syntax.kind() {
856 MATCH_ARM => Some(MatchArm { syntax }),
857 _ => None,
858 }
859 }
860 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
861}
862
863impl<'a> MatchArm<'a> {
864 pub fn pats(self) -> impl Iterator<Item = Pat<'a>> + 'a {
865 super::children(self)
866 }
867pub fn guard(self) -> Option<MatchGuard<'a>> {
868 super::child_opt(self)
869 }
870pub fn expr(self) -> Option<Expr<'a>> {
871 super::child_opt(self)
872 }
873}
874
875// MatchArmList
876#[derive(Debug, Clone, Copy)]
877pub struct MatchArmList<'a> {
878 syntax: SyntaxNodeRef<'a>,
879}
880
881impl<'a> AstNode<'a> for MatchArmList<'a> {
882 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
883 match syntax.kind() {
884 MATCH_ARM_LIST => Some(MatchArmList { syntax }),
885 _ => None,
886 }
887 }
888 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
889}
890
891impl<'a> MatchArmList<'a> {
892 pub fn arms(self) -> impl Iterator<Item = MatchArm<'a>> + 'a {
893 super::children(self)
894 }
895}
896
897// MatchExpr
898#[derive(Debug, Clone, Copy)]
899pub struct MatchExpr<'a> {
900 syntax: SyntaxNodeRef<'a>,
901}
902
903impl<'a> AstNode<'a> for MatchExpr<'a> {
904 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
905 match syntax.kind() {
906 MATCH_EXPR => Some(MatchExpr { syntax }),
907 _ => None,
908 }
909 }
910 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
911}
912
913impl<'a> MatchExpr<'a> {pub fn expr(self) -> Option<Expr<'a>> {
914 super::child_opt(self)
915 }
916pub fn match_arm_list(self) -> Option<MatchArmList<'a>> {
917 super::child_opt(self)
918 }
919}
920
921// MatchGuard
922#[derive(Debug, Clone, Copy)]
923pub struct MatchGuard<'a> {
924 syntax: SyntaxNodeRef<'a>,
925}
926
927impl<'a> AstNode<'a> for MatchGuard<'a> {
928 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
929 match syntax.kind() {
930 MATCH_GUARD => Some(MatchGuard { syntax }),
931 _ => None,
932 }
933 }
934 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
935}
936
937impl<'a> MatchGuard<'a> {}
938
939// MethodCallExpr
940#[derive(Debug, Clone, Copy)]
941pub struct MethodCallExpr<'a> {
942 syntax: SyntaxNodeRef<'a>,
943}
944
945impl<'a> AstNode<'a> for MethodCallExpr<'a> {
946 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
947 match syntax.kind() {
948 METHOD_CALL_EXPR => Some(MethodCallExpr { syntax }),
949 _ => None,
950 }
951 }
952 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
953}
954
955impl<'a> ast::ArgListOwner<'a> for MethodCallExpr<'a> {}
956impl<'a> MethodCallExpr<'a> {pub fn expr(self) -> Option<Expr<'a>> {
957 super::child_opt(self)
958 }
959}
960
961// Module
962#[derive(Debug, Clone, Copy)]
963pub struct Module<'a> {
964 syntax: SyntaxNodeRef<'a>,
965}
966
967impl<'a> AstNode<'a> for Module<'a> {
968 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
969 match syntax.kind() {
970 MODULE => Some(Module { syntax }),
971 _ => None,
972 }
973 }
974 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
975}
976
977impl<'a> ast::NameOwner<'a> for Module<'a> {}
978impl<'a> ast::AttrsOwner<'a> for Module<'a> {}
979impl<'a> Module<'a> {pub fn item_list(self) -> Option<ItemList<'a>> {
980 super::child_opt(self)
981 }
982}
983
984// ModuleItem
985#[derive(Debug, Clone, Copy)]
986pub enum ModuleItem<'a> {
987 StructDef(StructDef<'a>),
988 EnumDef(EnumDef<'a>),
989 FnDef(FnDef<'a>),
990 TraitDef(TraitDef<'a>),
991 TypeDef(TypeDef<'a>),
992 ImplItem(ImplItem<'a>),
993 UseItem(UseItem<'a>),
994 ExternCrateItem(ExternCrateItem<'a>),
995 ConstDef(ConstDef<'a>),
996 StaticDef(StaticDef<'a>),
997 Module(Module<'a>),
998}
999
1000impl<'a> AstNode<'a> for ModuleItem<'a> {
1001 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1002 match syntax.kind() {
1003 STRUCT_DEF => Some(ModuleItem::StructDef(StructDef { syntax })),
1004 ENUM_DEF => Some(ModuleItem::EnumDef(EnumDef { syntax })),
1005 FN_DEF => Some(ModuleItem::FnDef(FnDef { syntax })),
1006 TRAIT_DEF => Some(ModuleItem::TraitDef(TraitDef { syntax })),
1007 TYPE_DEF => Some(ModuleItem::TypeDef(TypeDef { syntax })),
1008 IMPL_ITEM => Some(ModuleItem::ImplItem(ImplItem { syntax })),
1009 USE_ITEM => Some(ModuleItem::UseItem(UseItem { syntax })),
1010 EXTERN_CRATE_ITEM => Some(ModuleItem::ExternCrateItem(ExternCrateItem { syntax })),
1011 CONST_DEF => Some(ModuleItem::ConstDef(ConstDef { syntax })),
1012 STATIC_DEF => Some(ModuleItem::StaticDef(StaticDef { syntax })),
1013 MODULE => Some(ModuleItem::Module(Module { syntax })),
1014 _ => None,
1015 }
1016 }
1017 fn syntax(self) -> SyntaxNodeRef<'a> {
1018 match self {
1019 ModuleItem::StructDef(inner) => inner.syntax(),
1020 ModuleItem::EnumDef(inner) => inner.syntax(),
1021 ModuleItem::FnDef(inner) => inner.syntax(),
1022 ModuleItem::TraitDef(inner) => inner.syntax(),
1023 ModuleItem::TypeDef(inner) => inner.syntax(),
1024 ModuleItem::ImplItem(inner) => inner.syntax(),
1025 ModuleItem::UseItem(inner) => inner.syntax(),
1026 ModuleItem::ExternCrateItem(inner) => inner.syntax(),
1027 ModuleItem::ConstDef(inner) => inner.syntax(),
1028 ModuleItem::StaticDef(inner) => inner.syntax(),
1029 ModuleItem::Module(inner) => inner.syntax(),
1030 }
1031 }
1032}
1033
1034impl<'a> ModuleItem<'a> {}
1035
1036// Name
1037#[derive(Debug, Clone, Copy)]
1038pub struct Name<'a> {
1039 syntax: SyntaxNodeRef<'a>,
1040}
1041
1042impl<'a> AstNode<'a> for Name<'a> {
1043 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1044 match syntax.kind() {
1045 NAME => Some(Name { syntax }),
1046 _ => None,
1047 }
1048 }
1049 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1050}
1051
1052impl<'a> Name<'a> {}
1053
1054// NameRef
1055#[derive(Debug, Clone, Copy)]
1056pub struct NameRef<'a> {
1057 syntax: SyntaxNodeRef<'a>,
1058}
1059
1060impl<'a> AstNode<'a> for NameRef<'a> {
1061 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1062 match syntax.kind() {
1063 NAME_REF => Some(NameRef { syntax }),
1064 _ => None,
1065 }
1066 }
1067 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1068}
1069
1070impl<'a> NameRef<'a> {}
1071
1072// NamedField
1073#[derive(Debug, Clone, Copy)]
1074pub struct NamedField<'a> {
1075 syntax: SyntaxNodeRef<'a>,
1076}
1077
1078impl<'a> AstNode<'a> for NamedField<'a> {
1079 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1080 match syntax.kind() {
1081 NAMED_FIELD => Some(NamedField { syntax }),
1082 _ => None,
1083 }
1084 }
1085 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1086}
1087
1088impl<'a> NamedField<'a> {}
1089
1090// NamedFieldDef
1091#[derive(Debug, Clone, Copy)]
1092pub struct NamedFieldDef<'a> {
1093 syntax: SyntaxNodeRef<'a>,
1094}
1095
1096impl<'a> AstNode<'a> for NamedFieldDef<'a> {
1097 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1098 match syntax.kind() {
1099 NAMED_FIELD_DEF => Some(NamedFieldDef { syntax }),
1100 _ => None,
1101 }
1102 }
1103 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1104}
1105
1106impl<'a> ast::NameOwner<'a> for NamedFieldDef<'a> {}
1107impl<'a> ast::AttrsOwner<'a> for NamedFieldDef<'a> {}
1108impl<'a> NamedFieldDef<'a> {}
1109
1110// NamedFieldList
1111#[derive(Debug, Clone, Copy)]
1112pub struct NamedFieldList<'a> {
1113 syntax: SyntaxNodeRef<'a>,
1114}
1115
1116impl<'a> AstNode<'a> for NamedFieldList<'a> {
1117 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1118 match syntax.kind() {
1119 NAMED_FIELD_LIST => Some(NamedFieldList { syntax }),
1120 _ => None,
1121 }
1122 }
1123 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1124}
1125
1126impl<'a> NamedFieldList<'a> {}
1127
1128// NeverType
1129#[derive(Debug, Clone, Copy)]
1130pub struct NeverType<'a> {
1131 syntax: SyntaxNodeRef<'a>,
1132}
1133
1134impl<'a> AstNode<'a> for NeverType<'a> {
1135 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1136 match syntax.kind() {
1137 NEVER_TYPE => Some(NeverType { syntax }),
1138 _ => None,
1139 }
1140 }
1141 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1142}
1143
1144impl<'a> NeverType<'a> {}
1145
1146// NominalDef
1147#[derive(Debug, Clone, Copy)]
1148pub enum NominalDef<'a> {
1149 StructDef(StructDef<'a>),
1150 EnumDef(EnumDef<'a>),
1151}
1152
1153impl<'a> AstNode<'a> for NominalDef<'a> {
1154 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1155 match syntax.kind() {
1156 STRUCT_DEF => Some(NominalDef::StructDef(StructDef { syntax })),
1157 ENUM_DEF => Some(NominalDef::EnumDef(EnumDef { syntax })),
1158 _ => None,
1159 }
1160 }
1161 fn syntax(self) -> SyntaxNodeRef<'a> {
1162 match self {
1163 NominalDef::StructDef(inner) => inner.syntax(),
1164 NominalDef::EnumDef(inner) => inner.syntax(),
1165 }
1166 }
1167}
1168
1169impl<'a> ast::NameOwner<'a> for NominalDef<'a> {}
1170impl<'a> ast::TypeParamsOwner<'a> for NominalDef<'a> {}
1171impl<'a> ast::AttrsOwner<'a> for NominalDef<'a> {}
1172impl<'a> NominalDef<'a> {}
1173
1174// Param
1175#[derive(Debug, Clone, Copy)]
1176pub struct Param<'a> {
1177 syntax: SyntaxNodeRef<'a>,
1178}
1179
1180impl<'a> AstNode<'a> for Param<'a> {
1181 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1182 match syntax.kind() {
1183 PARAM => Some(Param { syntax }),
1184 _ => None,
1185 }
1186 }
1187 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1188}
1189
1190impl<'a> Param<'a> {pub fn pat(self) -> Option<Pat<'a>> {
1191 super::child_opt(self)
1192 }
1193}
1194
1195// ParamList
1196#[derive(Debug, Clone, Copy)]
1197pub struct ParamList<'a> {
1198 syntax: SyntaxNodeRef<'a>,
1199}
1200
1201impl<'a> AstNode<'a> for ParamList<'a> {
1202 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1203 match syntax.kind() {
1204 PARAM_LIST => Some(ParamList { syntax }),
1205 _ => None,
1206 }
1207 }
1208 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1209}
1210
1211impl<'a> ParamList<'a> {
1212 pub fn params(self) -> impl Iterator<Item = Param<'a>> + 'a {
1213 super::children(self)
1214 }
1215pub fn self_param(self) -> Option<SelfParam<'a>> {
1216 super::child_opt(self)
1217 }
1218}
1219
1220// ParenExpr
1221#[derive(Debug, Clone, Copy)]
1222pub struct ParenExpr<'a> {
1223 syntax: SyntaxNodeRef<'a>,
1224}
1225
1226impl<'a> AstNode<'a> for ParenExpr<'a> {
1227 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1228 match syntax.kind() {
1229 PAREN_EXPR => Some(ParenExpr { syntax }),
1230 _ => None,
1231 }
1232 }
1233 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1234}
1235
1236impl<'a> ParenExpr<'a> {}
1237
1238// ParenType
1239#[derive(Debug, Clone, Copy)]
1240pub struct ParenType<'a> {
1241 syntax: SyntaxNodeRef<'a>,
1242}
1243
1244impl<'a> AstNode<'a> for ParenType<'a> {
1245 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1246 match syntax.kind() {
1247 PAREN_TYPE => Some(ParenType { syntax }),
1248 _ => None,
1249 }
1250 }
1251 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1252}
1253
1254impl<'a> ParenType<'a> {}
1255
1256// Pat
1257#[derive(Debug, Clone, Copy)]
1258pub enum Pat<'a> {
1259 RefPat(RefPat<'a>),
1260 BindPat(BindPat<'a>),
1261 PlaceholderPat(PlaceholderPat<'a>),
1262 PathPat(PathPat<'a>),
1263 StructPat(StructPat<'a>),
1264 FieldPatList(FieldPatList<'a>),
1265 TupleStructPat(TupleStructPat<'a>),
1266 TuplePat(TuplePat<'a>),
1267 SlicePat(SlicePat<'a>),
1268 RangePat(RangePat<'a>),
1269}
1270
1271impl<'a> AstNode<'a> for Pat<'a> {
1272 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1273 match syntax.kind() {
1274 REF_PAT => Some(Pat::RefPat(RefPat { syntax })),
1275 BIND_PAT => Some(Pat::BindPat(BindPat { syntax })),
1276 PLACEHOLDER_PAT => Some(Pat::PlaceholderPat(PlaceholderPat { syntax })),
1277 PATH_PAT => Some(Pat::PathPat(PathPat { syntax })),
1278 STRUCT_PAT => Some(Pat::StructPat(StructPat { syntax })),
1279 FIELD_PAT_LIST => Some(Pat::FieldPatList(FieldPatList { syntax })),
1280 TUPLE_STRUCT_PAT => Some(Pat::TupleStructPat(TupleStructPat { syntax })),
1281 TUPLE_PAT => Some(Pat::TuplePat(TuplePat { syntax })),
1282 SLICE_PAT => Some(Pat::SlicePat(SlicePat { syntax })),
1283 RANGE_PAT => Some(Pat::RangePat(RangePat { syntax })),
1284 _ => None,
1285 }
1286 }
1287 fn syntax(self) -> SyntaxNodeRef<'a> {
1288 match self {
1289 Pat::RefPat(inner) => inner.syntax(),
1290 Pat::BindPat(inner) => inner.syntax(),
1291 Pat::PlaceholderPat(inner) => inner.syntax(),
1292 Pat::PathPat(inner) => inner.syntax(),
1293 Pat::StructPat(inner) => inner.syntax(),
1294 Pat::FieldPatList(inner) => inner.syntax(),
1295 Pat::TupleStructPat(inner) => inner.syntax(),
1296 Pat::TuplePat(inner) => inner.syntax(),
1297 Pat::SlicePat(inner) => inner.syntax(),
1298 Pat::RangePat(inner) => inner.syntax(),
1299 }
1300 }
1301}
1302
1303impl<'a> Pat<'a> {}
1304
1305// Path
1306#[derive(Debug, Clone, Copy)]
1307pub struct Path<'a> {
1308 syntax: SyntaxNodeRef<'a>,
1309}
1310
1311impl<'a> AstNode<'a> for Path<'a> {
1312 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1313 match syntax.kind() {
1314 PATH => Some(Path { syntax }),
1315 _ => None,
1316 }
1317 }
1318 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1319}
1320
1321impl<'a> Path<'a> {pub fn segment(self) -> Option<PathSegment<'a>> {
1322 super::child_opt(self)
1323 }
1324}
1325
1326// PathExpr
1327#[derive(Debug, Clone, Copy)]
1328pub struct PathExpr<'a> {
1329 syntax: SyntaxNodeRef<'a>,
1330}
1331
1332impl<'a> AstNode<'a> for PathExpr<'a> {
1333 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1334 match syntax.kind() {
1335 PATH_EXPR => Some(PathExpr { syntax }),
1336 _ => None,
1337 }
1338 }
1339 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1340}
1341
1342impl<'a> PathExpr<'a> {}
1343
1344// PathPat
1345#[derive(Debug, Clone, Copy)]
1346pub struct PathPat<'a> {
1347 syntax: SyntaxNodeRef<'a>,
1348}
1349
1350impl<'a> AstNode<'a> for PathPat<'a> {
1351 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1352 match syntax.kind() {
1353 PATH_PAT => Some(PathPat { syntax }),
1354 _ => None,
1355 }
1356 }
1357 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1358}
1359
1360impl<'a> PathPat<'a> {}
1361
1362// PathSegment
1363#[derive(Debug, Clone, Copy)]
1364pub struct PathSegment<'a> {
1365 syntax: SyntaxNodeRef<'a>,
1366}
1367
1368impl<'a> AstNode<'a> for PathSegment<'a> {
1369 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1370 match syntax.kind() {
1371 PATH_SEGMENT => Some(PathSegment { syntax }),
1372 _ => None,
1373 }
1374 }
1375 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1376}
1377
1378impl<'a> PathSegment<'a> {pub fn name_ref(self) -> Option<NameRef<'a>> {
1379 super::child_opt(self)
1380 }
1381}
1382
1383// PathType
1384#[derive(Debug, Clone, Copy)]
1385pub struct PathType<'a> {
1386 syntax: SyntaxNodeRef<'a>,
1387}
1388
1389impl<'a> AstNode<'a> for PathType<'a> {
1390 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1391 match syntax.kind() {
1392 PATH_TYPE => Some(PathType { syntax }),
1393 _ => None,
1394 }
1395 }
1396 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1397}
1398
1399impl<'a> PathType<'a> {}
1400
1401// PlaceholderPat
1402#[derive(Debug, Clone, Copy)]
1403pub struct PlaceholderPat<'a> {
1404 syntax: SyntaxNodeRef<'a>,
1405}
1406
1407impl<'a> AstNode<'a> for PlaceholderPat<'a> {
1408 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1409 match syntax.kind() {
1410 PLACEHOLDER_PAT => Some(PlaceholderPat { syntax }),
1411 _ => None,
1412 }
1413 }
1414 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1415}
1416
1417impl<'a> PlaceholderPat<'a> {}
1418
1419// PlaceholderType
1420#[derive(Debug, Clone, Copy)]
1421pub struct PlaceholderType<'a> {
1422 syntax: SyntaxNodeRef<'a>,
1423}
1424
1425impl<'a> AstNode<'a> for PlaceholderType<'a> {
1426 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1427 match syntax.kind() {
1428 PLACEHOLDER_TYPE => Some(PlaceholderType { syntax }),
1429 _ => None,
1430 }
1431 }
1432 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1433}
1434
1435impl<'a> PlaceholderType<'a> {}
1436
1437// PointerType
1438#[derive(Debug, Clone, Copy)]
1439pub struct PointerType<'a> {
1440 syntax: SyntaxNodeRef<'a>,
1441}
1442
1443impl<'a> AstNode<'a> for PointerType<'a> {
1444 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1445 match syntax.kind() {
1446 POINTER_TYPE => Some(PointerType { syntax }),
1447 _ => None,
1448 }
1449 }
1450 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1451}
1452
1453impl<'a> PointerType<'a> {}
1454
1455// PrefixExpr
1456#[derive(Debug, Clone, Copy)]
1457pub struct PrefixExpr<'a> {
1458 syntax: SyntaxNodeRef<'a>,
1459}
1460
1461impl<'a> AstNode<'a> for PrefixExpr<'a> {
1462 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1463 match syntax.kind() {
1464 PREFIX_EXPR => Some(PrefixExpr { syntax }),
1465 _ => None,
1466 }
1467 }
1468 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1469}
1470
1471impl<'a> PrefixExpr<'a> {}
1472
1473// RangeExpr
1474#[derive(Debug, Clone, Copy)]
1475pub struct RangeExpr<'a> {
1476 syntax: SyntaxNodeRef<'a>,
1477}
1478
1479impl<'a> AstNode<'a> for RangeExpr<'a> {
1480 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1481 match syntax.kind() {
1482 RANGE_EXPR => Some(RangeExpr { syntax }),
1483 _ => None,
1484 }
1485 }
1486 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1487}
1488
1489impl<'a> RangeExpr<'a> {}
1490
1491// RangePat
1492#[derive(Debug, Clone, Copy)]
1493pub struct RangePat<'a> {
1494 syntax: SyntaxNodeRef<'a>,
1495}
1496
1497impl<'a> AstNode<'a> for RangePat<'a> {
1498 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1499 match syntax.kind() {
1500 RANGE_PAT => Some(RangePat { syntax }),
1501 _ => None,
1502 }
1503 }
1504 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1505}
1506
1507impl<'a> RangePat<'a> {}
1508
1509// RefExpr
1510#[derive(Debug, Clone, Copy)]
1511pub struct RefExpr<'a> {
1512 syntax: SyntaxNodeRef<'a>,
1513}
1514
1515impl<'a> AstNode<'a> for RefExpr<'a> {
1516 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1517 match syntax.kind() {
1518 REF_EXPR => Some(RefExpr { syntax }),
1519 _ => None,
1520 }
1521 }
1522 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1523}
1524
1525impl<'a> RefExpr<'a> {}
1526
1527// RefPat
1528#[derive(Debug, Clone, Copy)]
1529pub struct RefPat<'a> {
1530 syntax: SyntaxNodeRef<'a>,
1531}
1532
1533impl<'a> AstNode<'a> for RefPat<'a> {
1534 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1535 match syntax.kind() {
1536 REF_PAT => Some(RefPat { syntax }),
1537 _ => None,
1538 }
1539 }
1540 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1541}
1542
1543impl<'a> RefPat<'a> {}
1544
1545// ReferenceType
1546#[derive(Debug, Clone, Copy)]
1547pub struct ReferenceType<'a> {
1548 syntax: SyntaxNodeRef<'a>,
1549}
1550
1551impl<'a> AstNode<'a> for ReferenceType<'a> {
1552 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1553 match syntax.kind() {
1554 REFERENCE_TYPE => Some(ReferenceType { syntax }),
1555 _ => None,
1556 }
1557 }
1558 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1559}
1560
1561impl<'a> ReferenceType<'a> {}
1562
1563// RetType
1564#[derive(Debug, Clone, Copy)]
1565pub struct RetType<'a> {
1566 syntax: SyntaxNodeRef<'a>,
1567}
1568
1569impl<'a> AstNode<'a> for RetType<'a> {
1570 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1571 match syntax.kind() {
1572 RET_TYPE => Some(RetType { syntax }),
1573 _ => None,
1574 }
1575 }
1576 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1577}
1578
1579impl<'a> RetType<'a> {}
1580
1581// ReturnExpr
1582#[derive(Debug, Clone, Copy)]
1583pub struct ReturnExpr<'a> {
1584 syntax: SyntaxNodeRef<'a>,
1585}
1586
1587impl<'a> AstNode<'a> for ReturnExpr<'a> {
1588 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1589 match syntax.kind() {
1590 RETURN_EXPR => Some(ReturnExpr { syntax }),
1591 _ => None,
1592 }
1593 }
1594 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1595}
1596
1597impl<'a> ReturnExpr<'a> {}
1598
1599// Root
1600#[derive(Debug, Clone, Copy)]
1601pub struct Root<'a> {
1602 syntax: SyntaxNodeRef<'a>,
1603}
1604
1605impl<'a> AstNode<'a> for Root<'a> {
1606 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1607 match syntax.kind() {
1608 ROOT => Some(Root { syntax }),
1609 _ => None,
1610 }
1611 }
1612 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1613}
1614
1615impl<'a> ast::ModuleItemOwner<'a> for Root<'a> {}
1616impl<'a> ast::FnDefOwner<'a> for Root<'a> {}
1617impl<'a> Root<'a> {
1618 pub fn modules(self) -> impl Iterator<Item = Module<'a>> + 'a {
1619 super::children(self)
1620 }
1621}
1622
1623// SelfParam
1624#[derive(Debug, Clone, Copy)]
1625pub struct SelfParam<'a> {
1626 syntax: SyntaxNodeRef<'a>,
1627}
1628
1629impl<'a> AstNode<'a> for SelfParam<'a> {
1630 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1631 match syntax.kind() {
1632 SELF_PARAM => Some(SelfParam { syntax }),
1633 _ => None,
1634 }
1635 }
1636 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1637}
1638
1639impl<'a> SelfParam<'a> {}
1640
1641// SlicePat
1642#[derive(Debug, Clone, Copy)]
1643pub struct SlicePat<'a> {
1644 syntax: SyntaxNodeRef<'a>,
1645}
1646
1647impl<'a> AstNode<'a> for SlicePat<'a> {
1648 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1649 match syntax.kind() {
1650 SLICE_PAT => Some(SlicePat { syntax }),
1651 _ => None,
1652 }
1653 }
1654 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1655}
1656
1657impl<'a> SlicePat<'a> {}
1658
1659// SliceType
1660#[derive(Debug, Clone, Copy)]
1661pub struct SliceType<'a> {
1662 syntax: SyntaxNodeRef<'a>,
1663}
1664
1665impl<'a> AstNode<'a> for SliceType<'a> {
1666 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1667 match syntax.kind() {
1668 SLICE_TYPE => Some(SliceType { syntax }),
1669 _ => None,
1670 }
1671 }
1672 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1673}
1674
1675impl<'a> SliceType<'a> {}
1676
1677// StaticDef
1678#[derive(Debug, Clone, Copy)]
1679pub struct StaticDef<'a> {
1680 syntax: SyntaxNodeRef<'a>,
1681}
1682
1683impl<'a> AstNode<'a> for StaticDef<'a> {
1684 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1685 match syntax.kind() {
1686 STATIC_DEF => Some(StaticDef { syntax }),
1687 _ => None,
1688 }
1689 }
1690 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1691}
1692
1693impl<'a> ast::NameOwner<'a> for StaticDef<'a> {}
1694impl<'a> ast::TypeParamsOwner<'a> for StaticDef<'a> {}
1695impl<'a> ast::AttrsOwner<'a> for StaticDef<'a> {}
1696impl<'a> StaticDef<'a> {}
1697
1698// Stmt
1699#[derive(Debug, Clone, Copy)]
1700pub enum Stmt<'a> {
1701 ExprStmt(ExprStmt<'a>),
1702 LetStmt(LetStmt<'a>),
1703}
1704
1705impl<'a> AstNode<'a> for Stmt<'a> {
1706 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1707 match syntax.kind() {
1708 EXPR_STMT => Some(Stmt::ExprStmt(ExprStmt { syntax })),
1709 LET_STMT => Some(Stmt::LetStmt(LetStmt { syntax })),
1710 _ => None,
1711 }
1712 }
1713 fn syntax(self) -> SyntaxNodeRef<'a> {
1714 match self {
1715 Stmt::ExprStmt(inner) => inner.syntax(),
1716 Stmt::LetStmt(inner) => inner.syntax(),
1717 }
1718 }
1719}
1720
1721impl<'a> Stmt<'a> {}
1722
1723// StructDef
1724#[derive(Debug, Clone, Copy)]
1725pub struct StructDef<'a> {
1726 syntax: SyntaxNodeRef<'a>,
1727}
1728
1729impl<'a> AstNode<'a> for StructDef<'a> {
1730 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1731 match syntax.kind() {
1732 STRUCT_DEF => Some(StructDef { syntax }),
1733 _ => None,
1734 }
1735 }
1736 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1737}
1738
1739impl<'a> ast::NameOwner<'a> for StructDef<'a> {}
1740impl<'a> ast::TypeParamsOwner<'a> for StructDef<'a> {}
1741impl<'a> ast::AttrsOwner<'a> for StructDef<'a> {}
1742impl<'a> StructDef<'a> {
1743 pub fn fields(self) -> impl Iterator<Item = NamedFieldDef<'a>> + 'a {
1744 super::children(self)
1745 }
1746}
1747
1748// StructLit
1749#[derive(Debug, Clone, Copy)]
1750pub struct StructLit<'a> {
1751 syntax: SyntaxNodeRef<'a>,
1752}
1753
1754impl<'a> AstNode<'a> for StructLit<'a> {
1755 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1756 match syntax.kind() {
1757 STRUCT_LIT => Some(StructLit { syntax }),
1758 _ => None,
1759 }
1760 }
1761 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1762}
1763
1764impl<'a> StructLit<'a> {}
1765
1766// StructPat
1767#[derive(Debug, Clone, Copy)]
1768pub struct StructPat<'a> {
1769 syntax: SyntaxNodeRef<'a>,
1770}
1771
1772impl<'a> AstNode<'a> for StructPat<'a> {
1773 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1774 match syntax.kind() {
1775 STRUCT_PAT => Some(StructPat { syntax }),
1776 _ => None,
1777 }
1778 }
1779 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1780}
1781
1782impl<'a> StructPat<'a> {}
1783
1784// TokenTree
1785#[derive(Debug, Clone, Copy)]
1786pub struct TokenTree<'a> {
1787 syntax: SyntaxNodeRef<'a>,
1788}
1789
1790impl<'a> AstNode<'a> for TokenTree<'a> {
1791 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1792 match syntax.kind() {
1793 TOKEN_TREE => Some(TokenTree { syntax }),
1794 _ => None,
1795 }
1796 }
1797 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1798}
1799
1800impl<'a> TokenTree<'a> {}
1801
1802// TraitDef
1803#[derive(Debug, Clone, Copy)]
1804pub struct TraitDef<'a> {
1805 syntax: SyntaxNodeRef<'a>,
1806}
1807
1808impl<'a> AstNode<'a> for TraitDef<'a> {
1809 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1810 match syntax.kind() {
1811 TRAIT_DEF => Some(TraitDef { syntax }),
1812 _ => None,
1813 }
1814 }
1815 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1816}
1817
1818impl<'a> ast::NameOwner<'a> for TraitDef<'a> {}
1819impl<'a> ast::AttrsOwner<'a> for TraitDef<'a> {}
1820impl<'a> TraitDef<'a> {}
1821
1822// TryExpr
1823#[derive(Debug, Clone, Copy)]
1824pub struct TryExpr<'a> {
1825 syntax: SyntaxNodeRef<'a>,
1826}
1827
1828impl<'a> AstNode<'a> for TryExpr<'a> {
1829 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1830 match syntax.kind() {
1831 TRY_EXPR => Some(TryExpr { syntax }),
1832 _ => None,
1833 }
1834 }
1835 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1836}
1837
1838impl<'a> TryExpr<'a> {}
1839
1840// TupleExpr
1841#[derive(Debug, Clone, Copy)]
1842pub struct TupleExpr<'a> {
1843 syntax: SyntaxNodeRef<'a>,
1844}
1845
1846impl<'a> AstNode<'a> for TupleExpr<'a> {
1847 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1848 match syntax.kind() {
1849 TUPLE_EXPR => Some(TupleExpr { syntax }),
1850 _ => None,
1851 }
1852 }
1853 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1854}
1855
1856impl<'a> TupleExpr<'a> {}
1857
1858// TuplePat
1859#[derive(Debug, Clone, Copy)]
1860pub struct TuplePat<'a> {
1861 syntax: SyntaxNodeRef<'a>,
1862}
1863
1864impl<'a> AstNode<'a> for TuplePat<'a> {
1865 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1866 match syntax.kind() {
1867 TUPLE_PAT => Some(TuplePat { syntax }),
1868 _ => None,
1869 }
1870 }
1871 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1872}
1873
1874impl<'a> TuplePat<'a> {}
1875
1876// TupleStructPat
1877#[derive(Debug, Clone, Copy)]
1878pub struct TupleStructPat<'a> {
1879 syntax: SyntaxNodeRef<'a>,
1880}
1881
1882impl<'a> AstNode<'a> for TupleStructPat<'a> {
1883 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1884 match syntax.kind() {
1885 TUPLE_STRUCT_PAT => Some(TupleStructPat { syntax }),
1886 _ => None,
1887 }
1888 }
1889 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1890}
1891
1892impl<'a> TupleStructPat<'a> {}
1893
1894// TupleType
1895#[derive(Debug, Clone, Copy)]
1896pub struct TupleType<'a> {
1897 syntax: SyntaxNodeRef<'a>,
1898}
1899
1900impl<'a> AstNode<'a> for TupleType<'a> {
1901 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1902 match syntax.kind() {
1903 TUPLE_TYPE => Some(TupleType { syntax }),
1904 _ => None,
1905 }
1906 }
1907 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1908}
1909
1910impl<'a> TupleType<'a> {}
1911
1912// TypeDef
1913#[derive(Debug, Clone, Copy)]
1914pub struct TypeDef<'a> {
1915 syntax: SyntaxNodeRef<'a>,
1916}
1917
1918impl<'a> AstNode<'a> for TypeDef<'a> {
1919 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1920 match syntax.kind() {
1921 TYPE_DEF => Some(TypeDef { syntax }),
1922 _ => None,
1923 }
1924 }
1925 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1926}
1927
1928impl<'a> ast::NameOwner<'a> for TypeDef<'a> {}
1929impl<'a> ast::TypeParamsOwner<'a> for TypeDef<'a> {}
1930impl<'a> ast::AttrsOwner<'a> for TypeDef<'a> {}
1931impl<'a> TypeDef<'a> {}
1932
1933// TypeParam
1934#[derive(Debug, Clone, Copy)]
1935pub struct TypeParam<'a> {
1936 syntax: SyntaxNodeRef<'a>,
1937}
1938
1939impl<'a> AstNode<'a> for TypeParam<'a> {
1940 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1941 match syntax.kind() {
1942 TYPE_PARAM => Some(TypeParam { syntax }),
1943 _ => None,
1944 }
1945 }
1946 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1947}
1948
1949impl<'a> ast::NameOwner<'a> for TypeParam<'a> {}
1950impl<'a> TypeParam<'a> {}
1951
1952// TypeParamList
1953#[derive(Debug, Clone, Copy)]
1954pub struct TypeParamList<'a> {
1955 syntax: SyntaxNodeRef<'a>,
1956}
1957
1958impl<'a> AstNode<'a> for TypeParamList<'a> {
1959 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1960 match syntax.kind() {
1961 TYPE_PARAM_LIST => Some(TypeParamList { syntax }),
1962 _ => None,
1963 }
1964 }
1965 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1966}
1967
1968impl<'a> TypeParamList<'a> {
1969 pub fn type_params(self) -> impl Iterator<Item = TypeParam<'a>> + 'a {
1970 super::children(self)
1971 }
1972
1973 pub fn lifetime_params(self) -> impl Iterator<Item = LifetimeParam<'a>> + 'a {
1974 super::children(self)
1975 }
1976}
1977
1978// TypeRef
1979#[derive(Debug, Clone, Copy)]
1980pub enum TypeRef<'a> {
1981 ParenType(ParenType<'a>),
1982 TupleType(TupleType<'a>),
1983 NeverType(NeverType<'a>),
1984 PathType(PathType<'a>),
1985 PointerType(PointerType<'a>),
1986 ArrayType(ArrayType<'a>),
1987 SliceType(SliceType<'a>),
1988 ReferenceType(ReferenceType<'a>),
1989 PlaceholderType(PlaceholderType<'a>),
1990 FnPointerType(FnPointerType<'a>),
1991 ForType(ForType<'a>),
1992 ImplTraitType(ImplTraitType<'a>),
1993 DynTraitType(DynTraitType<'a>),
1994}
1995
1996impl<'a> AstNode<'a> for TypeRef<'a> {
1997 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1998 match syntax.kind() {
1999 PAREN_TYPE => Some(TypeRef::ParenType(ParenType { syntax })),
2000 TUPLE_TYPE => Some(TypeRef::TupleType(TupleType { syntax })),
2001 NEVER_TYPE => Some(TypeRef::NeverType(NeverType { syntax })),
2002 PATH_TYPE => Some(TypeRef::PathType(PathType { syntax })),
2003 POINTER_TYPE => Some(TypeRef::PointerType(PointerType { syntax })),
2004 ARRAY_TYPE => Some(TypeRef::ArrayType(ArrayType { syntax })),
2005 SLICE_TYPE => Some(TypeRef::SliceType(SliceType { syntax })),
2006 REFERENCE_TYPE => Some(TypeRef::ReferenceType(ReferenceType { syntax })),
2007 PLACEHOLDER_TYPE => Some(TypeRef::PlaceholderType(PlaceholderType { syntax })),
2008 FN_POINTER_TYPE => Some(TypeRef::FnPointerType(FnPointerType { syntax })),
2009 FOR_TYPE => Some(TypeRef::ForType(ForType { syntax })),
2010 IMPL_TRAIT_TYPE => Some(TypeRef::ImplTraitType(ImplTraitType { syntax })),
2011 DYN_TRAIT_TYPE => Some(TypeRef::DynTraitType(DynTraitType { syntax })),
2012 _ => None,
2013 }
2014 }
2015 fn syntax(self) -> SyntaxNodeRef<'a> {
2016 match self {
2017 TypeRef::ParenType(inner) => inner.syntax(),
2018 TypeRef::TupleType(inner) => inner.syntax(),
2019 TypeRef::NeverType(inner) => inner.syntax(),
2020 TypeRef::PathType(inner) => inner.syntax(),
2021 TypeRef::PointerType(inner) => inner.syntax(),
2022 TypeRef::ArrayType(inner) => inner.syntax(),
2023 TypeRef::SliceType(inner) => inner.syntax(),
2024 TypeRef::ReferenceType(inner) => inner.syntax(),
2025 TypeRef::PlaceholderType(inner) => inner.syntax(),
2026 TypeRef::FnPointerType(inner) => inner.syntax(),
2027 TypeRef::ForType(inner) => inner.syntax(),
2028 TypeRef::ImplTraitType(inner) => inner.syntax(),
2029 TypeRef::DynTraitType(inner) => inner.syntax(),
2030 }
2031 }
2032}
2033
2034impl<'a> TypeRef<'a> {}
2035
2036// UseItem
2037#[derive(Debug, Clone, Copy)]
2038pub struct UseItem<'a> {
2039 syntax: SyntaxNodeRef<'a>,
2040}
2041
2042impl<'a> AstNode<'a> for UseItem<'a> {
2043 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
2044 match syntax.kind() {
2045 USE_ITEM => Some(UseItem { syntax }),
2046 _ => None,
2047 }
2048 }
2049 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
2050}
2051
2052impl<'a> UseItem<'a> {pub fn use_tree(self) -> Option<UseTree<'a>> {
2053 super::child_opt(self)
2054 }
2055}
2056
2057// UseTree
2058#[derive(Debug, Clone, Copy)]
2059pub struct UseTree<'a> {
2060 syntax: SyntaxNodeRef<'a>,
2061}
2062
2063impl<'a> AstNode<'a> for UseTree<'a> {
2064 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
2065 match syntax.kind() {
2066 USE_TREE => Some(UseTree { syntax }),
2067 _ => None,
2068 }
2069 }
2070 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
2071}
2072
2073impl<'a> UseTree<'a> {pub fn path(self) -> Option<Path<'a>> {
2074 super::child_opt(self)
2075 }
2076pub fn use_tree_list(self) -> Option<UseTreeList<'a>> {
2077 super::child_opt(self)
2078 }
2079}
2080
2081// UseTreeList
2082#[derive(Debug, Clone, Copy)]
2083pub struct UseTreeList<'a> {
2084 syntax: SyntaxNodeRef<'a>,
2085}
2086
2087impl<'a> AstNode<'a> for UseTreeList<'a> {
2088 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
2089 match syntax.kind() {
2090 USE_TREE_LIST => Some(UseTreeList { syntax }),
2091 _ => None,
2092 }
2093 }
2094 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
2095}
2096
2097impl<'a> UseTreeList<'a> {
2098 pub fn use_trees(self) -> impl Iterator<Item = UseTree<'a>> + 'a {
2099 super::children(self)
2100 }
2101}
2102
2103// WhereClause
2104#[derive(Debug, Clone, Copy)]
2105pub struct WhereClause<'a> {
2106 syntax: SyntaxNodeRef<'a>,
2107}
2108
2109impl<'a> AstNode<'a> for WhereClause<'a> {
2110 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
2111 match syntax.kind() {
2112 WHERE_CLAUSE => Some(WhereClause { syntax }),
2113 _ => None,
2114 }
2115 }
2116 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
2117}
2118
2119impl<'a> WhereClause<'a> {}
2120
2121// WhileExpr
2122#[derive(Debug, Clone, Copy)]
2123pub struct WhileExpr<'a> {
2124 syntax: SyntaxNodeRef<'a>,
2125}
2126
2127impl<'a> AstNode<'a> for WhileExpr<'a> {
2128 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
2129 match syntax.kind() {
2130 WHILE_EXPR => Some(WhileExpr { syntax }),
2131 _ => None,
2132 }
2133 }
2134 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
2135}
2136
2137impl<'a> ast::LoopBodyOwner<'a> for WhileExpr<'a> {}
2138impl<'a> WhileExpr<'a> {pub fn condition(self) -> Option<Condition<'a>> {
2139 super::child_opt(self)
2140 }
2141}
2142
diff --git a/crates/ra_syntax/src/ast/generated.rs.tera b/crates/ra_syntax/src/ast/generated.rs.tera
new file mode 100644
index 000000000..a72e9b732
--- /dev/null
+++ b/crates/ra_syntax/src/ast/generated.rs.tera
@@ -0,0 +1,83 @@
1use {
2 ast,
3 SyntaxNodeRef, AstNode,
4 SyntaxKind::*,
5};
6{% for node, methods in ast %}
7// {{ node }}
8{%- if methods.enum %}
9#[derive(Debug, Clone, Copy)]
10pub enum {{ node }}<'a> {
11{%- for kind in methods.enum %}
12 {{ kind }}({{ kind }}<'a>),
13{%- endfor %}
14}
15
16impl<'a> AstNode<'a> for {{ node }}<'a> {
17 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
18 match syntax.kind() {
19{%- for kind in methods.enum %}
20 {{ kind | SCREAM }} => Some({{ node }}::{{ kind }}({{ kind }} { syntax })),
21{%- endfor %}
22 _ => None,
23 }
24 }
25 fn syntax(self) -> SyntaxNodeRef<'a> {
26 match self {
27{%- for kind in methods.enum %}
28 {{ node }}::{{ kind }}(inner) => inner.syntax(),
29{%- endfor %}
30 }
31 }
32}
33{% else %}
34#[derive(Debug, Clone, Copy)]
35pub struct {{ node }}<'a> {
36 syntax: SyntaxNodeRef<'a>,
37}
38
39impl<'a> AstNode<'a> for {{ node }}<'a> {
40 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
41 match syntax.kind() {
42 {{ node | SCREAM }} => Some({{ node }} { syntax }),
43 _ => None,
44 }
45 }
46 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
47}
48{% endif %}
49{% if methods.traits -%}
50{%- for t in methods.traits -%}
51impl<'a> ast::{{ t }}<'a> for {{ node }}<'a> {}
52{% endfor -%}
53{%- endif -%}
54
55impl<'a> {{ node }}<'a> {
56{%- if methods.collections -%}
57{%- for m in methods.collections -%}
58{%- set method_name = m.0 -%}
59{%- set ChildName = m.1 %}
60 pub fn {{ method_name }}(self) -> impl Iterator<Item = {{ ChildName }}<'a>> + 'a {
61 super::children(self)
62 }
63{% endfor -%}
64{%- endif -%}
65
66{%- if methods.options -%}
67{%- for m in methods.options -%}
68
69{%- if m is string -%}
70{%- set method_name = m | snake -%}
71{%- set ChildName = m %}
72{%- else -%}
73{%- set method_name = m.0 -%}
74{%- set ChildName = m.1 %}
75{%- endif -%}
76
77 pub fn {{ method_name }}(self) -> Option<{{ ChildName }}<'a>> {
78 super::child_opt(self)
79 }
80{% endfor -%}
81{%- endif -%}
82}
83{% endfor %}
diff --git a/crates/ra_syntax/src/ast/mod.rs b/crates/ra_syntax/src/ast/mod.rs
new file mode 100644
index 000000000..a6da82957
--- /dev/null
+++ b/crates/ra_syntax/src/ast/mod.rs
@@ -0,0 +1,206 @@
1mod generated;
2
3use std::marker::PhantomData;
4
5use itertools::Itertools;
6use smol_str::SmolStr;
7
8use {
9 SyntaxNodeRef, SyntaxKind::*,
10 yellow::{RefRoot, SyntaxNodeChildren},
11};
12pub use self::generated::*;
13
14pub trait AstNode<'a>: Clone + Copy + 'a {
15 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self>
16 where Self: Sized;
17 fn syntax(self) -> SyntaxNodeRef<'a>;
18}
19
20pub trait NameOwner<'a>: AstNode<'a> {
21 fn name(self) -> Option<Name<'a>> {
22 child_opt(self)
23 }
24}
25
26pub trait LoopBodyOwner<'a>: AstNode<'a> {
27 fn loop_body(self) -> Option<Block<'a>> {
28 child_opt(self)
29 }
30}
31
32pub trait ArgListOwner<'a>: AstNode<'a> {
33 fn arg_list(self) -> Option<ArgList<'a>> {
34 child_opt(self)
35 }
36}
37
38pub trait FnDefOwner<'a>: AstNode<'a> {
39 fn functions(self) -> AstChildren<'a, FnDef<'a>> {
40 children(self)
41 }
42}
43
44pub trait ModuleItemOwner<'a>: AstNode<'a> {
45 fn items(self) -> AstChildren<'a, ModuleItem<'a>> {
46 children(self)
47 }
48}
49
50pub trait TypeParamsOwner<'a>: AstNode<'a> {
51 fn type_param_list(self) -> Option<TypeParamList<'a>> {
52 child_opt(self)
53 }
54
55 fn where_clause(self) -> Option<WhereClause<'a>> {
56 child_opt(self)
57 }
58}
59
60pub trait AttrsOwner<'a>: AstNode<'a> {
61 fn attrs(self) -> AstChildren<'a, Attr<'a>> {
62 children(self)
63 }
64}
65
66impl<'a> FnDef<'a> {
67 pub fn has_atom_attr(&self, atom: &str) -> bool {
68 self.attrs()
69 .filter_map(|x| x.as_atom())
70 .any(|x| x == atom)
71 }
72}
73
74impl<'a> Attr<'a> {
75 pub fn as_atom(&self) -> Option<SmolStr> {
76 let tt = self.value()?;
77 let (_bra, attr, _ket) = tt.syntax().children().collect_tuple()?;
78 if attr.kind() == IDENT {
79 Some(attr.leaf_text().unwrap())
80 } else {
81 None
82 }
83 }
84
85 pub fn as_call(&self) -> Option<(SmolStr, TokenTree<'a>)> {
86 let tt = self.value()?;
87 let (_bra, attr, args, _ket) = tt.syntax().children().collect_tuple()?;
88 let args = TokenTree::cast(args)?;
89 if attr.kind() == IDENT {
90 Some((attr.leaf_text().unwrap(), args))
91 } else {
92 None
93 }
94 }
95}
96
97impl<'a> Lifetime<'a> {
98 pub fn text(&self) -> SmolStr {
99 self.syntax().leaf_text().unwrap()
100 }
101}
102
103impl<'a> Name<'a> {
104 pub fn text(&self) -> SmolStr {
105 let ident = self.syntax().first_child()
106 .unwrap();
107 ident.leaf_text().unwrap()
108 }
109}
110
111impl<'a> NameRef<'a> {
112 pub fn text(&self) -> SmolStr {
113 let ident = self.syntax().first_child()
114 .unwrap();
115 ident.leaf_text().unwrap()
116 }
117}
118
119impl<'a> ImplItem<'a> {
120 pub fn target_type(self) -> Option<TypeRef<'a>> {
121 match self.target() {
122 (Some(t), None) | (_, Some(t)) => Some(t),
123 _ => None,
124 }
125 }
126
127 pub fn target_trait(self) -> Option<TypeRef<'a>> {
128 match self.target() {
129 (Some(t), Some(_)) => Some(t),
130 _ => None,
131 }
132 }
133
134 fn target(self) -> (Option<TypeRef<'a>>, Option<TypeRef<'a>>) {
135 let mut types = children(self);
136 let first = types.next();
137 let second = types.next();
138 (first, second)
139 }
140}
141
142impl<'a> Module<'a> {
143 pub fn has_semi(self) -> bool {
144 match self.syntax().last_child() {
145 None => false,
146 Some(node) => node.kind() == SEMI,
147 }
148 }
149}
150
151impl<'a> LetStmt<'a> {
152 pub fn has_semi(self) -> bool {
153 match self.syntax().last_child() {
154 None => false,
155 Some(node) => node.kind() == SEMI,
156 }
157 }
158}
159
160impl<'a> IfExpr<'a> {
161 pub fn then_branch(self) -> Option<Block<'a>> {
162 self.blocks().nth(0)
163 }
164 pub fn else_branch(self) -> Option<Block<'a>> {
165 self.blocks().nth(1)
166 }
167 fn blocks(self) -> AstChildren<'a, Block<'a>> {
168 children(self)
169 }
170}
171
172fn child_opt<'a, P: AstNode<'a>, C: AstNode<'a>>(parent: P) -> Option<C> {
173 children(parent).next()
174}
175
176fn children<'a, P: AstNode<'a>, C: AstNode<'a>>(parent: P) -> AstChildren<'a, C> {
177 AstChildren::new(parent.syntax())
178}
179
180
181#[derive(Debug)]
182pub struct AstChildren<'a, N> {
183 inner: SyntaxNodeChildren<RefRoot<'a>>,
184 ph: PhantomData<N>,
185}
186
187impl<'a, N> AstChildren<'a, N> {
188 fn new(parent: SyntaxNodeRef<'a>) -> Self {
189 AstChildren {
190 inner: parent.children(),
191 ph: PhantomData,
192 }
193 }
194}
195
196impl<'a, N: AstNode<'a>> Iterator for AstChildren<'a, N> {
197 type Item = N;
198 fn next(&mut self) -> Option<N> {
199 loop {
200 match N::cast(self.inner.next()?) {
201 Some(n) => return Some(n),
202 None => (),
203 }
204 }
205 }
206}
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
new file mode 100644
index 000000000..77ae4c7db
--- /dev/null
+++ b/crates/ra_syntax/src/grammar.ron
@@ -0,0 +1,538 @@
1Grammar(
2 single_byte_tokens: [
3 [";", "SEMI"],
4 [",", "COMMA"],
5 ["(", "L_PAREN"],
6 [")", "R_PAREN"],
7 ["{", "L_CURLY"],
8 ["}", "R_CURLY"],
9 ["[", "L_BRACK"],
10 ["]", "R_BRACK"],
11 ["<", "L_ANGLE"],
12 [">", "R_ANGLE"],
13 ["@", "AT"],
14 ["#", "POUND"],
15 ["~", "TILDE"],
16 ["?", "QUESTION"],
17 ["$", "DOLLAR"],
18 ["&", "AMP"],
19 ["|", "PIPE"],
20 ["+", "PLUS"],
21 ["*", "STAR"],
22 ["/", "SLASH"],
23 ["^", "CARET"],
24 ["%", "PERCENT"],
25 ],
26 multi_byte_tokens: [
27 [".", "DOT"],
28 ["..", "DOTDOT"],
29 ["...", "DOTDOTDOT"],
30 ["..=", "DOTDOTEQ"],
31 [":", "COLON"],
32 ["::", "COLONCOLON"],
33 ["=", "EQ"],
34 ["==", "EQEQ"],
35 ["=>", "FAT_ARROW"],
36 ["!", "EXCL"],
37 ["!=", "NEQ"],
38 ["-", "MINUS"],
39 ["->", "THIN_ARROW"],
40 ["<=", "LTEQ"],
41 [">=", "GTEQ"],
42 ["+=", "PLUSEQ"],
43 ["-=", "MINUSEQ"],
44 ["|=", "PIPEEQ"],
45 ["&=", "AMPEQ"],
46 ["^=", "CARETEQ"],
47 ["/=", "SLASHEQ"],
48 ["*=", "STAREQ"],
49 ["&&", "AMPAMP"],
50 ["||", "PIPEPIPE"],
51 ["<<", "SHL"],
52 [">>", "SHR"],
53 ["<<=", "SHLEQ"],
54 [">>=", "SHREQ"],
55 ],
56 keywords: [
57 "use",
58 "fn",
59 "struct",
60 "enum",
61 "trait",
62 "impl",
63 "dyn",
64 "true",
65 "false",
66 "as",
67 "extern",
68 "crate",
69 "mod",
70 "pub",
71 "self",
72 "super",
73 "in",
74 "where",
75 "for",
76 "loop",
77 "while",
78 "continue",
79 "break",
80 "if",
81 "else",
82 "match",
83 "const",
84 "static",
85 "mut",
86 "unsafe",
87 "type",
88 "ref",
89 "let",
90 "move",
91 "return",
92 ],
93 contextual_keywords: [
94 "auto",
95 "default",
96 "union",
97 ],
98 tokens: [
99 "ERROR",
100 "IDENT",
101 "UNDERSCORE",
102 "WHITESPACE",
103 "INT_NUMBER",
104 "FLOAT_NUMBER",
105 "LIFETIME",
106 "CHAR",
107 "BYTE",
108 "STRING",
109 "RAW_STRING",
110 "BYTE_STRING",
111 "RAW_BYTE_STRING",
112 "COMMENT",
113 "DOC_COMMENT",
114 "SHEBANG",
115 ],
116 nodes: [
117 "ROOT",
118
119 "STRUCT_DEF",
120 "ENUM_DEF",
121 "FN_DEF",
122 "RET_TYPE",
123 "EXTERN_CRATE_ITEM",
124 "MODULE",
125 "USE_ITEM",
126 "STATIC_DEF",
127 "CONST_DEF",
128 "TRAIT_DEF",
129 "IMPL_ITEM",
130 "TYPE_DEF",
131 "MACRO_CALL",
132 "TOKEN_TREE",
133
134 "PAREN_TYPE",
135 "TUPLE_TYPE",
136 "NEVER_TYPE",
137 "PATH_TYPE",
138 "POINTER_TYPE",
139 "ARRAY_TYPE",
140 "SLICE_TYPE",
141 "REFERENCE_TYPE",
142 "PLACEHOLDER_TYPE",
143 "FN_POINTER_TYPE",
144 "FOR_TYPE",
145 "IMPL_TRAIT_TYPE",
146 "DYN_TRAIT_TYPE",
147
148 "REF_PAT",
149 "BIND_PAT",
150 "PLACEHOLDER_PAT",
151 "PATH_PAT",
152 "STRUCT_PAT",
153 "FIELD_PAT_LIST",
154 "TUPLE_STRUCT_PAT",
155 "TUPLE_PAT",
156 "SLICE_PAT",
157 "RANGE_PAT",
158
159 // atoms
160 "TUPLE_EXPR",
161 "ARRAY_EXPR",
162 "PAREN_EXPR",
163 "PATH_EXPR",
164 "LAMBDA_EXPR",
165 "IF_EXPR",
166 "WHILE_EXPR",
167 "CONDITION",
168 "LOOP_EXPR",
169 "FOR_EXPR",
170 "CONTINUE_EXPR",
171 "BREAK_EXPR",
172 "LABEL",
173 "BLOCK_EXPR",
174 "RETURN_EXPR",
175 "MATCH_EXPR",
176 "MATCH_ARM_LIST",
177 "MATCH_ARM",
178 "MATCH_GUARD",
179 "STRUCT_LIT",
180 "NAMED_FIELD_LIST",
181 "NAMED_FIELD",
182
183 // postfix
184 "CALL_EXPR",
185 "INDEX_EXPR",
186 "METHOD_CALL_EXPR",
187 "FIELD_EXPR",
188 "TRY_EXPR",
189 "CAST_EXPR",
190
191 // unary
192 "REF_EXPR",
193 "PREFIX_EXPR",
194
195 "RANGE_EXPR", // just weird
196 "BIN_EXPR",
197
198 "BLOCK",
199 "EXTERN_BLOCK",
200 "EXTERN_ITEM_LIST",
201 "ENUM_VARIANT",
202 "NAMED_FIELD_DEF_LIST",
203 "NAMED_FIELD_DEF",
204 "POS_FIELD_LIST",
205 "POS_FIELD",
206 "ENUM_VARIANT_LIST",
207 "ITEM_LIST",
208 "ATTR",
209 "META_ITEM", // not an item actually
210 "USE_TREE",
211 "USE_TREE_LIST",
212 "PATH",
213 "PATH_SEGMENT",
214 "LITERAL",
215 "ALIAS",
216 "VISIBILITY",
217 "WHERE_CLAUSE",
218 "WHERE_PRED",
219 "ABI",
220 "NAME",
221 "NAME_REF",
222
223 "LET_STMT",
224 "EXPR_STMT",
225
226 "TYPE_PARAM_LIST",
227 "LIFETIME_PARAM",
228 "TYPE_PARAM",
229 "TYPE_ARG_LIST",
230 "LIFETIME_ARG",
231 "TYPE_ARG",
232 "ASSOC_TYPE_ARG",
233
234 "PARAM_LIST",
235 "PARAM",
236 "SELF_PARAM",
237 "ARG_LIST",
238 ],
239 ast: {
240 "Root": (
241 traits: [ "ModuleItemOwner", "FnDefOwner" ],
242 collections: [
243 ["modules", "Module"],
244 ]
245 ),
246 "FnDef": (
247 traits: [
248 "NameOwner",
249 "TypeParamsOwner",
250 "AttrsOwner",
251 ],
252 options: [ "ParamList", ["body", "Block"], "RetType" ],
253 ),
254 "RetType": (),
255 "StructDef": (
256 traits: [
257 "NameOwner",
258 "TypeParamsOwner",
259 "AttrsOwner",
260 ],
261 collections: [
262 ["fields", "NamedFieldDef"]
263 ]
264 ),
265 "NamedFieldDef": ( traits: ["NameOwner", "AttrsOwner"] ),
266 "EnumDef": ( traits: [
267 "NameOwner",
268 "TypeParamsOwner",
269 "AttrsOwner",
270 ] ),
271 "TraitDef": ( traits: ["NameOwner", "AttrsOwner"] ),
272 "Module": (
273 traits: ["NameOwner", "AttrsOwner" ],
274 options: [ "ItemList" ]
275 ),
276 "ItemList": (
277 traits: [ "FnDefOwner", "ModuleItemOwner" ],
278 ),
279 "ConstDef": ( traits: [
280 "NameOwner",
281 "TypeParamsOwner",
282 "AttrsOwner",
283 ] ),
284 "StaticDef": ( traits: [
285 "NameOwner",
286 "TypeParamsOwner",
287 "AttrsOwner",
288 ] ),
289 "TypeDef": ( traits: [
290 "NameOwner",
291 "TypeParamsOwner",
292 "AttrsOwner",
293 ] ),
294 "ImplItem": (),
295
296 "ParenType": (),
297 "TupleType": (),
298 "NeverType": (),
299 "PathType": (),
300 "PointerType": (),
301 "ArrayType": (),
302 "SliceType": (),
303 "ReferenceType": (),
304 "PlaceholderType": (),
305 "FnPointerType": (),
306 "ForType": (),
307 "ImplTraitType": (),
308 "DynTraitType": (),
309
310 "TypeRef": ( enum: [
311 "ParenType",
312 "TupleType",
313 "NeverType",
314 "PathType",
315 "PointerType",
316 "ArrayType",
317 "SliceType",
318 "ReferenceType",
319 "PlaceholderType",
320 "FnPointerType",
321 "ForType",
322 "ImplTraitType",
323 "DynTraitType",
324 ]),
325
326 "NominalDef": (
327 enum: ["StructDef", "EnumDef"],
328 traits: [
329 "NameOwner",
330 "TypeParamsOwner",
331 "AttrsOwner"
332 ],
333 ),
334 "ModuleItem": (
335 enum: ["StructDef", "EnumDef", "FnDef", "TraitDef", "TypeDef", "ImplItem",
336 "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ]
337 ),
338
339 "TupleExpr": (),
340 "ArrayExpr": (),
341 "ParenExpr": (),
342 "PathExpr": (),
343 "LambdaExpr": (
344 options: [
345 "ParamList",
346 ["body", "Expr"],
347 ]
348 ),
349 "IfExpr": (
350 options: [ "Condition" ]
351 ),
352 "LoopExpr": (
353 traits: ["LoopBodyOwner"],
354 ),
355 "ForExpr": (
356 traits: ["LoopBodyOwner"],
357 options: [
358 "Pat",
359 ["iterable", "Expr"],
360 ]
361 ),
362 "WhileExpr": (
363 traits: ["LoopBodyOwner"],
364 options: [ "Condition" ]
365 ),
366 "ContinueExpr": (),
367 "BreakExpr": (),
368 "Label": (),
369 "BlockExpr": (
370 options: [ "Block" ]
371 ),
372 "ReturnExpr": (),
373 "MatchExpr": (
374 options: [ "Expr", "MatchArmList" ],
375 ),
376 "MatchArmList": (
377 collections: [ ["arms", "MatchArm"] ],
378 ),
379 "MatchArm": (
380 options: [
381 [ "guard", "MatchGuard" ],
382 "Expr",
383 ],
384 collections: [ [ "pats", "Pat" ] ]
385 ),
386 "MatchGuard": (),
387 "StructLit": (),
388 "NamedFieldList": (),
389 "NamedField": (),
390 "CallExpr": (
391 traits: ["ArgListOwner"],
392 options: [ "Expr" ],
393 ),
394 "MethodCallExpr": (
395 traits: ["ArgListOwner"],
396 options: [ "Expr" ],
397 ),
398 "IndexExpr": (),
399 "FieldExpr": (),
400 "TryExpr": (),
401 "CastExpr": (),
402 "RefExpr": (),
403 "PrefixExpr": (),
404 "RangeExpr": (),
405 "BinExpr": (),
406 "Literal": (),
407
408 "Expr": (
409 enum: [
410 "TupleExpr",
411 "ArrayExpr",
412 "ParenExpr",
413 "PathExpr",
414 "LambdaExpr",
415 "IfExpr",
416 "LoopExpr",
417 "ForExpr",
418 "WhileExpr",
419 "ContinueExpr",
420 "BreakExpr",
421 "Label",
422 "BlockExpr",
423 "ReturnExpr",
424 "MatchExpr",
425 "MatchArmList",
426 "MatchArm",
427 "MatchGuard",
428 "StructLit",
429 "NamedFieldList",
430 "NamedField",
431 "CallExpr",
432 "IndexExpr",
433 "MethodCallExpr",
434 "FieldExpr",
435 "TryExpr",
436 "CastExpr",
437 "RefExpr",
438 "PrefixExpr",
439 "RangeExpr",
440 "BinExpr",
441 "Literal",
442 ],
443 ),
444
445 "RefPat": (),
446 "BindPat": ( traits: ["NameOwner"] ),
447 "PlaceholderPat": (),
448 "PathPat": (),
449 "StructPat": (),
450 "FieldPatList": (),
451 "TupleStructPat": (),
452 "TuplePat": (),
453 "SlicePat": (),
454 "RangePat": (),
455
456 "Pat": (
457 enum: [
458 "RefPat",
459 "BindPat",
460 "PlaceholderPat",
461 "PathPat",
462 "StructPat",
463 "FieldPatList",
464 "TupleStructPat",
465 "TuplePat",
466 "SlicePat",
467 "RangePat",
468 ],
469 ),
470
471 "Name": (),
472 "NameRef": (),
473 "Attr": ( options: [ ["value", "TokenTree"] ] ),
474 "TokenTree": (),
475 "TypeParamList": (
476 collections: [
477 ["type_params", "TypeParam" ],
478 ["lifetime_params", "LifetimeParam" ],
479 ]
480 ),
481 "TypeParam": ( traits: ["NameOwner"] ),
482 "LifetimeParam": ( options: [ "Lifetime" ] ),
483 "Lifetime": (),
484 "WhereClause": (),
485 "ExprStmt": (
486 options: [ ["expr", "Expr"] ]
487 ),
488 "LetStmt": ( options: [
489 ["pat", "Pat"],
490 ["initializer", "Expr"],
491 ]),
492 "Condition": (
493 options: [ "Pat", "Expr" ]
494 ),
495 "Stmt": (
496 enum: ["ExprStmt", "LetStmt"],
497 ),
498 "Block": (
499 options: [ "Expr" ],
500 collections: [
501 ["statements", "Stmt"],
502 ]
503 ),
504 "ParamList": (
505 options: [ "SelfParam" ],
506 collections: [
507 ["params", "Param"]
508 ]
509 ),
510 "SelfParam": (),
511 "Param": (
512 options: [ "Pat" ],
513 ),
514 "UseItem": (
515 options: [ "UseTree" ]
516 ),
517 "UseTree": (
518 options: [ "Path", "UseTreeList" ]
519 ),
520 "UseTreeList": (
521 collections: [["use_trees", "UseTree"]]
522 ),
523 "ExternCrateItem": (),
524 "ArgList": (
525 collections: [
526 ["args", "Expr"]
527 ]
528 ),
529 "Path": (
530 options: [
531 ["segment", "PathSegment"]
532 ]
533 ),
534 "PathSegment": (
535 options: [ "NameRef" ]
536 ),
537 },
538)
diff --git a/crates/ra_syntax/src/grammar/attributes.rs b/crates/ra_syntax/src/grammar/attributes.rs
new file mode 100644
index 000000000..cd30e8a45
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/attributes.rs
@@ -0,0 +1,31 @@
1use super::*;
2
3pub(super) fn inner_attributes(p: &mut Parser) {
4 while p.current() == POUND && p.nth(1) == EXCL {
5 attribute(p, true)
6 }
7}
8
9pub(super) fn outer_attributes(p: &mut Parser) {
10 while p.at(POUND) {
11 attribute(p, false)
12 }
13}
14
15fn attribute(p: &mut Parser, inner: bool) {
16 let attr = p.start();
17 assert!(p.at(POUND));
18 p.bump();
19
20 if inner {
21 assert!(p.at(EXCL));
22 p.bump();
23 }
24
25 if p.at(L_BRACK) {
26 items::token_tree(p);
27 } else {
28 p.error("expected `[`");
29 }
30 attr.complete(p, ATTR);
31}
diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs
new file mode 100644
index 000000000..f01df56bc
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/expressions/atom.rs
@@ -0,0 +1,400 @@
1use super::*;
2
3// test expr_literals
4// fn foo() {
5// let _ = true;
6// let _ = false;
7// let _ = 1;
8// let _ = 2.0;
9// let _ = b'a';
10// let _ = 'b';
11// let _ = "c";
12// let _ = r"d";
13// let _ = b"e";
14// let _ = br"f";
15// }
16pub(crate) const LITERAL_FIRST: TokenSet =
17 token_set![TRUE_KW, FALSE_KW, INT_NUMBER, FLOAT_NUMBER, BYTE, CHAR,
18 STRING, RAW_STRING, BYTE_STRING, RAW_BYTE_STRING];
19
20pub(crate) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
21 if !p.at_ts(LITERAL_FIRST) {
22 return None;
23 }
24 let m = p.start();
25 p.bump();
26 Some(m.complete(p, LITERAL))
27}
28
29pub(super) const ATOM_EXPR_FIRST: TokenSet =
30 token_set_union![
31 LITERAL_FIRST,
32 token_set![L_CURLY, L_PAREN, L_BRACK, PIPE, MOVE_KW, IF_KW, WHILE_KW, MATCH_KW, UNSAFE_KW,
33 RETURN_KW, IDENT, SELF_KW, SUPER_KW, COLONCOLON, BREAK_KW, CONTINUE_KW, LIFETIME ],
34 ];
35
36const EXPR_RECOVERY_SET: TokenSet =
37 token_set![LET_KW];
38
39pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> {
40 match literal(p) {
41 Some(m) => return Some(m),
42 None => (),
43 }
44 if paths::is_path_start(p) || p.at(L_ANGLE) {
45 return Some(path_expr(p, r));
46 }
47 let la = p.nth(1);
48 let done = match p.current() {
49 L_PAREN => tuple_expr(p),
50 L_BRACK => array_expr(p),
51 PIPE => lambda_expr(p),
52 MOVE_KW if la == PIPE => lambda_expr(p),
53 IF_KW => if_expr(p),
54
55 LOOP_KW => loop_expr(p, None),
56 FOR_KW => for_expr(p, None),
57 WHILE_KW => while_expr(p, None),
58 LIFETIME if la == COLON => {
59 let m = p.start();
60 label(p);
61 match p.current() {
62 LOOP_KW => loop_expr(p, Some(m)),
63 FOR_KW => for_expr(p, Some(m)),
64 WHILE_KW => while_expr(p, Some(m)),
65 L_CURLY => block_expr(p, Some(m)),
66 _ => {
67 // test misplaced_label_err
68 // fn main() {
69 // 'loop: impl
70 // }
71 p.error("expected a loop");
72 m.complete(p, ERROR);
73 return None;
74 }
75 }
76 }
77
78 MATCH_KW => match_expr(p),
79 UNSAFE_KW if la == L_CURLY => {
80 let m = p.start();
81 p.bump();
82 block_expr(p, Some(m))
83 },
84 L_CURLY => block_expr(p, None),
85 RETURN_KW => return_expr(p),
86 CONTINUE_KW => continue_expr(p),
87 BREAK_KW => break_expr(p),
88 _ => {
89 p.err_recover("expected expression", EXPR_RECOVERY_SET);
90 return None;
91 }
92 };
93 Some(done)
94}
95
96// test tuple_expr
97// fn foo() {
98// ();
99// (1);
100// (1,);
101// }
102fn tuple_expr(p: &mut Parser) -> CompletedMarker {
103 assert!(p.at(L_PAREN));
104 let m = p.start();
105 p.expect(L_PAREN);
106
107 let mut saw_comma = false;
108 let mut saw_expr = false;
109 while !p.at(EOF) && !p.at(R_PAREN) {
110 saw_expr = true;
111 if !p.at_ts(EXPR_FIRST) {
112 p.error("expected expression");
113 break;
114 }
115 expr(p);
116 if !p.at(R_PAREN) {
117 saw_comma = true;
118 p.expect(COMMA);
119 }
120 }
121 p.expect(R_PAREN);
122 m.complete(p, if saw_expr && !saw_comma { PAREN_EXPR } else { TUPLE_EXPR })
123}
124
125// test array_expr
126// fn foo() {
127// [];
128// [1];
129// [1, 2,];
130// [1; 2];
131// }
132fn array_expr(p: &mut Parser) -> CompletedMarker {
133 assert!(p.at(L_BRACK));
134 let m = p.start();
135 p.bump();
136 if p.eat(R_BRACK) {
137 return m.complete(p, ARRAY_EXPR);
138 }
139 expr(p);
140 if p.eat(SEMI) {
141 expr(p);
142 p.expect(R_BRACK);
143 return m.complete(p, ARRAY_EXPR);
144 }
145 while !p.at(EOF) && !p.at(R_BRACK) {
146 p.expect(COMMA);
147 if p.at(R_BRACK) {
148 break;
149 }
150 if !p.at_ts(EXPR_FIRST) {
151 p.error("expected expression");
152 break;
153 }
154 expr(p);
155 }
156 p.expect(R_BRACK);
157 m.complete(p, ARRAY_EXPR)
158}
159
160// test lambda_expr
161// fn foo() {
162// || ();
163// || -> i32 { 92 };
164// |x| x;
165// move |x: i32,| x;
166// }
167fn lambda_expr(p: &mut Parser) -> CompletedMarker {
168 assert!(p.at(PIPE) || (p.at(MOVE_KW) && p.nth(1) == PIPE));
169 let m = p.start();
170 p.eat(MOVE_KW);
171 params::param_list_opt_types(p);
172 if opt_fn_ret_type(p) {
173 if !p.at(L_CURLY) {
174 p.error("expected `{`");
175 }
176 }
177 expr(p);
178 m.complete(p, LAMBDA_EXPR)
179}
180
181// test if_expr
182// fn foo() {
183// if true {};
184// if true {} else {};
185// if true {} else if false {} else {};
186// if S {};
187// }
188fn if_expr(p: &mut Parser) -> CompletedMarker {
189 assert!(p.at(IF_KW));
190 let m = p.start();
191 p.bump();
192 cond(p);
193 block(p);
194 if p.at(ELSE_KW) {
195 p.bump();
196 if p.at(IF_KW) {
197 if_expr(p);
198 } else {
199 block(p);
200 }
201 }
202 m.complete(p, IF_EXPR)
203}
204
205// test label
206// fn foo() {
207// 'a: loop {}
208// 'b: while true {}
209// 'c: for x in () {}
210// }
211fn label(p: &mut Parser) {
212 assert!(p.at(LIFETIME) && p.nth(1) == COLON);
213 let m = p.start();
214 p.bump();
215 p.bump();
216 m.complete(p, LABEL);
217}
218
219// test loop_expr
220// fn foo() {
221// loop {};
222// }
223fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
224 assert!(p.at(LOOP_KW));
225 let m = m.unwrap_or_else(|| p.start());
226 p.bump();
227 block(p);
228 m.complete(p, LOOP_EXPR)
229}
230
231// test while_expr
232// fn foo() {
233// while true {};
234// while let Some(x) = it.next() {};
235// }
236fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
237 assert!(p.at(WHILE_KW));
238 let m = m.unwrap_or_else(|| p.start());
239 p.bump();
240 cond(p);
241 block(p);
242 m.complete(p, WHILE_EXPR)
243}
244
245// test for_expr
246// fn foo() {
247// for x in [] {};
248// }
249fn for_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
250 assert!(p.at(FOR_KW));
251 let m = m.unwrap_or_else(|| p.start());
252 p.bump();
253 patterns::pattern(p);
254 p.expect(IN_KW);
255 expr_no_struct(p);
256 block(p);
257 m.complete(p, FOR_EXPR)
258}
259
260// test cond
261// fn foo() { if let Some(_) = None {} }
262fn cond(p: &mut Parser) {
263 let m = p.start();
264 if p.eat(LET_KW) {
265 patterns::pattern(p);
266 p.expect(EQ);
267 }
268 expr_no_struct(p);
269 m.complete(p, CONDITION);
270}
271
272// test match_expr
273// fn foo() {
274// match () { };
275// match S {};
276// }
277fn match_expr(p: &mut Parser) -> CompletedMarker {
278 assert!(p.at(MATCH_KW));
279 let m = p.start();
280 p.bump();
281 expr_no_struct(p);
282 if p.at(L_CURLY) {
283 match_arm_list(p);
284 } else {
285 p.error("expected `{`")
286 }
287 m.complete(p, MATCH_EXPR)
288}
289
290pub(crate) fn match_arm_list(p: &mut Parser) {
291 assert!(p.at(L_CURLY));
292 let m = p.start();
293 p.eat(L_CURLY);
294 while !p.at(EOF) && !p.at(R_CURLY) {
295 if p.at(L_CURLY) {
296 error_block(p, "expected match arm");
297 continue;
298 }
299 // test match_arms_commas
300 // fn foo() {
301 // match () {
302 // _ => (),
303 // _ => {}
304 // _ => ()
305 // }
306 // }
307 if match_arm(p).is_block() {
308 p.eat(COMMA);
309 } else if !p.at(R_CURLY) {
310 p.expect(COMMA);
311 }
312 }
313 p.expect(R_CURLY);
314 m.complete(p, MATCH_ARM_LIST);
315}
316
317// test match_arm
318// fn foo() {
319// match () {
320// _ => (),
321// X | Y if Z => (),
322// };
323// }
324fn match_arm(p: &mut Parser) -> BlockLike {
325 let m = p.start();
326 patterns::pattern_r(p, TokenSet::EMPTY);
327 while p.eat(PIPE) {
328 patterns::pattern(p);
329 }
330 if p.eat(IF_KW) {
331 expr_no_struct(p);
332 }
333 p.expect(FAT_ARROW);
334 let ret = expr_stmt(p);
335 m.complete(p, MATCH_ARM);
336 ret
337}
338
339// test block_expr
340// fn foo() {
341// {};
342// unsafe {};
343// 'label: {};
344// }
345fn block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
346 assert!(p.at(L_CURLY));
347 let m = m.unwrap_or_else(|| p.start());
348 block(p);
349 m.complete(p, BLOCK_EXPR)
350}
351
352// test return_expr
353// fn foo() {
354// return;
355// return 92;
356// }
357fn return_expr(p: &mut Parser) -> CompletedMarker {
358 assert!(p.at(RETURN_KW));
359 let m = p.start();
360 p.bump();
361 if p.at_ts(EXPR_FIRST) {
362 expr(p);
363 }
364 m.complete(p, RETURN_EXPR)
365}
366
367// test continue_expr
368// fn foo() {
369// loop {
370// continue;
371// continue 'l;
372// }
373// }
374fn continue_expr(p: &mut Parser) -> CompletedMarker {
375 assert!(p.at(CONTINUE_KW));
376 let m = p.start();
377 p.bump();
378 p.eat(LIFETIME);
379 m.complete(p, CONTINUE_EXPR)
380}
381
382// test break_expr
383// fn foo() {
384// loop {
385// break;
386// break 'l;
387// break 92;
388// break 'l 92;
389// }
390// }
391fn break_expr(p: &mut Parser) -> CompletedMarker {
392 assert!(p.at(BREAK_KW));
393 let m = p.start();
394 p.bump();
395 p.eat(LIFETIME);
396 if p.at_ts(EXPR_FIRST) {
397 expr(p);
398 }
399 m.complete(p, BREAK_EXPR)
400}
diff --git a/crates/ra_syntax/src/grammar/expressions/mod.rs b/crates/ra_syntax/src/grammar/expressions/mod.rs
new file mode 100644
index 000000000..20e0fa328
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/expressions/mod.rs
@@ -0,0 +1,450 @@
1mod atom;
2
3use super::*;
4pub(super) use self::atom::{literal, LITERAL_FIRST};
5pub(crate) use self::atom::match_arm_list;
6
7const EXPR_FIRST: TokenSet = LHS_FIRST;
8
9pub(super) fn expr(p: &mut Parser) -> BlockLike {
10 let r = Restrictions { forbid_structs: false, prefer_stmt: false };
11 expr_bp(p, r, 1)
12}
13
14pub(super) fn expr_stmt(p: &mut Parser) -> BlockLike {
15 let r = Restrictions { forbid_structs: false, prefer_stmt: true };
16 expr_bp(p, r, 1)
17}
18
19fn expr_no_struct(p: &mut Parser) {
20 let r = Restrictions { forbid_structs: true, prefer_stmt: false };
21 expr_bp(p, r, 1);
22}
23
24// test block
25// fn a() {}
26// fn b() { let _ = 1; }
27// fn c() { 1; 2; }
28// fn d() { 1; 2 }
29pub(crate) fn block(p: &mut Parser) {
30 if !p.at(L_CURLY) {
31 p.error("expected a block");
32 return;
33 }
34 let m = p.start();
35 p.bump();
36 while !p.at(EOF) && !p.at(R_CURLY) {
37 match p.current() {
38 LET_KW => let_stmt(p),
39 _ => {
40 // test block_items
41 // fn a() { fn b() {} }
42 let m = p.start();
43 match items::maybe_item(p, items::ItemFlavor::Mod) {
44 items::MaybeItem::Item(kind) => {
45 m.complete(p, kind);
46 }
47 items::MaybeItem::Modifiers => {
48 m.abandon(p);
49 p.error("expected an item");
50 }
51 // test pub_expr
52 // fn foo() { pub 92; } //FIXME
53 items::MaybeItem::None => {
54 let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block;
55 if p.at(R_CURLY) {
56 m.abandon(p);
57 } else {
58 if is_blocklike {
59 p.eat(SEMI);
60 } else {
61 p.expect(SEMI);
62 }
63 m.complete(p, EXPR_STMT);
64 }
65 }
66 }
67 }
68 }
69 }
70 p.expect(R_CURLY);
71 m.complete(p, BLOCK);
72
73 // test let_stmt;
74 // fn foo() {
75 // let a;
76 // let b: i32;
77 // let c = 92;
78 // let d: i32 = 92;
79 // }
80 fn let_stmt(p: &mut Parser) {
81 assert!(p.at(LET_KW));
82 let m = p.start();
83 p.bump();
84 patterns::pattern(p);
85 if p.at(COLON) {
86 types::ascription(p);
87 }
88 if p.eat(EQ) {
89 expressions::expr(p);
90 }
91 p.expect(SEMI);
92 m.complete(p, LET_STMT);
93 }
94}
95
96#[derive(Clone, Copy)]
97struct Restrictions {
98 forbid_structs: bool,
99 prefer_stmt: bool,
100}
101
102enum Op {
103 Simple,
104 Composite(SyntaxKind, u8),
105}
106
107fn current_op(p: &Parser) -> (u8, Op) {
108 if let Some(t) = p.next3() {
109 match t {
110 (L_ANGLE, L_ANGLE, EQ) =>
111 return (1, Op::Composite(SHLEQ, 3)),
112 (R_ANGLE, R_ANGLE, EQ) =>
113 return (1, Op::Composite(SHREQ, 3)),
114 _ => (),
115 }
116 }
117
118 if let Some(t) = p.next2() {
119 match t {
120 (PLUS, EQ) => return (1, Op::Composite(PLUSEQ, 2)),
121 (MINUS, EQ) => return (1, Op::Composite(MINUSEQ, 2)),
122 (STAR, EQ) => return (1, Op::Composite(STAREQ, 2)),
123 (SLASH, EQ) => return (1, Op::Composite(SLASHEQ, 2)),
124 (PIPE, EQ) => return (1, Op::Composite(PIPEEQ, 2)),
125 (AMP, EQ) => return (1, Op::Composite(AMPEQ, 2)),
126 (CARET, EQ) => return (1, Op::Composite(CARETEQ, 2)),
127 (PIPE, PIPE) => return (3, Op::Composite(PIPEPIPE, 2)),
128 (AMP, AMP) => return (4, Op::Composite(AMPAMP, 2)),
129 (L_ANGLE, EQ) => return (5, Op::Composite(LTEQ, 2)),
130 (R_ANGLE, EQ) => return (5, Op::Composite(GTEQ, 2)),
131 (L_ANGLE, L_ANGLE) => return (9, Op::Composite(SHL, 2)),
132 (R_ANGLE, R_ANGLE) => return (9, Op::Composite(SHR, 2)),
133 _ => (),
134 }
135 }
136
137 let bp = match p.current() {
138 EQ => 1,
139 DOTDOT => 2,
140 EQEQ | NEQ | L_ANGLE | R_ANGLE => 5,
141 PIPE => 6,
142 CARET => 7,
143 AMP => 8,
144 MINUS | PLUS => 10,
145 STAR | SLASH | PERCENT => 11,
146 _ => 0,
147 };
148 (bp, Op::Simple)
149}
150
151// Parses expression with binding power of at least bp.
152fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike {
153 let mut lhs = match lhs(p, r) {
154 Some(lhs) => {
155 // test stmt_bin_expr_ambiguity
156 // fn foo() {
157 // let _ = {1} & 2;
158 // {1} &2;
159 // }
160 if r.prefer_stmt && is_block(lhs.kind()) {
161 return BlockLike::Block;
162 }
163 lhs
164 }
165 None => return BlockLike::NotBlock,
166 };
167
168 loop {
169 let is_range = p.current() == DOTDOT;
170 let (op_bp, op) = current_op(p);
171 if op_bp < bp {
172 break;
173 }
174 let m = lhs.precede(p);
175 match op {
176 Op::Simple => p.bump(),
177 Op::Composite(kind, n) => {
178 p.bump_compound(kind, n);
179 }
180 }
181 expr_bp(p, r, op_bp + 1);
182 lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR });
183 }
184 BlockLike::NotBlock
185}
186
187// test no_semi_after_block
188// fn foo() {
189// if true {}
190// loop {}
191// match () {}
192// while true {}
193// for _ in () {}
194// {}
195// {}
196// }
197fn is_block(kind: SyntaxKind) -> bool {
198 match kind {
199 IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => true,
200 _ => false,
201 }
202}
203
204const LHS_FIRST: TokenSet =
205 token_set_union![
206 token_set![AMP, STAR, EXCL, DOTDOT, MINUS],
207 atom::ATOM_EXPR_FIRST,
208 ];
209
210fn lhs(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> {
211 let m;
212 let kind = match p.current() {
213 // test ref_expr
214 // fn foo() {
215 // let _ = &1;
216 // let _ = &mut &f();
217 // }
218 AMP => {
219 m = p.start();
220 p.bump();
221 p.eat(MUT_KW);
222 REF_EXPR
223 }
224 // test unary_expr
225 // fn foo() {
226 // **&1;
227 // !!true;
228 // --1;
229 // }
230 STAR | EXCL | MINUS => {
231 m = p.start();
232 p.bump();
233 PREFIX_EXPR
234 }
235 // test full_range_expr
236 // fn foo() { xs[..]; }
237 DOTDOT => {
238 m = p.start();
239 p.bump();
240 if p.at_ts(EXPR_FIRST) {
241 expr_bp(p, r, 2);
242 }
243 return Some(m.complete(p, RANGE_EXPR));
244 }
245 _ => {
246 let lhs = atom::atom_expr(p, r)?;
247 return Some(postfix_expr(p, r, lhs));
248 }
249 };
250 expr_bp(p, r, 255);
251 Some(m.complete(p, kind))
252}
253
254fn postfix_expr(p: &mut Parser, r: Restrictions, mut lhs: CompletedMarker) -> CompletedMarker {
255 let mut allow_calls = !r.prefer_stmt || !is_block(lhs.kind());
256 loop {
257 lhs = match p.current() {
258 // test stmt_postfix_expr_ambiguity
259 // fn foo() {
260 // match () {
261 // _ => {}
262 // () => {}
263 // [] => {}
264 // }
265 // }
266 L_PAREN if allow_calls => call_expr(p, lhs),
267 L_BRACK if allow_calls => index_expr(p, lhs),
268 DOT if p.nth(1) == IDENT => if p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON {
269 method_call_expr(p, lhs)
270 } else {
271 field_expr(p, lhs)
272 },
273 DOT if p.nth(1) == INT_NUMBER => field_expr(p, lhs),
274 // test postfix_range
275 // fn foo() { let x = 1..; }
276 DOTDOT if !EXPR_FIRST.contains(p.nth(1)) => {
277 let m = lhs.precede(p);
278 p.bump();
279 m.complete(p, RANGE_EXPR)
280 }
281 QUESTION => try_expr(p, lhs),
282 AS_KW => cast_expr(p, lhs),
283 _ => break,
284 };
285 allow_calls = true
286 }
287 lhs
288}
289
290// test call_expr
291// fn foo() {
292// let _ = f();
293// let _ = f()(1)(1, 2,);
294// }
295fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
296 assert!(p.at(L_PAREN));
297 let m = lhs.precede(p);
298 arg_list(p);
299 m.complete(p, CALL_EXPR)
300}
301
302// test index_expr
303// fn foo() {
304// x[1][2];
305// }
306fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
307 assert!(p.at(L_BRACK));
308 let m = lhs.precede(p);
309 p.bump();
310 expr(p);
311 p.expect(R_BRACK);
312 m.complete(p, INDEX_EXPR)
313}
314
315// test method_call_expr
316// fn foo() {
317// x.foo();
318// y.bar::<T>(1, 2,);
319// }
320fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
321 assert!(
322 p.at(DOT) && p.nth(1) == IDENT
323 && (p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON)
324 );
325 let m = lhs.precede(p);
326 p.bump();
327 name_ref(p);
328 type_args::opt_type_arg_list(p, true);
329 if p.at(L_PAREN) {
330 arg_list(p);
331 }
332 m.complete(p, METHOD_CALL_EXPR)
333}
334
335// test field_expr
336// fn foo() {
337// x.foo;
338// x.0.bar;
339// }
340fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
341 assert!(p.at(DOT) && (p.nth(1) == IDENT || p.nth(1) == INT_NUMBER));
342 let m = lhs.precede(p);
343 p.bump();
344 if p.at(IDENT) {
345 name_ref(p)
346 } else {
347 p.bump()
348 }
349 m.complete(p, FIELD_EXPR)
350}
351
352// test try_expr
353// fn foo() {
354// x?;
355// }
356fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
357 assert!(p.at(QUESTION));
358 let m = lhs.precede(p);
359 p.bump();
360 m.complete(p, TRY_EXPR)
361}
362
363// test cast_expr
364// fn foo() {
365// 82 as i32;
366// }
367fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
368 assert!(p.at(AS_KW));
369 let m = lhs.precede(p);
370 p.bump();
371 types::type_(p);
372 m.complete(p, CAST_EXPR)
373}
374
375fn arg_list(p: &mut Parser) {
376 assert!(p.at(L_PAREN));
377 let m = p.start();
378 p.bump();
379 while !p.at(R_PAREN) && !p.at(EOF) {
380 if !p.at_ts(EXPR_FIRST) {
381 p.error("expected expression");
382 break;
383 }
384 expr(p);
385 if !p.at(R_PAREN) && !p.expect(COMMA) {
386 break;
387 }
388 }
389 p.eat(R_PAREN);
390 m.complete(p, ARG_LIST);
391}
392
393// test path_expr
394// fn foo() {
395// let _ = a;
396// let _ = a::b;
397// let _ = ::a::<b>;
398// let _ = format!();
399// }
400fn path_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker {
401 assert!(paths::is_path_start(p) || p.at(L_ANGLE));
402 let m = p.start();
403 paths::expr_path(p);
404 match p.current() {
405 L_CURLY if !r.forbid_structs => {
406 named_field_list(p);
407 m.complete(p, STRUCT_LIT)
408 }
409 EXCL => {
410 items::macro_call_after_excl(p);
411 m.complete(p, MACRO_CALL)
412 }
413 _ => m.complete(p, PATH_EXPR)
414 }
415}
416
417// test struct_lit
418// fn foo() {
419// S {};
420// S { x, y: 32, };
421// S { x, y: 32, ..Default::default() };
422// }
423pub(crate) fn named_field_list(p: &mut Parser) {
424 assert!(p.at(L_CURLY));
425 let m = p.start();
426 p.bump();
427 while !p.at(EOF) && !p.at(R_CURLY) {
428 match p.current() {
429 IDENT => {
430 let m = p.start();
431 name_ref(p);
432 if p.eat(COLON) {
433 expr(p);
434 }
435 m.complete(p, NAMED_FIELD);
436 }
437 DOTDOT => {
438 p.bump();
439 expr(p);
440 }
441 L_CURLY => error_block(p, "expected a field"),
442 _ => p.err_and_bump("expected identifier"),
443 }
444 if !p.at(R_CURLY) {
445 p.expect(COMMA);
446 }
447 }
448 p.expect(R_CURLY);
449 m.complete(p, NAMED_FIELD_LIST);
450}
diff --git a/crates/ra_syntax/src/grammar/items/consts.rs b/crates/ra_syntax/src/grammar/items/consts.rs
new file mode 100644
index 000000000..5a5852f83
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/items/consts.rs
@@ -0,0 +1,21 @@
1use super::*;
2
3pub(super) fn static_def(p: &mut Parser) {
4 const_or_static(p, STATIC_KW)
5}
6
7pub(super) fn const_def(p: &mut Parser) {
8 const_or_static(p, CONST_KW)
9}
10
11fn const_or_static(p: &mut Parser, kw: SyntaxKind) {
12 assert!(p.at(kw));
13 p.bump();
14 p.eat(MUT_KW); // TODO: validator to forbid const mut
15 name(p);
16 types::ascription(p);
17 if p.eat(EQ) {
18 expressions::expr(p);
19 }
20 p.expect(SEMI);
21}
diff --git a/crates/ra_syntax/src/grammar/items/mod.rs b/crates/ra_syntax/src/grammar/items/mod.rs
new file mode 100644
index 000000000..2567313ab
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/items/mod.rs
@@ -0,0 +1,393 @@
1
2mod consts;
3mod nominal;
4mod traits;
5mod use_item;
6
7use super::*;
8pub(crate) use self::{
9 expressions::{named_field_list, match_arm_list},
10 nominal::{enum_variant_list, named_field_def_list},
11 traits::{trait_item_list, impl_item_list},
12 use_item::use_tree_list,
13};
14
15// test mod_contents
16// fn foo() {}
17// macro_rules! foo {}
18// foo::bar!();
19// super::baz! {}
20// struct S;
21pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) {
22 attributes::inner_attributes(p);
23 while !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) {
24 item_or_macro(p, stop_on_r_curly, ItemFlavor::Mod)
25 }
26}
27
28pub(super) enum ItemFlavor {
29 Mod, Trait
30}
31
32const ITEM_RECOVERY_SET: TokenSet =
33 token_set![FN_KW, STRUCT_KW, ENUM_KW, IMPL_KW, TRAIT_KW, CONST_KW, STATIC_KW, LET_KW,
34 MOD_KW, PUB_KW, CRATE_KW];
35
36pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) {
37 let m = p.start();
38 match maybe_item(p, flavor) {
39 MaybeItem::Item(kind) => {
40 m.complete(p, kind);
41 }
42 MaybeItem::None => {
43 if paths::is_path_start(p) {
44 match macro_call(p) {
45 BlockLike::Block => (),
46 BlockLike::NotBlock => {
47 p.expect(SEMI);
48 }
49 }
50 m.complete(p, MACRO_CALL);
51 } else {
52 m.abandon(p);
53 if p.at(L_CURLY) {
54 error_block(p, "expected an item");
55 } else if p.at(R_CURLY) && !stop_on_r_curly {
56 let e = p.start();
57 p.error("unmatched `}`");
58 p.bump();
59 e.complete(p, ERROR);
60 } else if !p.at(EOF) && !p.at(R_CURLY) {
61 p.err_and_bump("expected an item");
62 } else {
63 p.error("expected an item");
64 }
65 }
66 }
67 MaybeItem::Modifiers => {
68 p.error("expected fn, trait or impl");
69 m.complete(p, ERROR);
70 }
71 }
72}
73
74pub(super) enum MaybeItem {
75 None,
76 Item(SyntaxKind),
77 Modifiers,
78}
79
80pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
81 attributes::outer_attributes(p);
82 opt_visibility(p);
83 if let Some(kind) = items_without_modifiers(p) {
84 return MaybeItem::Item(kind);
85 }
86
87 let mut has_mods = false;
88 // modifiers
89 has_mods |= p.eat(CONST_KW);
90
91 // test unsafe_block_in_mod
92 // fn foo(){} unsafe { } fn bar(){}
93 if p.at(UNSAFE_KW) && p.nth(1) != L_CURLY {
94 p.eat(UNSAFE_KW);
95 has_mods = true;
96 }
97 if p.at(EXTERN_KW) {
98 has_mods = true;
99 abi(p);
100 }
101 if p.at(IDENT) && p.at_contextual_kw("auto") && p.nth(1) == TRAIT_KW {
102 p.bump_remap(AUTO_KW);
103 has_mods = true;
104 }
105 if p.at(IDENT) && p.at_contextual_kw("default") && p.nth(1) == IMPL_KW {
106 p.bump_remap(DEFAULT_KW);
107 has_mods = true;
108 }
109
110 // items
111 let kind = match p.current() {
112 // test extern_fn
113 // extern fn foo() {}
114
115 // test const_fn
116 // const fn foo() {}
117
118 // test const_unsafe_fn
119 // const unsafe fn foo() {}
120
121 // test unsafe_extern_fn
122 // unsafe extern "C" fn foo() {}
123
124 // test unsafe_fn
125 // unsafe fn foo() {}
126 FN_KW => {
127 fn_def(p, flavor);
128 FN_DEF
129 }
130
131 // test unsafe_trait
132 // unsafe trait T {}
133
134 // test auto_trait
135 // auto trait T {}
136
137 // test unsafe_auto_trait
138 // unsafe auto trait T {}
139 TRAIT_KW => {
140 traits::trait_def(p);
141 TRAIT_DEF
142 }
143
144 // test unsafe_impl
145 // unsafe impl Foo {}
146
147 // test default_impl
148 // default impl Foo {}
149
150 // test unsafe_default_impl
151 // unsafe default impl Foo {}
152 IMPL_KW => {
153 traits::impl_item(p);
154 IMPL_ITEM
155 }
156 _ => return if has_mods {
157 MaybeItem::Modifiers
158 } else {
159 MaybeItem::None
160 }
161 };
162
163 MaybeItem::Item(kind)
164}
165
166fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {
167 let la = p.nth(1);
168 let kind = match p.current() {
169 // test extern_crate
170 // extern crate foo;
171 EXTERN_KW if la == CRATE_KW => {
172 extern_crate_item(p);
173 EXTERN_CRATE_ITEM
174 }
175 TYPE_KW => {
176 type_def(p);
177 TYPE_DEF
178 }
179 MOD_KW => {
180 mod_item(p);
181 MODULE
182 }
183 STRUCT_KW => {
184 // test struct_items
185 // struct Foo;
186 // struct Foo {}
187 // struct Foo();
188 // struct Foo(String, usize);
189 // struct Foo {
190 // a: i32,
191 // b: f32,
192 // }
193 nominal::struct_def(p, STRUCT_KW);
194 if p.at(SEMI) {
195 p.err_and_bump(
196 "expected item, found `;`\n\
197 consider removing this semicolon"
198 );
199 }
200 STRUCT_DEF
201 }
202 IDENT if p.at_contextual_kw("union") => {
203 // test union_items
204 // union Foo {}
205 // union Foo {
206 // a: i32,
207 // b: f32,
208 // }
209 nominal::struct_def(p, UNION_KW);
210 STRUCT_DEF
211 }
212 ENUM_KW => {
213 nominal::enum_def(p);
214 ENUM_DEF
215 }
216 USE_KW => {
217 use_item::use_item(p);
218 USE_ITEM
219 }
220 CONST_KW if (la == IDENT || la == MUT_KW) => {
221 consts::const_def(p);
222 CONST_DEF
223 }
224 STATIC_KW => {
225 consts::static_def(p);
226 STATIC_DEF
227 }
228 // test extern_block
229 // extern {}
230 EXTERN_KW if la == L_CURLY || ((la == STRING || la == RAW_STRING) && p.nth(2) == L_CURLY) => {
231 abi(p);
232 extern_item_list(p);
233 EXTERN_BLOCK
234 }
235 _ => return None,
236 };
237 Some(kind)
238}
239
240fn extern_crate_item(p: &mut Parser) {
241 assert!(p.at(EXTERN_KW));
242 p.bump();
243 assert!(p.at(CRATE_KW));
244 p.bump();
245 name(p);
246 opt_alias(p);
247 p.expect(SEMI);
248}
249
250pub(crate) fn extern_item_list(p: &mut Parser) {
251 assert!(p.at(L_CURLY));
252 let m = p.start();
253 p.bump();
254 mod_contents(p, true);
255 p.expect(R_CURLY);
256 m.complete(p, EXTERN_ITEM_LIST);
257}
258
259fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
260 assert!(p.at(FN_KW));
261 p.bump();
262
263 name_r(p, ITEM_RECOVERY_SET);
264 // test function_type_params
265 // fn foo<T: Clone + Copy>(){}
266 type_params::opt_type_param_list(p);
267
268 if p.at(L_PAREN) {
269 match flavor {
270 ItemFlavor::Mod =>
271 params::param_list(p),
272 ItemFlavor::Trait =>
273 params::param_list_opt_patterns(p),
274 }
275 } else {
276 p.error("expected function arguments");
277 }
278 // test function_ret_type
279 // fn foo() {}
280 // fn bar() -> () {}
281 opt_fn_ret_type(p);
282
283 // test function_where_clause
284 // fn foo<T>() where T: Copy {}
285 type_params::opt_where_clause(p);
286
287 // test fn_decl
288 // trait T { fn foo(); }
289 if p.at(SEMI) {
290 p.bump();
291 } else {
292 expressions::block(p)
293 }
294}
295
296// test type_item
297// type Foo = Bar;
298fn type_def(p: &mut Parser) {
299 assert!(p.at(TYPE_KW));
300 p.bump();
301
302 name(p);
303
304 // test type_item_type_params
305 // type Result<T> = ();
306 type_params::opt_type_param_list(p);
307
308 if p.at(COLON) {
309 type_params::bounds(p);
310 }
311
312 // test type_item_where_clause
313 // type Foo where Foo: Copy = ();
314 type_params::opt_where_clause(p);
315
316 if p.eat(EQ) {
317 types::type_(p);
318 }
319 p.expect(SEMI);
320}
321
322pub(crate) fn mod_item(p: &mut Parser) {
323 assert!(p.at(MOD_KW));
324 p.bump();
325
326 name(p);
327 if p.at(L_CURLY) {
328 mod_item_list(p);
329 } else if !p.eat(SEMI) {
330 p.error("expected `;` or `{`");
331 }
332}
333
334pub(crate) fn mod_item_list(p: &mut Parser) {
335 assert!(p.at(L_CURLY));
336 let m = p.start();
337 p.bump();
338 mod_contents(p, true);
339 p.expect(R_CURLY);
340 m.complete(p, ITEM_LIST);
341}
342
343fn macro_call(p: &mut Parser) -> BlockLike {
344 assert!(paths::is_path_start(p));
345 paths::use_path(p);
346 macro_call_after_excl(p)
347}
348
349pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike {
350 p.expect(EXCL);
351 p.eat(IDENT);
352 let flavor = match p.current() {
353 L_CURLY => {
354 token_tree(p);
355 BlockLike::Block
356 }
357 L_PAREN | L_BRACK => {
358 token_tree(p);
359 BlockLike::NotBlock
360 }
361 _ => {
362 p.error("expected `{`, `[`, `(`");
363 BlockLike::NotBlock
364 },
365 };
366
367 flavor
368}
369
370pub(crate) fn token_tree(p: &mut Parser) {
371 let closing_paren_kind = match p.current() {
372 L_CURLY => R_CURLY,
373 L_PAREN => R_PAREN,
374 L_BRACK => R_BRACK,
375 _ => unreachable!(),
376 };
377 let m = p.start();
378 p.bump();
379 while !p.at(EOF) && !p.at(closing_paren_kind) {
380 match p.current() {
381 L_CURLY | L_PAREN | L_BRACK => token_tree(p),
382 R_CURLY => {
383 p.error("unmatched `}`");
384 m.complete(p, TOKEN_TREE);
385 return;
386 }
387 R_PAREN | R_BRACK => p.err_and_bump("unmatched brace"),
388 _ => p.bump()
389 }
390 };
391 p.expect(closing_paren_kind);
392 m.complete(p, TOKEN_TREE);
393}
diff --git a/crates/ra_syntax/src/grammar/items/nominal.rs b/crates/ra_syntax/src/grammar/items/nominal.rs
new file mode 100644
index 000000000..8d02ad555
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/items/nominal.rs
@@ -0,0 +1,154 @@
1use super::*;
2
3pub(super) fn struct_def(p: &mut Parser, kind: SyntaxKind) {
4 assert!(p.at(STRUCT_KW) || p.at_contextual_kw("union"));
5 p.bump_remap(kind);
6
7 name_r(p, ITEM_RECOVERY_SET);
8 type_params::opt_type_param_list(p);
9 match p.current() {
10 WHERE_KW => {
11 type_params::opt_where_clause(p);
12 match p.current() {
13 SEMI => {
14 p.bump();
15 return;
16 }
17 L_CURLY => named_field_def_list(p),
18 _ => {
19 //TODO: special case `(` error message
20 p.error("expected `;` or `{`");
21 return;
22 }
23 }
24 }
25 SEMI if kind == STRUCT_KW => {
26 p.bump();
27 return;
28 }
29 L_CURLY => named_field_def_list(p),
30 L_PAREN if kind == STRUCT_KW => {
31 pos_field_list(p);
32 p.expect(SEMI);
33 }
34 _ if kind == STRUCT_KW => {
35 p.error("expected `;`, `{`, or `(`");
36 return;
37 }
38 _ => {
39 p.error("expected `{`");
40 return;
41 }
42 }
43}
44
45pub(super) fn enum_def(p: &mut Parser) {
46 assert!(p.at(ENUM_KW));
47 p.bump();
48 name_r(p, ITEM_RECOVERY_SET);
49 type_params::opt_type_param_list(p);
50 type_params::opt_where_clause(p);
51 if p.at(L_CURLY) {
52 enum_variant_list(p);
53 } else {
54 p.error("expected `{`")
55 }
56}
57
58pub(crate) fn enum_variant_list(p: &mut Parser) {
59 assert!(p.at(L_CURLY));
60 let m = p.start();
61 p.bump();
62 while !p.at(EOF) && !p.at(R_CURLY) {
63 if p.at(L_CURLY) {
64 error_block(p, "expected enum variant");
65 continue;
66 }
67 let var = p.start();
68 attributes::outer_attributes(p);
69 if p.at(IDENT) {
70 name(p);
71 match p.current() {
72 L_CURLY => named_field_def_list(p),
73 L_PAREN => pos_field_list(p),
74 EQ => {
75 p.bump();
76 expressions::expr(p);
77 }
78 _ => (),
79 }
80 var.complete(p, ENUM_VARIANT);
81 } else {
82 var.abandon(p);
83 p.err_and_bump("expected enum variant");
84 }
85 if !p.at(R_CURLY) {
86 p.expect(COMMA);
87 }
88 }
89 p.expect(R_CURLY);
90 m.complete(p, ENUM_VARIANT_LIST);
91}
92
93pub(crate) fn named_field_def_list(p: &mut Parser) {
94 assert!(p.at(L_CURLY));
95 let m = p.start();
96 p.bump();
97 while !p.at(R_CURLY) && !p.at(EOF) {
98 if p.at(L_CURLY) {
99 error_block(p, "expected field");
100 continue;
101 }
102 named_field_def(p);
103 if !p.at(R_CURLY) {
104 p.expect(COMMA);
105 }
106 }
107 p.expect(R_CURLY);
108 m.complete(p, NAMED_FIELD_DEF_LIST);
109
110 fn named_field_def(p: &mut Parser) {
111 let m = p.start();
112 // test field_attrs
113 // struct S {
114 // #[serde(with = "url_serde")]
115 // pub uri: Uri,
116 // }
117 attributes::outer_attributes(p);
118 opt_visibility(p);
119 if p.at(IDENT) {
120 name(p);
121 p.expect(COLON);
122 types::type_(p);
123 m.complete(p, NAMED_FIELD_DEF);
124 } else {
125 m.abandon(p);
126 p.err_and_bump("expected field declaration");
127 }
128 }
129}
130
131fn pos_field_list(p: &mut Parser) {
132 assert!(p.at(L_PAREN));
133 let m = p.start();
134 if !p.expect(L_PAREN) {
135 return;
136 }
137 while !p.at(R_PAREN) && !p.at(EOF) {
138 let m = p.start();
139 opt_visibility(p);
140 if !p.at_ts(types::TYPE_FIRST) {
141 p.error("expected a type");
142 m.complete(p, ERROR);
143 break;
144 }
145 types::type_(p);
146 m.complete(p, POS_FIELD);
147
148 if !p.at(R_PAREN) {
149 p.expect(COMMA);
150 }
151 }
152 p.expect(R_PAREN);
153 m.complete(p, POS_FIELD_LIST);
154}
diff --git a/crates/ra_syntax/src/grammar/items/traits.rs b/crates/ra_syntax/src/grammar/items/traits.rs
new file mode 100644
index 000000000..c21cfb1a9
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/items/traits.rs
@@ -0,0 +1,117 @@
1use super::*;
2
3// test trait_item
4// trait T<U>: Hash + Clone where U: Copy {}
5pub(super) fn trait_def(p: &mut Parser) {
6 assert!(p.at(TRAIT_KW));
7 p.bump();
8 name_r(p, ITEM_RECOVERY_SET);
9 type_params::opt_type_param_list(p);
10 if p.at(COLON) {
11 type_params::bounds(p);
12 }
13 type_params::opt_where_clause(p);
14 if p.at(L_CURLY) {
15 trait_item_list(p);
16 } else {
17 p.error("expected `{`");
18 }
19}
20
21// test trait_item_list
22// impl F {
23// type A: Clone;
24// const B: i32;
25// fn foo() {}
26// fn bar(&self);
27// }
28pub(crate) fn trait_item_list(p: &mut Parser) {
29 assert!(p.at(L_CURLY));
30 let m = p.start();
31 p.bump();
32 while !p.at(EOF) && !p.at(R_CURLY) {
33 if p.at(L_CURLY) {
34 error_block(p, "expected an item");
35 continue;
36 }
37 item_or_macro(p, true, ItemFlavor::Trait);
38 }
39 p.expect(R_CURLY);
40 m.complete(p, ITEM_LIST);
41}
42
43// test impl_item
44// impl Foo {}
45pub(super) fn impl_item(p: &mut Parser) {
46 assert!(p.at(IMPL_KW));
47 p.bump();
48 if choose_type_params_over_qpath(p) {
49 type_params::opt_type_param_list(p);
50 }
51
52 // TODO: never type
53 // impl ! {}
54
55 // test impl_item_neg
56 // impl !Send for X {}
57 p.eat(EXCL);
58 types::type_(p);
59 if p.eat(FOR_KW) {
60 types::type_(p);
61 }
62 type_params::opt_where_clause(p);
63 if p.at(L_CURLY) {
64 impl_item_list(p);
65 } else {
66 p.error("expected `{`");
67 }
68}
69
70// test impl_item_list
71// impl F {
72// type A = i32;
73// const B: i32 = 92;
74// fn foo() {}
75// fn bar(&self) {}
76// }
77pub(crate) fn impl_item_list(p: &mut Parser) {
78 assert!(p.at(L_CURLY));
79 let m = p.start();
80 p.bump();
81
82 while !p.at(EOF) && !p.at(R_CURLY) {
83 if p.at(L_CURLY) {
84 error_block(p, "expected an item");
85 continue;
86 }
87 item_or_macro(p, true, ItemFlavor::Mod);
88 }
89 p.expect(R_CURLY);
90 m.complete(p, ITEM_LIST);
91}
92
93fn choose_type_params_over_qpath(p: &Parser) -> bool {
94 // There's an ambiguity between generic parameters and qualified paths in impls.
95 // If we see `<` it may start both, so we have to inspect some following tokens.
96 // The following combinations can only start generics,
97 // but not qualified paths (with one exception):
98 // `<` `>` - empty generic parameters
99 // `<` `#` - generic parameters with attributes
100 // `<` (LIFETIME|IDENT) `>` - single generic parameter
101 // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
102 // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
103 // `<` (LIFETIME|IDENT) `=` - generic parameter with a default
104 // The only truly ambiguous case is
105 // `<` IDENT `>` `::` IDENT ...
106 // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
107 // because this is what almost always expected in practice, qualified paths in impls
108 // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
109 if !p.at(L_ANGLE) {
110 return false;
111 }
112 if p.nth(1) == POUND || p.nth(1) == R_ANGLE {
113 return true;
114 }
115 (p.nth(1) == LIFETIME || p.nth(1) == IDENT)
116 && (p.nth(2) == R_ANGLE || p.nth(2) == COMMA || p.nth(2) == COLON || p.nth(2) == EQ)
117}
diff --git a/crates/ra_syntax/src/grammar/items/use_item.rs b/crates/ra_syntax/src/grammar/items/use_item.rs
new file mode 100644
index 000000000..1ee4349fd
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/items/use_item.rs
@@ -0,0 +1,68 @@
1use super::*;
2
3pub(super) fn use_item(p: &mut Parser) {
4 assert!(p.at(USE_KW));
5 p.bump();
6 use_tree(p);
7 p.expect(SEMI);
8}
9
10fn use_tree(p: &mut Parser) {
11 let la = p.nth(1);
12 let m = p.start();
13 match (p.current(), la) {
14 (STAR, _) => p.bump(),
15 (COLONCOLON, STAR) => {
16 p.bump();
17 p.bump();
18 }
19 (L_CURLY, _) | (COLONCOLON, L_CURLY) => {
20 if p.at(COLONCOLON) {
21 p.bump();
22 }
23 use_tree_list(p);
24 }
25 _ if paths::is_path_start(p) => {
26 paths::use_path(p);
27 match p.current() {
28 AS_KW => {
29 opt_alias(p);
30 }
31 COLONCOLON => {
32 p.bump();
33 match p.current() {
34 STAR => {
35 p.bump();
36 }
37 L_CURLY => use_tree_list(p),
38 _ => {
39 // is this unreachable?
40 p.error("expected `{` or `*`");
41 }
42 }
43 }
44 _ => (),
45 }
46 }
47 _ => {
48 m.abandon(p);
49 p.err_and_bump("expected one of `*`, `::`, `{`, `self`, `super`, `indent`");
50 return;
51 }
52 }
53 m.complete(p, USE_TREE);
54}
55
56pub(crate) fn use_tree_list(p: &mut Parser) {
57 assert!(p.at(L_CURLY));
58 let m = p.start();
59 p.bump();
60 while !p.at(EOF) && !p.at(R_CURLY) {
61 use_tree(p);
62 if !p.at(R_CURLY) {
63 p.expect(COMMA);
64 }
65 }
66 p.expect(R_CURLY);
67 m.complete(p, USE_TREE_LIST);
68}
diff --git a/crates/ra_syntax/src/grammar/mod.rs b/crates/ra_syntax/src/grammar/mod.rs
new file mode 100644
index 000000000..2cb11dc1e
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/mod.rs
@@ -0,0 +1,188 @@
1//! This is the actual "grammar" of the Rust language.
2//!
3//! Each function in this module and its children corresponds
4//! to a production of the format grammar. Submodules roughly
5//! correspond to different *areas* of the grammar. By convention,
6//! each submodule starts with `use super::*` import and exports
7//! "public" productions via `pub(super)`.
8//!
9//! See docs for `Parser` to learn about API, available to the grammar,
10//! and see docs for `Event` to learn how this actually manages to
11//! produce parse trees.
12//!
13//! Code in this module also contains inline tests, which start with
14//! `// test name-of-the-test` comment and look like this:
15//!
16//! ```
17//! // test function_with_zero_parameters
18//! // fn foo() {}
19//! ```
20//!
21//! After adding a new inline-test, run `cargo collect-tests` to extract
22//! it as a standalone text-fixture into `tests/data/parser/inline`, and
23//! run `cargo test` once to create the "gold" value.
24mod attributes;
25mod expressions;
26mod items;
27mod params;
28mod paths;
29mod patterns;
30mod type_args;
31mod type_params;
32mod types;
33
34use {
35 token_set::TokenSet,
36 parser_api::{Marker, CompletedMarker, Parser},
37 SyntaxKind::{self, *},
38};
39pub(crate) use self::{
40 expressions::{
41 block,
42 },
43 items::{
44 enum_variant_list,
45 extern_item_list,
46 impl_item_list,
47 match_arm_list,
48 mod_item_list,
49 named_field_def_list,
50 named_field_list,
51 token_tree,
52 trait_item_list,
53 use_tree_list,
54 },
55};
56
57pub(crate) fn root(p: &mut Parser) {
58 let m = p.start();
59 p.eat(SHEBANG);
60 items::mod_contents(p, false);
61 m.complete(p, ROOT);
62}
63
64
65#[derive(Clone, Copy, PartialEq, Eq)]
66enum BlockLike {
67 Block,
68 NotBlock,
69}
70
71impl BlockLike {
72 fn is_block(self) -> bool { self == BlockLike::Block }
73}
74
75fn opt_visibility(p: &mut Parser) {
76 match p.current() {
77 PUB_KW => {
78 let m = p.start();
79 p.bump();
80 if p.at(L_PAREN) {
81 match p.nth(1) {
82 // test crate_visibility
83 // pub(crate) struct S;
84 // pub(self) struct S;
85 // pub(self) struct S;
86 // pub(self) struct S;
87 CRATE_KW | SELF_KW | SUPER_KW => {
88 p.bump();
89 p.bump();
90 p.expect(R_PAREN);
91 }
92 IN_KW => {
93 p.bump();
94 p.bump();
95 paths::use_path(p);
96 p.expect(R_PAREN);
97 }
98 _ => (),
99 }
100 }
101 m.complete(p, VISIBILITY);
102 }
103 // test crate_keyword_vis
104 // crate fn main() { }
105 CRATE_KW => {
106 let m = p.start();
107 p.bump();
108 m.complete(p, VISIBILITY);
109 }
110 _ => (),
111 }
112}
113
114fn opt_alias(p: &mut Parser) {
115 if p.at(AS_KW) {
116 let m = p.start();
117 p.bump();
118 name(p);
119 m.complete(p, ALIAS);
120 }
121}
122
123fn abi(p: &mut Parser) {
124 assert!(p.at(EXTERN_KW));
125 let abi = p.start();
126 p.bump();
127 match p.current() {
128 STRING | RAW_STRING => p.bump(),
129 _ => (),
130 }
131 abi.complete(p, ABI);
132}
133
134fn opt_fn_ret_type(p: &mut Parser) -> bool {
135 if p.at(THIN_ARROW) {
136 let m = p.start();
137 p.bump();
138 types::type_(p);
139 m.complete(p, RET_TYPE);
140 true
141 } else {
142 false
143 }
144}
145
146fn name_r(p: &mut Parser, recovery: TokenSet) {
147 if p.at(IDENT) {
148 let m = p.start();
149 p.bump();
150 m.complete(p, NAME);
151 } else {
152 p.err_recover("expected a name", recovery);
153 }
154}
155
156fn name(p: &mut Parser) {
157 name_r(p, TokenSet::EMPTY)
158}
159
160fn name_ref(p: &mut Parser) {
161 if p.at(IDENT) {
162 let m = p.start();
163 p.bump();
164 m.complete(p, NAME_REF);
165 } else {
166 p.err_and_bump("expected identifier");
167 }
168}
169
170fn error_block(p: &mut Parser, message: &str) {
171 go(p, Some(message));
172 fn go(p: &mut Parser, message: Option<&str>) {
173 assert!(p.at(L_CURLY));
174 let m = p.start();
175 if let Some(message) = message {
176 p.error(message);
177 }
178 p.bump();
179 while !p.at(EOF) && !p.at(R_CURLY) {
180 match p.current() {
181 L_CURLY => go(p, None),
182 _ => p.bump(),
183 }
184 }
185 p.eat(R_CURLY);
186 m.complete(p, ERROR);
187 }
188}
diff --git a/crates/ra_syntax/src/grammar/params.rs b/crates/ra_syntax/src/grammar/params.rs
new file mode 100644
index 000000000..903c25939
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/params.rs
@@ -0,0 +1,142 @@
1use super::*;
2
3// test param_list
4// fn a() {}
5// fn b(x: i32) {}
6// fn c(x: i32, ) {}
7// fn d(x: i32, y: ()) {}
8pub(super) fn param_list(p: &mut Parser) {
9 list_(p, Flavor::Normal)
10}
11
12// test param_list_opt_patterns
13// fn foo<F: FnMut(&mut Foo<'a>)>(){}
14pub(super) fn param_list_opt_patterns(p: &mut Parser) {
15 list_(p, Flavor::OptionalPattern)
16}
17
18pub(super) fn param_list_opt_types(p: &mut Parser) {
19 list_(p, Flavor::OptionalType)
20}
21
22#[derive(Clone, Copy, Eq, PartialEq)]
23enum Flavor {
24 OptionalType,
25 OptionalPattern,
26 Normal,
27}
28
29impl Flavor {
30 fn type_required(self) -> bool {
31 match self {
32 Flavor::OptionalType => false,
33 _ => true,
34 }
35 }
36}
37
38fn list_(p: &mut Parser, flavor: Flavor) {
39 let (bra, ket) = if flavor.type_required() {
40 (L_PAREN, R_PAREN)
41 } else {
42 (PIPE, PIPE)
43 };
44 assert!(p.at(bra));
45 let m = p.start();
46 p.bump();
47 if flavor.type_required() {
48 opt_self_param(p);
49 }
50 while !p.at(EOF) && !p.at(ket) {
51 if !p.at_ts(VALUE_PARAMETER_FIRST) {
52 p.error("expected value parameter");
53 break;
54 }
55 value_parameter(p, flavor);
56 if !p.at(ket) {
57 p.expect(COMMA);
58 }
59 }
60 p.expect(ket);
61 m.complete(p, PARAM_LIST);
62}
63
64
65const VALUE_PARAMETER_FIRST: TokenSet =
66 token_set_union![
67 patterns::PATTERN_FIRST,
68 types::TYPE_FIRST,
69 ];
70
71fn value_parameter(p: &mut Parser, flavor: Flavor) {
72 let m = p.start();
73 match flavor {
74 Flavor::OptionalType | Flavor::Normal => {
75 patterns::pattern(p);
76 if p.at(COLON) || flavor.type_required() {
77 types::ascription(p)
78 }
79 },
80 // test value_parameters_no_patterns
81 // type F = Box<Fn(a: i32, &b: &i32, &mut c: &i32, ())>;
82 Flavor::OptionalPattern => {
83 let la0 = p.current();
84 let la1 = p.nth(1);
85 let la2 = p.nth(2);
86 let la3 = p.nth(3);
87 if la0 == IDENT && la1 == COLON
88 || la0 == AMP && la1 == IDENT && la2 == COLON
89 || la0 == AMP && la1 == MUT_KW && la2 == IDENT && la3 == COLON {
90 patterns::pattern(p);
91 types::ascription(p);
92 } else {
93 types::type_(p);
94 }
95 },
96 }
97 m.complete(p, PARAM);
98}
99
100// test self_param
101// impl S {
102// fn a(self) {}
103// fn b(&self,) {}
104// fn c(&'a self,) {}
105// fn d(&'a mut self, x: i32) {}
106// fn e(mut self) {}
107// }
108fn opt_self_param(p: &mut Parser) {
109 let m;
110 if p.at(SELF_KW) || p.at(MUT_KW) && p.nth(1) == SELF_KW {
111 m = p.start();
112 p.eat(MUT_KW);
113 p.eat(SELF_KW);
114 // test arb_self_types
115 // impl S {
116 // fn a(self: &Self) {}
117 // fn b(mut self: Box<Self>) {}
118 // }
119 if p.at(COLON) {
120 types::ascription(p);
121 }
122 } else {
123 let la1 = p.nth(1);
124 let la2 = p.nth(2);
125 let la3 = p.nth(3);
126 let n_toks = match (p.current(), la1, la2, la3) {
127 (AMP, SELF_KW, _, _) => 2,
128 (AMP, MUT_KW, SELF_KW, _) => 3,
129 (AMP, LIFETIME, SELF_KW, _) => 3,
130 (AMP, LIFETIME, MUT_KW, SELF_KW) => 4,
131 _ => return,
132 };
133 m = p.start();
134 for _ in 0..n_toks {
135 p.bump();
136 }
137 }
138 m.complete(p, SELF_PARAM);
139 if !p.at(R_PAREN) {
140 p.expect(COMMA);
141 }
142}
diff --git a/crates/ra_syntax/src/grammar/paths.rs b/crates/ra_syntax/src/grammar/paths.rs
new file mode 100644
index 000000000..7c9fb8be2
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/paths.rs
@@ -0,0 +1,101 @@
1use super::*;
2
3pub(super) const PATH_FIRST: TokenSet =
4 token_set![IDENT, SELF_KW, SUPER_KW, COLONCOLON, L_ANGLE];
5
6pub(super) fn is_path_start(p: &Parser) -> bool {
7 match p.current() {
8 IDENT | SELF_KW | SUPER_KW | COLONCOLON => true,
9 _ => false,
10 }
11}
12
13pub(super) fn use_path(p: &mut Parser) {
14 path(p, Mode::Use)
15}
16
17pub(super) fn type_path(p: &mut Parser) {
18 path(p, Mode::Type)
19}
20
21pub(super) fn expr_path(p: &mut Parser) {
22 path(p, Mode::Expr)
23}
24
25#[derive(Clone, Copy, Eq, PartialEq)]
26enum Mode {
27 Use,
28 Type,
29 Expr,
30}
31
32fn path(p: &mut Parser, mode: Mode) {
33 let path = p.start();
34 path_segment(p, mode, true);
35 let mut qual = path.complete(p, PATH);
36 loop {
37 let use_tree = match p.nth(1) {
38 STAR | L_CURLY => true,
39 _ => false,
40 };
41 if p.at(COLONCOLON) && !use_tree {
42 let path = qual.precede(p);
43 p.bump();
44 path_segment(p, mode, false);
45 let path = path.complete(p, PATH);
46 qual = path;
47 } else {
48 break;
49 }
50 }
51}
52
53fn path_segment(p: &mut Parser, mode: Mode, first: bool) {
54 let m = p.start();
55 // test qual_paths
56 // type X = <A as B>::Output;
57 // fn foo() { <usize as Default>::default(); }
58 if first && p.eat(L_ANGLE) {
59 types::type_(p);
60 if p.eat(AS_KW) {
61 if is_path_start(p) {
62 types::path_type(p);
63 } else {
64 p.error("expected a trait");
65 }
66 }
67 p.expect(R_ANGLE);
68 } else {
69 if first {
70 p.eat(COLONCOLON);
71 }
72 match p.current() {
73 IDENT => {
74 name_ref(p);
75 opt_path_type_args(p, mode);
76 }
77 SELF_KW | SUPER_KW => p.bump(),
78 _ => {
79 p.err_and_bump("expected identifier");
80 }
81 };
82 }
83 m.complete(p, PATH_SEGMENT);
84}
85
86fn opt_path_type_args(p: &mut Parser, mode: Mode) {
87 match mode {
88 Mode::Use => return,
89 Mode::Type => {
90 // test path_fn_trait_args
91 // type F = Box<Fn(x: i32) -> ()>;
92 if p.at(L_PAREN) {
93 params::param_list_opt_patterns(p);
94 opt_fn_ret_type(p);
95 } else {
96 type_args::opt_type_arg_list(p, false)
97 }
98 },
99 Mode::Expr => type_args::opt_type_arg_list(p, true),
100 }
101}
diff --git a/crates/ra_syntax/src/grammar/patterns.rs b/crates/ra_syntax/src/grammar/patterns.rs
new file mode 100644
index 000000000..420bae7a7
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/patterns.rs
@@ -0,0 +1,224 @@
1use super::*;
2
3pub(super) const PATTERN_FIRST: TokenSet =
4 token_set_union![
5 token_set![REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE],
6 expressions::LITERAL_FIRST,
7 paths::PATH_FIRST,
8 ];
9
10pub(super) fn pattern(p: &mut Parser) {
11 pattern_r(p, PAT_RECOVERY_SET)
12}
13
14pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) {
15 if let Some(lhs) = atom_pat(p, recovery_set) {
16 // test range_pat
17 // fn main() {
18 // match 92 { 0 ... 100 => () }
19 // }
20 if p.at(DOTDOTDOT) {
21 let m = lhs.precede(p);
22 p.bump();
23 atom_pat(p, recovery_set);
24 m.complete(p, RANGE_PAT);
25 }
26 }
27}
28
29const PAT_RECOVERY_SET: TokenSet =
30 token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA];
31
32
33fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
34 let la0 = p.nth(0);
35 let la1 = p.nth(1);
36 if la0 == REF_KW || la0 == MUT_KW
37 || (la0 == IDENT && !(la1 == COLONCOLON || la1 == L_PAREN || la1 == L_CURLY)) {
38 return Some(bind_pat(p, true));
39 }
40 if paths::is_path_start(p) {
41 return Some(path_pat(p));
42 }
43
44 // test literal_pattern
45 // fn main() {
46 // match () {
47 // 92 => (),
48 // 'c' => (),
49 // "hello" => (),
50 // }
51 // }
52 match expressions::literal(p) {
53 Some(m) => return Some(m),
54 None => (),
55 }
56
57 let m = match la0 {
58 UNDERSCORE => placeholder_pat(p),
59 AMP => ref_pat(p),
60 L_PAREN => tuple_pat(p),
61 L_BRACK => slice_pat(p),
62 _ => {
63 p.err_recover("expected pattern", recovery_set);
64 return None;
65 }
66 };
67 Some(m)
68}
69
70// test path_part
71// fn foo() {
72// let foo::Bar = ();
73// let ::Bar = ();
74// let Bar { .. } = ();
75// let Bar(..) = ();
76// }
77fn path_pat(p: &mut Parser) -> CompletedMarker {
78 assert!(paths::is_path_start(p));
79 let m = p.start();
80 paths::expr_path(p);
81 let kind = match p.current() {
82 L_PAREN => {
83 tuple_pat_fields(p);
84 TUPLE_STRUCT_PAT
85 }
86 L_CURLY => {
87 field_pat_list(p);
88 STRUCT_PAT
89 }
90 _ => PATH_PAT
91 };
92 m.complete(p, kind)
93}
94
95// test tuple_pat_fields
96// fn foo() {
97// let S() = ();
98// let S(_) = ();
99// let S(_,) = ();
100// let S(_, .. , x) = ();
101// }
102fn tuple_pat_fields(p: &mut Parser) {
103 assert!(p.at(L_PAREN));
104 p.bump();
105 pat_list(p, R_PAREN);
106 p.expect(R_PAREN);
107}
108
109// test field_pat_list
110// fn foo() {
111// let S {} = ();
112// let S { f, ref mut g } = ();
113// let S { h: _, ..} = ();
114// let S { h: _, } = ();
115// }
116fn field_pat_list(p: &mut Parser) {
117 assert!(p.at(L_CURLY));
118 let m = p.start();
119 p.bump();
120 while !p.at(EOF) && !p.at(R_CURLY) {
121 match p.current() {
122 DOTDOT => p.bump(),
123 IDENT if p.nth(1) == COLON => {
124 p.bump();
125 p.bump();
126 pattern(p);
127 }
128 L_CURLY => error_block(p, "expected ident"),
129 _ => {
130 bind_pat(p, false);
131 }
132 }
133 if !p.at(R_CURLY) {
134 p.expect(COMMA);
135 }
136 }
137 p.expect(R_CURLY);
138 m.complete(p, FIELD_PAT_LIST);
139}
140
141// test placeholder_pat
142// fn main() { let _ = (); }
143fn placeholder_pat(p: &mut Parser) -> CompletedMarker {
144 assert!(p.at(UNDERSCORE));
145 let m = p.start();
146 p.bump();
147 m.complete(p, PLACEHOLDER_PAT)
148}
149
150// test ref_pat
151// fn main() {
152// let &a = ();
153// let &mut b = ();
154// }
155fn ref_pat(p: &mut Parser) -> CompletedMarker {
156 assert!(p.at(AMP));
157 let m = p.start();
158 p.bump();
159 p.eat(MUT_KW);
160 pattern(p);
161 m.complete(p, REF_PAT)
162}
163
164// test tuple_pat
165// fn main() {
166// let (a, b, ..) = ();
167// }
168fn tuple_pat(p: &mut Parser) -> CompletedMarker {
169 assert!(p.at(L_PAREN));
170 let m = p.start();
171 tuple_pat_fields(p);
172 m.complete(p, TUPLE_PAT)
173}
174
175// test slice_pat
176// fn main() {
177// let [a, b, ..] = [];
178// }
179fn slice_pat(p: &mut Parser) -> CompletedMarker {
180 assert!(p.at(L_BRACK));
181 let m = p.start();
182 p.bump();
183 pat_list(p, R_BRACK);
184 p.expect(R_BRACK);
185 m.complete(p, SLICE_PAT)
186}
187
188fn pat_list(p: &mut Parser, ket: SyntaxKind) {
189 while !p.at(EOF) && !p.at(ket) {
190 match p.current() {
191 DOTDOT => p.bump(),
192 _ => {
193 if !p.at_ts(PATTERN_FIRST) {
194 p.error("expected a pattern");
195 break;
196 }
197 pattern(p)
198 },
199 }
200 if !p.at(ket) {
201 p.expect(COMMA);
202 }
203 }
204}
205
206// test bind_pat
207// fn main() {
208// let a = ();
209// let mut b = ();
210// let ref c = ();
211// let ref mut d = ();
212// let e @ _ = ();
213// let ref mut f @ g @ _ = ();
214// }
215fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
216 let m = p.start();
217 p.eat(REF_KW);
218 p.eat(MUT_KW);
219 name(p);
220 if with_at && p.eat(AT) {
221 pattern(p);
222 }
223 m.complete(p, BIND_PAT)
224}
diff --git a/crates/ra_syntax/src/grammar/type_args.rs b/crates/ra_syntax/src/grammar/type_args.rs
new file mode 100644
index 000000000..29ff6e534
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/type_args.rs
@@ -0,0 +1,48 @@
1use super::*;
2
3pub(super) fn opt_type_arg_list(p: &mut Parser, colon_colon_required: bool) {
4 let m;
5 match (colon_colon_required, p.nth(0), p.nth(1)) {
6 (_, COLONCOLON, L_ANGLE) => {
7 m = p.start();
8 p.bump();
9 p.bump();
10 }
11 (false, L_ANGLE, _) => {
12 m = p.start();
13 p.bump();
14 }
15 _ => return,
16 };
17
18 while !p.at(EOF) && !p.at(R_ANGLE) {
19 type_arg(p);
20 if !p.at(R_ANGLE) && !p.expect(COMMA) {
21 break;
22 }
23 }
24 p.expect(R_ANGLE);
25 m.complete(p, TYPE_ARG_LIST);
26}
27
28// test type_arg
29// type A = B<'static, i32, Item=u64>
30fn type_arg(p: &mut Parser) {
31 let m = p.start();
32 match p.current() {
33 LIFETIME => {
34 p.bump();
35 m.complete(p, LIFETIME_ARG);
36 }
37 IDENT if p.nth(1) == EQ => {
38 name_ref(p);
39 p.bump();
40 types::type_(p);
41 m.complete(p, ASSOC_TYPE_ARG);
42 }
43 _ => {
44 types::type_(p);
45 m.complete(p, TYPE_ARG);
46 }
47 }
48}
diff --git a/crates/ra_syntax/src/grammar/type_params.rs b/crates/ra_syntax/src/grammar/type_params.rs
new file mode 100644
index 000000000..79bc95ce4
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/type_params.rs
@@ -0,0 +1,136 @@
1use super::*;
2
3pub(super) fn opt_type_param_list(p: &mut Parser) {
4 if !p.at(L_ANGLE) {
5 return;
6 }
7 let m = p.start();
8 p.bump();
9
10 while !p.at(EOF) && !p.at(R_ANGLE) {
11 match p.current() {
12 LIFETIME => lifetime_param(p),
13 IDENT => type_param(p),
14 _ => p.err_and_bump("expected type parameter"),
15 }
16 if !p.at(R_ANGLE) && !p.expect(COMMA) {
17 break;
18 }
19 }
20 p.expect(R_ANGLE);
21 m.complete(p, TYPE_PARAM_LIST);
22
23 fn lifetime_param(p: &mut Parser) {
24 assert!(p.at(LIFETIME));
25 let m = p.start();
26 p.bump();
27 if p.at(COLON) {
28 lifetime_bounds(p);
29 }
30 m.complete(p, LIFETIME_PARAM);
31 }
32
33 fn type_param(p: &mut Parser) {
34 assert!(p.at(IDENT));
35 let m = p.start();
36 name(p);
37 if p.at(COLON) {
38 bounds(p);
39 }
40 // test type_param_default
41 // struct S<T = i32>;
42 if p.at(EQ) {
43 p.bump();
44 types::type_(p)
45 }
46 m.complete(p, TYPE_PARAM);
47 }
48}
49
50// test type_param_bounds
51// struct S<T: 'a + ?Sized + (Copy)>;
52pub(super) fn bounds(p: &mut Parser) {
53 assert!(p.at(COLON));
54 p.bump();
55 bounds_without_colon(p);
56}
57
58fn lifetime_bounds(p: &mut Parser) {
59 assert!(p.at(COLON));
60 p.bump();
61 while p.at(LIFETIME) {
62 p.bump();
63 if !p.eat(PLUS) {
64 break;
65 }
66 }
67}
68
69pub(super) fn bounds_without_colon(p: &mut Parser) {
70 loop {
71 let has_paren = p.eat(L_PAREN);
72 p.eat(QUESTION);
73 match p.current() {
74 LIFETIME => p.bump(),
75 FOR_KW => {
76 types::for_type(p)
77 }
78 _ if paths::is_path_start(p) => {
79 types::path_type(p)
80 }
81 _ => break,
82 }
83 if has_paren {
84 p.expect(R_PAREN);
85 }
86 if !p.eat(PLUS) {
87 break;
88 }
89 }
90}
91
92// test where_clause
93// fn foo()
94// where
95// 'a: 'b + 'c,
96// T: Clone + Copy + 'static,
97// Iterator::Item: 'a,
98// {}
99pub(super) fn opt_where_clause(p: &mut Parser) {
100 if !p.at(WHERE_KW) {
101 return;
102 }
103 let m = p.start();
104 p.bump();
105 loop {
106 if !(paths::is_path_start(p) || p.current() == LIFETIME) {
107 break
108 }
109 where_predicate(p);
110 if p.current() != L_CURLY && p.current() != SEMI {
111 p.expect(COMMA);
112 }
113 }
114 m.complete(p, WHERE_CLAUSE);
115}
116
117fn where_predicate(p: &mut Parser) {
118 let m = p.start();
119 if p.at(LIFETIME) {
120 p.eat(LIFETIME);
121 if p.at(COLON) {
122 lifetime_bounds(p)
123 } else {
124 p.error("expected colon")
125 }
126 } else {
127 types::path_type(p);
128 if p.at(COLON) {
129 bounds(p);
130 } else {
131 p.error("expected colon")
132 }
133
134 }
135 m.complete(p, WHERE_PRED);
136}
diff --git a/crates/ra_syntax/src/grammar/types.rs b/crates/ra_syntax/src/grammar/types.rs
new file mode 100644
index 000000000..27e5b086e
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/types.rs
@@ -0,0 +1,247 @@
1use super::*;
2
3pub(super) const TYPE_FIRST: TokenSet =
4 token_set_union![
5 token_set![
6 L_PAREN, EXCL, STAR, L_BRACK, AMP, UNDERSCORE, FN_KW, UNSAFE_KW, EXTERN_KW, FOR_KW, IMPL_KW, DYN_KW, L_ANGLE,
7 ],
8 paths::PATH_FIRST,
9 ];
10
11const TYPE_RECOVERY_SET: TokenSet =
12 token_set![R_PAREN, COMMA];
13
14pub(super) fn type_(p: &mut Parser) {
15 match p.current() {
16 L_PAREN => paren_or_tuple_type(p),
17 EXCL => never_type(p),
18 STAR => pointer_type(p),
19 L_BRACK => array_or_slice_type(p),
20 AMP => reference_type(p),
21 UNDERSCORE => placeholder_type(p),
22 FN_KW | UNSAFE_KW | EXTERN_KW => fn_pointer_type(p),
23 FOR_KW => for_type(p),
24 IMPL_KW => impl_trait_type(p),
25 DYN_KW => dyn_trait_type(p),
26 L_ANGLE => path_type(p),
27 _ if paths::is_path_start(p) => path_type(p),
28 _ => {
29 p.err_recover("expected type", TYPE_RECOVERY_SET);
30 }
31 }
32}
33
34pub(super) fn ascription(p: &mut Parser) {
35 p.expect(COLON);
36 type_(p)
37}
38
39fn type_no_plus(p: &mut Parser) {
40 type_(p);
41}
42
43fn paren_or_tuple_type(p: &mut Parser) {
44 assert!(p.at(L_PAREN));
45 let m = p.start();
46 p.bump();
47 let mut n_types: u32 = 0;
48 let mut trailing_comma: bool = false;
49 while !p.at(EOF) && !p.at(R_PAREN) {
50 n_types += 1;
51 type_(p);
52 if p.eat(COMMA) {
53 trailing_comma = true;
54 } else {
55 trailing_comma = false;
56 break;
57 }
58 }
59 p.expect(R_PAREN);
60
61 let kind = if n_types == 1 && !trailing_comma {
62 // test paren_type
63 // type T = (i32);
64 PAREN_TYPE
65 } else {
66 // test unit_type
67 // type T = ();
68
69 // test singleton_tuple_type
70 // type T = (i32,);
71 TUPLE_TYPE
72 };
73 m.complete(p, kind);
74}
75
76// test never_type
77// type Never = !;
78fn never_type(p: &mut Parser) {
79 assert!(p.at(EXCL));
80 let m = p.start();
81 p.bump();
82 m.complete(p, NEVER_TYPE);
83}
84
85fn pointer_type(p: &mut Parser) {
86 assert!(p.at(STAR));
87 let m = p.start();
88 p.bump();
89
90 match p.current() {
91 // test pointer_type_mut
92 // type M = *mut ();
93 // type C = *mut ();
94 MUT_KW | CONST_KW => p.bump(),
95 _ => {
96 // test pointer_type_no_mutability
97 // type T = *();
98 p.error(
99 "expected mut or const in raw pointer type \
100 (use `*mut T` or `*const T` as appropriate)",
101 );
102 }
103 };
104
105 type_no_plus(p);
106 m.complete(p, POINTER_TYPE);
107}
108
109fn array_or_slice_type(p: &mut Parser) {
110 assert!(p.at(L_BRACK));
111 let m = p.start();
112 p.bump();
113
114 type_(p);
115 let kind = match p.current() {
116 // test slice_type
117 // type T = [()];
118 R_BRACK => {
119 p.bump();
120 SLICE_TYPE
121 }
122
123 // test array_type
124 // type T = [(); 92];
125 SEMI => {
126 p.bump();
127 expressions::expr(p);
128 p.expect(R_BRACK);
129 ARRAY_TYPE
130 }
131 // test array_type_missing_semi
132 // type T = [() 92];
133 _ => {
134 p.error("expected `;` or `]`");
135 SLICE_TYPE
136 }
137 };
138 m.complete(p, kind);
139}
140
141// test reference_type;
142// type A = &();
143// type B = &'static ();
144// type C = &mut ();
145fn reference_type(p: &mut Parser) {
146 assert!(p.at(AMP));
147 let m = p.start();
148 p.bump();
149 p.eat(LIFETIME);
150 p.eat(MUT_KW);
151 type_no_plus(p);
152 m.complete(p, REFERENCE_TYPE);
153}
154
155// test placeholder_type
156// type Placeholder = _;
157fn placeholder_type(p: &mut Parser) {
158 assert!(p.at(UNDERSCORE));
159 let m = p.start();
160 p.bump();
161 m.complete(p, PLACEHOLDER_TYPE);
162}
163
164// test fn_pointer_type
165// type A = fn();
166// type B = unsafe fn();
167// type C = unsafe extern "C" fn();
168fn fn_pointer_type(p: &mut Parser) {
169 let m = p.start();
170 p.eat(UNSAFE_KW);
171 if p.at(EXTERN_KW) {
172 abi(p);
173 }
174 // test fn_pointer_type_missing_fn
175 // type F = unsafe ();
176 if !p.eat(FN_KW) {
177 m.abandon(p);
178 p.error("expected `fn`");
179 return;
180 }
181 if p.at(L_PAREN) {
182 params::param_list_opt_patterns(p);
183 } else {
184 p.error("expected parameters")
185 }
186 // test fn_pointer_type_with_ret
187 // type F = fn() -> ();
188 opt_fn_ret_type(p);
189 m.complete(p, FN_POINTER_TYPE);
190}
191
192// test for_type
193// type A = for<'a> fn() -> ();
194pub(super) fn for_type(p: &mut Parser) {
195 assert!(p.at(FOR_KW));
196 let m = p.start();
197 p.bump();
198 type_params::opt_type_param_list(p);
199 match p.current() {
200 FN_KW | UNSAFE_KW | EXTERN_KW => fn_pointer_type(p),
201 _ if paths::is_path_start(p) => path_type_(p, false),
202 _ => p.error("expected a path"),
203
204 }
205 m.complete(p, FOR_TYPE);
206}
207
208// test impl_trait_type
209// type A = impl Iterator<Item=Foo<'a>> + 'a;
210fn impl_trait_type(p: &mut Parser) {
211 assert!(p.at(IMPL_KW));
212 let m = p.start();
213 p.bump();
214 type_params::bounds_without_colon(p);
215 m.complete(p, IMPL_TRAIT_TYPE);
216}
217
218// test dyn_trait_type
219// type A = dyn Iterator<Item=Foo<'a>> + 'a;
220fn dyn_trait_type(p: &mut Parser) {
221 assert!(p.at(DYN_KW));
222 let m = p.start();
223 p.bump();
224 type_params::bounds_without_colon(p);
225 m.complete(p, DYN_TRAIT_TYPE);
226}
227
228// test path_type
229// type A = Foo;
230// type B = ::Foo;
231// type C = self::Foo;
232// type D = super::Foo;
233pub(super) fn path_type(p: &mut Parser) {
234 path_type_(p, true)
235}
236
237pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) {
238 assert!(paths::is_path_start(p) || p.at(L_ANGLE));
239 let m = p.start();
240 paths::type_path(p);
241 // test path_type_with_bounds
242 // fn foo() -> Box<T + 'f> {}
243 if allow_bounds && p.eat(PLUS) {
244 type_params::bounds_without_colon(p);
245 }
246 m.complete(p, PATH_TYPE);
247}
diff --git a/crates/ra_syntax/src/lexer/classes.rs b/crates/ra_syntax/src/lexer/classes.rs
new file mode 100644
index 000000000..4235d2648
--- /dev/null
+++ b/crates/ra_syntax/src/lexer/classes.rs
@@ -0,0 +1,26 @@
1use unicode_xid::UnicodeXID;
2
3pub fn is_ident_start(c: char) -> bool {
4 (c >= 'a' && c <= 'z')
5 || (c >= 'A' && c <= 'Z')
6 || c == '_'
7 || (c > '\x7f' && UnicodeXID::is_xid_start(c))
8}
9
10pub fn is_ident_continue(c: char) -> bool {
11 (c >= 'a' && c <= 'z')
12 || (c >= 'A' && c <= 'Z')
13 || (c >= '0' && c <= '9')
14 || c == '_'
15 || (c > '\x7f' && UnicodeXID::is_xid_continue(c))
16}
17
18pub fn is_whitespace(c: char) -> bool {
19 //FIXME: use is_pattern_whitespace
20 //https://github.com/behnam/rust-unic/issues/192
21 c.is_whitespace()
22}
23
24pub fn is_dec_digit(c: char) -> bool {
25 '0' <= c && c <= '9'
26}
diff --git a/crates/ra_syntax/src/lexer/comments.rs b/crates/ra_syntax/src/lexer/comments.rs
new file mode 100644
index 000000000..eb417c2dc
--- /dev/null
+++ b/crates/ra_syntax/src/lexer/comments.rs
@@ -0,0 +1,57 @@
1use lexer::ptr::Ptr;
2
3use SyntaxKind::{self, *};
4
5pub(crate) fn scan_shebang(ptr: &mut Ptr) -> bool {
6 if ptr.at_str("!/") {
7 ptr.bump();
8 ptr.bump();
9 bump_until_eol(ptr);
10 true
11 } else {
12 false
13 }
14}
15
16fn scan_block_comment(ptr: &mut Ptr) -> Option<SyntaxKind> {
17 if ptr.at('*') {
18 ptr.bump();
19 let mut depth: u32 = 1;
20 while depth > 0 {
21 if ptr.at_str("*/") {
22 depth -= 1;
23 ptr.bump();
24 ptr.bump();
25 } else if ptr.at_str("/*") {
26 depth += 1;
27 ptr.bump();
28 ptr.bump();
29 } else if ptr.bump().is_none() {
30 break;
31 }
32 }
33 Some(COMMENT)
34 } else {
35 None
36 }
37}
38
39pub(crate) fn scan_comment(ptr: &mut Ptr) -> Option<SyntaxKind> {
40 if ptr.at('/') {
41 bump_until_eol(ptr);
42 Some(COMMENT)
43 } else {
44 scan_block_comment(ptr)
45 }
46}
47
48fn bump_until_eol(ptr: &mut Ptr) {
49 loop {
50 if ptr.at('\n') || ptr.at_str("\r\n") {
51 return;
52 }
53 if ptr.bump().is_none() {
54 break;
55 }
56 }
57}
diff --git a/crates/ra_syntax/src/lexer/mod.rs b/crates/ra_syntax/src/lexer/mod.rs
new file mode 100644
index 000000000..3e11db88b
--- /dev/null
+++ b/crates/ra_syntax/src/lexer/mod.rs
@@ -0,0 +1,209 @@
1mod classes;
2mod comments;
3mod numbers;
4mod ptr;
5mod strings;
6
7use {
8 SyntaxKind::{self, *},
9 TextUnit,
10};
11
12use self::{
13 classes::*,
14 comments::{scan_comment, scan_shebang},
15 numbers::scan_number,
16 ptr::Ptr,
17 strings::{
18 is_string_literal_start, scan_byte_char_or_string, scan_char, scan_raw_string, scan_string,
19 },
20};
21
22/// A token of Rust source.
23#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
24pub struct Token {
25 /// The kind of token.
26 pub kind: SyntaxKind,
27 /// The length of the token.
28 pub len: TextUnit,
29}
30
31/// Break a string up into its component tokens
32pub fn tokenize(text: &str) -> Vec<Token> {
33 let mut text = text;
34 let mut acc = Vec::new();
35 while !text.is_empty() {
36 let token = next_token(text);
37 acc.push(token);
38 let len: u32 = token.len.into();
39 text = &text[len as usize..];
40 }
41 acc
42}
43
44/// Get the next token from a string
45pub fn next_token(text: &str) -> Token {
46 assert!(!text.is_empty());
47 let mut ptr = Ptr::new(text);
48 let c = ptr.bump().unwrap();
49 let kind = next_token_inner(c, &mut ptr);
50 let len = ptr.into_len();
51 Token { kind, len }
52}
53
54fn next_token_inner(c: char, ptr: &mut Ptr) -> SyntaxKind {
55 if is_whitespace(c) {
56 ptr.bump_while(is_whitespace);
57 return WHITESPACE;
58 }
59
60 match c {
61 '#' => if scan_shebang(ptr) {
62 return SHEBANG;
63 },
64 '/' => if let Some(kind) = scan_comment(ptr) {
65 return kind;
66 },
67 _ => (),
68 }
69
70 let ident_start = is_ident_start(c) && !is_string_literal_start(c, ptr.current(), ptr.nth(1));
71 if ident_start {
72 return scan_ident(c, ptr);
73 }
74
75 if is_dec_digit(c) {
76 let kind = scan_number(c, ptr);
77 scan_literal_suffix(ptr);
78 return kind;
79 }
80
81 // One-byte tokens.
82 if let Some(kind) = SyntaxKind::from_char(c) {
83 return kind;
84 }
85
86 match c {
87 // Multi-byte tokens.
88 '.' => {
89 return match (ptr.current(), ptr.nth(1)) {
90 (Some('.'), Some('.')) => {
91 ptr.bump();
92 ptr.bump();
93 DOTDOTDOT
94 }
95 (Some('.'), Some('=')) => {
96 ptr.bump();
97 ptr.bump();
98 DOTDOTEQ
99 }
100 (Some('.'), _) => {
101 ptr.bump();
102 DOTDOT
103 }
104 _ => DOT,
105 };
106 }
107 ':' => {
108 return match ptr.current() {
109 Some(':') => {
110 ptr.bump();
111 COLONCOLON
112 }
113 _ => COLON,
114 };
115 }
116 '=' => {
117 return match ptr.current() {
118 Some('=') => {
119 ptr.bump();
120 EQEQ
121 }
122 Some('>') => {
123 ptr.bump();
124 FAT_ARROW
125 }
126 _ => EQ,
127 };
128 }
129 '!' => {
130 return match ptr.current() {
131 Some('=') => {
132 ptr.bump();
133 NEQ
134 }
135 _ => EXCL,
136 };
137 }
138 '-' => {
139 return if ptr.at('>') {
140 ptr.bump();
141 THIN_ARROW
142 } else {
143 MINUS
144 };
145 }
146
147 // If the character is an ident start not followed by another single
148 // quote, then this is a lifetime name:
149 '\'' => {
150 return if ptr.at_p(is_ident_start) && !ptr.at_str("''") {
151 ptr.bump();
152 while ptr.at_p(is_ident_continue) {
153 ptr.bump();
154 }
155 // lifetimes shouldn't end with a single quote
156 // if we find one, then this is an invalid character literal
157 if ptr.at('\'') {
158 ptr.bump();
159 return CHAR; // TODO: error reporting
160 }
161 LIFETIME
162 } else {
163 scan_char(ptr);
164 scan_literal_suffix(ptr);
165 CHAR
166 };
167 }
168 'b' => {
169 let kind = scan_byte_char_or_string(ptr);
170 scan_literal_suffix(ptr);
171 return kind;
172 }
173 '"' => {
174 scan_string(ptr);
175 scan_literal_suffix(ptr);
176 return STRING;
177 }
178 'r' => {
179 scan_raw_string(ptr);
180 scan_literal_suffix(ptr);
181 return RAW_STRING;
182 }
183 _ => (),
184 }
185 ERROR
186}
187
188fn scan_ident(c: char, ptr: &mut Ptr) -> SyntaxKind {
189 let is_single_letter = match ptr.current() {
190 None => true,
191 Some(c) if !is_ident_continue(c) => true,
192 _ => false,
193 };
194 if is_single_letter {
195 return if c == '_' { UNDERSCORE } else { IDENT };
196 }
197 ptr.bump_while(is_ident_continue);
198 if let Some(kind) = SyntaxKind::from_keyword(ptr.current_token_text()) {
199 return kind;
200 }
201 IDENT
202}
203
204fn scan_literal_suffix(ptr: &mut Ptr) {
205 if ptr.at_p(is_ident_start) {
206 ptr.bump();
207 }
208 ptr.bump_while(is_ident_continue);
209}
diff --git a/crates/ra_syntax/src/lexer/numbers.rs b/crates/ra_syntax/src/lexer/numbers.rs
new file mode 100644
index 000000000..22e7d4e99
--- /dev/null
+++ b/crates/ra_syntax/src/lexer/numbers.rs
@@ -0,0 +1,67 @@
1use lexer::classes::*;
2use lexer::ptr::Ptr;
3
4use SyntaxKind::{self, *};
5
6pub(crate) fn scan_number(c: char, ptr: &mut Ptr) -> SyntaxKind {
7 if c == '0' {
8 match ptr.current().unwrap_or('\0') {
9 'b' | 'o' => {
10 ptr.bump();
11 scan_digits(ptr, false);
12 }
13 'x' => {
14 ptr.bump();
15 scan_digits(ptr, true);
16 }
17 '0'...'9' | '_' | '.' | 'e' | 'E' => {
18 scan_digits(ptr, true);
19 }
20 _ => return INT_NUMBER,
21 }
22 } else {
23 scan_digits(ptr, false);
24 }
25
26 // might be a float, but don't be greedy if this is actually an
27 // integer literal followed by field/method access or a range pattern
28 // (`0..2` and `12.foo()`)
29 if ptr.at('.') && !(ptr.at_str("..") || ptr.nth_is_p(1, is_ident_start)) {
30 // might have stuff after the ., and if it does, it needs to start
31 // with a number
32 ptr.bump();
33 scan_digits(ptr, false);
34 scan_float_exponent(ptr);
35 return FLOAT_NUMBER;
36 }
37 // it might be a float if it has an exponent
38 if ptr.at('e') || ptr.at('E') {
39 scan_float_exponent(ptr);
40 return FLOAT_NUMBER;
41 }
42 INT_NUMBER
43}
44
45fn scan_digits(ptr: &mut Ptr, allow_hex: bool) {
46 while let Some(c) = ptr.current() {
47 match c {
48 '_' | '0'...'9' => {
49 ptr.bump();
50 }
51 'a'...'f' | 'A'...'F' if allow_hex => {
52 ptr.bump();
53 }
54 _ => return,
55 }
56 }
57}
58
59fn scan_float_exponent(ptr: &mut Ptr) {
60 if ptr.at('e') || ptr.at('E') {
61 ptr.bump();
62 if ptr.at('-') || ptr.at('+') {
63 ptr.bump();
64 }
65 scan_digits(ptr, false);
66 }
67}
diff --git a/crates/ra_syntax/src/lexer/ptr.rs b/crates/ra_syntax/src/lexer/ptr.rs
new file mode 100644
index 000000000..c9a5354ea
--- /dev/null
+++ b/crates/ra_syntax/src/lexer/ptr.rs
@@ -0,0 +1,166 @@
1use TextUnit;
2
3use std::str::Chars;
4
5/// A simple view into the characters of a string.
6pub(crate) struct Ptr<'s> {
7 text: &'s str,
8 len: TextUnit,
9}
10
11impl<'s> Ptr<'s> {
12 /// Creates a new `Ptr` from a string.
13 pub fn new(text: &'s str) -> Ptr<'s> {
14 Ptr {
15 text,
16 len: 0.into(),
17 }
18 }
19
20 /// Gets the length of the remaining string.
21 pub fn into_len(self) -> TextUnit {
22 self.len
23 }
24
25 /// Gets the current character, if one exists.
26 pub fn current(&self) -> Option<char> {
27 self.chars().next()
28 }
29
30 /// Gets the nth character from the current.
31 /// For example, 0 will return the current token, 1 will return the next, etc.
32 pub fn nth(&self, n: u32) -> Option<char> {
33 let mut chars = self.chars().peekable();
34 chars.by_ref().skip(n as usize).next()
35 }
36
37 /// Checks whether the current character is `c`.
38 pub fn at(&self, c: char) -> bool {
39 self.current() == Some(c)
40 }
41
42 /// Checks whether the next characters match `s`.
43 pub fn at_str(&self, s: &str) -> bool {
44 let chars = self.chars();
45 chars.as_str().starts_with(s)
46 }
47
48 /// Checks whether the current character satisfies the predicate `p`.
49 pub fn at_p<P: Fn(char) -> bool>(&self, p: P) -> bool {
50 self.current().map(p) == Some(true)
51 }
52
53 /// Checks whether the nth character satisfies the predicate `p`.
54 pub fn nth_is_p<P: Fn(char) -> bool>(&self, n: u32, p: P) -> bool {
55 self.nth(n).map(p) == Some(true)
56 }
57
58 /// Moves to the next character.
59 pub fn bump(&mut self) -> Option<char> {
60 let ch = self.chars().next()?;
61 self.len += TextUnit::of_char(ch);
62 Some(ch)
63 }
64
65 /// Moves to the next character as long as `pred` is satisfied.
66 pub fn bump_while<F: Fn(char) -> bool>(&mut self, pred: F) {
67 loop {
68 match self.current() {
69 Some(c) if pred(c) => {
70 self.bump();
71 }
72 _ => return,
73 }
74 }
75 }
76
77 /// Returns the text up to the current point.
78 pub fn current_token_text(&self) -> &str {
79 let len: u32 = self.len.into();
80 &self.text[..len as usize]
81 }
82
83 /// Returns an iterator over the remaining characters.
84 fn chars(&self) -> Chars {
85 let len: u32 = self.len.into();
86 self.text[len as usize..].chars()
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn test_current() {
96 let ptr = Ptr::new("test");
97 assert_eq!(ptr.current(), Some('t'));
98 }
99
100 #[test]
101 fn test_nth() {
102 let ptr = Ptr::new("test");
103 assert_eq!(ptr.nth(0), Some('t'));
104 assert_eq!(ptr.nth(1), Some('e'));
105 assert_eq!(ptr.nth(2), Some('s'));
106 assert_eq!(ptr.nth(3), Some('t'));
107 assert_eq!(ptr.nth(4), None);
108 }
109
110 #[test]
111 fn test_at() {
112 let ptr = Ptr::new("test");
113 assert!(ptr.at('t'));
114 assert!(!ptr.at('a'));
115 }
116
117 #[test]
118 fn test_at_str() {
119 let ptr = Ptr::new("test");
120 assert!(ptr.at_str("t"));
121 assert!(ptr.at_str("te"));
122 assert!(ptr.at_str("test"));
123 assert!(!ptr.at_str("tests"));
124 assert!(!ptr.at_str("rust"));
125 }
126
127 #[test]
128 fn test_at_p() {
129 let ptr = Ptr::new("test");
130 assert!(ptr.at_p(|c| c == 't'));
131 assert!(!ptr.at_p(|c| c == 'e'));
132 }
133
134 #[test]
135 fn test_nth_is_p() {
136 let ptr = Ptr::new("test");
137 assert!(ptr.nth_is_p(0,|c| c == 't'));
138 assert!(!ptr.nth_is_p(1,|c| c == 't'));
139 assert!(ptr.nth_is_p(3,|c| c == 't'));
140 assert!(!ptr.nth_is_p(150,|c| c == 't'));
141 }
142
143 #[test]
144 fn test_bump() {
145 let mut ptr = Ptr::new("test");
146 assert_eq!(ptr.current(), Some('t'));
147 ptr.bump();
148 assert_eq!(ptr.current(), Some('e'));
149 ptr.bump();
150 assert_eq!(ptr.current(), Some('s'));
151 ptr.bump();
152 assert_eq!(ptr.current(), Some('t'));
153 ptr.bump();
154 assert_eq!(ptr.current(), None);
155 ptr.bump();
156 assert_eq!(ptr.current(), None);
157 }
158
159 #[test]
160 fn test_bump_while() {
161 let mut ptr = Ptr::new("test");
162 assert_eq!(ptr.current(), Some('t'));
163 ptr.bump_while(|c| c != 's');
164 assert_eq!(ptr.current(), Some('s'));
165 }
166}
diff --git a/crates/ra_syntax/src/lexer/strings.rs b/crates/ra_syntax/src/lexer/strings.rs
new file mode 100644
index 000000000..5ff483d14
--- /dev/null
+++ b/crates/ra_syntax/src/lexer/strings.rs
@@ -0,0 +1,123 @@
1use SyntaxKind::{self, *};
2
3use lexer::ptr::Ptr;
4
5pub(crate) fn is_string_literal_start(c: char, c1: Option<char>, c2: Option<char>) -> bool {
6 match (c, c1, c2) {
7 ('r', Some('"'), _)
8 | ('r', Some('#'), _)
9 | ('b', Some('"'), _)
10 | ('b', Some('\''), _)
11 | ('b', Some('r'), Some('"'))
12 | ('b', Some('r'), Some('#')) => true,
13 _ => false,
14 }
15}
16
17pub(crate) fn scan_char(ptr: &mut Ptr) {
18 while let Some(c) = ptr.current() {
19 match c {
20 '\\' => {
21 ptr.bump();
22 if ptr.at('\\') || ptr.at('\'') {
23 ptr.bump();
24 }
25 }
26 '\'' => {
27 ptr.bump();
28 return;
29 }
30 '\n' => return,
31 _ => {
32 ptr.bump();
33 }
34 }
35 }
36}
37
38pub(crate) fn scan_byte_char_or_string(ptr: &mut Ptr) -> SyntaxKind {
39 // unwrapping and not-exhaustive match are ok
40 // because of string_literal_start
41 let c = ptr.bump().unwrap();
42 match c {
43 '\'' => {
44 scan_byte(ptr);
45 BYTE
46 }
47 '"' => {
48 scan_byte_string(ptr);
49 BYTE_STRING
50 }
51 'r' => {
52 scan_raw_byte_string(ptr);
53 RAW_BYTE_STRING
54 }
55 _ => unreachable!(),
56 }
57}
58
59pub(crate) fn scan_string(ptr: &mut Ptr) {
60 while let Some(c) = ptr.current() {
61 match c {
62 '\\' => {
63 ptr.bump();
64 if ptr.at('\\') || ptr.at('"') {
65 ptr.bump();
66 }
67 }
68 '"' => {
69 ptr.bump();
70 return;
71 }
72 _ => {
73 ptr.bump();
74 },
75 }
76 }
77}
78
79pub(crate) fn scan_raw_string(ptr: &mut Ptr) {
80 let mut hashes = 0;
81 while ptr.at('#') {
82 hashes += 1;
83 ptr.bump();
84 }
85 if !ptr.at('"') {
86 return;
87 }
88 ptr.bump();
89
90 while let Some(c) = ptr.bump() {
91 if c == '"' {
92 let mut hashes_left = hashes;
93 while ptr.at('#') && hashes_left > 0{
94 hashes_left -= 1;
95 ptr.bump();
96 }
97 if hashes_left == 0 {
98 return;
99 }
100 }
101 }
102}
103
104fn scan_byte(ptr: &mut Ptr) {
105 scan_char(ptr)
106}
107
108fn scan_byte_string(ptr: &mut Ptr) {
109 scan_string(ptr)
110}
111
112fn scan_raw_byte_string(ptr: &mut Ptr) {
113 if !ptr.at('"') {
114 return;
115 }
116 ptr.bump();
117
118 while let Some(c) = ptr.bump() {
119 if c == '"' {
120 return;
121 }
122 }
123}
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
new file mode 100644
index 000000000..eb271762e
--- /dev/null
+++ b/crates/ra_syntax/src/lib.rs
@@ -0,0 +1,105 @@
1//! An experimental implementation of [Rust RFC#2256 libsyntax2.0][rfc#2256].
2//!
3//! The intent is to be an IDE-ready parser, i.e. one that offers
4//!
5//! - easy and fast incremental re-parsing,
6//! - graceful handling of errors, and
7//! - maintains all information in the source file.
8//!
9//! For more information, see [the RFC][rfc#2265], or [the working draft][RFC.md].
10//!
11//! [rfc#2256]: <https://github.com/rust-lang/rfcs/pull/2256>
12//! [RFC.md]: <https://github.com/matklad/libsyntax2/blob/master/docs/RFC.md>
13
14#![forbid(
15 missing_debug_implementations,
16 unconditional_recursion,
17 future_incompatible
18)]
19#![deny(bad_style, missing_docs)]
20#![allow(missing_docs)]
21//#![warn(unreachable_pub)] // rust-lang/rust#47816
22
23extern crate itertools;
24extern crate unicode_xid;
25extern crate drop_bomb;
26extern crate parking_lot;
27extern crate smol_str;
28extern crate text_unit;
29
30#[cfg(test)]
31#[macro_use]
32extern crate test_utils;
33
34pub mod algo;
35pub mod ast;
36mod lexer;
37#[macro_use]
38mod token_set;
39mod parser_api;
40mod grammar;
41mod parser_impl;
42mod reparsing;
43
44mod syntax_kinds;
45mod yellow;
46/// Utilities for simple uses of the parser.
47pub mod utils;
48pub mod text_utils;
49
50pub use {
51 text_unit::{TextRange, TextUnit},
52 smol_str::SmolStr,
53 ast::AstNode,
54 lexer::{tokenize, Token},
55 syntax_kinds::SyntaxKind,
56 yellow::{SyntaxNode, SyntaxNodeRef, OwnedRoot, RefRoot, TreeRoot, SyntaxError},
57 reparsing::AtomEdit,
58};
59
60use {
61 yellow::{GreenNode, SyntaxRoot},
62};
63
64#[derive(Clone, Debug, Hash)]
65pub struct File {
66 root: SyntaxNode
67}
68
69impl File {
70 fn new(green: GreenNode, errors: Vec<SyntaxError>) -> File {
71 let root = SyntaxRoot::new(green, errors);
72 let root = SyntaxNode::new_owned(root);
73 if cfg!(debug_assertions) {
74 utils::validate_block_structure(root.borrowed());
75 }
76 File { root }
77 }
78 pub fn parse(text: &str) -> File {
79 let tokens = tokenize(&text);
80 let (green, errors) = parser_impl::parse_with::<yellow::GreenBuilder>(
81 text, &tokens, grammar::root,
82 );
83 File::new(green, errors)
84 }
85 pub fn reparse(&self, edit: &AtomEdit) -> File {
86 self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit))
87 }
88 pub fn incremental_reparse(&self, edit: &AtomEdit) -> Option<File> {
89 reparsing::incremental_reparse(self.syntax(), edit, self.errors())
90 .map(|(green_node, errors)| File::new(green_node, errors))
91 }
92 fn full_reparse(&self, edit: &AtomEdit) -> File {
93 let text = text_utils::replace_range(self.syntax().text().to_string(), edit.delete, &edit.insert);
94 File::parse(&text)
95 }
96 pub fn ast(&self) -> ast::Root {
97 ast::Root::cast(self.syntax()).unwrap()
98 }
99 pub fn syntax(&self) -> SyntaxNodeRef {
100 self.root.borrowed()
101 }
102 pub fn errors(&self) -> Vec<SyntaxError> {
103 self.syntax().root.syntax_root().errors.clone()
104 }
105}
diff --git a/crates/ra_syntax/src/parser_api.rs b/crates/ra_syntax/src/parser_api.rs
new file mode 100644
index 000000000..772d753af
--- /dev/null
+++ b/crates/ra_syntax/src/parser_api.rs
@@ -0,0 +1,178 @@
1use {
2 token_set::TokenSet,
3 parser_impl::ParserImpl,
4 SyntaxKind::{self, ERROR},
5 drop_bomb::DropBomb,
6};
7
8/// `Parser` struct provides the low-level API for
9/// navigating through the stream of tokens and
10/// constructing the parse tree. The actual parsing
11/// happens in the `grammar` module.
12///
13/// However, the result of this `Parser` is not a real
14/// tree, but rather a flat stream of events of the form
15/// "start expression, consume number literal,
16/// finish expression". See `Event` docs for more.
17pub(crate) struct Parser<'t>(pub(super) ParserImpl<'t>);
18
19impl<'t> Parser<'t> {
20 /// Returns the kind of the current token.
21 /// If parser has already reached the end of input,
22 /// the special `EOF` kind is returned.
23 pub(crate) fn current(&self) -> SyntaxKind {
24 self.nth(0)
25 }
26
27 /// Lookahead operation: returns the kind of the next nth
28 /// token.
29 pub(crate) fn nth(&self, n: u32) -> SyntaxKind {
30 self.0.nth(n)
31 }
32
33 /// Checks if the current token is `kind`.
34 pub(crate) fn at(&self, kind: SyntaxKind) -> bool {
35 self.current() == kind
36 }
37
38 /// Checks if the current token is `kind`.
39 pub(crate) fn at_ts(&self, kinds: TokenSet) -> bool {
40 kinds.contains(self.current())
41 }
42
43 pub(crate) fn next2(&self) -> Option<(SyntaxKind, SyntaxKind)> {
44 self.0.next2()
45 }
46
47 pub(crate) fn next3(&self) -> Option<(SyntaxKind, SyntaxKind, SyntaxKind)> {
48 self.0.next3()
49 }
50
51 /// Checks if the current token is contextual keyword with text `t`.
52 pub(crate) fn at_contextual_kw(&self, t: &str) -> bool {
53 self.0.at_kw(t)
54 }
55
56 /// Starts a new node in the syntax tree. All nodes and tokens
57 /// consumed between the `start` and the corresponding `Marker::complete`
58 /// belong to the same node.
59 pub(crate) fn start(&mut self) -> Marker {
60 Marker::new(self.0.start())
61 }
62
63 /// Advances the parser by one token.
64 pub(crate) fn bump(&mut self) {
65 self.0.bump();
66 }
67
68 /// Advances the parser by one token, remapping its kind.
69 /// This is useful to create contextual keywords from
70 /// identifiers. For example, the lexer creates an `union`
71 /// *identifier* token, but the parser remaps it to the
72 /// `union` keyword, and keyword is what ends up in the
73 /// final tree.
74 pub(crate) fn bump_remap(&mut self, kind: SyntaxKind) {
75 self.0.bump_remap(kind);
76 }
77
78 /// Advances the parser by `n` tokens, remapping its kind.
79 /// This is useful to create compound tokens from parts. For
80 /// example, an `<<` token is two consecutive remapped `<` tokens
81 pub(crate) fn bump_compound(&mut self, kind: SyntaxKind, n: u8) {
82 self.0.bump_compound(kind, n);
83 }
84
85 /// Emit error with the `message`
86 /// TODO: this should be much more fancy and support
87 /// structured errors with spans and notes, like rustc
88 /// does.
89 pub(crate) fn error<T: Into<String>>(&mut self, message: T) {
90 self.0.error(message.into())
91 }
92
93 /// Consume the next token if it is `kind`.
94 pub(crate) fn eat(&mut self, kind: SyntaxKind) -> bool {
95 if !self.at(kind) {
96 return false;
97 }
98 self.bump();
99 true
100 }
101
102 /// Consume the next token if it is `kind` or emit an error
103 /// otherwise.
104 pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
105 if self.eat(kind) {
106 return true;
107 }
108 self.error(format!("expected {:?}", kind));
109 false
110 }
111
112 /// Create an error node and consume the next token.
113 pub(crate) fn err_and_bump(&mut self, message: &str) {
114 self.err_recover(message, TokenSet::EMPTY);
115 }
116
117 /// Create an error node and consume the next token.
118 pub(crate) fn err_recover(&mut self, message: &str, recovery: TokenSet) {
119 if self.at(SyntaxKind::L_CURLY)
120 || self.at(SyntaxKind::R_CURLY)
121 || self.at_ts(recovery) {
122 self.error(message);
123 } else {
124 let m = self.start();
125 self.error(message);
126 self.bump();
127 m.complete(self, ERROR);
128 };
129 }
130}
131
132/// See `Parser::start`.
133pub(crate) struct Marker {
134 pos: u32,
135 bomb: DropBomb,
136}
137
138impl Marker {
139 fn new(pos: u32) -> Marker {
140 Marker {
141 pos,
142 bomb: DropBomb::new("Marker must be either completed or abandoned"),
143 }
144 }
145
146 /// Finishes the syntax tree node and assigns `kind` to it.
147 pub(crate) fn complete(mut self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker {
148 self.bomb.defuse();
149 p.0.complete(self.pos, kind);
150 CompletedMarker(self.pos, kind)
151 }
152
153 /// Abandons the syntax tree node. All its children
154 /// are attached to its parent instead.
155 pub(crate) fn abandon(mut self, p: &mut Parser) {
156 self.bomb.defuse();
157 p.0.abandon(self.pos);
158 }
159}
160
161pub(crate) struct CompletedMarker(u32, SyntaxKind);
162
163impl CompletedMarker {
164 /// This one is tricky :-)
165 /// This method allows to create a new node which starts
166 /// *before* the current one. That is, parser could start
167 /// node `A`, then complete it, and then after parsing the
168 /// whole `A`, decide that it should have started some node
169 /// `B` before starting `A`. `precede` allows to do exactly
170 /// that. See also docs about `forward_parent` in `Event::Start`.
171 pub(crate) fn precede(self, p: &mut Parser) -> Marker {
172 Marker::new(p.0.precede(self.0))
173 }
174
175 pub(crate) fn kind(&self) -> SyntaxKind {
176 self.1
177 }
178}
diff --git a/crates/ra_syntax/src/parser_impl/event.rs b/crates/ra_syntax/src/parser_impl/event.rs
new file mode 100644
index 000000000..9fd56b996
--- /dev/null
+++ b/crates/ra_syntax/src/parser_impl/event.rs
@@ -0,0 +1,154 @@
1//! This module provides a way to construct a `File`.
2//! It is intended to be completely decoupled from the
3//! parser, so as to allow to evolve the tree representation
4//! and the parser algorithm independently.
5//!
6//! The `Sink` trait is the bridge between the parser and the
7//! tree builder: the parser produces a stream of events like
8//! `start node`, `finish node`, and `FileBuilder` converts
9//! this stream to a real tree.
10use std::mem;
11use {
12 lexer::Token,
13 parser_impl::Sink,
14 SyntaxKind::{self, TOMBSTONE},
15};
16
17
18/// `Parser` produces a flat list of `Event`s.
19/// They are converted to a tree-structure in
20/// a separate pass, via `TreeBuilder`.
21#[derive(Debug)]
22pub(crate) enum Event {
23 /// This event signifies the start of the node.
24 /// It should be either abandoned (in which case the
25 /// `kind` is `TOMBSTONE`, and the event is ignored),
26 /// or completed via a `Finish` event.
27 ///
28 /// All tokens between a `Start` and a `Finish` would
29 /// become the children of the respective node.
30 ///
31 /// For left-recursive syntactic constructs, the parser produces
32 /// a child node before it sees a parent. `forward_parent`
33 /// exists to allow to tweak parent-child relationships.
34 ///
35 /// Consider this path
36 ///
37 /// foo::bar
38 ///
39 /// The events for it would look like this:
40 ///
41 ///
42 /// START(PATH) IDENT('foo') FINISH START(PATH) COLONCOLON IDENT('bar') FINISH
43 /// | /\
44 /// | |
45 /// +------forward-parent------+
46 ///
47 /// And the tree would look like this
48 ///
49 /// +--PATH---------+
50 /// | | |
51 /// | | |
52 /// | '::' 'bar'
53 /// |
54 /// PATH
55 /// |
56 /// 'foo'
57 ///
58 /// See also `CompletedMarker::precede`.
59 Start {
60 kind: SyntaxKind,
61 forward_parent: Option<u32>,
62 },
63
64 /// Complete the previous `Start` event
65 Finish,
66
67 /// Produce a single leaf-element.
68 /// `n_raw_tokens` is used to glue complex contextual tokens.
69 /// For example, lexer tokenizes `>>` as `>`, `>`, and
70 /// `n_raw_tokens = 2` is used to produced a single `>>`.
71 Token {
72 kind: SyntaxKind,
73 n_raw_tokens: u8,
74 },
75
76 Error {
77 msg: String,
78 },
79}
80
81
82pub(super) fn process<'a, S: Sink<'a>>(builder: &mut S, tokens: &[Token], mut events: Vec<Event>) {
83 fn tombstone() -> Event {
84 Event::Start { kind: TOMBSTONE, forward_parent: None }
85 }
86 let eat_ws = |idx: &mut usize, builder: &mut S| {
87 while let Some(token) = tokens.get(*idx) {
88 if !token.kind.is_trivia() {
89 break;
90 }
91 builder.leaf(token.kind, token.len);
92 *idx += 1
93 }
94 };
95
96 let events: &mut [Event] = &mut events;
97 let mut depth = 0;
98 let mut forward_parents = Vec::new();
99 let mut next_tok_idx = 0;
100 for i in 0..events.len() {
101 match mem::replace(&mut events[i], tombstone()) {
102 Event::Start {
103 kind: TOMBSTONE, ..
104 } => (),
105
106 Event::Start { kind, forward_parent } => {
107 forward_parents.push(kind);
108 let mut idx = i;
109 let mut fp = forward_parent;
110 while let Some(fwd) = fp {
111 idx += fwd as usize;
112 fp = match mem::replace(&mut events[idx], tombstone()) {
113 Event::Start {
114 kind,
115 forward_parent,
116 } => {
117 forward_parents.push(kind);
118 forward_parent
119 },
120 _ => unreachable!(),
121 };
122 }
123 for kind in forward_parents.drain(..).rev() {
124 if depth > 0 {
125 eat_ws(&mut next_tok_idx, builder);
126 }
127 depth += 1;
128 builder.start_internal(kind);
129 }
130 }
131 Event::Finish => {
132 depth -= 1;
133 if depth == 0 {
134 eat_ws(&mut next_tok_idx, builder);
135 }
136
137 builder.finish_internal();
138 }
139 Event::Token {
140 kind,
141 mut n_raw_tokens,
142 } => {
143 eat_ws(&mut next_tok_idx, builder);
144 let mut len = 0.into();
145 for _ in 0..n_raw_tokens {
146 len += tokens[next_tok_idx].len;
147 next_tok_idx += 1;
148 }
149 builder.leaf(kind, len);
150 }
151 Event::Error { msg } => builder.error(msg),
152 }
153 }
154}
diff --git a/crates/ra_syntax/src/parser_impl/input.rs b/crates/ra_syntax/src/parser_impl/input.rs
new file mode 100644
index 000000000..c0fe4d488
--- /dev/null
+++ b/crates/ra_syntax/src/parser_impl/input.rs
@@ -0,0 +1,86 @@
1use {lexer::Token, SyntaxKind, SyntaxKind::EOF, TextRange, TextUnit};
2
3use std::ops::{Add, AddAssign};
4
5pub(crate) struct ParserInput<'t> {
6 text: &'t str,
7 start_offsets: Vec<TextUnit>,
8 tokens: Vec<Token>, // non-whitespace tokens
9}
10
11impl<'t> ParserInput<'t> {
12 pub fn new(text: &'t str, raw_tokens: &'t [Token]) -> ParserInput<'t> {
13 let mut tokens = Vec::new();
14 let mut start_offsets = Vec::new();
15 let mut len = 0.into();
16 for &token in raw_tokens.iter() {
17 if !token.kind.is_trivia() {
18 tokens.push(token);
19 start_offsets.push(len);
20 }
21 len += token.len;
22 }
23
24 ParserInput {
25 text,
26 start_offsets,
27 tokens,
28 }
29 }
30
31 pub fn kind(&self, pos: InputPosition) -> SyntaxKind {
32 let idx = pos.0 as usize;
33 if !(idx < self.tokens.len()) {
34 return EOF;
35 }
36 self.tokens[idx].kind
37 }
38
39 pub fn len(&self, pos: InputPosition) -> TextUnit {
40 let idx = pos.0 as usize;
41 if !(idx < self.tokens.len()) {
42 return 0.into();
43 }
44 self.tokens[idx].len
45 }
46
47 pub fn start(&self, pos: InputPosition) -> TextUnit {
48 let idx = pos.0 as usize;
49 if !(idx < self.tokens.len()) {
50 return 0.into();
51 }
52 self.start_offsets[idx]
53 }
54
55 pub fn text(&self, pos: InputPosition) -> &'t str {
56 let idx = pos.0 as usize;
57 if !(idx < self.tokens.len()) {
58 return "";
59 }
60 let range = TextRange::offset_len(self.start_offsets[idx], self.tokens[idx].len);
61 &self.text[range]
62 }
63}
64
65#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
66pub(crate) struct InputPosition(u32);
67
68impl InputPosition {
69 pub fn new() -> Self {
70 InputPosition(0)
71 }
72}
73
74impl Add<u32> for InputPosition {
75 type Output = InputPosition;
76
77 fn add(self, rhs: u32) -> InputPosition {
78 InputPosition(self.0 + rhs)
79 }
80}
81
82impl AddAssign<u32> for InputPosition {
83 fn add_assign(&mut self, rhs: u32) {
84 self.0 += rhs
85 }
86}
diff --git a/crates/ra_syntax/src/parser_impl/mod.rs b/crates/ra_syntax/src/parser_impl/mod.rs
new file mode 100644
index 000000000..b343b404f
--- /dev/null
+++ b/crates/ra_syntax/src/parser_impl/mod.rs
@@ -0,0 +1,194 @@
1mod event;
2mod input;
3
4use std::cell::Cell;
5
6use {
7 lexer::Token,
8 parser_api::Parser,
9 parser_impl::{
10 event::{process, Event},
11 input::{InputPosition, ParserInput},
12 },
13 TextUnit,
14};
15
16use SyntaxKind::{self, EOF, TOMBSTONE};
17
18pub(crate) trait Sink<'a> {
19 type Tree;
20
21 fn new(text: &'a str) -> Self;
22
23 fn leaf(&mut self, kind: SyntaxKind, len: TextUnit);
24 fn start_internal(&mut self, kind: SyntaxKind);
25 fn finish_internal(&mut self);
26 fn error(&mut self, err: String);
27 fn finish(self) -> Self::Tree;
28}
29
30/// Parse a sequence of tokens into the representative node tree
31pub(crate) fn parse_with<'a, S: Sink<'a>>(
32 text: &'a str,
33 tokens: &[Token],
34 parser: fn(&mut Parser),
35) -> S::Tree {
36 let events = {
37 let input = input::ParserInput::new(text, tokens);
38 let parser_impl = ParserImpl::new(&input);
39 let mut parser_api = Parser(parser_impl);
40 parser(&mut parser_api);
41 parser_api.0.into_events()
42 };
43 let mut sink = S::new(text);
44 process(&mut sink, tokens, events);
45 sink.finish()
46}
47
48/// Implementation details of `Parser`, extracted
49/// to a separate struct in order not to pollute
50/// the public API of the `Parser`.
51pub(crate) struct ParserImpl<'t> {
52 inp: &'t ParserInput<'t>,
53
54 pos: InputPosition,
55 events: Vec<Event>,
56 steps: Cell<u32>,
57}
58
59impl<'t> ParserImpl<'t> {
60 pub(crate) fn new(inp: &'t ParserInput<'t>) -> ParserImpl<'t> {
61 ParserImpl {
62 inp,
63
64 pos: InputPosition::new(),
65 events: Vec::new(),
66 steps: Cell::new(0),
67 }
68 }
69
70 pub(crate) fn into_events(self) -> Vec<Event> {
71 assert_eq!(self.nth(0), EOF);
72 self.events
73 }
74
75 pub(super) fn next2(&self) -> Option<(SyntaxKind, SyntaxKind)> {
76 let c1 = self.inp.kind(self.pos);
77 let c2 = self.inp.kind(self.pos + 1);
78 if self.inp.start(self.pos + 1) == self.inp.start(self.pos) + self.inp.len(self.pos) {
79 Some((c1, c2))
80 } else {
81 None
82 }
83 }
84
85 pub(super) fn next3(&self) -> Option<(SyntaxKind, SyntaxKind, SyntaxKind)> {
86 let c1 = self.inp.kind(self.pos);
87 let c2 = self.inp.kind(self.pos + 1);
88 let c3 = self.inp.kind(self.pos + 2);
89 if self.inp.start(self.pos + 1) == self.inp.start(self.pos) + self.inp.len(self.pos)
90 && self.inp.start(self.pos + 2) == self.inp.start(self.pos + 1) + self.inp.len(self.pos + 1){
91 Some((c1, c2, c3))
92 } else {
93 None
94 }
95 }
96
97 pub(super) fn nth(&self, n: u32) -> SyntaxKind {
98 let steps = self.steps.get();
99 if steps > 10_000_000 {
100 panic!("the parser seems stuck");
101 }
102 self.steps.set(steps + 1);
103
104 self.inp.kind(self.pos + n)
105 }
106
107 pub(super) fn at_kw(&self, t: &str) -> bool {
108 self.inp.text(self.pos) == t
109 }
110
111 pub(super) fn start(&mut self) -> u32 {
112 let pos = self.events.len() as u32;
113 self.event(Event::Start {
114 kind: TOMBSTONE,
115 forward_parent: None,
116 });
117 pos
118 }
119
120 pub(super) fn bump(&mut self) {
121 let kind = self.nth(0);
122 if kind == EOF {
123 return;
124 }
125 self.do_bump(kind, 1);
126 }
127
128 pub(super) fn bump_remap(&mut self, kind: SyntaxKind) {
129 if self.nth(0) == EOF {
130 // TODO: panic!?
131 return;
132 }
133 self.do_bump(kind, 1);
134 }
135
136 pub(super) fn bump_compound(&mut self, kind: SyntaxKind, n: u8) {
137 self.do_bump(kind, n);
138 }
139
140 fn do_bump(&mut self, kind: SyntaxKind, n_raw_tokens: u8) {
141 self.pos += u32::from(n_raw_tokens);
142 self.event(Event::Token {
143 kind,
144 n_raw_tokens,
145 });
146 }
147
148 pub(super) fn error(&mut self, msg: String) {
149 self.event(Event::Error { msg })
150 }
151
152 pub(super) fn complete(&mut self, pos: u32, kind: SyntaxKind) {
153 match self.events[pos as usize] {
154 Event::Start {
155 kind: ref mut slot, ..
156 } => {
157 *slot = kind;
158 }
159 _ => unreachable!(),
160 }
161 self.event(Event::Finish);
162 }
163
164 pub(super) fn abandon(&mut self, pos: u32) {
165 let idx = pos as usize;
166 if idx == self.events.len() - 1 {
167 match self.events.pop() {
168 Some(Event::Start {
169 kind: TOMBSTONE,
170 forward_parent: None,
171 }) => (),
172 _ => unreachable!(),
173 }
174 }
175 }
176
177 pub(super) fn precede(&mut self, pos: u32) -> u32 {
178 let new_pos = self.start();
179 match self.events[pos as usize] {
180 Event::Start {
181 ref mut forward_parent,
182 ..
183 } => {
184 *forward_parent = Some(new_pos - pos);
185 }
186 _ => unreachable!(),
187 }
188 new_pos
189 }
190
191 fn event(&mut self, event: Event) {
192 self.events.push(event)
193 }
194}
diff --git a/crates/ra_syntax/src/reparsing.rs b/crates/ra_syntax/src/reparsing.rs
new file mode 100644
index 000000000..da44913c5
--- /dev/null
+++ b/crates/ra_syntax/src/reparsing.rs
@@ -0,0 +1,343 @@
1use algo;
2use grammar;
3use lexer::{tokenize, Token};
4use text_unit::{TextRange, TextUnit};
5use yellow::{self, SyntaxNodeRef, GreenNode, SyntaxError};
6use parser_impl;
7use parser_api::Parser;
8use {
9 SyntaxKind::*,
10};
11use text_utils::replace_range;
12
13#[derive(Debug, Clone)]
14pub struct AtomEdit {
15 pub delete: TextRange,
16 pub insert: String,
17}
18
19impl AtomEdit {
20 pub fn replace(range: TextRange, replace_with: String) -> AtomEdit {
21 AtomEdit { delete: range, insert: replace_with }
22 }
23
24 pub fn delete(range: TextRange) -> AtomEdit {
25 AtomEdit::replace(range, String::new())
26 }
27
28 pub fn insert(offset: TextUnit, text: String) -> AtomEdit {
29 AtomEdit::replace(TextRange::offset_len(offset, 0.into()), text)
30 }
31}
32
33pub(crate) fn incremental_reparse(
34 node: SyntaxNodeRef,
35 edit: &AtomEdit,
36 errors: Vec<SyntaxError>,
37) -> Option<(GreenNode, Vec<SyntaxError>)> {
38 let (node, green, new_errors) =
39 reparse_leaf(node, &edit).or_else(|| reparse_block(node, &edit))?;
40 let green_root = node.replace_with(green);
41 let errors = merge_errors(errors, new_errors, node, edit);
42 Some((green_root, errors))
43}
44
45fn reparse_leaf<'node>(
46 node: SyntaxNodeRef<'node>,
47 edit: &AtomEdit,
48) -> Option<(SyntaxNodeRef<'node>, GreenNode, Vec<SyntaxError>)> {
49 let node = algo::find_covering_node(node, edit.delete);
50 match node.kind() {
51 | WHITESPACE
52 | COMMENT
53 | DOC_COMMENT
54 | IDENT
55 | STRING
56 | RAW_STRING => {
57 let text = get_text_after_edit(node, &edit);
58 let tokens = tokenize(&text);
59 let token = match tokens[..] {
60 [token] if token.kind == node.kind() => token,
61 _ => return None,
62 };
63
64 if token.kind == IDENT && is_contextual_kw(&text) {
65 return None;
66 }
67
68 let green = GreenNode::new_leaf(node.kind(), &text);
69 let new_errors = vec![];
70 Some((node, green, new_errors))
71 }
72 _ => None,
73 }
74}
75
76fn reparse_block<'node>(
77 node: SyntaxNodeRef<'node>,
78 edit: &AtomEdit,
79) -> Option<(SyntaxNodeRef<'node>, GreenNode, Vec<SyntaxError>)> {
80 let (node, reparser) = find_reparsable_node(node, edit.delete)?;
81 let text = get_text_after_edit(node, &edit);
82 let tokens = tokenize(&text);
83 if !is_balanced(&tokens) {
84 return None;
85 }
86 let (green, new_errors) =
87 parser_impl::parse_with::<yellow::GreenBuilder>(
88 &text, &tokens, reparser,
89 );
90 Some((node, green, new_errors))
91}
92
93fn get_text_after_edit(node: SyntaxNodeRef, edit: &AtomEdit) -> String {
94 replace_range(
95 node.text().to_string(),
96 edit.delete - node.range().start(),
97 &edit.insert,
98 )
99}
100
101fn is_contextual_kw(text: &str) -> bool {
102 match text {
103 | "auto"
104 | "default"
105 | "union" => true,
106 _ => false,
107 }
108}
109
110fn find_reparsable_node<'node>(
111 node: SyntaxNodeRef<'node>,
112 range: TextRange,
113) -> Option<(SyntaxNodeRef<'node>, fn(&mut Parser))> {
114 let node = algo::find_covering_node(node, range);
115 return algo::ancestors(node)
116 .filter_map(|node| reparser(node).map(|r| (node, r)))
117 .next();
118
119 fn reparser(node: SyntaxNodeRef) -> Option<fn(&mut Parser)> {
120 let res = match node.kind() {
121 BLOCK => grammar::block,
122 NAMED_FIELD_DEF_LIST => grammar::named_field_def_list,
123 NAMED_FIELD_LIST => grammar::named_field_list,
124 ENUM_VARIANT_LIST => grammar::enum_variant_list,
125 MATCH_ARM_LIST => grammar::match_arm_list,
126 USE_TREE_LIST => grammar::use_tree_list,
127 EXTERN_ITEM_LIST => grammar::extern_item_list,
128 TOKEN_TREE if node.first_child().unwrap().kind() == L_CURLY => grammar::token_tree,
129 ITEM_LIST => {
130 let parent = node.parent().unwrap();
131 match parent.kind() {
132 IMPL_ITEM => grammar::impl_item_list,
133 TRAIT_DEF => grammar::trait_item_list,
134 MODULE => grammar::mod_item_list,
135 _ => return None,
136 }
137 }
138 _ => return None,
139 };
140 Some(res)
141 }
142}
143
144fn is_balanced(tokens: &[Token]) -> bool {
145 if tokens.len() == 0
146 || tokens.first().unwrap().kind != L_CURLY
147 || tokens.last().unwrap().kind != R_CURLY {
148 return false;
149 }
150 let mut balance = 0usize;
151 for t in tokens.iter() {
152 match t.kind {
153 L_CURLY => balance += 1,
154 R_CURLY => balance = match balance.checked_sub(1) {
155 Some(b) => b,
156 None => return false,
157 },
158 _ => (),
159 }
160 }
161 balance == 0
162}
163
164fn merge_errors(
165 old_errors: Vec<SyntaxError>,
166 new_errors: Vec<SyntaxError>,
167 old_node: SyntaxNodeRef,
168 edit: &AtomEdit,
169) -> Vec<SyntaxError> {
170 let mut res = Vec::new();
171 for e in old_errors {
172 if e.offset <= old_node.range().start() {
173 res.push(e)
174 } else if e.offset >= old_node.range().end() {
175 res.push(SyntaxError {
176 msg: e.msg,
177 offset: e.offset + TextUnit::of_str(&edit.insert) - edit.delete.len(),
178 })
179 }
180 }
181 for e in new_errors {
182 res.push(SyntaxError {
183 msg: e.msg,
184 offset: e.offset + old_node.range().start(),
185 })
186 }
187 res
188}
189
190#[cfg(test)]
191mod tests {
192 use super::{
193 super::{
194 File,
195 test_utils::extract_range,
196 text_utils::replace_range,
197 utils::dump_tree,
198 },
199 reparse_leaf, reparse_block, AtomEdit, GreenNode, SyntaxError, SyntaxNodeRef,
200 };
201
202 fn do_check<F>(
203 before: &str,
204 replace_with: &str,
205 reparser: F,
206 ) where
207 for<'a> F: Fn(
208 SyntaxNodeRef<'a>,
209 &AtomEdit,
210 ) -> Option<(SyntaxNodeRef<'a>, GreenNode, Vec<SyntaxError>)>
211 {
212 let (range, before) = extract_range(before);
213 let after = replace_range(before.clone(), range, replace_with);
214
215 let fully_reparsed = File::parse(&after);
216 let incrementally_reparsed = {
217 let f = File::parse(&before);
218 let edit = AtomEdit { delete: range, insert: replace_with.to_string() };
219 let (node, green, new_errors) =
220 reparser(f.syntax(), &edit).expect("cannot incrementally reparse");
221 let green_root = node.replace_with(green);
222 let errors = super::merge_errors(f.errors(), new_errors, node, &edit);
223 File::new(green_root, errors)
224 };
225
226 assert_eq_text!(
227 &dump_tree(fully_reparsed.syntax()),
228 &dump_tree(incrementally_reparsed.syntax()),
229 )
230 }
231
232 #[test]
233 fn reparse_block_tests() {
234 let do_check = |before, replace_to|
235 do_check(before, replace_to, reparse_block);
236
237 do_check(r"
238fn foo() {
239 let x = foo + <|>bar<|>
240}
241", "baz");
242 do_check(r"
243fn foo() {
244 let x = foo<|> + bar<|>
245}
246", "baz");
247 do_check(r"
248struct Foo {
249 f: foo<|><|>
250}
251", ",\n g: (),");
252 do_check(r"
253fn foo {
254 let;
255 1 + 1;
256 <|>92<|>;
257}
258", "62");
259 do_check(r"
260mod foo {
261 fn <|><|>
262}
263", "bar");
264 do_check(r"
265trait Foo {
266 type <|>Foo<|>;
267}
268", "Output");
269 do_check(r"
270impl IntoIterator<Item=i32> for Foo {
271 f<|><|>
272}
273", "n next(");
274 do_check(r"
275use a::b::{foo,<|>,bar<|>};
276 ", "baz");
277 do_check(r"
278pub enum A {
279 Foo<|><|>
280}
281", "\nBar;\n");
282 do_check(r"
283foo!{a, b<|><|> d}
284", ", c[3]");
285 do_check(r"
286fn foo() {
287 vec![<|><|>]
288}
289", "123");
290 do_check(r"
291extern {
292 fn<|>;<|>
293}
294", " exit(code: c_int)");
295 }
296
297 #[test]
298 fn reparse_leaf_tests() {
299 let do_check = |before, replace_to|
300 do_check(before, replace_to, reparse_leaf);
301
302 do_check(r"<|><|>
303fn foo() -> i32 { 1 }
304", "\n\n\n \n");
305 do_check(r"
306fn foo() -> <|><|> {}
307", " \n");
308 do_check(r"
309fn <|>foo<|>() -> i32 { 1 }
310", "bar");
311 do_check(r"
312fn foo<|><|>foo() { }
313", "bar");
314 do_check(r"
315fn foo /* <|><|> */ () {}
316", "some comment");
317 do_check(r"
318fn baz <|><|> () {}
319", " \t\t\n\n");
320 do_check(r"
321fn baz <|><|> () {}
322", " \t\t\n\n");
323 do_check(r"
324/// foo <|><|>omment
325mod { }
326", "c");
327 do_check(r#"
328fn -> &str { "Hello<|><|>" }
329"#, ", world");
330 do_check(r#"
331fn -> &str { // "Hello<|><|>"
332"#, ", world");
333 do_check(r##"
334fn -> &str { r#"Hello<|><|>"#
335"##, ", world");
336 do_check(r"
337#[derive(<|>Copy<|>)]
338enum Foo {
339
340}
341", "Clone");
342 }
343} \ No newline at end of file
diff --git a/crates/ra_syntax/src/syntax_kinds/generated.rs b/crates/ra_syntax/src/syntax_kinds/generated.rs
new file mode 100644
index 000000000..7882bded9
--- /dev/null
+++ b/crates/ra_syntax/src/syntax_kinds/generated.rs
@@ -0,0 +1,562 @@
1#![allow(bad_style, missing_docs, unreachable_pub)]
2#![cfg_attr(rustfmt, rustfmt_skip)]
3use super::SyntaxInfo;
4
5/// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT_DEF`.
6#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub enum SyntaxKind {
8 // Technical SyntaxKinds: they appear temporally during parsing,
9 // but never end up in the final tree
10 #[doc(hidden)]
11 TOMBSTONE,
12 #[doc(hidden)]
13 EOF,
14 SEMI,
15 COMMA,
16 L_PAREN,
17 R_PAREN,
18 L_CURLY,
19 R_CURLY,
20 L_BRACK,
21 R_BRACK,
22 L_ANGLE,
23 R_ANGLE,
24 AT,
25 POUND,
26 TILDE,
27 QUESTION,
28 DOLLAR,
29 AMP,
30 PIPE,
31 PLUS,
32 STAR,
33 SLASH,
34 CARET,
35 PERCENT,
36 DOT,
37 DOTDOT,
38 DOTDOTDOT,
39 DOTDOTEQ,
40 COLON,
41 COLONCOLON,
42 EQ,
43 EQEQ,
44 FAT_ARROW,
45 EXCL,
46 NEQ,
47 MINUS,
48 THIN_ARROW,
49 LTEQ,
50 GTEQ,
51 PLUSEQ,
52 MINUSEQ,
53 PIPEEQ,
54 AMPEQ,
55 CARETEQ,
56 SLASHEQ,
57 STAREQ,
58 AMPAMP,
59 PIPEPIPE,
60 SHL,
61 SHR,
62 SHLEQ,
63 SHREQ,
64 USE_KW,
65 FN_KW,
66 STRUCT_KW,
67 ENUM_KW,
68 TRAIT_KW,
69 IMPL_KW,
70 DYN_KW,
71 TRUE_KW,
72 FALSE_KW,
73 AS_KW,
74 EXTERN_KW,
75 CRATE_KW,
76 MOD_KW,
77 PUB_KW,
78 SELF_KW,
79 SUPER_KW,
80 IN_KW,
81 WHERE_KW,
82 FOR_KW,
83 LOOP_KW,
84 WHILE_KW,
85 CONTINUE_KW,
86 BREAK_KW,
87 IF_KW,
88 ELSE_KW,
89 MATCH_KW,
90 CONST_KW,
91 STATIC_KW,
92 MUT_KW,
93 UNSAFE_KW,
94 TYPE_KW,
95 REF_KW,
96 LET_KW,
97 MOVE_KW,
98 RETURN_KW,
99 AUTO_KW,
100 DEFAULT_KW,
101 UNION_KW,
102 ERROR,
103 IDENT,
104 UNDERSCORE,
105 WHITESPACE,
106 INT_NUMBER,
107 FLOAT_NUMBER,
108 LIFETIME,
109 CHAR,
110 BYTE,
111 STRING,
112 RAW_STRING,
113 BYTE_STRING,
114 RAW_BYTE_STRING,
115 COMMENT,
116 DOC_COMMENT,
117 SHEBANG,
118 ROOT,
119 STRUCT_DEF,
120 ENUM_DEF,
121 FN_DEF,
122 RET_TYPE,
123 EXTERN_CRATE_ITEM,
124 MODULE,
125 USE_ITEM,
126 STATIC_DEF,
127 CONST_DEF,
128 TRAIT_DEF,
129 IMPL_ITEM,
130 TYPE_DEF,
131 MACRO_CALL,
132 TOKEN_TREE,
133 PAREN_TYPE,
134 TUPLE_TYPE,
135 NEVER_TYPE,
136 PATH_TYPE,
137 POINTER_TYPE,
138 ARRAY_TYPE,
139 SLICE_TYPE,
140 REFERENCE_TYPE,
141 PLACEHOLDER_TYPE,
142 FN_POINTER_TYPE,
143 FOR_TYPE,
144 IMPL_TRAIT_TYPE,
145 DYN_TRAIT_TYPE,
146 REF_PAT,
147 BIND_PAT,
148 PLACEHOLDER_PAT,
149 PATH_PAT,
150 STRUCT_PAT,
151 FIELD_PAT_LIST,
152 TUPLE_STRUCT_PAT,
153 TUPLE_PAT,
154 SLICE_PAT,
155 RANGE_PAT,
156 TUPLE_EXPR,
157 ARRAY_EXPR,
158 PAREN_EXPR,
159 PATH_EXPR,
160 LAMBDA_EXPR,
161 IF_EXPR,
162 WHILE_EXPR,
163 CONDITION,
164 LOOP_EXPR,
165 FOR_EXPR,
166 CONTINUE_EXPR,
167 BREAK_EXPR,
168 LABEL,
169 BLOCK_EXPR,
170 RETURN_EXPR,
171 MATCH_EXPR,
172 MATCH_ARM_LIST,
173 MATCH_ARM,
174 MATCH_GUARD,
175 STRUCT_LIT,
176 NAMED_FIELD_LIST,
177 NAMED_FIELD,
178 CALL_EXPR,
179 INDEX_EXPR,
180 METHOD_CALL_EXPR,
181 FIELD_EXPR,
182 TRY_EXPR,
183 CAST_EXPR,
184 REF_EXPR,
185 PREFIX_EXPR,
186 RANGE_EXPR,
187 BIN_EXPR,
188 BLOCK,
189 EXTERN_BLOCK,
190 EXTERN_ITEM_LIST,
191 ENUM_VARIANT,
192 NAMED_FIELD_DEF_LIST,
193 NAMED_FIELD_DEF,
194 POS_FIELD_LIST,
195 POS_FIELD,
196 ENUM_VARIANT_LIST,
197 ITEM_LIST,
198 ATTR,
199 META_ITEM,
200 USE_TREE,
201 USE_TREE_LIST,
202 PATH,
203 PATH_SEGMENT,
204 LITERAL,
205 ALIAS,
206 VISIBILITY,
207 WHERE_CLAUSE,
208 WHERE_PRED,
209 ABI,
210 NAME,
211 NAME_REF,
212 LET_STMT,
213 EXPR_STMT,
214 TYPE_PARAM_LIST,
215 LIFETIME_PARAM,
216 TYPE_PARAM,
217 TYPE_ARG_LIST,
218 LIFETIME_ARG,
219 TYPE_ARG,
220 ASSOC_TYPE_ARG,
221 PARAM_LIST,
222 PARAM,
223 SELF_PARAM,
224 ARG_LIST,
225}
226use self::SyntaxKind::*;
227
228impl SyntaxKind {
229 pub fn is_keyword(self) -> bool {
230 match self {
231 | USE_KW
232 | FN_KW
233 | STRUCT_KW
234 | ENUM_KW
235 | TRAIT_KW
236 | IMPL_KW
237 | DYN_KW
238 | TRUE_KW
239 | FALSE_KW
240 | AS_KW
241 | EXTERN_KW
242 | CRATE_KW
243 | MOD_KW
244 | PUB_KW
245 | SELF_KW
246 | SUPER_KW
247 | IN_KW
248 | WHERE_KW
249 | FOR_KW
250 | LOOP_KW
251 | WHILE_KW
252 | CONTINUE_KW
253 | BREAK_KW
254 | IF_KW
255 | ELSE_KW
256 | MATCH_KW
257 | CONST_KW
258 | STATIC_KW
259 | MUT_KW
260 | UNSAFE_KW
261 | TYPE_KW
262 | REF_KW
263 | LET_KW
264 | MOVE_KW
265 | RETURN_KW
266 | AUTO_KW
267 | DEFAULT_KW
268 | UNION_KW
269 => true,
270 _ => false
271 }
272 }
273
274 pub(crate) fn info(self) -> &'static SyntaxInfo {
275 match self {
276 SEMI => &SyntaxInfo { name: "SEMI" },
277 COMMA => &SyntaxInfo { name: "COMMA" },
278 L_PAREN => &SyntaxInfo { name: "L_PAREN" },
279 R_PAREN => &SyntaxInfo { name: "R_PAREN" },
280 L_CURLY => &SyntaxInfo { name: "L_CURLY" },
281 R_CURLY => &SyntaxInfo { name: "R_CURLY" },
282 L_BRACK => &SyntaxInfo { name: "L_BRACK" },
283 R_BRACK => &SyntaxInfo { name: "R_BRACK" },
284 L_ANGLE => &SyntaxInfo { name: "L_ANGLE" },
285 R_ANGLE => &SyntaxInfo { name: "R_ANGLE" },
286 AT => &SyntaxInfo { name: "AT" },
287 POUND => &SyntaxInfo { name: "POUND" },
288 TILDE => &SyntaxInfo { name: "TILDE" },
289 QUESTION => &SyntaxInfo { name: "QUESTION" },
290 DOLLAR => &SyntaxInfo { name: "DOLLAR" },
291 AMP => &SyntaxInfo { name: "AMP" },
292 PIPE => &SyntaxInfo { name: "PIPE" },
293 PLUS => &SyntaxInfo { name: "PLUS" },
294 STAR => &SyntaxInfo { name: "STAR" },
295 SLASH => &SyntaxInfo { name: "SLASH" },
296 CARET => &SyntaxInfo { name: "CARET" },
297 PERCENT => &SyntaxInfo { name: "PERCENT" },
298 DOT => &SyntaxInfo { name: "DOT" },
299 DOTDOT => &SyntaxInfo { name: "DOTDOT" },
300 DOTDOTDOT => &SyntaxInfo { name: "DOTDOTDOT" },
301 DOTDOTEQ => &SyntaxInfo { name: "DOTDOTEQ" },
302 COLON => &SyntaxInfo { name: "COLON" },
303 COLONCOLON => &SyntaxInfo { name: "COLONCOLON" },
304 EQ => &SyntaxInfo { name: "EQ" },
305 EQEQ => &SyntaxInfo { name: "EQEQ" },
306 FAT_ARROW => &SyntaxInfo { name: "FAT_ARROW" },
307 EXCL => &SyntaxInfo { name: "EXCL" },
308 NEQ => &SyntaxInfo { name: "NEQ" },
309 MINUS => &SyntaxInfo { name: "MINUS" },
310 THIN_ARROW => &SyntaxInfo { name: "THIN_ARROW" },
311 LTEQ => &SyntaxInfo { name: "LTEQ" },
312 GTEQ => &SyntaxInfo { name: "GTEQ" },
313 PLUSEQ => &SyntaxInfo { name: "PLUSEQ" },
314 MINUSEQ => &SyntaxInfo { name: "MINUSEQ" },
315 PIPEEQ => &SyntaxInfo { name: "PIPEEQ" },
316 AMPEQ => &SyntaxInfo { name: "AMPEQ" },
317 CARETEQ => &SyntaxInfo { name: "CARETEQ" },
318 SLASHEQ => &SyntaxInfo { name: "SLASHEQ" },
319 STAREQ => &SyntaxInfo { name: "STAREQ" },
320 AMPAMP => &SyntaxInfo { name: "AMPAMP" },
321 PIPEPIPE => &SyntaxInfo { name: "PIPEPIPE" },
322 SHL => &SyntaxInfo { name: "SHL" },
323 SHR => &SyntaxInfo { name: "SHR" },
324 SHLEQ => &SyntaxInfo { name: "SHLEQ" },
325 SHREQ => &SyntaxInfo { name: "SHREQ" },
326 USE_KW => &SyntaxInfo { name: "USE_KW" },
327 FN_KW => &SyntaxInfo { name: "FN_KW" },
328 STRUCT_KW => &SyntaxInfo { name: "STRUCT_KW" },
329 ENUM_KW => &SyntaxInfo { name: "ENUM_KW" },
330 TRAIT_KW => &SyntaxInfo { name: "TRAIT_KW" },
331 IMPL_KW => &SyntaxInfo { name: "IMPL_KW" },
332 DYN_KW => &SyntaxInfo { name: "DYN_KW" },
333 TRUE_KW => &SyntaxInfo { name: "TRUE_KW" },
334 FALSE_KW => &SyntaxInfo { name: "FALSE_KW" },
335 AS_KW => &SyntaxInfo { name: "AS_KW" },
336 EXTERN_KW => &SyntaxInfo { name: "EXTERN_KW" },
337 CRATE_KW => &SyntaxInfo { name: "CRATE_KW" },
338 MOD_KW => &SyntaxInfo { name: "MOD_KW" },
339 PUB_KW => &SyntaxInfo { name: "PUB_KW" },
340 SELF_KW => &SyntaxInfo { name: "SELF_KW" },
341 SUPER_KW => &SyntaxInfo { name: "SUPER_KW" },
342 IN_KW => &SyntaxInfo { name: "IN_KW" },
343 WHERE_KW => &SyntaxInfo { name: "WHERE_KW" },
344 FOR_KW => &SyntaxInfo { name: "FOR_KW" },
345 LOOP_KW => &SyntaxInfo { name: "LOOP_KW" },
346 WHILE_KW => &SyntaxInfo { name: "WHILE_KW" },
347 CONTINUE_KW => &SyntaxInfo { name: "CONTINUE_KW" },
348 BREAK_KW => &SyntaxInfo { name: "BREAK_KW" },
349 IF_KW => &SyntaxInfo { name: "IF_KW" },
350 ELSE_KW => &SyntaxInfo { name: "ELSE_KW" },
351 MATCH_KW => &SyntaxInfo { name: "MATCH_KW" },
352 CONST_KW => &SyntaxInfo { name: "CONST_KW" },
353 STATIC_KW => &SyntaxInfo { name: "STATIC_KW" },
354 MUT_KW => &SyntaxInfo { name: "MUT_KW" },
355 UNSAFE_KW => &SyntaxInfo { name: "UNSAFE_KW" },
356 TYPE_KW => &SyntaxInfo { name: "TYPE_KW" },
357 REF_KW => &SyntaxInfo { name: "REF_KW" },
358 LET_KW => &SyntaxInfo { name: "LET_KW" },
359 MOVE_KW => &SyntaxInfo { name: "MOVE_KW" },
360 RETURN_KW => &SyntaxInfo { name: "RETURN_KW" },
361 AUTO_KW => &SyntaxInfo { name: "AUTO_KW" },
362 DEFAULT_KW => &SyntaxInfo { name: "DEFAULT_KW" },
363 UNION_KW => &SyntaxInfo { name: "UNION_KW" },
364 ERROR => &SyntaxInfo { name: "ERROR" },
365 IDENT => &SyntaxInfo { name: "IDENT" },
366 UNDERSCORE => &SyntaxInfo { name: "UNDERSCORE" },
367 WHITESPACE => &SyntaxInfo { name: "WHITESPACE" },
368 INT_NUMBER => &SyntaxInfo { name: "INT_NUMBER" },
369 FLOAT_NUMBER => &SyntaxInfo { name: "FLOAT_NUMBER" },
370 LIFETIME => &SyntaxInfo { name: "LIFETIME" },
371 CHAR => &SyntaxInfo { name: "CHAR" },
372 BYTE => &SyntaxInfo { name: "BYTE" },
373 STRING => &SyntaxInfo { name: "STRING" },
374 RAW_STRING => &SyntaxInfo { name: "RAW_STRING" },
375 BYTE_STRING => &SyntaxInfo { name: "BYTE_STRING" },
376 RAW_BYTE_STRING => &SyntaxInfo { name: "RAW_BYTE_STRING" },
377 COMMENT => &SyntaxInfo { name: "COMMENT" },
378 DOC_COMMENT => &SyntaxInfo { name: "DOC_COMMENT" },
379 SHEBANG => &SyntaxInfo { name: "SHEBANG" },
380 ROOT => &SyntaxInfo { name: "ROOT" },
381 STRUCT_DEF => &SyntaxInfo { name: "STRUCT_DEF" },
382 ENUM_DEF => &SyntaxInfo { name: "ENUM_DEF" },
383 FN_DEF => &SyntaxInfo { name: "FN_DEF" },
384 RET_TYPE => &SyntaxInfo { name: "RET_TYPE" },
385 EXTERN_CRATE_ITEM => &SyntaxInfo { name: "EXTERN_CRATE_ITEM" },
386 MODULE => &SyntaxInfo { name: "MODULE" },
387 USE_ITEM => &SyntaxInfo { name: "USE_ITEM" },
388 STATIC_DEF => &SyntaxInfo { name: "STATIC_DEF" },
389 CONST_DEF => &SyntaxInfo { name: "CONST_DEF" },
390 TRAIT_DEF => &SyntaxInfo { name: "TRAIT_DEF" },
391 IMPL_ITEM => &SyntaxInfo { name: "IMPL_ITEM" },
392 TYPE_DEF => &SyntaxInfo { name: "TYPE_DEF" },
393 MACRO_CALL => &SyntaxInfo { name: "MACRO_CALL" },
394 TOKEN_TREE => &SyntaxInfo { name: "TOKEN_TREE" },
395 PAREN_TYPE => &SyntaxInfo { name: "PAREN_TYPE" },
396 TUPLE_TYPE => &SyntaxInfo { name: "TUPLE_TYPE" },
397 NEVER_TYPE => &SyntaxInfo { name: "NEVER_TYPE" },
398 PATH_TYPE => &SyntaxInfo { name: "PATH_TYPE" },
399 POINTER_TYPE => &SyntaxInfo { name: "POINTER_TYPE" },
400 ARRAY_TYPE => &SyntaxInfo { name: "ARRAY_TYPE" },
401 SLICE_TYPE => &SyntaxInfo { name: "SLICE_TYPE" },
402 REFERENCE_TYPE => &SyntaxInfo { name: "REFERENCE_TYPE" },
403 PLACEHOLDER_TYPE => &SyntaxInfo { name: "PLACEHOLDER_TYPE" },
404 FN_POINTER_TYPE => &SyntaxInfo { name: "FN_POINTER_TYPE" },
405 FOR_TYPE => &SyntaxInfo { name: "FOR_TYPE" },
406 IMPL_TRAIT_TYPE => &SyntaxInfo { name: "IMPL_TRAIT_TYPE" },
407 DYN_TRAIT_TYPE => &SyntaxInfo { name: "DYN_TRAIT_TYPE" },
408 REF_PAT => &SyntaxInfo { name: "REF_PAT" },
409 BIND_PAT => &SyntaxInfo { name: "BIND_PAT" },
410 PLACEHOLDER_PAT => &SyntaxInfo { name: "PLACEHOLDER_PAT" },
411 PATH_PAT => &SyntaxInfo { name: "PATH_PAT" },
412 STRUCT_PAT => &SyntaxInfo { name: "STRUCT_PAT" },
413 FIELD_PAT_LIST => &SyntaxInfo { name: "FIELD_PAT_LIST" },
414 TUPLE_STRUCT_PAT => &SyntaxInfo { name: "TUPLE_STRUCT_PAT" },
415 TUPLE_PAT => &SyntaxInfo { name: "TUPLE_PAT" },
416 SLICE_PAT => &SyntaxInfo { name: "SLICE_PAT" },
417 RANGE_PAT => &SyntaxInfo { name: "RANGE_PAT" },
418 TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" },
419 ARRAY_EXPR => &SyntaxInfo { name: "ARRAY_EXPR" },
420 PAREN_EXPR => &SyntaxInfo { name: "PAREN_EXPR" },
421 PATH_EXPR => &SyntaxInfo { name: "PATH_EXPR" },
422 LAMBDA_EXPR => &SyntaxInfo { name: "LAMBDA_EXPR" },
423 IF_EXPR => &SyntaxInfo { name: "IF_EXPR" },
424 WHILE_EXPR => &SyntaxInfo { name: "WHILE_EXPR" },
425 CONDITION => &SyntaxInfo { name: "CONDITION" },
426 LOOP_EXPR => &SyntaxInfo { name: "LOOP_EXPR" },
427 FOR_EXPR => &SyntaxInfo { name: "FOR_EXPR" },
428 CONTINUE_EXPR => &SyntaxInfo { name: "CONTINUE_EXPR" },
429 BREAK_EXPR => &SyntaxInfo { name: "BREAK_EXPR" },
430 LABEL => &SyntaxInfo { name: "LABEL" },
431 BLOCK_EXPR => &SyntaxInfo { name: "BLOCK_EXPR" },
432 RETURN_EXPR => &SyntaxInfo { name: "RETURN_EXPR" },
433 MATCH_EXPR => &SyntaxInfo { name: "MATCH_EXPR" },
434 MATCH_ARM_LIST => &SyntaxInfo { name: "MATCH_ARM_LIST" },
435 MATCH_ARM => &SyntaxInfo { name: "MATCH_ARM" },
436 MATCH_GUARD => &SyntaxInfo { name: "MATCH_GUARD" },
437 STRUCT_LIT => &SyntaxInfo { name: "STRUCT_LIT" },
438 NAMED_FIELD_LIST => &SyntaxInfo { name: "NAMED_FIELD_LIST" },
439 NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" },
440 CALL_EXPR => &SyntaxInfo { name: "CALL_EXPR" },
441 INDEX_EXPR => &SyntaxInfo { name: "INDEX_EXPR" },
442 METHOD_CALL_EXPR => &SyntaxInfo { name: "METHOD_CALL_EXPR" },
443 FIELD_EXPR => &SyntaxInfo { name: "FIELD_EXPR" },
444 TRY_EXPR => &SyntaxInfo { name: "TRY_EXPR" },
445 CAST_EXPR => &SyntaxInfo { name: "CAST_EXPR" },
446 REF_EXPR => &SyntaxInfo { name: "REF_EXPR" },
447 PREFIX_EXPR => &SyntaxInfo { name: "PREFIX_EXPR" },
448 RANGE_EXPR => &SyntaxInfo { name: "RANGE_EXPR" },
449 BIN_EXPR => &SyntaxInfo { name: "BIN_EXPR" },
450 BLOCK => &SyntaxInfo { name: "BLOCK" },
451 EXTERN_BLOCK => &SyntaxInfo { name: "EXTERN_BLOCK" },
452 EXTERN_ITEM_LIST => &SyntaxInfo { name: "EXTERN_ITEM_LIST" },
453 ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" },
454 NAMED_FIELD_DEF_LIST => &SyntaxInfo { name: "NAMED_FIELD_DEF_LIST" },
455 NAMED_FIELD_DEF => &SyntaxInfo { name: "NAMED_FIELD_DEF" },
456 POS_FIELD_LIST => &SyntaxInfo { name: "POS_FIELD_LIST" },
457 POS_FIELD => &SyntaxInfo { name: "POS_FIELD" },
458 ENUM_VARIANT_LIST => &SyntaxInfo { name: "ENUM_VARIANT_LIST" },
459 ITEM_LIST => &SyntaxInfo { name: "ITEM_LIST" },
460 ATTR => &SyntaxInfo { name: "ATTR" },
461 META_ITEM => &SyntaxInfo { name: "META_ITEM" },
462 USE_TREE => &SyntaxInfo { name: "USE_TREE" },
463 USE_TREE_LIST => &SyntaxInfo { name: "USE_TREE_LIST" },
464 PATH => &SyntaxInfo { name: "PATH" },
465 PATH_SEGMENT => &SyntaxInfo { name: "PATH_SEGMENT" },
466 LITERAL => &SyntaxInfo { name: "LITERAL" },
467 ALIAS => &SyntaxInfo { name: "ALIAS" },
468 VISIBILITY => &SyntaxInfo { name: "VISIBILITY" },
469 WHERE_CLAUSE => &SyntaxInfo { name: "WHERE_CLAUSE" },
470 WHERE_PRED => &SyntaxInfo { name: "WHERE_PRED" },
471 ABI => &SyntaxInfo { name: "ABI" },
472 NAME => &SyntaxInfo { name: "NAME" },
473 NAME_REF => &SyntaxInfo { name: "NAME_REF" },
474 LET_STMT => &SyntaxInfo { name: "LET_STMT" },
475 EXPR_STMT => &SyntaxInfo { name: "EXPR_STMT" },
476 TYPE_PARAM_LIST => &SyntaxInfo { name: "TYPE_PARAM_LIST" },
477 LIFETIME_PARAM => &SyntaxInfo { name: "LIFETIME_PARAM" },
478 TYPE_PARAM => &SyntaxInfo { name: "TYPE_PARAM" },
479 TYPE_ARG_LIST => &SyntaxInfo { name: "TYPE_ARG_LIST" },
480 LIFETIME_ARG => &SyntaxInfo { name: "LIFETIME_ARG" },
481 TYPE_ARG => &SyntaxInfo { name: "TYPE_ARG" },
482 ASSOC_TYPE_ARG => &SyntaxInfo { name: "ASSOC_TYPE_ARG" },
483 PARAM_LIST => &SyntaxInfo { name: "PARAM_LIST" },
484 PARAM => &SyntaxInfo { name: "PARAM" },
485 SELF_PARAM => &SyntaxInfo { name: "SELF_PARAM" },
486 ARG_LIST => &SyntaxInfo { name: "ARG_LIST" },
487 TOMBSTONE => &SyntaxInfo { name: "TOMBSTONE" },
488 EOF => &SyntaxInfo { name: "EOF" },
489 }
490 }
491 pub(crate) fn from_keyword(ident: &str) -> Option<SyntaxKind> {
492 let kw = match ident {
493 "use" => USE_KW,
494 "fn" => FN_KW,
495 "struct" => STRUCT_KW,
496 "enum" => ENUM_KW,
497 "trait" => TRAIT_KW,
498 "impl" => IMPL_KW,
499 "dyn" => DYN_KW,
500 "true" => TRUE_KW,
501 "false" => FALSE_KW,
502 "as" => AS_KW,
503 "extern" => EXTERN_KW,
504 "crate" => CRATE_KW,
505 "mod" => MOD_KW,
506 "pub" => PUB_KW,
507 "self" => SELF_KW,
508 "super" => SUPER_KW,
509 "in" => IN_KW,
510 "where" => WHERE_KW,
511 "for" => FOR_KW,
512 "loop" => LOOP_KW,
513 "while" => WHILE_KW,
514 "continue" => CONTINUE_KW,
515 "break" => BREAK_KW,
516 "if" => IF_KW,
517 "else" => ELSE_KW,
518 "match" => MATCH_KW,
519 "const" => CONST_KW,
520 "static" => STATIC_KW,
521 "mut" => MUT_KW,
522 "unsafe" => UNSAFE_KW,
523 "type" => TYPE_KW,
524 "ref" => REF_KW,
525 "let" => LET_KW,
526 "move" => MOVE_KW,
527 "return" => RETURN_KW,
528 _ => return None,
529 };
530 Some(kw)
531 }
532
533 pub(crate) fn from_char(c: char) -> Option<SyntaxKind> {
534 let tok = match c {
535 ';' => SEMI,
536 ',' => COMMA,
537 '(' => L_PAREN,
538 ')' => R_PAREN,
539 '{' => L_CURLY,
540 '}' => R_CURLY,
541 '[' => L_BRACK,
542 ']' => R_BRACK,
543 '<' => L_ANGLE,
544 '>' => R_ANGLE,
545 '@' => AT,
546 '#' => POUND,
547 '~' => TILDE,
548 '?' => QUESTION,
549 '$' => DOLLAR,
550 '&' => AMP,
551 '|' => PIPE,
552 '+' => PLUS,
553 '*' => STAR,
554 '/' => SLASH,
555 '^' => CARET,
556 '%' => PERCENT,
557 _ => return None,
558 };
559 Some(tok)
560 }
561}
562
diff --git a/crates/ra_syntax/src/syntax_kinds/generated.rs.tera b/crates/ra_syntax/src/syntax_kinds/generated.rs.tera
new file mode 100644
index 000000000..90618721a
--- /dev/null
+++ b/crates/ra_syntax/src/syntax_kinds/generated.rs.tera
@@ -0,0 +1,73 @@
1#![allow(bad_style, missing_docs, unreachable_pub)]
2#![cfg_attr(rustfmt, rustfmt_skip)]
3use super::SyntaxInfo;
4
5/// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT_DEF`.
6#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub enum SyntaxKind {
8 // Technical SyntaxKinds: they appear temporally during parsing,
9 // but never end up in the final tree
10 #[doc(hidden)]
11 TOMBSTONE,
12 #[doc(hidden)]
13 EOF,
14
15{%- for t in concat(a=single_byte_tokens, b=multi_byte_tokens) %}
16 {{t.1}},
17{%- endfor -%}
18{% for kw in concat(a=keywords, b=contextual_keywords) %}
19 {{kw | upper}}_KW,
20{%- endfor -%}
21{% for t in concat(a=tokens, b=nodes) %}
22 {{t}},
23{%- endfor %}
24}
25use self::SyntaxKind::*;
26
27impl SyntaxKind {
28 pub fn is_keyword(self) -> bool {
29 match self {
30{%- for kw in concat(a=keywords, b=contextual_keywords) %}
31 | {{kw | upper}}_KW
32{%- endfor %}
33 => true,
34 _ => false
35 }
36 }
37
38 pub(crate) fn info(self) -> &'static SyntaxInfo {
39 match self {
40{%- for t in concat(a=single_byte_tokens, b=multi_byte_tokens) %}
41 {{t.1}} => &SyntaxInfo { name: "{{t.1}}" },
42{%- endfor -%}
43{% for kw in concat(a=keywords, b=contextual_keywords) %}
44 {{kw | upper}}_KW => &SyntaxInfo { name: "{{kw | upper}}_KW" },
45{%- endfor -%}
46{% for t in concat(a=tokens, b=nodes) %}
47 {{t}} => &SyntaxInfo { name: "{{t}}" },
48{%- endfor %}
49 TOMBSTONE => &SyntaxInfo { name: "TOMBSTONE" },
50 EOF => &SyntaxInfo { name: "EOF" },
51 }
52 }
53 pub(crate) fn from_keyword(ident: &str) -> Option<SyntaxKind> {
54 let kw = match ident {
55{%- for kw in keywords %}
56 "{{kw}}" => {{kw | upper}}_KW,
57{%- endfor %}
58 _ => return None,
59 };
60 Some(kw)
61 }
62
63 pub(crate) fn from_char(c: char) -> Option<SyntaxKind> {
64 let tok = match c {
65{%- for t in single_byte_tokens %}
66 '{{t.0}}' => {{t.1}},
67{%- endfor %}
68 _ => return None,
69 };
70 Some(tok)
71 }
72}
73
diff --git a/crates/ra_syntax/src/syntax_kinds/mod.rs b/crates/ra_syntax/src/syntax_kinds/mod.rs
new file mode 100644
index 000000000..332cd13ac
--- /dev/null
+++ b/crates/ra_syntax/src/syntax_kinds/mod.rs
@@ -0,0 +1,26 @@
1mod generated;
2
3use std::fmt;
4use SyntaxKind::*;
5
6pub use self::generated::SyntaxKind;
7
8impl fmt::Debug for SyntaxKind {
9 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10 let name = self.info().name;
11 f.write_str(name)
12 }
13}
14
15pub(crate) struct SyntaxInfo {
16 pub name: &'static str,
17}
18
19impl SyntaxKind {
20 pub fn is_trivia(self) -> bool {
21 match self {
22 WHITESPACE | COMMENT | DOC_COMMENT => true,
23 _ => false,
24 }
25 }
26}
diff --git a/crates/ra_syntax/src/text_utils.rs b/crates/ra_syntax/src/text_utils.rs
new file mode 100644
index 000000000..58ae1e43e
--- /dev/null
+++ b/crates/ra_syntax/src/text_utils.rs
@@ -0,0 +1,26 @@
1use {TextRange, TextUnit};
2
3pub fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool {
4 range.start() <= offset && offset <= range.end()
5}
6
7pub fn is_subrange(range: TextRange, subrange: TextRange) -> bool {
8 range.start() <= subrange.start() && subrange.end() <= range.end()
9}
10
11pub fn intersect(r1: TextRange, r2: TextRange) -> Option<TextRange> {
12 let start = r1.start().max(r2.start());
13 let end = r1.end().min(r2.end());
14 if start <= end {
15 Some(TextRange::from_to(start, end))
16 } else {
17 None
18 }
19}
20
21pub fn replace_range(mut text: String, range: TextRange, replace_with: &str) -> String {
22 let start = u32::from(range.start()) as usize;
23 let end = u32::from(range.end()) as usize;
24 text.replace_range(start..end, replace_with);
25 text
26} \ No newline at end of file
diff --git a/crates/ra_syntax/src/token_set.rs b/crates/ra_syntax/src/token_set.rs
new file mode 100644
index 000000000..c83fba81b
--- /dev/null
+++ b/crates/ra_syntax/src/token_set.rs
@@ -0,0 +1,37 @@
1use SyntaxKind;
2
3#[derive(Clone, Copy)]
4pub(crate) struct TokenSet(pub(crate) u128);
5
6fn mask(kind: SyntaxKind) -> u128 {
7 1u128 << (kind as usize)
8}
9
10impl TokenSet {
11 pub const EMPTY: TokenSet = TokenSet(0);
12
13 pub fn contains(&self, kind: SyntaxKind) -> bool {
14 self.0 & mask(kind) != 0
15 }
16}
17
18#[macro_export]
19macro_rules! token_set {
20 ($($t:ident),*) => { TokenSet($(1u128 << ($t as usize))|*) };
21 ($($t:ident),* ,) => { token_set!($($t),*) };
22}
23
24#[macro_export]
25macro_rules! token_set_union {
26 ($($ts:expr),*) => { TokenSet($($ts.0)|*) };
27 ($($ts:expr),* ,) => { token_set_union!($($ts),*) };
28}
29
30#[test]
31fn token_set_works_for_tokens() {
32 use SyntaxKind::*;
33 let ts = token_set! { EOF, SHEBANG };
34 assert!(ts.contains(EOF));
35 assert!(ts.contains(SHEBANG));
36 assert!(!ts.contains(PLUS));
37}
diff --git a/crates/ra_syntax/src/utils.rs b/crates/ra_syntax/src/utils.rs
new file mode 100644
index 000000000..671dd7afa
--- /dev/null
+++ b/crates/ra_syntax/src/utils.rs
@@ -0,0 +1,85 @@
1use std::fmt::Write;
2use {
3 algo::walk::{preorder, walk, WalkEvent},
4 SyntaxKind, File, SyntaxNodeRef, TreeRoot,
5};
6
7/// Parse a file and create a string representation of the resulting parse tree.
8pub fn dump_tree(syntax: SyntaxNodeRef) -> String {
9 let mut errors: Vec<_> = syntax.root.syntax_root().errors.iter().cloned().collect();
10 errors.sort_by_key(|e| e.offset);
11 let mut err_pos = 0;
12 let mut level = 0;
13 let mut buf = String::new();
14 macro_rules! indent {
15 () => {
16 for _ in 0..level {
17 buf.push_str(" ");
18 }
19 };
20 }
21
22 for event in walk(syntax) {
23 match event {
24 WalkEvent::Enter(node) => {
25 indent!();
26 writeln!(buf, "{:?}", node).unwrap();
27 if node.first_child().is_none() {
28 let off = node.range().end();
29 while err_pos < errors.len() && errors[err_pos].offset <= off {
30 indent!();
31 writeln!(buf, "err: `{}`", errors[err_pos].msg).unwrap();
32 err_pos += 1;
33 }
34 }
35 level += 1;
36 }
37 WalkEvent::Exit(_) => level -= 1,
38 }
39 }
40
41 assert_eq!(level, 0);
42 for err in errors[err_pos..].iter() {
43 writeln!(buf, "err: `{}`", err.msg).unwrap();
44 }
45
46 return buf;
47}
48
49pub fn check_fuzz_invariants(text: &str) {
50 let file = File::parse(text);
51 let root = file.syntax();
52 validate_block_structure(root);
53 let _ = file.ast();
54 let _ = file.errors();
55}
56
57pub(crate) fn validate_block_structure(root: SyntaxNodeRef) {
58 let mut stack = Vec::new();
59 for node in preorder(root) {
60 match node.kind() {
61 SyntaxKind::L_CURLY => {
62 stack.push(node)
63 }
64 SyntaxKind::R_CURLY => {
65 if let Some(pair) = stack.pop() {
66 assert_eq!(
67 node.parent(),
68 pair.parent(),
69 "\nunpaired curleys:\n{}\n{}\n",
70 root.text(),
71 dump_tree(root),
72 );
73 assert!(
74 node.next_sibling().is_none() && pair.prev_sibling().is_none(),
75 "\nfloating curlys at {:?}\nfile:\n{}\nerror:\n{}\n",
76 node,
77 root.text(),
78 node.text(),
79 );
80 }
81 }
82 _ => (),
83 }
84 }
85}
diff --git a/crates/ra_syntax/src/yellow/builder.rs b/crates/ra_syntax/src/yellow/builder.rs
new file mode 100644
index 000000000..e4ab37899
--- /dev/null
+++ b/crates/ra_syntax/src/yellow/builder.rs
@@ -0,0 +1,64 @@
1use {
2 parser_impl::Sink,
3 yellow::{GreenNode, SyntaxError},
4 SyntaxKind, TextRange, TextUnit,
5};
6
7pub(crate) struct GreenBuilder<'a> {
8 text: &'a str,
9 parents: Vec<(SyntaxKind, usize)>,
10 children: Vec<GreenNode>,
11 pos: TextUnit,
12 errors: Vec<SyntaxError>,
13}
14
15impl<'a> Sink<'a> for GreenBuilder<'a> {
16 type Tree = (GreenNode, Vec<SyntaxError>);
17
18 fn new(text: &'a str) -> Self {
19 GreenBuilder {
20 text,
21 parents: Vec::new(),
22 children: Vec::new(),
23 pos: 0.into(),
24 errors: Vec::new(),
25 }
26 }
27
28 fn leaf(&mut self, kind: SyntaxKind, len: TextUnit) {
29 let range = TextRange::offset_len(self.pos, len);
30 self.pos += len;
31 let text = &self.text[range];
32 self.children.push(
33 GreenNode::new_leaf(kind, text)
34 );
35 }
36
37 fn start_internal(&mut self, kind: SyntaxKind) {
38 let len = self.children.len();
39 self.parents.push((kind, len));
40 }
41
42 fn finish_internal(&mut self) {
43 let (kind, first_child) = self.parents.pop().unwrap();
44 let children: Vec<_> = self.children
45 .drain(first_child..)
46 .collect();
47 self.children.push(
48 GreenNode::new_branch(kind, children.into_boxed_slice())
49 );
50 }
51
52 fn error(&mut self, message: String) {
53 self.errors.push(SyntaxError {
54 msg: message,
55 offset: self.pos,
56 })
57 }
58
59 fn finish(mut self) -> (GreenNode, Vec<SyntaxError>) {
60 assert_eq!(self.children.len(), 1);
61 let root = self.children.pop().unwrap();
62 (root, self.errors)
63 }
64}
diff --git a/crates/ra_syntax/src/yellow/green.rs b/crates/ra_syntax/src/yellow/green.rs
new file mode 100644
index 000000000..8fb691643
--- /dev/null
+++ b/crates/ra_syntax/src/yellow/green.rs
@@ -0,0 +1,90 @@
1use std::sync::Arc;
2
3use smol_str::SmolStr;
4
5use {SyntaxKind, TextUnit};
6
7#[derive(Clone, Debug)]
8pub(crate) enum GreenNode {
9 Leaf {
10 kind: SyntaxKind,
11 text: SmolStr,
12 },
13 Branch(Arc<GreenBranch>),
14}
15
16impl GreenNode {
17 pub(crate) fn new_leaf(kind: SyntaxKind, text: &str) -> GreenNode {
18 GreenNode::Leaf { kind, text: SmolStr::new(text) }
19 }
20
21 pub(crate) fn new_branch(kind: SyntaxKind, children: Box<[GreenNode]>) -> GreenNode {
22 GreenNode::Branch(Arc::new(GreenBranch::new(kind, children)))
23 }
24
25 pub fn kind(&self) -> SyntaxKind {
26 match self {
27 GreenNode::Leaf { kind, .. } => *kind,
28 GreenNode::Branch(b) => b.kind(),
29 }
30 }
31
32 pub fn text_len(&self) -> TextUnit {
33 match self {
34 GreenNode::Leaf { text, .. } => TextUnit::from(text.len() as u32),
35 GreenNode::Branch(b) => b.text_len(),
36 }
37 }
38
39 pub fn children(&self) -> &[GreenNode] {
40 match self {
41 GreenNode::Leaf { .. } => &[],
42 GreenNode::Branch(b) => b.children(),
43 }
44 }
45
46 pub fn leaf_text_ref(&self) -> Option<&SmolStr> {
47 match self {
48 GreenNode::Leaf { text, .. } => Some(text),
49 GreenNode::Branch(_) => None,
50 }
51 }
52}
53
54#[derive(Clone, Debug)]
55pub(crate) struct GreenBranch {
56 text_len: TextUnit,
57 kind: SyntaxKind,
58 children: Box<[GreenNode]>,
59}
60
61impl GreenBranch {
62 fn new(kind: SyntaxKind, children: Box<[GreenNode]>) -> GreenBranch {
63 let text_len = children.iter().map(|x| x.text_len()).sum::<TextUnit>();
64 GreenBranch {
65 text_len,
66 kind,
67 children,
68 }
69 }
70
71 pub fn kind(&self) -> SyntaxKind {
72 self.kind
73 }
74
75 pub fn text_len(&self) -> TextUnit {
76 self.text_len
77 }
78
79 pub fn children(&self) -> &[GreenNode] {
80 &*self.children
81 }
82}
83
84#[test]
85fn test_sizes() {
86 use std::mem::size_of;
87 println!("GreenBranch = {}", size_of::<GreenBranch>());
88 println!("GreenNode = {}", size_of::<GreenNode>());
89 println!("SmolStr = {}", size_of::<SmolStr>());
90}
diff --git a/crates/ra_syntax/src/yellow/mod.rs b/crates/ra_syntax/src/yellow/mod.rs
new file mode 100644
index 000000000..0596e702f
--- /dev/null
+++ b/crates/ra_syntax/src/yellow/mod.rs
@@ -0,0 +1,100 @@
1mod builder;
2mod green;
3mod red;
4mod syntax;
5mod syntax_text;
6
7use std::{
8 sync::Arc,
9 ptr,
10};
11pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxError, SyntaxNodeChildren};
12pub(crate) use self::{
13 builder::GreenBuilder,
14 green::GreenNode,
15 red::RedNode,
16 syntax_text::SyntaxText,
17};
18
19#[derive(Debug)]
20pub struct SyntaxRoot {
21 red: RedNode,
22 pub(crate) errors: Vec<SyntaxError>,
23}
24
25pub trait TreeRoot: Clone + Send + Sync {
26 fn borrowed(&self) -> RefRoot;
27 fn owned(&self) -> OwnedRoot;
28
29 #[doc(hidden)]
30 fn syntax_root(&self) -> &SyntaxRoot;
31}
32#[derive(Clone, Debug)]
33pub struct OwnedRoot(Arc<SyntaxRoot>);
34#[derive(Clone, Copy, Debug)]
35pub struct RefRoot<'a>(&'a OwnedRoot); // TODO: shared_from_this instead of double indirection
36
37impl<'a> RefRoot<'a> {
38 fn syntax_root(&self) -> &'a SyntaxRoot {
39 self.0.syntax_root()
40 }
41}
42
43impl TreeRoot for OwnedRoot {
44 fn borrowed(&self) -> RefRoot {
45 RefRoot(&self)
46 }
47 fn owned(&self) -> OwnedRoot {
48 self.clone()
49 }
50
51 fn syntax_root(&self) -> &SyntaxRoot {
52 &*self.0
53 }
54}
55
56impl<'a> TreeRoot for RefRoot<'a> {
57 fn borrowed(&self) -> RefRoot {
58 *self
59 }
60 fn owned(&self) -> OwnedRoot {
61 self.0.clone()
62 }
63 fn syntax_root(&self) -> &SyntaxRoot {
64 self.0.syntax_root()
65 }
66}
67
68impl SyntaxRoot {
69 pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> SyntaxRoot {
70 SyntaxRoot {
71 red: RedNode::new_root(green),
72 errors,
73 }
74 }
75}
76
77#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
78pub(crate) struct RedPtr(ptr::NonNull<RedNode>);
79
80unsafe impl Send for RedPtr {}
81
82unsafe impl Sync for RedPtr {}
83
84impl RedPtr {
85 fn new(red: &RedNode) -> RedPtr {
86 RedPtr(red.into())
87 }
88
89 unsafe fn get<'a>(self, _root: &'a SyntaxRoot) -> &'a RedNode {
90 &*self.0.as_ptr()
91 }
92}
93
94#[test]
95fn assert_send_sync() {
96 fn f<T: Send + Sync>() {}
97 f::<GreenNode>();
98 f::<RedNode>();
99 f::<SyntaxNode>();
100}
diff --git a/crates/ra_syntax/src/yellow/red.rs b/crates/ra_syntax/src/yellow/red.rs
new file mode 100644
index 000000000..84cfe4fba
--- /dev/null
+++ b/crates/ra_syntax/src/yellow/red.rs
@@ -0,0 +1,113 @@
1use parking_lot::RwLock;
2use {yellow::{GreenNode, RedPtr}, TextUnit};
3
4#[derive(Debug)]
5pub(crate) struct RedNode {
6 green: GreenNode,
7 parent: Option<ParentData>,
8 children: RwLock<Box<[RedChild]>>,
9}
10
11#[derive(Debug)]
12enum RedChild {
13 Zigot(TextUnit),
14 Child(RedNode)
15}
16
17impl RedChild {
18 fn set(&mut self, node: RedNode) -> &RedNode {
19 match self {
20 RedChild::Child(node) => return node,
21 RedChild::Zigot(_) => {
22 *self = RedChild::Child(node);
23 match self {
24 RedChild::Child(node) => return node,
25 RedChild::Zigot(_) => unreachable!()
26 }
27 }
28 }
29 }
30}
31
32#[derive(Debug)]
33struct ParentData {
34 parent: RedPtr,
35 start_offset: TextUnit,
36 index_in_parent: usize,
37}
38
39impl RedNode {
40 pub fn new_root(green: GreenNode) -> RedNode {
41 RedNode::new(green, None)
42 }
43
44 fn new_child(
45 green: GreenNode,
46 parent: RedPtr,
47 start_offset: TextUnit,
48 index_in_parent: usize,
49 ) -> RedNode {
50 let parent_data = ParentData {
51 parent,
52 start_offset,
53 index_in_parent,
54 };
55 RedNode::new(green, Some(parent_data))
56 }
57
58 fn new(green: GreenNode, parent: Option<ParentData>) -> RedNode {
59 let mut start_offset = parent.as_ref().map(|it| it.start_offset).unwrap_or(0.into());
60 let children = green.children()
61 .iter()
62 .map(|child| {
63 let off = start_offset;
64 start_offset += child.text_len();
65 RedChild::Zigot(off)
66 })
67 .collect::<Vec<_>>()
68 .into_boxed_slice();
69 RedNode {
70 green,
71 parent,
72 children: RwLock::new(children),
73 }
74 }
75
76 pub(crate) fn green(&self) -> &GreenNode {
77 &self.green
78 }
79
80 pub(crate) fn start_offset(&self) -> TextUnit {
81 match &self.parent {
82 None => 0.into(),
83 Some(p) => p.start_offset,
84 }
85 }
86
87 pub(crate) fn n_children(&self) -> usize {
88 self.green.children().len()
89 }
90
91 pub(crate) fn get_child(&self, idx: usize) -> Option<RedPtr> {
92 if idx >= self.n_children() {
93 return None;
94 }
95 let start_offset = match &self.children.read()[idx] {
96 RedChild::Child(child) => return Some(RedPtr::new(child)),
97 RedChild::Zigot(start_offset) => *start_offset,
98 };
99 let green_children = self.green.children();
100 let child =
101 RedNode::new_child(green_children[idx].clone(), RedPtr::new(self), start_offset, idx);
102 let mut children = self.children.write();
103 let child = children[idx].set(child);
104 Some(RedPtr::new(child))
105 }
106
107 pub(crate) fn parent(&self) -> Option<RedPtr> {
108 Some(self.parent.as_ref()?.parent)
109 }
110 pub(crate) fn index_in_parent(&self) -> Option<usize> {
111 Some(self.parent.as_ref()?.index_in_parent)
112 }
113}
diff --git a/crates/ra_syntax/src/yellow/syntax.rs b/crates/ra_syntax/src/yellow/syntax.rs
new file mode 100644
index 000000000..1d99cab4a
--- /dev/null
+++ b/crates/ra_syntax/src/yellow/syntax.rs
@@ -0,0 +1,215 @@
1use std::{
2 fmt, sync::Arc,
3 hash::{Hasher, Hash},
4 ops::Range,
5};
6
7use smol_str::SmolStr;
8
9use {
10 yellow::{GreenNode, RedNode, TreeRoot, SyntaxRoot, RedPtr, RefRoot, OwnedRoot, SyntaxText},
11 SyntaxKind::{self, *},
12 TextRange, TextUnit,
13};
14
15
16#[derive(Clone, Copy)]
17pub struct SyntaxNode<R: TreeRoot = OwnedRoot> {
18 pub(crate) root: R,
19 // Guaranteed to not dangle, because `root` holds a
20 // strong reference to red's ancestor
21 red: RedPtr,
22}
23
24unsafe impl<R: TreeRoot> Send for SyntaxNode<R> {}
25unsafe impl<R: TreeRoot> Sync for SyntaxNode<R> {}
26
27impl<R1: TreeRoot, R2: TreeRoot> PartialEq<SyntaxNode<R1>> for SyntaxNode<R2> {
28 fn eq(&self, other: &SyntaxNode<R1>) -> bool {
29 self.red == other.red
30 }
31}
32
33impl<R: TreeRoot> Eq for SyntaxNode<R> {}
34impl<R: TreeRoot> Hash for SyntaxNode<R> {
35 fn hash<H: Hasher>(&self, state: &mut H) {
36 self.red.hash(state)
37 }
38}
39
40pub type SyntaxNodeRef<'a> = SyntaxNode<RefRoot<'a>>;
41
42#[test]
43fn syntax_node_ref_is_copy() {
44 fn assert_copy<T: Copy>(){}
45 assert_copy::<SyntaxNodeRef>()
46}
47
48#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
49pub struct SyntaxError {
50 pub msg: String,
51 pub offset: TextUnit,
52}
53
54impl SyntaxNode<OwnedRoot> {
55 pub(crate) fn new_owned(root: SyntaxRoot) -> Self {
56 let root = OwnedRoot(Arc::new(root));
57 let red = RedPtr::new(&root.syntax_root().red);
58 SyntaxNode { root, red }
59 }
60}
61
62impl<'a> SyntaxNode<RefRoot<'a>> {
63 pub(crate) fn leaf_text_ref(self) -> Option<&'a SmolStr> {
64 let red = unsafe { self.red.get(self.root.syntax_root()) };
65 red.green().leaf_text_ref()
66 }
67}
68
69impl<R: TreeRoot> SyntaxNode<R> {
70 pub fn borrowed<'a>(&'a self) -> SyntaxNodeRef<'a> {
71 SyntaxNode {
72 root: self.root.borrowed(),
73 red: self.red,
74 }
75 }
76
77 pub fn owned(&self) -> SyntaxNode {
78 SyntaxNode {
79 root: self.root.owned(),
80 red: self.red,
81 }
82 }
83
84 pub fn kind(&self) -> SyntaxKind {
85 self.red().green().kind()
86 }
87
88 pub fn range(&self) -> TextRange {
89 let red = self.red();
90 TextRange::offset_len(red.start_offset(), red.green().text_len())
91 }
92
93 pub fn text(&self) -> SyntaxText {
94 SyntaxText::new(self.borrowed())
95 }
96
97 pub fn children(&self) -> SyntaxNodeChildren<R> {
98 SyntaxNodeChildren {
99 parent: self.clone(),
100 iter: (0..self.red().n_children())
101 }
102 }
103
104 pub fn parent(&self) -> Option<SyntaxNode<R>> {
105 let parent = self.red().parent()?;
106 Some(SyntaxNode {
107 root: self.root.clone(),
108 red: parent,
109 })
110 }
111
112 pub fn first_child(&self) -> Option<SyntaxNode<R>> {
113 let red = self.red().get_child(0)?;
114 Some(SyntaxNode { root: self.root.clone(), red })
115 }
116
117 pub fn last_child(&self) -> Option<SyntaxNode<R>> {
118 let n = self.red().n_children();
119 let n = n.checked_sub(1)?;
120 let red = self.red().get_child(n)?;
121 Some(SyntaxNode { root: self.root.clone(), red })
122 }
123
124 pub fn next_sibling(&self) -> Option<SyntaxNode<R>> {
125 let red = self.red();
126 let parent = self.parent()?;
127 let next_sibling_idx = red.index_in_parent()? + 1;
128 let sibling_red = parent.red().get_child(next_sibling_idx)?;
129 Some(SyntaxNode {
130 root: self.root.clone(),
131 red: sibling_red,
132 })
133 }
134
135 pub fn prev_sibling(&self) -> Option<SyntaxNode<R>> {
136 let red = self.red();
137 let parent = self.parent()?;
138 let prev_sibling_idx = red.index_in_parent()?.checked_sub(1)?;
139 let sibling_red = parent.red().get_child(prev_sibling_idx)?;
140 Some(SyntaxNode {
141 root: self.root.clone(),
142 red: sibling_red,
143 })
144 }
145
146 pub fn is_leaf(&self) -> bool {
147 self.first_child().is_none()
148 }
149
150 pub fn leaf_text(&self) -> Option<SmolStr> {
151 self.borrowed().leaf_text_ref().map(|it| it.clone())
152 }
153
154 pub(crate) fn replace_with(&self, green: GreenNode) -> GreenNode {
155 assert_eq!(self.kind(), green.kind());
156 match self.parent() {
157 None => green,
158 Some(parent) => {
159 let children: Vec<_> = parent.children().map(|child| {
160 if child == *self {
161 green.clone()
162 } else {
163 child.red().green().clone()
164 }
165 }).collect();
166 let new_parent = GreenNode::new_branch(
167 parent.kind(),
168 children.into_boxed_slice(),
169 );
170 parent.replace_with(new_parent)
171 },
172 }
173 }
174
175 fn red(&self) -> &RedNode {
176 unsafe { self.red.get(self.root.syntax_root()) }
177 }
178}
179
180impl<R: TreeRoot> fmt::Debug for SyntaxNode<R> {
181 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
182 write!(fmt, "{:?}@{:?}", self.kind(), self.range())?;
183 if has_short_text(self.kind()) {
184 write!(fmt, " \"{}\"", self.text())?;
185 }
186 Ok(())
187 }
188}
189
190#[derive(Debug)]
191pub struct SyntaxNodeChildren<R: TreeRoot> {
192 parent: SyntaxNode<R>,
193 iter: Range<usize>,
194}
195
196impl<R: TreeRoot> Iterator for SyntaxNodeChildren<R> {
197 type Item = SyntaxNode<R>;
198
199 fn next(&mut self) -> Option<SyntaxNode<R>> {
200 self.iter.next().map(|i| {
201 let red = self.parent.red();
202 SyntaxNode {
203 root: self.parent.root.clone(),
204 red: red.get_child(i).unwrap(),
205 }
206 })
207 }
208}
209
210fn has_short_text(kind: SyntaxKind) -> bool {
211 match kind {
212 IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true,
213 _ => false,
214 }
215}
diff --git a/crates/ra_syntax/src/yellow/syntax_text.rs b/crates/ra_syntax/src/yellow/syntax_text.rs
new file mode 100644
index 000000000..280bedd78
--- /dev/null
+++ b/crates/ra_syntax/src/yellow/syntax_text.rs
@@ -0,0 +1,122 @@
1use std::{
2 fmt, ops,
3};
4
5use {
6 SyntaxNodeRef, TextRange, TextUnit,
7 algo::walk::preorder,
8 text_utils::{intersect, contains_offset_nonstrict},
9};
10
11#[derive(Clone)]
12pub struct SyntaxText<'a> {
13 node: SyntaxNodeRef<'a>,
14 range: TextRange,
15}
16
17impl<'a> SyntaxText<'a> {
18 pub(crate) fn new(node: SyntaxNodeRef<'a>) -> SyntaxText<'a> {
19 SyntaxText {
20 node,
21 range: node.range()
22 }
23 }
24 pub fn chunks(&self) -> impl Iterator<Item=&'a str> {
25 let range = self.range;
26 preorder(self.node)
27 .filter_map(move |node| {
28 let text = node.leaf_text_ref()?;
29 let range = intersect(range, node.range())?;
30 let range = range - node.range().start();
31 Some(&text[range])
32 })
33 }
34 pub fn push_to(&self, buf: &mut String) {
35 self.chunks().for_each(|it| buf.push_str(it));
36 }
37 pub fn to_string(&self) -> String {
38 self.chunks().collect()
39 }
40 pub fn contains(&self, c: char) -> bool {
41 self.chunks().any(|it| it.contains(c))
42 }
43 pub fn find(&self, c: char) -> Option<TextUnit> {
44 let mut acc: TextUnit = 0.into();
45 for chunk in self.chunks() {
46 if let Some(pos) = chunk.find(c) {
47 let pos: TextUnit = (pos as u32).into();
48 return Some(acc + pos);
49 }
50 acc += TextUnit::of_str(chunk);
51 }
52 None
53 }
54 pub fn len(&self) -> TextUnit {
55 self.range.len()
56 }
57 pub fn slice(&self, range: impl SyntaxTextSlice) -> SyntaxText<'a> {
58 let range = range.restrict(self.range)
59 .unwrap_or_else(|| {
60 panic!("invalid slice, range: {:?}, slice: {:?}", self.range, range)
61 });
62 SyntaxText { node: self.node, range }
63 }
64 pub fn char_at(&self, offset: TextUnit) -> Option<char> {
65 let mut start: TextUnit = 0.into();
66 for chunk in self.chunks() {
67 let end = start + TextUnit::of_str(chunk);
68 if start <= offset && offset < end {
69 let off: usize = u32::from(offset - start) as usize;
70 return Some(chunk[off..].chars().next().unwrap());
71 }
72 start = end;
73 }
74 None
75 }
76}
77
78impl<'a> fmt::Debug for SyntaxText<'a> {
79 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80 fmt::Debug::fmt(&self.to_string(), f)
81 }
82}
83
84impl<'a> fmt::Display for SyntaxText<'a> {
85 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86 fmt::Display::fmt(&self.to_string(), f)
87 }
88}
89
90pub trait SyntaxTextSlice: fmt::Debug {
91 fn restrict(&self, range: TextRange) -> Option<TextRange>;
92}
93
94impl SyntaxTextSlice for TextRange {
95 fn restrict(&self, range: TextRange) -> Option<TextRange> {
96 intersect(*self, range)
97 }
98}
99
100impl SyntaxTextSlice for ops::RangeTo<TextUnit> {
101 fn restrict(&self, range: TextRange) -> Option<TextRange> {
102 if !contains_offset_nonstrict(range, self.end) {
103 return None;
104 }
105 Some(TextRange::from_to(range.start(), self.end))
106 }
107}
108
109impl SyntaxTextSlice for ops::RangeFrom<TextUnit> {
110 fn restrict(&self, range: TextRange) -> Option<TextRange> {
111 if !contains_offset_nonstrict(range, self.start) {
112 return None;
113 }
114 Some(TextRange::from_to(self.start, range.end()))
115 }
116}
117
118impl SyntaxTextSlice for ops::Range<TextUnit> {
119 fn restrict(&self, range: TextRange) -> Option<TextRange> {
120 TextRange::from_to(self.start, self.end).restrict(range)
121 }
122}