diff options
Diffstat (limited to 'crates/ra_syntax/src')
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 @@ | |||
1 | pub mod walk; | ||
2 | pub mod visit; | ||
3 | |||
4 | use { | ||
5 | SyntaxNodeRef, TextUnit, TextRange, | ||
6 | text_utils::{contains_offset_nonstrict, is_subrange}, | ||
7 | }; | ||
8 | |||
9 | pub 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)] | ||
44 | pub enum LeafAtOffset<'a> { | ||
45 | None, | ||
46 | Single(SyntaxNodeRef<'a>), | ||
47 | Between(SyntaxNodeRef<'a>, SyntaxNodeRef<'a>) | ||
48 | } | ||
49 | |||
50 | impl<'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 | |||
68 | impl<'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 | |||
80 | pub 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 | |||
93 | pub fn ancestors<'a>(node: SyntaxNodeRef<'a>) -> impl Iterator<Item=SyntaxNodeRef<'a>> { | ||
94 | generate(Some(node), |&node| node.parent()) | ||
95 | } | ||
96 | |||
97 | #[derive(Debug)] | ||
98 | pub enum Direction { | ||
99 | Forward, | ||
100 | Backward, | ||
101 | } | ||
102 | |||
103 | pub 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 | |||
113 | fn 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 | |||
122 | pub 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 @@ | |||
1 | use std::marker::PhantomData; | ||
2 | use {SyntaxNodeRef, AstNode}; | ||
3 | |||
4 | |||
5 | pub fn visitor<'a, T>() -> impl Visitor<'a, Output=T> { | ||
6 | EmptyVisitor { ph: PhantomData } | ||
7 | } | ||
8 | |||
9 | pub fn visitor_ctx<'a, T, C>(ctx: C) -> impl VisitorCtx<'a, Output=T, Ctx=C> { | ||
10 | EmptyVisitorCtx { ph: PhantomData, ctx } | ||
11 | } | ||
12 | |||
13 | pub 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 | |||
24 | pub 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)] | ||
37 | struct EmptyVisitor<T> { | ||
38 | ph: PhantomData<fn() -> T> | ||
39 | } | ||
40 | |||
41 | impl<'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)] | ||
50 | struct EmptyVisitorCtx<T, C> { | ||
51 | ctx: C, | ||
52 | ph: PhantomData<fn() -> T>, | ||
53 | } | ||
54 | |||
55 | impl<'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)] | ||
65 | pub struct Vis<V, N, F> { | ||
66 | inner: V, | ||
67 | f: F, | ||
68 | ph: PhantomData<fn(N)>, | ||
69 | } | ||
70 | |||
71 | impl<'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)] | ||
86 | pub struct VisCtx<V, N, F> { | ||
87 | inner: V, | ||
88 | f: F, | ||
89 | ph: PhantomData<fn(N)>, | ||
90 | } | ||
91 | |||
92 | impl<'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 @@ | |||
1 | use { | ||
2 | SyntaxNodeRef, | ||
3 | algo::generate, | ||
4 | }; | ||
5 | |||
6 | pub 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)] | ||
14 | pub enum WalkEvent<'a> { | ||
15 | Enter(SyntaxNodeRef<'a>), | ||
16 | Exit(SyntaxNodeRef<'a>), | ||
17 | } | ||
18 | |||
19 | pub 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 @@ | |||
1 | use { | ||
2 | ast, | ||
3 | SyntaxNodeRef, AstNode, | ||
4 | SyntaxKind::*, | ||
5 | }; | ||
6 | |||
7 | // ArgList | ||
8 | #[derive(Debug, Clone, Copy)] | ||
9 | pub struct ArgList<'a> { | ||
10 | syntax: SyntaxNodeRef<'a>, | ||
11 | } | ||
12 | |||
13 | impl<'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 | |||
23 | impl<'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)] | ||
31 | pub struct ArrayExpr<'a> { | ||
32 | syntax: SyntaxNodeRef<'a>, | ||
33 | } | ||
34 | |||
35 | impl<'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 | |||
45 | impl<'a> ArrayExpr<'a> {} | ||
46 | |||
47 | // ArrayType | ||
48 | #[derive(Debug, Clone, Copy)] | ||
49 | pub struct ArrayType<'a> { | ||
50 | syntax: SyntaxNodeRef<'a>, | ||
51 | } | ||
52 | |||
53 | impl<'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 | |||
63 | impl<'a> ArrayType<'a> {} | ||
64 | |||
65 | // Attr | ||
66 | #[derive(Debug, Clone, Copy)] | ||
67 | pub struct Attr<'a> { | ||
68 | syntax: SyntaxNodeRef<'a>, | ||
69 | } | ||
70 | |||
71 | impl<'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 | |||
81 | impl<'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)] | ||
88 | pub struct BinExpr<'a> { | ||
89 | syntax: SyntaxNodeRef<'a>, | ||
90 | } | ||
91 | |||
92 | impl<'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 | |||
102 | impl<'a> BinExpr<'a> {} | ||
103 | |||
104 | // BindPat | ||
105 | #[derive(Debug, Clone, Copy)] | ||
106 | pub struct BindPat<'a> { | ||
107 | syntax: SyntaxNodeRef<'a>, | ||
108 | } | ||
109 | |||
110 | impl<'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 | |||
120 | impl<'a> ast::NameOwner<'a> for BindPat<'a> {} | ||
121 | impl<'a> BindPat<'a> {} | ||
122 | |||
123 | // Block | ||
124 | #[derive(Debug, Clone, Copy)] | ||
125 | pub struct Block<'a> { | ||
126 | syntax: SyntaxNodeRef<'a>, | ||
127 | } | ||
128 | |||
129 | impl<'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 | |||
139 | impl<'a> Block<'a> { | ||
140 | pub fn statements(self) -> impl Iterator<Item = Stmt<'a>> + 'a { | ||
141 | super::children(self) | ||
142 | } | ||
143 | pub fn expr(self) -> Option<Expr<'a>> { | ||
144 | super::child_opt(self) | ||
145 | } | ||
146 | } | ||
147 | |||
148 | // BlockExpr | ||
149 | #[derive(Debug, Clone, Copy)] | ||
150 | pub struct BlockExpr<'a> { | ||
151 | syntax: SyntaxNodeRef<'a>, | ||
152 | } | ||
153 | |||
154 | impl<'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 | |||
164 | impl<'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)] | ||
171 | pub struct BreakExpr<'a> { | ||
172 | syntax: SyntaxNodeRef<'a>, | ||
173 | } | ||
174 | |||
175 | impl<'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 | |||
185 | impl<'a> BreakExpr<'a> {} | ||
186 | |||
187 | // CallExpr | ||
188 | #[derive(Debug, Clone, Copy)] | ||
189 | pub struct CallExpr<'a> { | ||
190 | syntax: SyntaxNodeRef<'a>, | ||
191 | } | ||
192 | |||
193 | impl<'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 | |||
203 | impl<'a> ast::ArgListOwner<'a> for CallExpr<'a> {} | ||
204 | impl<'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)] | ||
211 | pub struct CastExpr<'a> { | ||
212 | syntax: SyntaxNodeRef<'a>, | ||
213 | } | ||
214 | |||
215 | impl<'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 | |||
225 | impl<'a> CastExpr<'a> {} | ||
226 | |||
227 | // Condition | ||
228 | #[derive(Debug, Clone, Copy)] | ||
229 | pub struct Condition<'a> { | ||
230 | syntax: SyntaxNodeRef<'a>, | ||
231 | } | ||
232 | |||
233 | impl<'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 | |||
243 | impl<'a> Condition<'a> {pub fn pat(self) -> Option<Pat<'a>> { | ||
244 | super::child_opt(self) | ||
245 | } | ||
246 | pub fn expr(self) -> Option<Expr<'a>> { | ||
247 | super::child_opt(self) | ||
248 | } | ||
249 | } | ||
250 | |||
251 | // ConstDef | ||
252 | #[derive(Debug, Clone, Copy)] | ||
253 | pub struct ConstDef<'a> { | ||
254 | syntax: SyntaxNodeRef<'a>, | ||
255 | } | ||
256 | |||
257 | impl<'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 | |||
267 | impl<'a> ast::NameOwner<'a> for ConstDef<'a> {} | ||
268 | impl<'a> ast::TypeParamsOwner<'a> for ConstDef<'a> {} | ||
269 | impl<'a> ast::AttrsOwner<'a> for ConstDef<'a> {} | ||
270 | impl<'a> ConstDef<'a> {} | ||
271 | |||
272 | // ContinueExpr | ||
273 | #[derive(Debug, Clone, Copy)] | ||
274 | pub struct ContinueExpr<'a> { | ||
275 | syntax: SyntaxNodeRef<'a>, | ||
276 | } | ||
277 | |||
278 | impl<'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 | |||
288 | impl<'a> ContinueExpr<'a> {} | ||
289 | |||
290 | // DynTraitType | ||
291 | #[derive(Debug, Clone, Copy)] | ||
292 | pub struct DynTraitType<'a> { | ||
293 | syntax: SyntaxNodeRef<'a>, | ||
294 | } | ||
295 | |||
296 | impl<'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 | |||
306 | impl<'a> DynTraitType<'a> {} | ||
307 | |||
308 | // EnumDef | ||
309 | #[derive(Debug, Clone, Copy)] | ||
310 | pub struct EnumDef<'a> { | ||
311 | syntax: SyntaxNodeRef<'a>, | ||
312 | } | ||
313 | |||
314 | impl<'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 | |||
324 | impl<'a> ast::NameOwner<'a> for EnumDef<'a> {} | ||
325 | impl<'a> ast::TypeParamsOwner<'a> for EnumDef<'a> {} | ||
326 | impl<'a> ast::AttrsOwner<'a> for EnumDef<'a> {} | ||
327 | impl<'a> EnumDef<'a> {} | ||
328 | |||
329 | // Expr | ||
330 | #[derive(Debug, Clone, Copy)] | ||
331 | pub 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 | |||
366 | impl<'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 | |||
442 | impl<'a> Expr<'a> {} | ||
443 | |||
444 | // ExprStmt | ||
445 | #[derive(Debug, Clone, Copy)] | ||
446 | pub struct ExprStmt<'a> { | ||
447 | syntax: SyntaxNodeRef<'a>, | ||
448 | } | ||
449 | |||
450 | impl<'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 | |||
460 | impl<'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)] | ||
467 | pub struct ExternCrateItem<'a> { | ||
468 | syntax: SyntaxNodeRef<'a>, | ||
469 | } | ||
470 | |||
471 | impl<'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 | |||
481 | impl<'a> ExternCrateItem<'a> {} | ||
482 | |||
483 | // FieldExpr | ||
484 | #[derive(Debug, Clone, Copy)] | ||
485 | pub struct FieldExpr<'a> { | ||
486 | syntax: SyntaxNodeRef<'a>, | ||
487 | } | ||
488 | |||
489 | impl<'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 | |||
499 | impl<'a> FieldExpr<'a> {} | ||
500 | |||
501 | // FieldPatList | ||
502 | #[derive(Debug, Clone, Copy)] | ||
503 | pub struct FieldPatList<'a> { | ||
504 | syntax: SyntaxNodeRef<'a>, | ||
505 | } | ||
506 | |||
507 | impl<'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 | |||
517 | impl<'a> FieldPatList<'a> {} | ||
518 | |||
519 | // FnDef | ||
520 | #[derive(Debug, Clone, Copy)] | ||
521 | pub struct FnDef<'a> { | ||
522 | syntax: SyntaxNodeRef<'a>, | ||
523 | } | ||
524 | |||
525 | impl<'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 | |||
535 | impl<'a> ast::NameOwner<'a> for FnDef<'a> {} | ||
536 | impl<'a> ast::TypeParamsOwner<'a> for FnDef<'a> {} | ||
537 | impl<'a> ast::AttrsOwner<'a> for FnDef<'a> {} | ||
538 | impl<'a> FnDef<'a> {pub fn param_list(self) -> Option<ParamList<'a>> { | ||
539 | super::child_opt(self) | ||
540 | } | ||
541 | pub fn body(self) -> Option<Block<'a>> { | ||
542 | super::child_opt(self) | ||
543 | } | ||
544 | pub fn ret_type(self) -> Option<RetType<'a>> { | ||
545 | super::child_opt(self) | ||
546 | } | ||
547 | } | ||
548 | |||
549 | // FnPointerType | ||
550 | #[derive(Debug, Clone, Copy)] | ||
551 | pub struct FnPointerType<'a> { | ||
552 | syntax: SyntaxNodeRef<'a>, | ||
553 | } | ||
554 | |||
555 | impl<'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 | |||
565 | impl<'a> FnPointerType<'a> {} | ||
566 | |||
567 | // ForExpr | ||
568 | #[derive(Debug, Clone, Copy)] | ||
569 | pub struct ForExpr<'a> { | ||
570 | syntax: SyntaxNodeRef<'a>, | ||
571 | } | ||
572 | |||
573 | impl<'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 | |||
583 | impl<'a> ast::LoopBodyOwner<'a> for ForExpr<'a> {} | ||
584 | impl<'a> ForExpr<'a> {pub fn pat(self) -> Option<Pat<'a>> { | ||
585 | super::child_opt(self) | ||
586 | } | ||
587 | pub fn iterable(self) -> Option<Expr<'a>> { | ||
588 | super::child_opt(self) | ||
589 | } | ||
590 | } | ||
591 | |||
592 | // ForType | ||
593 | #[derive(Debug, Clone, Copy)] | ||
594 | pub struct ForType<'a> { | ||
595 | syntax: SyntaxNodeRef<'a>, | ||
596 | } | ||
597 | |||
598 | impl<'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 | |||
608 | impl<'a> ForType<'a> {} | ||
609 | |||
610 | // IfExpr | ||
611 | #[derive(Debug, Clone, Copy)] | ||
612 | pub struct IfExpr<'a> { | ||
613 | syntax: SyntaxNodeRef<'a>, | ||
614 | } | ||
615 | |||
616 | impl<'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 | |||
626 | impl<'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)] | ||
633 | pub struct ImplItem<'a> { | ||
634 | syntax: SyntaxNodeRef<'a>, | ||
635 | } | ||
636 | |||
637 | impl<'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 | |||
647 | impl<'a> ImplItem<'a> {} | ||
648 | |||
649 | // ImplTraitType | ||
650 | #[derive(Debug, Clone, Copy)] | ||
651 | pub struct ImplTraitType<'a> { | ||
652 | syntax: SyntaxNodeRef<'a>, | ||
653 | } | ||
654 | |||
655 | impl<'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 | |||
665 | impl<'a> ImplTraitType<'a> {} | ||
666 | |||
667 | // IndexExpr | ||
668 | #[derive(Debug, Clone, Copy)] | ||
669 | pub struct IndexExpr<'a> { | ||
670 | syntax: SyntaxNodeRef<'a>, | ||
671 | } | ||
672 | |||
673 | impl<'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 | |||
683 | impl<'a> IndexExpr<'a> {} | ||
684 | |||
685 | // ItemList | ||
686 | #[derive(Debug, Clone, Copy)] | ||
687 | pub struct ItemList<'a> { | ||
688 | syntax: SyntaxNodeRef<'a>, | ||
689 | } | ||
690 | |||
691 | impl<'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 | |||
701 | impl<'a> ast::FnDefOwner<'a> for ItemList<'a> {} | ||
702 | impl<'a> ast::ModuleItemOwner<'a> for ItemList<'a> {} | ||
703 | impl<'a> ItemList<'a> {} | ||
704 | |||
705 | // Label | ||
706 | #[derive(Debug, Clone, Copy)] | ||
707 | pub struct Label<'a> { | ||
708 | syntax: SyntaxNodeRef<'a>, | ||
709 | } | ||
710 | |||
711 | impl<'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 | |||
721 | impl<'a> Label<'a> {} | ||
722 | |||
723 | // LambdaExpr | ||
724 | #[derive(Debug, Clone, Copy)] | ||
725 | pub struct LambdaExpr<'a> { | ||
726 | syntax: SyntaxNodeRef<'a>, | ||
727 | } | ||
728 | |||
729 | impl<'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 | |||
739 | impl<'a> LambdaExpr<'a> {pub fn param_list(self) -> Option<ParamList<'a>> { | ||
740 | super::child_opt(self) | ||
741 | } | ||
742 | pub fn body(self) -> Option<Expr<'a>> { | ||
743 | super::child_opt(self) | ||
744 | } | ||
745 | } | ||
746 | |||
747 | // LetStmt | ||
748 | #[derive(Debug, Clone, Copy)] | ||
749 | pub struct LetStmt<'a> { | ||
750 | syntax: SyntaxNodeRef<'a>, | ||
751 | } | ||
752 | |||
753 | impl<'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 | |||
763 | impl<'a> LetStmt<'a> {pub fn pat(self) -> Option<Pat<'a>> { | ||
764 | super::child_opt(self) | ||
765 | } | ||
766 | pub fn initializer(self) -> Option<Expr<'a>> { | ||
767 | super::child_opt(self) | ||
768 | } | ||
769 | } | ||
770 | |||
771 | // Lifetime | ||
772 | #[derive(Debug, Clone, Copy)] | ||
773 | pub struct Lifetime<'a> { | ||
774 | syntax: SyntaxNodeRef<'a>, | ||
775 | } | ||
776 | |||
777 | impl<'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 | |||
787 | impl<'a> Lifetime<'a> {} | ||
788 | |||
789 | // LifetimeParam | ||
790 | #[derive(Debug, Clone, Copy)] | ||
791 | pub struct LifetimeParam<'a> { | ||
792 | syntax: SyntaxNodeRef<'a>, | ||
793 | } | ||
794 | |||
795 | impl<'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 | |||
805 | impl<'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)] | ||
812 | pub struct Literal<'a> { | ||
813 | syntax: SyntaxNodeRef<'a>, | ||
814 | } | ||
815 | |||
816 | impl<'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 | |||
826 | impl<'a> Literal<'a> {} | ||
827 | |||
828 | // LoopExpr | ||
829 | #[derive(Debug, Clone, Copy)] | ||
830 | pub struct LoopExpr<'a> { | ||
831 | syntax: SyntaxNodeRef<'a>, | ||
832 | } | ||
833 | |||
834 | impl<'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 | |||
844 | impl<'a> ast::LoopBodyOwner<'a> for LoopExpr<'a> {} | ||
845 | impl<'a> LoopExpr<'a> {} | ||
846 | |||
847 | // MatchArm | ||
848 | #[derive(Debug, Clone, Copy)] | ||
849 | pub struct MatchArm<'a> { | ||
850 | syntax: SyntaxNodeRef<'a>, | ||
851 | } | ||
852 | |||
853 | impl<'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 | |||
863 | impl<'a> MatchArm<'a> { | ||
864 | pub fn pats(self) -> impl Iterator<Item = Pat<'a>> + 'a { | ||
865 | super::children(self) | ||
866 | } | ||
867 | pub fn guard(self) -> Option<MatchGuard<'a>> { | ||
868 | super::child_opt(self) | ||
869 | } | ||
870 | pub fn expr(self) -> Option<Expr<'a>> { | ||
871 | super::child_opt(self) | ||
872 | } | ||
873 | } | ||
874 | |||
875 | // MatchArmList | ||
876 | #[derive(Debug, Clone, Copy)] | ||
877 | pub struct MatchArmList<'a> { | ||
878 | syntax: SyntaxNodeRef<'a>, | ||
879 | } | ||
880 | |||
881 | impl<'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 | |||
891 | impl<'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)] | ||
899 | pub struct MatchExpr<'a> { | ||
900 | syntax: SyntaxNodeRef<'a>, | ||
901 | } | ||
902 | |||
903 | impl<'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 | |||
913 | impl<'a> MatchExpr<'a> {pub fn expr(self) -> Option<Expr<'a>> { | ||
914 | super::child_opt(self) | ||
915 | } | ||
916 | pub fn match_arm_list(self) -> Option<MatchArmList<'a>> { | ||
917 | super::child_opt(self) | ||
918 | } | ||
919 | } | ||
920 | |||
921 | // MatchGuard | ||
922 | #[derive(Debug, Clone, Copy)] | ||
923 | pub struct MatchGuard<'a> { | ||
924 | syntax: SyntaxNodeRef<'a>, | ||
925 | } | ||
926 | |||
927 | impl<'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 | |||
937 | impl<'a> MatchGuard<'a> {} | ||
938 | |||
939 | // MethodCallExpr | ||
940 | #[derive(Debug, Clone, Copy)] | ||
941 | pub struct MethodCallExpr<'a> { | ||
942 | syntax: SyntaxNodeRef<'a>, | ||
943 | } | ||
944 | |||
945 | impl<'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 | |||
955 | impl<'a> ast::ArgListOwner<'a> for MethodCallExpr<'a> {} | ||
956 | impl<'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)] | ||
963 | pub struct Module<'a> { | ||
964 | syntax: SyntaxNodeRef<'a>, | ||
965 | } | ||
966 | |||
967 | impl<'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 | |||
977 | impl<'a> ast::NameOwner<'a> for Module<'a> {} | ||
978 | impl<'a> ast::AttrsOwner<'a> for Module<'a> {} | ||
979 | impl<'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)] | ||
986 | pub 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 | |||
1000 | impl<'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 | |||
1034 | impl<'a> ModuleItem<'a> {} | ||
1035 | |||
1036 | // Name | ||
1037 | #[derive(Debug, Clone, Copy)] | ||
1038 | pub struct Name<'a> { | ||
1039 | syntax: SyntaxNodeRef<'a>, | ||
1040 | } | ||
1041 | |||
1042 | impl<'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 | |||
1052 | impl<'a> Name<'a> {} | ||
1053 | |||
1054 | // NameRef | ||
1055 | #[derive(Debug, Clone, Copy)] | ||
1056 | pub struct NameRef<'a> { | ||
1057 | syntax: SyntaxNodeRef<'a>, | ||
1058 | } | ||
1059 | |||
1060 | impl<'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 | |||
1070 | impl<'a> NameRef<'a> {} | ||
1071 | |||
1072 | // NamedField | ||
1073 | #[derive(Debug, Clone, Copy)] | ||
1074 | pub struct NamedField<'a> { | ||
1075 | syntax: SyntaxNodeRef<'a>, | ||
1076 | } | ||
1077 | |||
1078 | impl<'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 | |||
1088 | impl<'a> NamedField<'a> {} | ||
1089 | |||
1090 | // NamedFieldDef | ||
1091 | #[derive(Debug, Clone, Copy)] | ||
1092 | pub struct NamedFieldDef<'a> { | ||
1093 | syntax: SyntaxNodeRef<'a>, | ||
1094 | } | ||
1095 | |||
1096 | impl<'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 | |||
1106 | impl<'a> ast::NameOwner<'a> for NamedFieldDef<'a> {} | ||
1107 | impl<'a> ast::AttrsOwner<'a> for NamedFieldDef<'a> {} | ||
1108 | impl<'a> NamedFieldDef<'a> {} | ||
1109 | |||
1110 | // NamedFieldList | ||
1111 | #[derive(Debug, Clone, Copy)] | ||
1112 | pub struct NamedFieldList<'a> { | ||
1113 | syntax: SyntaxNodeRef<'a>, | ||
1114 | } | ||
1115 | |||
1116 | impl<'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 | |||
1126 | impl<'a> NamedFieldList<'a> {} | ||
1127 | |||
1128 | // NeverType | ||
1129 | #[derive(Debug, Clone, Copy)] | ||
1130 | pub struct NeverType<'a> { | ||
1131 | syntax: SyntaxNodeRef<'a>, | ||
1132 | } | ||
1133 | |||
1134 | impl<'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 | |||
1144 | impl<'a> NeverType<'a> {} | ||
1145 | |||
1146 | // NominalDef | ||
1147 | #[derive(Debug, Clone, Copy)] | ||
1148 | pub enum NominalDef<'a> { | ||
1149 | StructDef(StructDef<'a>), | ||
1150 | EnumDef(EnumDef<'a>), | ||
1151 | } | ||
1152 | |||
1153 | impl<'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 | |||
1169 | impl<'a> ast::NameOwner<'a> for NominalDef<'a> {} | ||
1170 | impl<'a> ast::TypeParamsOwner<'a> for NominalDef<'a> {} | ||
1171 | impl<'a> ast::AttrsOwner<'a> for NominalDef<'a> {} | ||
1172 | impl<'a> NominalDef<'a> {} | ||
1173 | |||
1174 | // Param | ||
1175 | #[derive(Debug, Clone, Copy)] | ||
1176 | pub struct Param<'a> { | ||
1177 | syntax: SyntaxNodeRef<'a>, | ||
1178 | } | ||
1179 | |||
1180 | impl<'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 | |||
1190 | impl<'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)] | ||
1197 | pub struct ParamList<'a> { | ||
1198 | syntax: SyntaxNodeRef<'a>, | ||
1199 | } | ||
1200 | |||
1201 | impl<'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 | |||
1211 | impl<'a> ParamList<'a> { | ||
1212 | pub fn params(self) -> impl Iterator<Item = Param<'a>> + 'a { | ||
1213 | super::children(self) | ||
1214 | } | ||
1215 | pub fn self_param(self) -> Option<SelfParam<'a>> { | ||
1216 | super::child_opt(self) | ||
1217 | } | ||
1218 | } | ||
1219 | |||
1220 | // ParenExpr | ||
1221 | #[derive(Debug, Clone, Copy)] | ||
1222 | pub struct ParenExpr<'a> { | ||
1223 | syntax: SyntaxNodeRef<'a>, | ||
1224 | } | ||
1225 | |||
1226 | impl<'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 | |||
1236 | impl<'a> ParenExpr<'a> {} | ||
1237 | |||
1238 | // ParenType | ||
1239 | #[derive(Debug, Clone, Copy)] | ||
1240 | pub struct ParenType<'a> { | ||
1241 | syntax: SyntaxNodeRef<'a>, | ||
1242 | } | ||
1243 | |||
1244 | impl<'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 | |||
1254 | impl<'a> ParenType<'a> {} | ||
1255 | |||
1256 | // Pat | ||
1257 | #[derive(Debug, Clone, Copy)] | ||
1258 | pub 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 | |||
1271 | impl<'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 | |||
1303 | impl<'a> Pat<'a> {} | ||
1304 | |||
1305 | // Path | ||
1306 | #[derive(Debug, Clone, Copy)] | ||
1307 | pub struct Path<'a> { | ||
1308 | syntax: SyntaxNodeRef<'a>, | ||
1309 | } | ||
1310 | |||
1311 | impl<'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 | |||
1321 | impl<'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)] | ||
1328 | pub struct PathExpr<'a> { | ||
1329 | syntax: SyntaxNodeRef<'a>, | ||
1330 | } | ||
1331 | |||
1332 | impl<'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 | |||
1342 | impl<'a> PathExpr<'a> {} | ||
1343 | |||
1344 | // PathPat | ||
1345 | #[derive(Debug, Clone, Copy)] | ||
1346 | pub struct PathPat<'a> { | ||
1347 | syntax: SyntaxNodeRef<'a>, | ||
1348 | } | ||
1349 | |||
1350 | impl<'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 | |||
1360 | impl<'a> PathPat<'a> {} | ||
1361 | |||
1362 | // PathSegment | ||
1363 | #[derive(Debug, Clone, Copy)] | ||
1364 | pub struct PathSegment<'a> { | ||
1365 | syntax: SyntaxNodeRef<'a>, | ||
1366 | } | ||
1367 | |||
1368 | impl<'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 | |||
1378 | impl<'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)] | ||
1385 | pub struct PathType<'a> { | ||
1386 | syntax: SyntaxNodeRef<'a>, | ||
1387 | } | ||
1388 | |||
1389 | impl<'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 | |||
1399 | impl<'a> PathType<'a> {} | ||
1400 | |||
1401 | // PlaceholderPat | ||
1402 | #[derive(Debug, Clone, Copy)] | ||
1403 | pub struct PlaceholderPat<'a> { | ||
1404 | syntax: SyntaxNodeRef<'a>, | ||
1405 | } | ||
1406 | |||
1407 | impl<'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 | |||
1417 | impl<'a> PlaceholderPat<'a> {} | ||
1418 | |||
1419 | // PlaceholderType | ||
1420 | #[derive(Debug, Clone, Copy)] | ||
1421 | pub struct PlaceholderType<'a> { | ||
1422 | syntax: SyntaxNodeRef<'a>, | ||
1423 | } | ||
1424 | |||
1425 | impl<'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 | |||
1435 | impl<'a> PlaceholderType<'a> {} | ||
1436 | |||
1437 | // PointerType | ||
1438 | #[derive(Debug, Clone, Copy)] | ||
1439 | pub struct PointerType<'a> { | ||
1440 | syntax: SyntaxNodeRef<'a>, | ||
1441 | } | ||
1442 | |||
1443 | impl<'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 | |||
1453 | impl<'a> PointerType<'a> {} | ||
1454 | |||
1455 | // PrefixExpr | ||
1456 | #[derive(Debug, Clone, Copy)] | ||
1457 | pub struct PrefixExpr<'a> { | ||
1458 | syntax: SyntaxNodeRef<'a>, | ||
1459 | } | ||
1460 | |||
1461 | impl<'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 | |||
1471 | impl<'a> PrefixExpr<'a> {} | ||
1472 | |||
1473 | // RangeExpr | ||
1474 | #[derive(Debug, Clone, Copy)] | ||
1475 | pub struct RangeExpr<'a> { | ||
1476 | syntax: SyntaxNodeRef<'a>, | ||
1477 | } | ||
1478 | |||
1479 | impl<'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 | |||
1489 | impl<'a> RangeExpr<'a> {} | ||
1490 | |||
1491 | // RangePat | ||
1492 | #[derive(Debug, Clone, Copy)] | ||
1493 | pub struct RangePat<'a> { | ||
1494 | syntax: SyntaxNodeRef<'a>, | ||
1495 | } | ||
1496 | |||
1497 | impl<'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 | |||
1507 | impl<'a> RangePat<'a> {} | ||
1508 | |||
1509 | // RefExpr | ||
1510 | #[derive(Debug, Clone, Copy)] | ||
1511 | pub struct RefExpr<'a> { | ||
1512 | syntax: SyntaxNodeRef<'a>, | ||
1513 | } | ||
1514 | |||
1515 | impl<'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 | |||
1525 | impl<'a> RefExpr<'a> {} | ||
1526 | |||
1527 | // RefPat | ||
1528 | #[derive(Debug, Clone, Copy)] | ||
1529 | pub struct RefPat<'a> { | ||
1530 | syntax: SyntaxNodeRef<'a>, | ||
1531 | } | ||
1532 | |||
1533 | impl<'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 | |||
1543 | impl<'a> RefPat<'a> {} | ||
1544 | |||
1545 | // ReferenceType | ||
1546 | #[derive(Debug, Clone, Copy)] | ||
1547 | pub struct ReferenceType<'a> { | ||
1548 | syntax: SyntaxNodeRef<'a>, | ||
1549 | } | ||
1550 | |||
1551 | impl<'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 | |||
1561 | impl<'a> ReferenceType<'a> {} | ||
1562 | |||
1563 | // RetType | ||
1564 | #[derive(Debug, Clone, Copy)] | ||
1565 | pub struct RetType<'a> { | ||
1566 | syntax: SyntaxNodeRef<'a>, | ||
1567 | } | ||
1568 | |||
1569 | impl<'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 | |||
1579 | impl<'a> RetType<'a> {} | ||
1580 | |||
1581 | // ReturnExpr | ||
1582 | #[derive(Debug, Clone, Copy)] | ||
1583 | pub struct ReturnExpr<'a> { | ||
1584 | syntax: SyntaxNodeRef<'a>, | ||
1585 | } | ||
1586 | |||
1587 | impl<'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 | |||
1597 | impl<'a> ReturnExpr<'a> {} | ||
1598 | |||
1599 | // Root | ||
1600 | #[derive(Debug, Clone, Copy)] | ||
1601 | pub struct Root<'a> { | ||
1602 | syntax: SyntaxNodeRef<'a>, | ||
1603 | } | ||
1604 | |||
1605 | impl<'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 | |||
1615 | impl<'a> ast::ModuleItemOwner<'a> for Root<'a> {} | ||
1616 | impl<'a> ast::FnDefOwner<'a> for Root<'a> {} | ||
1617 | impl<'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)] | ||
1625 | pub struct SelfParam<'a> { | ||
1626 | syntax: SyntaxNodeRef<'a>, | ||
1627 | } | ||
1628 | |||
1629 | impl<'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 | |||
1639 | impl<'a> SelfParam<'a> {} | ||
1640 | |||
1641 | // SlicePat | ||
1642 | #[derive(Debug, Clone, Copy)] | ||
1643 | pub struct SlicePat<'a> { | ||
1644 | syntax: SyntaxNodeRef<'a>, | ||
1645 | } | ||
1646 | |||
1647 | impl<'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 | |||
1657 | impl<'a> SlicePat<'a> {} | ||
1658 | |||
1659 | // SliceType | ||
1660 | #[derive(Debug, Clone, Copy)] | ||
1661 | pub struct SliceType<'a> { | ||
1662 | syntax: SyntaxNodeRef<'a>, | ||
1663 | } | ||
1664 | |||
1665 | impl<'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 | |||
1675 | impl<'a> SliceType<'a> {} | ||
1676 | |||
1677 | // StaticDef | ||
1678 | #[derive(Debug, Clone, Copy)] | ||
1679 | pub struct StaticDef<'a> { | ||
1680 | syntax: SyntaxNodeRef<'a>, | ||
1681 | } | ||
1682 | |||
1683 | impl<'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 | |||
1693 | impl<'a> ast::NameOwner<'a> for StaticDef<'a> {} | ||
1694 | impl<'a> ast::TypeParamsOwner<'a> for StaticDef<'a> {} | ||
1695 | impl<'a> ast::AttrsOwner<'a> for StaticDef<'a> {} | ||
1696 | impl<'a> StaticDef<'a> {} | ||
1697 | |||
1698 | // Stmt | ||
1699 | #[derive(Debug, Clone, Copy)] | ||
1700 | pub enum Stmt<'a> { | ||
1701 | ExprStmt(ExprStmt<'a>), | ||
1702 | LetStmt(LetStmt<'a>), | ||
1703 | } | ||
1704 | |||
1705 | impl<'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 | |||
1721 | impl<'a> Stmt<'a> {} | ||
1722 | |||
1723 | // StructDef | ||
1724 | #[derive(Debug, Clone, Copy)] | ||
1725 | pub struct StructDef<'a> { | ||
1726 | syntax: SyntaxNodeRef<'a>, | ||
1727 | } | ||
1728 | |||
1729 | impl<'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 | |||
1739 | impl<'a> ast::NameOwner<'a> for StructDef<'a> {} | ||
1740 | impl<'a> ast::TypeParamsOwner<'a> for StructDef<'a> {} | ||
1741 | impl<'a> ast::AttrsOwner<'a> for StructDef<'a> {} | ||
1742 | impl<'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)] | ||
1750 | pub struct StructLit<'a> { | ||
1751 | syntax: SyntaxNodeRef<'a>, | ||
1752 | } | ||
1753 | |||
1754 | impl<'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 | |||
1764 | impl<'a> StructLit<'a> {} | ||
1765 | |||
1766 | // StructPat | ||
1767 | #[derive(Debug, Clone, Copy)] | ||
1768 | pub struct StructPat<'a> { | ||
1769 | syntax: SyntaxNodeRef<'a>, | ||
1770 | } | ||
1771 | |||
1772 | impl<'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 | |||
1782 | impl<'a> StructPat<'a> {} | ||
1783 | |||
1784 | // TokenTree | ||
1785 | #[derive(Debug, Clone, Copy)] | ||
1786 | pub struct TokenTree<'a> { | ||
1787 | syntax: SyntaxNodeRef<'a>, | ||
1788 | } | ||
1789 | |||
1790 | impl<'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 | |||
1800 | impl<'a> TokenTree<'a> {} | ||
1801 | |||
1802 | // TraitDef | ||
1803 | #[derive(Debug, Clone, Copy)] | ||
1804 | pub struct TraitDef<'a> { | ||
1805 | syntax: SyntaxNodeRef<'a>, | ||
1806 | } | ||
1807 | |||
1808 | impl<'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 | |||
1818 | impl<'a> ast::NameOwner<'a> for TraitDef<'a> {} | ||
1819 | impl<'a> ast::AttrsOwner<'a> for TraitDef<'a> {} | ||
1820 | impl<'a> TraitDef<'a> {} | ||
1821 | |||
1822 | // TryExpr | ||
1823 | #[derive(Debug, Clone, Copy)] | ||
1824 | pub struct TryExpr<'a> { | ||
1825 | syntax: SyntaxNodeRef<'a>, | ||
1826 | } | ||
1827 | |||
1828 | impl<'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 | |||
1838 | impl<'a> TryExpr<'a> {} | ||
1839 | |||
1840 | // TupleExpr | ||
1841 | #[derive(Debug, Clone, Copy)] | ||
1842 | pub struct TupleExpr<'a> { | ||
1843 | syntax: SyntaxNodeRef<'a>, | ||
1844 | } | ||
1845 | |||
1846 | impl<'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 | |||
1856 | impl<'a> TupleExpr<'a> {} | ||
1857 | |||
1858 | // TuplePat | ||
1859 | #[derive(Debug, Clone, Copy)] | ||
1860 | pub struct TuplePat<'a> { | ||
1861 | syntax: SyntaxNodeRef<'a>, | ||
1862 | } | ||
1863 | |||
1864 | impl<'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 | |||
1874 | impl<'a> TuplePat<'a> {} | ||
1875 | |||
1876 | // TupleStructPat | ||
1877 | #[derive(Debug, Clone, Copy)] | ||
1878 | pub struct TupleStructPat<'a> { | ||
1879 | syntax: SyntaxNodeRef<'a>, | ||
1880 | } | ||
1881 | |||
1882 | impl<'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 | |||
1892 | impl<'a> TupleStructPat<'a> {} | ||
1893 | |||
1894 | // TupleType | ||
1895 | #[derive(Debug, Clone, Copy)] | ||
1896 | pub struct TupleType<'a> { | ||
1897 | syntax: SyntaxNodeRef<'a>, | ||
1898 | } | ||
1899 | |||
1900 | impl<'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 | |||
1910 | impl<'a> TupleType<'a> {} | ||
1911 | |||
1912 | // TypeDef | ||
1913 | #[derive(Debug, Clone, Copy)] | ||
1914 | pub struct TypeDef<'a> { | ||
1915 | syntax: SyntaxNodeRef<'a>, | ||
1916 | } | ||
1917 | |||
1918 | impl<'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 | |||
1928 | impl<'a> ast::NameOwner<'a> for TypeDef<'a> {} | ||
1929 | impl<'a> ast::TypeParamsOwner<'a> for TypeDef<'a> {} | ||
1930 | impl<'a> ast::AttrsOwner<'a> for TypeDef<'a> {} | ||
1931 | impl<'a> TypeDef<'a> {} | ||
1932 | |||
1933 | // TypeParam | ||
1934 | #[derive(Debug, Clone, Copy)] | ||
1935 | pub struct TypeParam<'a> { | ||
1936 | syntax: SyntaxNodeRef<'a>, | ||
1937 | } | ||
1938 | |||
1939 | impl<'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 | |||
1949 | impl<'a> ast::NameOwner<'a> for TypeParam<'a> {} | ||
1950 | impl<'a> TypeParam<'a> {} | ||
1951 | |||
1952 | // TypeParamList | ||
1953 | #[derive(Debug, Clone, Copy)] | ||
1954 | pub struct TypeParamList<'a> { | ||
1955 | syntax: SyntaxNodeRef<'a>, | ||
1956 | } | ||
1957 | |||
1958 | impl<'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 | |||
1968 | impl<'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)] | ||
1980 | pub 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 | |||
1996 | impl<'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 | |||
2034 | impl<'a> TypeRef<'a> {} | ||
2035 | |||
2036 | // UseItem | ||
2037 | #[derive(Debug, Clone, Copy)] | ||
2038 | pub struct UseItem<'a> { | ||
2039 | syntax: SyntaxNodeRef<'a>, | ||
2040 | } | ||
2041 | |||
2042 | impl<'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 | |||
2052 | impl<'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)] | ||
2059 | pub struct UseTree<'a> { | ||
2060 | syntax: SyntaxNodeRef<'a>, | ||
2061 | } | ||
2062 | |||
2063 | impl<'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 | |||
2073 | impl<'a> UseTree<'a> {pub fn path(self) -> Option<Path<'a>> { | ||
2074 | super::child_opt(self) | ||
2075 | } | ||
2076 | pub fn use_tree_list(self) -> Option<UseTreeList<'a>> { | ||
2077 | super::child_opt(self) | ||
2078 | } | ||
2079 | } | ||
2080 | |||
2081 | // UseTreeList | ||
2082 | #[derive(Debug, Clone, Copy)] | ||
2083 | pub struct UseTreeList<'a> { | ||
2084 | syntax: SyntaxNodeRef<'a>, | ||
2085 | } | ||
2086 | |||
2087 | impl<'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 | |||
2097 | impl<'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)] | ||
2105 | pub struct WhereClause<'a> { | ||
2106 | syntax: SyntaxNodeRef<'a>, | ||
2107 | } | ||
2108 | |||
2109 | impl<'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 | |||
2119 | impl<'a> WhereClause<'a> {} | ||
2120 | |||
2121 | // WhileExpr | ||
2122 | #[derive(Debug, Clone, Copy)] | ||
2123 | pub struct WhileExpr<'a> { | ||
2124 | syntax: SyntaxNodeRef<'a>, | ||
2125 | } | ||
2126 | |||
2127 | impl<'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 | |||
2137 | impl<'a> ast::LoopBodyOwner<'a> for WhileExpr<'a> {} | ||
2138 | impl<'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 @@ | |||
1 | use { | ||
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)] | ||
10 | pub enum {{ node }}<'a> { | ||
11 | {%- for kind in methods.enum %} | ||
12 | {{ kind }}({{ kind }}<'a>), | ||
13 | {%- endfor %} | ||
14 | } | ||
15 | |||
16 | impl<'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)] | ||
35 | pub struct {{ node }}<'a> { | ||
36 | syntax: SyntaxNodeRef<'a>, | ||
37 | } | ||
38 | |||
39 | impl<'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 -%} | ||
51 | impl<'a> ast::{{ t }}<'a> for {{ node }}<'a> {} | ||
52 | {% endfor -%} | ||
53 | {%- endif -%} | ||
54 | |||
55 | impl<'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 @@ | |||
1 | mod generated; | ||
2 | |||
3 | use std::marker::PhantomData; | ||
4 | |||
5 | use itertools::Itertools; | ||
6 | use smol_str::SmolStr; | ||
7 | |||
8 | use { | ||
9 | SyntaxNodeRef, SyntaxKind::*, | ||
10 | yellow::{RefRoot, SyntaxNodeChildren}, | ||
11 | }; | ||
12 | pub use self::generated::*; | ||
13 | |||
14 | pub 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 | |||
20 | pub trait NameOwner<'a>: AstNode<'a> { | ||
21 | fn name(self) -> Option<Name<'a>> { | ||
22 | child_opt(self) | ||
23 | } | ||
24 | } | ||
25 | |||
26 | pub trait LoopBodyOwner<'a>: AstNode<'a> { | ||
27 | fn loop_body(self) -> Option<Block<'a>> { | ||
28 | child_opt(self) | ||
29 | } | ||
30 | } | ||
31 | |||
32 | pub trait ArgListOwner<'a>: AstNode<'a> { | ||
33 | fn arg_list(self) -> Option<ArgList<'a>> { | ||
34 | child_opt(self) | ||
35 | } | ||
36 | } | ||
37 | |||
38 | pub trait FnDefOwner<'a>: AstNode<'a> { | ||
39 | fn functions(self) -> AstChildren<'a, FnDef<'a>> { | ||
40 | children(self) | ||
41 | } | ||
42 | } | ||
43 | |||
44 | pub trait ModuleItemOwner<'a>: AstNode<'a> { | ||
45 | fn items(self) -> AstChildren<'a, ModuleItem<'a>> { | ||
46 | children(self) | ||
47 | } | ||
48 | } | ||
49 | |||
50 | pub 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 | |||
60 | pub trait AttrsOwner<'a>: AstNode<'a> { | ||
61 | fn attrs(self) -> AstChildren<'a, Attr<'a>> { | ||
62 | children(self) | ||
63 | } | ||
64 | } | ||
65 | |||
66 | impl<'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 | |||
74 | impl<'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 | |||
97 | impl<'a> Lifetime<'a> { | ||
98 | pub fn text(&self) -> SmolStr { | ||
99 | self.syntax().leaf_text().unwrap() | ||
100 | } | ||
101 | } | ||
102 | |||
103 | impl<'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 | |||
111 | impl<'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 | |||
119 | impl<'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 | |||
142 | impl<'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 | |||
151 | impl<'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 | |||
160 | impl<'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 | |||
172 | fn child_opt<'a, P: AstNode<'a>, C: AstNode<'a>>(parent: P) -> Option<C> { | ||
173 | children(parent).next() | ||
174 | } | ||
175 | |||
176 | fn children<'a, P: AstNode<'a>, C: AstNode<'a>>(parent: P) -> AstChildren<'a, C> { | ||
177 | AstChildren::new(parent.syntax()) | ||
178 | } | ||
179 | |||
180 | |||
181 | #[derive(Debug)] | ||
182 | pub struct AstChildren<'a, N> { | ||
183 | inner: SyntaxNodeChildren<RefRoot<'a>>, | ||
184 | ph: PhantomData<N>, | ||
185 | } | ||
186 | |||
187 | impl<'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 | |||
196 | impl<'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 @@ | |||
1 | Grammar( | ||
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 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(super) fn inner_attributes(p: &mut Parser) { | ||
4 | while p.current() == POUND && p.nth(1) == EXCL { | ||
5 | attribute(p, true) | ||
6 | } | ||
7 | } | ||
8 | |||
9 | pub(super) fn outer_attributes(p: &mut Parser) { | ||
10 | while p.at(POUND) { | ||
11 | attribute(p, false) | ||
12 | } | ||
13 | } | ||
14 | |||
15 | fn 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 @@ | |||
1 | use 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 | // } | ||
16 | pub(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 | |||
20 | pub(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 | |||
29 | pub(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 | |||
36 | const EXPR_RECOVERY_SET: TokenSet = | ||
37 | token_set![LET_KW]; | ||
38 | |||
39 | pub(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 | // } | ||
102 | fn 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 | // } | ||
132 | fn 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 | // } | ||
167 | fn 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 | // } | ||
188 | fn 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 | // } | ||
211 | fn 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 | // } | ||
223 | fn 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 | // } | ||
236 | fn 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 | // } | ||
249 | fn 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 {} } | ||
262 | fn 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 | // } | ||
277 | fn 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 | |||
290 | pub(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 | // } | ||
324 | fn 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 | // } | ||
345 | fn 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 | // } | ||
357 | fn 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 | // } | ||
374 | fn 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 | // } | ||
391 | fn 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 @@ | |||
1 | mod atom; | ||
2 | |||
3 | use super::*; | ||
4 | pub(super) use self::atom::{literal, LITERAL_FIRST}; | ||
5 | pub(crate) use self::atom::match_arm_list; | ||
6 | |||
7 | const EXPR_FIRST: TokenSet = LHS_FIRST; | ||
8 | |||
9 | pub(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 | |||
14 | pub(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 | |||
19 | fn 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 } | ||
29 | pub(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)] | ||
97 | struct Restrictions { | ||
98 | forbid_structs: bool, | ||
99 | prefer_stmt: bool, | ||
100 | } | ||
101 | |||
102 | enum Op { | ||
103 | Simple, | ||
104 | Composite(SyntaxKind, u8), | ||
105 | } | ||
106 | |||
107 | fn 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. | ||
152 | fn 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 | // } | ||
197 | fn 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 | |||
204 | const LHS_FIRST: TokenSet = | ||
205 | token_set_union![ | ||
206 | token_set![AMP, STAR, EXCL, DOTDOT, MINUS], | ||
207 | atom::ATOM_EXPR_FIRST, | ||
208 | ]; | ||
209 | |||
210 | fn 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 | |||
254 | fn 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 | // } | ||
295 | fn 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 | // } | ||
306 | fn 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 | // } | ||
320 | fn 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 | // } | ||
340 | fn 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 | // } | ||
356 | fn 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 | // } | ||
367 | fn 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 | |||
375 | fn 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 | // } | ||
400 | fn 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 | // } | ||
423 | pub(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 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(super) fn static_def(p: &mut Parser) { | ||
4 | const_or_static(p, STATIC_KW) | ||
5 | } | ||
6 | |||
7 | pub(super) fn const_def(p: &mut Parser) { | ||
8 | const_or_static(p, CONST_KW) | ||
9 | } | ||
10 | |||
11 | fn 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 | |||
2 | mod consts; | ||
3 | mod nominal; | ||
4 | mod traits; | ||
5 | mod use_item; | ||
6 | |||
7 | use super::*; | ||
8 | pub(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; | ||
21 | pub(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 | |||
28 | pub(super) enum ItemFlavor { | ||
29 | Mod, Trait | ||
30 | } | ||
31 | |||
32 | const 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 | |||
36 | pub(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 | |||
74 | pub(super) enum MaybeItem { | ||
75 | None, | ||
76 | Item(SyntaxKind), | ||
77 | Modifiers, | ||
78 | } | ||
79 | |||
80 | pub(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 | |||
166 | fn 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 | |||
240 | fn 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 | |||
250 | pub(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 | |||
259 | fn 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; | ||
298 | fn 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 | |||
322 | pub(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 | |||
334 | pub(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 | |||
343 | fn 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 | |||
349 | pub(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 | |||
370 | pub(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 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(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 | |||
45 | pub(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 | |||
58 | pub(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 | |||
93 | pub(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 | |||
131 | fn 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 @@ | |||
1 | use super::*; | ||
2 | |||
3 | // test trait_item | ||
4 | // trait T<U>: Hash + Clone where U: Copy {} | ||
5 | pub(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 | // } | ||
28 | pub(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 {} | ||
45 | pub(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 | // } | ||
77 | pub(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 | |||
93 | fn 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 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(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 | |||
10 | fn 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 | |||
56 | pub(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. | ||
24 | mod attributes; | ||
25 | mod expressions; | ||
26 | mod items; | ||
27 | mod params; | ||
28 | mod paths; | ||
29 | mod patterns; | ||
30 | mod type_args; | ||
31 | mod type_params; | ||
32 | mod types; | ||
33 | |||
34 | use { | ||
35 | token_set::TokenSet, | ||
36 | parser_api::{Marker, CompletedMarker, Parser}, | ||
37 | SyntaxKind::{self, *}, | ||
38 | }; | ||
39 | pub(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 | |||
57 | pub(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)] | ||
66 | enum BlockLike { | ||
67 | Block, | ||
68 | NotBlock, | ||
69 | } | ||
70 | |||
71 | impl BlockLike { | ||
72 | fn is_block(self) -> bool { self == BlockLike::Block } | ||
73 | } | ||
74 | |||
75 | fn 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 | |||
114 | fn 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 | |||
123 | fn 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 | |||
134 | fn 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 | |||
146 | fn 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 | |||
156 | fn name(p: &mut Parser) { | ||
157 | name_r(p, TokenSet::EMPTY) | ||
158 | } | ||
159 | |||
160 | fn 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 | |||
170 | fn 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 @@ | |||
1 | use 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: ()) {} | ||
8 | pub(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>)>(){} | ||
14 | pub(super) fn param_list_opt_patterns(p: &mut Parser) { | ||
15 | list_(p, Flavor::OptionalPattern) | ||
16 | } | ||
17 | |||
18 | pub(super) fn param_list_opt_types(p: &mut Parser) { | ||
19 | list_(p, Flavor::OptionalType) | ||
20 | } | ||
21 | |||
22 | #[derive(Clone, Copy, Eq, PartialEq)] | ||
23 | enum Flavor { | ||
24 | OptionalType, | ||
25 | OptionalPattern, | ||
26 | Normal, | ||
27 | } | ||
28 | |||
29 | impl Flavor { | ||
30 | fn type_required(self) -> bool { | ||
31 | match self { | ||
32 | Flavor::OptionalType => false, | ||
33 | _ => true, | ||
34 | } | ||
35 | } | ||
36 | } | ||
37 | |||
38 | fn 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 | |||
65 | const VALUE_PARAMETER_FIRST: TokenSet = | ||
66 | token_set_union![ | ||
67 | patterns::PATTERN_FIRST, | ||
68 | types::TYPE_FIRST, | ||
69 | ]; | ||
70 | |||
71 | fn 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 | // } | ||
108 | fn 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 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(super) const PATH_FIRST: TokenSet = | ||
4 | token_set![IDENT, SELF_KW, SUPER_KW, COLONCOLON, L_ANGLE]; | ||
5 | |||
6 | pub(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 | |||
13 | pub(super) fn use_path(p: &mut Parser) { | ||
14 | path(p, Mode::Use) | ||
15 | } | ||
16 | |||
17 | pub(super) fn type_path(p: &mut Parser) { | ||
18 | path(p, Mode::Type) | ||
19 | } | ||
20 | |||
21 | pub(super) fn expr_path(p: &mut Parser) { | ||
22 | path(p, Mode::Expr) | ||
23 | } | ||
24 | |||
25 | #[derive(Clone, Copy, Eq, PartialEq)] | ||
26 | enum Mode { | ||
27 | Use, | ||
28 | Type, | ||
29 | Expr, | ||
30 | } | ||
31 | |||
32 | fn 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 | |||
53 | fn 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 | |||
86 | fn 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 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(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 | |||
10 | pub(super) fn pattern(p: &mut Parser) { | ||
11 | pattern_r(p, PAT_RECOVERY_SET) | ||
12 | } | ||
13 | |||
14 | pub(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 | |||
29 | const PAT_RECOVERY_SET: TokenSet = | ||
30 | token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA]; | ||
31 | |||
32 | |||
33 | fn 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 | // } | ||
77 | fn 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 | // } | ||
102 | fn 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 | // } | ||
116 | fn 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 _ = (); } | ||
143 | fn 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 | // } | ||
155 | fn 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 | // } | ||
168 | fn 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 | // } | ||
179 | fn 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 | |||
188 | fn 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 | // } | ||
215 | fn 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 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(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> | ||
30 | fn 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 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(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)>; | ||
52 | pub(super) fn bounds(p: &mut Parser) { | ||
53 | assert!(p.at(COLON)); | ||
54 | p.bump(); | ||
55 | bounds_without_colon(p); | ||
56 | } | ||
57 | |||
58 | fn 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 | |||
69 | pub(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 | // {} | ||
99 | pub(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 | |||
117 | fn 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 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(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 | |||
11 | const TYPE_RECOVERY_SET: TokenSet = | ||
12 | token_set![R_PAREN, COMMA]; | ||
13 | |||
14 | pub(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 | |||
34 | pub(super) fn ascription(p: &mut Parser) { | ||
35 | p.expect(COLON); | ||
36 | type_(p) | ||
37 | } | ||
38 | |||
39 | fn type_no_plus(p: &mut Parser) { | ||
40 | type_(p); | ||
41 | } | ||
42 | |||
43 | fn 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 = !; | ||
78 | fn 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 | |||
85 | fn 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 | |||
109 | fn 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 (); | ||
145 | fn 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 = _; | ||
157 | fn 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(); | ||
168 | fn 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() -> (); | ||
194 | pub(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; | ||
210 | fn 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; | ||
220 | fn 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; | ||
233 | pub(super) fn path_type(p: &mut Parser) { | ||
234 | path_type_(p, true) | ||
235 | } | ||
236 | |||
237 | pub(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 @@ | |||
1 | use unicode_xid::UnicodeXID; | ||
2 | |||
3 | pub 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 | |||
10 | pub 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 | |||
18 | pub 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 | |||
24 | pub 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 @@ | |||
1 | use lexer::ptr::Ptr; | ||
2 | |||
3 | use SyntaxKind::{self, *}; | ||
4 | |||
5 | pub(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 | |||
16 | fn 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 | |||
39 | pub(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 | |||
48 | fn 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 @@ | |||
1 | mod classes; | ||
2 | mod comments; | ||
3 | mod numbers; | ||
4 | mod ptr; | ||
5 | mod strings; | ||
6 | |||
7 | use { | ||
8 | SyntaxKind::{self, *}, | ||
9 | TextUnit, | ||
10 | }; | ||
11 | |||
12 | use 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)] | ||
24 | pub 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 | ||
32 | pub 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 | ||
45 | pub 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 | |||
54 | fn 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 | |||
188 | fn 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 | |||
204 | fn 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 @@ | |||
1 | use lexer::classes::*; | ||
2 | use lexer::ptr::Ptr; | ||
3 | |||
4 | use SyntaxKind::{self, *}; | ||
5 | |||
6 | pub(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 | |||
45 | fn 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 | |||
59 | fn 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 @@ | |||
1 | use TextUnit; | ||
2 | |||
3 | use std::str::Chars; | ||
4 | |||
5 | /// A simple view into the characters of a string. | ||
6 | pub(crate) struct Ptr<'s> { | ||
7 | text: &'s str, | ||
8 | len: TextUnit, | ||
9 | } | ||
10 | |||
11 | impl<'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)] | ||
91 | mod 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 @@ | |||
1 | use SyntaxKind::{self, *}; | ||
2 | |||
3 | use lexer::ptr::Ptr; | ||
4 | |||
5 | pub(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 | |||
17 | pub(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 | |||
38 | pub(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 | |||
59 | pub(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 | |||
79 | pub(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 | |||
104 | fn scan_byte(ptr: &mut Ptr) { | ||
105 | scan_char(ptr) | ||
106 | } | ||
107 | |||
108 | fn scan_byte_string(ptr: &mut Ptr) { | ||
109 | scan_string(ptr) | ||
110 | } | ||
111 | |||
112 | fn 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 | |||
23 | extern crate itertools; | ||
24 | extern crate unicode_xid; | ||
25 | extern crate drop_bomb; | ||
26 | extern crate parking_lot; | ||
27 | extern crate smol_str; | ||
28 | extern crate text_unit; | ||
29 | |||
30 | #[cfg(test)] | ||
31 | #[macro_use] | ||
32 | extern crate test_utils; | ||
33 | |||
34 | pub mod algo; | ||
35 | pub mod ast; | ||
36 | mod lexer; | ||
37 | #[macro_use] | ||
38 | mod token_set; | ||
39 | mod parser_api; | ||
40 | mod grammar; | ||
41 | mod parser_impl; | ||
42 | mod reparsing; | ||
43 | |||
44 | mod syntax_kinds; | ||
45 | mod yellow; | ||
46 | /// Utilities for simple uses of the parser. | ||
47 | pub mod utils; | ||
48 | pub mod text_utils; | ||
49 | |||
50 | pub 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 | |||
60 | use { | ||
61 | yellow::{GreenNode, SyntaxRoot}, | ||
62 | }; | ||
63 | |||
64 | #[derive(Clone, Debug, Hash)] | ||
65 | pub struct File { | ||
66 | root: SyntaxNode | ||
67 | } | ||
68 | |||
69 | impl 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 @@ | |||
1 | use { | ||
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. | ||
17 | pub(crate) struct Parser<'t>(pub(super) ParserImpl<'t>); | ||
18 | |||
19 | impl<'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`. | ||
133 | pub(crate) struct Marker { | ||
134 | pos: u32, | ||
135 | bomb: DropBomb, | ||
136 | } | ||
137 | |||
138 | impl 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 | |||
161 | pub(crate) struct CompletedMarker(u32, SyntaxKind); | ||
162 | |||
163 | impl 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. | ||
10 | use std::mem; | ||
11 | use { | ||
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)] | ||
22 | pub(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 | |||
82 | pub(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 @@ | |||
1 | use {lexer::Token, SyntaxKind, SyntaxKind::EOF, TextRange, TextUnit}; | ||
2 | |||
3 | use std::ops::{Add, AddAssign}; | ||
4 | |||
5 | pub(crate) struct ParserInput<'t> { | ||
6 | text: &'t str, | ||
7 | start_offsets: Vec<TextUnit>, | ||
8 | tokens: Vec<Token>, // non-whitespace tokens | ||
9 | } | ||
10 | |||
11 | impl<'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)] | ||
66 | pub(crate) struct InputPosition(u32); | ||
67 | |||
68 | impl InputPosition { | ||
69 | pub fn new() -> Self { | ||
70 | InputPosition(0) | ||
71 | } | ||
72 | } | ||
73 | |||
74 | impl Add<u32> for InputPosition { | ||
75 | type Output = InputPosition; | ||
76 | |||
77 | fn add(self, rhs: u32) -> InputPosition { | ||
78 | InputPosition(self.0 + rhs) | ||
79 | } | ||
80 | } | ||
81 | |||
82 | impl 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 @@ | |||
1 | mod event; | ||
2 | mod input; | ||
3 | |||
4 | use std::cell::Cell; | ||
5 | |||
6 | use { | ||
7 | lexer::Token, | ||
8 | parser_api::Parser, | ||
9 | parser_impl::{ | ||
10 | event::{process, Event}, | ||
11 | input::{InputPosition, ParserInput}, | ||
12 | }, | ||
13 | TextUnit, | ||
14 | }; | ||
15 | |||
16 | use SyntaxKind::{self, EOF, TOMBSTONE}; | ||
17 | |||
18 | pub(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 | ||
31 | pub(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`. | ||
51 | pub(crate) struct ParserImpl<'t> { | ||
52 | inp: &'t ParserInput<'t>, | ||
53 | |||
54 | pos: InputPosition, | ||
55 | events: Vec<Event>, | ||
56 | steps: Cell<u32>, | ||
57 | } | ||
58 | |||
59 | impl<'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 @@ | |||
1 | use algo; | ||
2 | use grammar; | ||
3 | use lexer::{tokenize, Token}; | ||
4 | use text_unit::{TextRange, TextUnit}; | ||
5 | use yellow::{self, SyntaxNodeRef, GreenNode, SyntaxError}; | ||
6 | use parser_impl; | ||
7 | use parser_api::Parser; | ||
8 | use { | ||
9 | SyntaxKind::*, | ||
10 | }; | ||
11 | use text_utils::replace_range; | ||
12 | |||
13 | #[derive(Debug, Clone)] | ||
14 | pub struct AtomEdit { | ||
15 | pub delete: TextRange, | ||
16 | pub insert: String, | ||
17 | } | ||
18 | |||
19 | impl 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 | |||
33 | pub(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 | |||
45 | fn 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 | |||
76 | fn 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 | |||
93 | fn 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 | |||
101 | fn is_contextual_kw(text: &str) -> bool { | ||
102 | match text { | ||
103 | | "auto" | ||
104 | | "default" | ||
105 | | "union" => true, | ||
106 | _ => false, | ||
107 | } | ||
108 | } | ||
109 | |||
110 | fn 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 | |||
144 | fn 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 | |||
164 | fn 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)] | ||
191 | mod 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" | ||
238 | fn foo() { | ||
239 | let x = foo + <|>bar<|> | ||
240 | } | ||
241 | ", "baz"); | ||
242 | do_check(r" | ||
243 | fn foo() { | ||
244 | let x = foo<|> + bar<|> | ||
245 | } | ||
246 | ", "baz"); | ||
247 | do_check(r" | ||
248 | struct Foo { | ||
249 | f: foo<|><|> | ||
250 | } | ||
251 | ", ",\n g: (),"); | ||
252 | do_check(r" | ||
253 | fn foo { | ||
254 | let; | ||
255 | 1 + 1; | ||
256 | <|>92<|>; | ||
257 | } | ||
258 | ", "62"); | ||
259 | do_check(r" | ||
260 | mod foo { | ||
261 | fn <|><|> | ||
262 | } | ||
263 | ", "bar"); | ||
264 | do_check(r" | ||
265 | trait Foo { | ||
266 | type <|>Foo<|>; | ||
267 | } | ||
268 | ", "Output"); | ||
269 | do_check(r" | ||
270 | impl IntoIterator<Item=i32> for Foo { | ||
271 | f<|><|> | ||
272 | } | ||
273 | ", "n next("); | ||
274 | do_check(r" | ||
275 | use a::b::{foo,<|>,bar<|>}; | ||
276 | ", "baz"); | ||
277 | do_check(r" | ||
278 | pub enum A { | ||
279 | Foo<|><|> | ||
280 | } | ||
281 | ", "\nBar;\n"); | ||
282 | do_check(r" | ||
283 | foo!{a, b<|><|> d} | ||
284 | ", ", c[3]"); | ||
285 | do_check(r" | ||
286 | fn foo() { | ||
287 | vec![<|><|>] | ||
288 | } | ||
289 | ", "123"); | ||
290 | do_check(r" | ||
291 | extern { | ||
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"<|><|> | ||
303 | fn foo() -> i32 { 1 } | ||
304 | ", "\n\n\n \n"); | ||
305 | do_check(r" | ||
306 | fn foo() -> <|><|> {} | ||
307 | ", " \n"); | ||
308 | do_check(r" | ||
309 | fn <|>foo<|>() -> i32 { 1 } | ||
310 | ", "bar"); | ||
311 | do_check(r" | ||
312 | fn foo<|><|>foo() { } | ||
313 | ", "bar"); | ||
314 | do_check(r" | ||
315 | fn foo /* <|><|> */ () {} | ||
316 | ", "some comment"); | ||
317 | do_check(r" | ||
318 | fn baz <|><|> () {} | ||
319 | ", " \t\t\n\n"); | ||
320 | do_check(r" | ||
321 | fn baz <|><|> () {} | ||
322 | ", " \t\t\n\n"); | ||
323 | do_check(r" | ||
324 | /// foo <|><|>omment | ||
325 | mod { } | ||
326 | ", "c"); | ||
327 | do_check(r#" | ||
328 | fn -> &str { "Hello<|><|>" } | ||
329 | "#, ", world"); | ||
330 | do_check(r#" | ||
331 | fn -> &str { // "Hello<|><|>" | ||
332 | "#, ", world"); | ||
333 | do_check(r##" | ||
334 | fn -> &str { r#"Hello<|><|>"# | ||
335 | "##, ", world"); | ||
336 | do_check(r" | ||
337 | #[derive(<|>Copy<|>)] | ||
338 | enum 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)] | ||
3 | use 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)] | ||
7 | pub 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 | } | ||
226 | use self::SyntaxKind::*; | ||
227 | |||
228 | impl 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)] | ||
3 | use 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)] | ||
7 | pub 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 | } | ||
25 | use self::SyntaxKind::*; | ||
26 | |||
27 | impl 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 @@ | |||
1 | mod generated; | ||
2 | |||
3 | use std::fmt; | ||
4 | use SyntaxKind::*; | ||
5 | |||
6 | pub use self::generated::SyntaxKind; | ||
7 | |||
8 | impl 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 | |||
15 | pub(crate) struct SyntaxInfo { | ||
16 | pub name: &'static str, | ||
17 | } | ||
18 | |||
19 | impl 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 @@ | |||
1 | use {TextRange, TextUnit}; | ||
2 | |||
3 | pub fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool { | ||
4 | range.start() <= offset && offset <= range.end() | ||
5 | } | ||
6 | |||
7 | pub fn is_subrange(range: TextRange, subrange: TextRange) -> bool { | ||
8 | range.start() <= subrange.start() && subrange.end() <= range.end() | ||
9 | } | ||
10 | |||
11 | pub 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 | |||
21 | pub 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 @@ | |||
1 | use SyntaxKind; | ||
2 | |||
3 | #[derive(Clone, Copy)] | ||
4 | pub(crate) struct TokenSet(pub(crate) u128); | ||
5 | |||
6 | fn mask(kind: SyntaxKind) -> u128 { | ||
7 | 1u128 << (kind as usize) | ||
8 | } | ||
9 | |||
10 | impl 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] | ||
19 | macro_rules! token_set { | ||
20 | ($($t:ident),*) => { TokenSet($(1u128 << ($t as usize))|*) }; | ||
21 | ($($t:ident),* ,) => { token_set!($($t),*) }; | ||
22 | } | ||
23 | |||
24 | #[macro_export] | ||
25 | macro_rules! token_set_union { | ||
26 | ($($ts:expr),*) => { TokenSet($($ts.0)|*) }; | ||
27 | ($($ts:expr),* ,) => { token_set_union!($($ts),*) }; | ||
28 | } | ||
29 | |||
30 | #[test] | ||
31 | fn 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 @@ | |||
1 | use std::fmt::Write; | ||
2 | use { | ||
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. | ||
8 | pub 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 | |||
49 | pub 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 | |||
57 | pub(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 @@ | |||
1 | use { | ||
2 | parser_impl::Sink, | ||
3 | yellow::{GreenNode, SyntaxError}, | ||
4 | SyntaxKind, TextRange, TextUnit, | ||
5 | }; | ||
6 | |||
7 | pub(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 | |||
15 | impl<'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 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
3 | use smol_str::SmolStr; | ||
4 | |||
5 | use {SyntaxKind, TextUnit}; | ||
6 | |||
7 | #[derive(Clone, Debug)] | ||
8 | pub(crate) enum GreenNode { | ||
9 | Leaf { | ||
10 | kind: SyntaxKind, | ||
11 | text: SmolStr, | ||
12 | }, | ||
13 | Branch(Arc<GreenBranch>), | ||
14 | } | ||
15 | |||
16 | impl 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)] | ||
55 | pub(crate) struct GreenBranch { | ||
56 | text_len: TextUnit, | ||
57 | kind: SyntaxKind, | ||
58 | children: Box<[GreenNode]>, | ||
59 | } | ||
60 | |||
61 | impl 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] | ||
85 | fn 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 @@ | |||
1 | mod builder; | ||
2 | mod green; | ||
3 | mod red; | ||
4 | mod syntax; | ||
5 | mod syntax_text; | ||
6 | |||
7 | use std::{ | ||
8 | sync::Arc, | ||
9 | ptr, | ||
10 | }; | ||
11 | pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxError, SyntaxNodeChildren}; | ||
12 | pub(crate) use self::{ | ||
13 | builder::GreenBuilder, | ||
14 | green::GreenNode, | ||
15 | red::RedNode, | ||
16 | syntax_text::SyntaxText, | ||
17 | }; | ||
18 | |||
19 | #[derive(Debug)] | ||
20 | pub struct SyntaxRoot { | ||
21 | red: RedNode, | ||
22 | pub(crate) errors: Vec<SyntaxError>, | ||
23 | } | ||
24 | |||
25 | pub 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)] | ||
33 | pub struct OwnedRoot(Arc<SyntaxRoot>); | ||
34 | #[derive(Clone, Copy, Debug)] | ||
35 | pub struct RefRoot<'a>(&'a OwnedRoot); // TODO: shared_from_this instead of double indirection | ||
36 | |||
37 | impl<'a> RefRoot<'a> { | ||
38 | fn syntax_root(&self) -> &'a SyntaxRoot { | ||
39 | self.0.syntax_root() | ||
40 | } | ||
41 | } | ||
42 | |||
43 | impl 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 | |||
56 | impl<'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 | |||
68 | impl 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)] | ||
78 | pub(crate) struct RedPtr(ptr::NonNull<RedNode>); | ||
79 | |||
80 | unsafe impl Send for RedPtr {} | ||
81 | |||
82 | unsafe impl Sync for RedPtr {} | ||
83 | |||
84 | impl 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] | ||
95 | fn 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 @@ | |||
1 | use parking_lot::RwLock; | ||
2 | use {yellow::{GreenNode, RedPtr}, TextUnit}; | ||
3 | |||
4 | #[derive(Debug)] | ||
5 | pub(crate) struct RedNode { | ||
6 | green: GreenNode, | ||
7 | parent: Option<ParentData>, | ||
8 | children: RwLock<Box<[RedChild]>>, | ||
9 | } | ||
10 | |||
11 | #[derive(Debug)] | ||
12 | enum RedChild { | ||
13 | Zigot(TextUnit), | ||
14 | Child(RedNode) | ||
15 | } | ||
16 | |||
17 | impl 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)] | ||
33 | struct ParentData { | ||
34 | parent: RedPtr, | ||
35 | start_offset: TextUnit, | ||
36 | index_in_parent: usize, | ||
37 | } | ||
38 | |||
39 | impl 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 @@ | |||
1 | use std::{ | ||
2 | fmt, sync::Arc, | ||
3 | hash::{Hasher, Hash}, | ||
4 | ops::Range, | ||
5 | }; | ||
6 | |||
7 | use smol_str::SmolStr; | ||
8 | |||
9 | use { | ||
10 | yellow::{GreenNode, RedNode, TreeRoot, SyntaxRoot, RedPtr, RefRoot, OwnedRoot, SyntaxText}, | ||
11 | SyntaxKind::{self, *}, | ||
12 | TextRange, TextUnit, | ||
13 | }; | ||
14 | |||
15 | |||
16 | #[derive(Clone, Copy)] | ||
17 | pub 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 | |||
24 | unsafe impl<R: TreeRoot> Send for SyntaxNode<R> {} | ||
25 | unsafe impl<R: TreeRoot> Sync for SyntaxNode<R> {} | ||
26 | |||
27 | impl<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 | |||
33 | impl<R: TreeRoot> Eq for SyntaxNode<R> {} | ||
34 | impl<R: TreeRoot> Hash for SyntaxNode<R> { | ||
35 | fn hash<H: Hasher>(&self, state: &mut H) { | ||
36 | self.red.hash(state) | ||
37 | } | ||
38 | } | ||
39 | |||
40 | pub type SyntaxNodeRef<'a> = SyntaxNode<RefRoot<'a>>; | ||
41 | |||
42 | #[test] | ||
43 | fn 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)] | ||
49 | pub struct SyntaxError { | ||
50 | pub msg: String, | ||
51 | pub offset: TextUnit, | ||
52 | } | ||
53 | |||
54 | impl 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 | |||
62 | impl<'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 | |||
69 | impl<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 | |||
180 | impl<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)] | ||
191 | pub struct SyntaxNodeChildren<R: TreeRoot> { | ||
192 | parent: SyntaxNode<R>, | ||
193 | iter: Range<usize>, | ||
194 | } | ||
195 | |||
196 | impl<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 | |||
210 | fn 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 @@ | |||
1 | use std::{ | ||
2 | fmt, ops, | ||
3 | }; | ||
4 | |||
5 | use { | ||
6 | SyntaxNodeRef, TextRange, TextUnit, | ||
7 | algo::walk::preorder, | ||
8 | text_utils::{intersect, contains_offset_nonstrict}, | ||
9 | }; | ||
10 | |||
11 | #[derive(Clone)] | ||
12 | pub struct SyntaxText<'a> { | ||
13 | node: SyntaxNodeRef<'a>, | ||
14 | range: TextRange, | ||
15 | } | ||
16 | |||
17 | impl<'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 | |||
78 | impl<'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 | |||
84 | impl<'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 | |||
90 | pub trait SyntaxTextSlice: fmt::Debug { | ||
91 | fn restrict(&self, range: TextRange) -> Option<TextRange>; | ||
92 | } | ||
93 | |||
94 | impl SyntaxTextSlice for TextRange { | ||
95 | fn restrict(&self, range: TextRange) -> Option<TextRange> { | ||
96 | intersect(*self, range) | ||
97 | } | ||
98 | } | ||
99 | |||
100 | impl 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 | |||
109 | impl 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 | |||
118 | impl 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 | } | ||