diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-04 04:36:40 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-04 04:36:40 +0000 |
commit | 6295bbe6ec9741538307cd619ada1c9566f99a5d (patch) | |
tree | 9a004a531fce65c4a01e2d243dff638fb76ae373 /crates/ra_syntax/src/parser_impl | |
parent | 2fcc6bdafa1caffd4ddf98968ee967e9fb091cc0 (diff) | |
parent | 58139c558aa085588264ba659b8483a036c1da0e (diff) |
Merge #391
391: docing parser methods r=csmoe a=csmoe
Co-authored-by: csmoe <[email protected]>
Diffstat (limited to 'crates/ra_syntax/src/parser_impl')
-rw-r--r-- | crates/ra_syntax/src/parser_impl/event.rs | 53 | ||||
-rw-r--r-- | crates/ra_syntax/src/parser_impl/input.rs | 27 |
2 files changed, 56 insertions, 24 deletions
diff --git a/crates/ra_syntax/src/parser_impl/event.rs b/crates/ra_syntax/src/parser_impl/event.rs index 3d8b062d5..73dd6e02b 100644 --- a/crates/ra_syntax/src/parser_impl/event.rs +++ b/crates/ra_syntax/src/parser_impl/event.rs | |||
@@ -36,7 +36,7 @@ pub(crate) enum Event { | |||
36 | /// | 36 | /// |
37 | /// For left-recursive syntactic constructs, the parser produces | 37 | /// For left-recursive syntactic constructs, the parser produces |
38 | /// a child node before it sees a parent. `forward_parent` | 38 | /// a child node before it sees a parent. `forward_parent` |
39 | /// exists to allow to tweak parent-child relationships. | 39 | /// saves the position of current event's parent. |
40 | /// | 40 | /// |
41 | /// Consider this path | 41 | /// Consider this path |
42 | /// | 42 | /// |
@@ -84,6 +84,15 @@ pub(crate) enum Event { | |||
84 | }, | 84 | }, |
85 | } | 85 | } |
86 | 86 | ||
87 | impl Event { | ||
88 | pub(crate) fn tombstone() -> Self { | ||
89 | Event::Start { | ||
90 | kind: TOMBSTONE, | ||
91 | forward_parent: None, | ||
92 | } | ||
93 | } | ||
94 | } | ||
95 | |||
87 | pub(super) struct EventProcessor<'a, S: Sink> { | 96 | pub(super) struct EventProcessor<'a, S: Sink> { |
88 | sink: S, | 97 | sink: S, |
89 | text_pos: TextUnit, | 98 | text_pos: TextUnit, |
@@ -110,17 +119,12 @@ impl<'a, S: Sink> EventProcessor<'a, S> { | |||
110 | } | 119 | } |
111 | } | 120 | } |
112 | 121 | ||
122 | /// Generate the syntax tree with the control of events. | ||
113 | pub(super) fn process(mut self) -> S { | 123 | pub(super) fn process(mut self) -> S { |
114 | fn tombstone() -> Event { | ||
115 | Event::Start { | ||
116 | kind: TOMBSTONE, | ||
117 | forward_parent: None, | ||
118 | } | ||
119 | } | ||
120 | let mut forward_parents = Vec::new(); | 124 | let mut forward_parents = Vec::new(); |
121 | 125 | ||
122 | for i in 0..self.events.len() { | 126 | for i in 0..self.events.len() { |
123 | match mem::replace(&mut self.events[i], tombstone()) { | 127 | match mem::replace(&mut self.events[i], Event::tombstone()) { |
124 | Event::Start { | 128 | Event::Start { |
125 | kind: TOMBSTONE, .. | 129 | kind: TOMBSTONE, .. |
126 | } => (), | 130 | } => (), |
@@ -129,12 +133,18 @@ impl<'a, S: Sink> EventProcessor<'a, S> { | |||
129 | kind, | 133 | kind, |
130 | forward_parent, | 134 | forward_parent, |
131 | } => { | 135 | } => { |
136 | // For events[A, B, C], B is A's forward_parent, C is B's forward_parent, | ||
137 | // in the normal control flow, the parent-child relation: `A -> B -> C`, | ||
138 | // while with the magic forward_parent, it writes: `C <- B <- A`. | ||
139 | |||
140 | // append `A` into parents. | ||
132 | forward_parents.push(kind); | 141 | forward_parents.push(kind); |
133 | let mut idx = i; | 142 | let mut idx = i; |
134 | let mut fp = forward_parent; | 143 | let mut fp = forward_parent; |
135 | while let Some(fwd) = fp { | 144 | while let Some(fwd) = fp { |
136 | idx += fwd as usize; | 145 | idx += fwd as usize; |
137 | fp = match mem::replace(&mut self.events[idx], tombstone()) { | 146 | // append `A`'s forward_parent `B` |
147 | fp = match mem::replace(&mut self.events[idx], Event::tombstone()) { | ||
138 | Event::Start { | 148 | Event::Start { |
139 | kind, | 149 | kind, |
140 | forward_parent, | 150 | forward_parent, |
@@ -144,17 +154,19 @@ impl<'a, S: Sink> EventProcessor<'a, S> { | |||
144 | } | 154 | } |
145 | _ => unreachable!(), | 155 | _ => unreachable!(), |
146 | }; | 156 | }; |
157 | // append `B`'s forward_parent `C` in the next stage. | ||
147 | } | 158 | } |
159 | |||
148 | for kind in forward_parents.drain(..).rev() { | 160 | for kind in forward_parents.drain(..).rev() { |
149 | self.start(kind); | 161 | self.start(kind); |
150 | } | 162 | } |
151 | } | 163 | } |
152 | Event::Finish => { | 164 | Event::Finish => { |
153 | let last = i == self.events.len() - 1; | 165 | let is_last = i == self.events.len() - 1; |
154 | self.finish(last); | 166 | self.finish(is_last); |
155 | } | 167 | } |
156 | Event::Token { kind, n_raw_tokens } => { | 168 | Event::Token { kind, n_raw_tokens } => { |
157 | self.eat_ws(); | 169 | self.eat_trivias(); |
158 | let n_raw_tokens = n_raw_tokens as usize; | 170 | let n_raw_tokens = n_raw_tokens as usize; |
159 | let len = self.tokens[self.token_pos..self.token_pos + n_raw_tokens] | 171 | let len = self.tokens[self.token_pos..self.token_pos + n_raw_tokens] |
160 | .iter() | 172 | .iter() |
@@ -171,9 +183,10 @@ impl<'a, S: Sink> EventProcessor<'a, S> { | |||
171 | self.sink | 183 | self.sink |
172 | } | 184 | } |
173 | 185 | ||
186 | /// Add the node into syntax tree but discard the comments/whitespaces. | ||
174 | fn start(&mut self, kind: SyntaxKind) { | 187 | fn start(&mut self, kind: SyntaxKind) { |
175 | if kind == SOURCE_FILE { | 188 | if kind == SOURCE_FILE { |
176 | self.sink.start_internal(kind); | 189 | self.sink.start_branch(kind); |
177 | return; | 190 | return; |
178 | } | 191 | } |
179 | let n_trivias = self.tokens[self.token_pos..] | 192 | let n_trivias = self.tokens[self.token_pos..] |
@@ -194,18 +207,18 @@ impl<'a, S: Sink> EventProcessor<'a, S> { | |||
194 | n_attached_trivias(kind, leading_trivias) | 207 | n_attached_trivias(kind, leading_trivias) |
195 | }; | 208 | }; |
196 | self.eat_n_trivias(n_trivias - n_attached_trivias); | 209 | self.eat_n_trivias(n_trivias - n_attached_trivias); |
197 | self.sink.start_internal(kind); | 210 | self.sink.start_branch(kind); |
198 | self.eat_n_trivias(n_attached_trivias); | 211 | self.eat_n_trivias(n_attached_trivias); |
199 | } | 212 | } |
200 | 213 | ||
201 | fn finish(&mut self, last: bool) { | 214 | fn finish(&mut self, is_last: bool) { |
202 | if last { | 215 | if is_last { |
203 | self.eat_ws() | 216 | self.eat_trivias() |
204 | } | 217 | } |
205 | self.sink.finish_internal(); | 218 | self.sink.finish_branch(); |
206 | } | 219 | } |
207 | 220 | ||
208 | fn eat_ws(&mut self) { | 221 | fn eat_trivias(&mut self) { |
209 | while let Some(&token) = self.tokens.get(self.token_pos) { | 222 | while let Some(&token) = self.tokens.get(self.token_pos) { |
210 | if !token.kind.is_trivia() { | 223 | if !token.kind.is_trivia() { |
211 | break; | 224 | break; |
@@ -236,7 +249,7 @@ fn n_attached_trivias<'a>( | |||
236 | trivias: impl Iterator<Item = (SyntaxKind, &'a str)>, | 249 | trivias: impl Iterator<Item = (SyntaxKind, &'a str)>, |
237 | ) -> usize { | 250 | ) -> usize { |
238 | match kind { | 251 | match kind { |
239 | STRUCT_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | MODULE => { | 252 | CONST_DEF | TYPE_DEF | STRUCT_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | MODULE => { |
240 | let mut res = 0; | 253 | let mut res = 0; |
241 | for (i, (kind, text)) in trivias.enumerate() { | 254 | for (i, (kind, text)) in trivias.enumerate() { |
242 | match kind { | 255 | match kind { |
diff --git a/crates/ra_syntax/src/parser_impl/input.rs b/crates/ra_syntax/src/parser_impl/input.rs index ac6d900d8..7fde5b3ab 100644 --- a/crates/ra_syntax/src/parser_impl/input.rs +++ b/crates/ra_syntax/src/parser_impl/input.rs | |||
@@ -4,11 +4,26 @@ use std::ops::{Add, AddAssign}; | |||
4 | 4 | ||
5 | pub(crate) struct ParserInput<'t> { | 5 | pub(crate) struct ParserInput<'t> { |
6 | text: &'t str, | 6 | text: &'t str, |
7 | /// start position of each token(expect whitespace and comment) | ||
8 | /// ```non-rust | ||
9 | /// struct Foo; | ||
10 | /// ^------^--- | ||
11 | /// | | ^- | ||
12 | /// 0 7 10 | ||
13 | /// ``` | ||
14 | /// (token, start_offset): `[(struct, 0), (Foo, 7), (;, 10)]` | ||
7 | start_offsets: Vec<TextUnit>, | 15 | start_offsets: Vec<TextUnit>, |
8 | tokens: Vec<Token>, // non-whitespace tokens | 16 | /// non-whitespace/comment tokens |
17 | /// ```non-rust | ||
18 | /// struct Foo {} | ||
19 | /// ^^^^^^ ^^^ ^^ | ||
20 | /// ``` | ||
21 | /// tokens: `[struct, Foo, {, }]` | ||
22 | tokens: Vec<Token>, | ||
9 | } | 23 | } |
10 | 24 | ||
11 | impl<'t> ParserInput<'t> { | 25 | impl<'t> ParserInput<'t> { |
26 | /// Generate input from tokens(expect comment and whitespace). | ||
12 | pub fn new(text: &'t str, raw_tokens: &'t [Token]) -> ParserInput<'t> { | 27 | pub fn new(text: &'t str, raw_tokens: &'t [Token]) -> ParserInput<'t> { |
13 | let mut tokens = Vec::new(); | 28 | let mut tokens = Vec::new(); |
14 | let mut start_offsets = Vec::new(); | 29 | let mut start_offsets = Vec::new(); |
@@ -28,6 +43,7 @@ impl<'t> ParserInput<'t> { | |||
28 | } | 43 | } |
29 | } | 44 | } |
30 | 45 | ||
46 | /// Get the syntax kind of token at given input position. | ||
31 | pub fn kind(&self, pos: InputPosition) -> SyntaxKind { | 47 | pub fn kind(&self, pos: InputPosition) -> SyntaxKind { |
32 | let idx = pos.0 as usize; | 48 | let idx = pos.0 as usize; |
33 | if !(idx < self.tokens.len()) { | 49 | if !(idx < self.tokens.len()) { |
@@ -36,7 +52,8 @@ impl<'t> ParserInput<'t> { | |||
36 | self.tokens[idx].kind | 52 | self.tokens[idx].kind |
37 | } | 53 | } |
38 | 54 | ||
39 | pub fn len(&self, pos: InputPosition) -> TextUnit { | 55 | /// Get the length of a token at given input position. |
56 | pub fn token_len(&self, pos: InputPosition) -> TextUnit { | ||
40 | let idx = pos.0 as usize; | 57 | let idx = pos.0 as usize; |
41 | if !(idx < self.tokens.len()) { | 58 | if !(idx < self.tokens.len()) { |
42 | return 0.into(); | 59 | return 0.into(); |
@@ -44,7 +61,8 @@ impl<'t> ParserInput<'t> { | |||
44 | self.tokens[idx].len | 61 | self.tokens[idx].len |
45 | } | 62 | } |
46 | 63 | ||
47 | pub fn start(&self, pos: InputPosition) -> TextUnit { | 64 | /// Get the start position of a taken at given input position. |
65 | pub fn token_start_at(&self, pos: InputPosition) -> TextUnit { | ||
48 | let idx = pos.0 as usize; | 66 | let idx = pos.0 as usize; |
49 | if !(idx < self.tokens.len()) { | 67 | if !(idx < self.tokens.len()) { |
50 | return 0.into(); | 68 | return 0.into(); |
@@ -52,7 +70,8 @@ impl<'t> ParserInput<'t> { | |||
52 | self.start_offsets[idx] | 70 | self.start_offsets[idx] |
53 | } | 71 | } |
54 | 72 | ||
55 | pub fn text(&self, pos: InputPosition) -> &'t str { | 73 | /// Get the raw text of a token at given input position. |
74 | pub fn token_text(&self, pos: InputPosition) -> &'t str { | ||
56 | let idx = pos.0 as usize; | 75 | let idx = pos.0 as usize; |
57 | if !(idx < self.tokens.len()) { | 76 | if !(idx < self.tokens.len()) { |
58 | return ""; | 77 | return ""; |