diff options
Diffstat (limited to 'crates/ra_syntax/src/parser_impl/event.rs')
-rw-r--r-- | crates/ra_syntax/src/parser_impl/event.rs | 148 |
1 files changed, 88 insertions, 60 deletions
diff --git a/crates/ra_syntax/src/parser_impl/event.rs b/crates/ra_syntax/src/parser_impl/event.rs index 9fd56b996..48f37c57c 100644 --- a/crates/ra_syntax/src/parser_impl/event.rs +++ b/crates/ra_syntax/src/parser_impl/event.rs | |||
@@ -9,6 +9,7 @@ | |||
9 | //! this stream to a real tree. | 9 | //! this stream to a real tree. |
10 | use std::mem; | 10 | use std::mem; |
11 | use { | 11 | use { |
12 | TextUnit, TextRange, SmolStr, | ||
12 | lexer::Token, | 13 | lexer::Token, |
13 | parser_impl::Sink, | 14 | parser_impl::Sink, |
14 | SyntaxKind::{self, TOMBSTONE}, | 15 | SyntaxKind::{self, TOMBSTONE}, |
@@ -78,77 +79,104 @@ pub(crate) enum Event { | |||
78 | }, | 79 | }, |
79 | } | 80 | } |
80 | 81 | ||
82 | pub(super) struct EventProcessor<'a, S: Sink> { | ||
83 | sink: S, | ||
84 | text_pos: TextUnit, | ||
85 | text: &'a str, | ||
86 | token_pos: usize, | ||
87 | tokens: &'a [Token], | ||
88 | events: &'a mut [Event], | ||
89 | } | ||
81 | 90 | ||
82 | pub(super) fn process<'a, S: Sink<'a>>(builder: &mut S, tokens: &[Token], mut events: Vec<Event>) { | 91 | impl<'a, S: Sink> EventProcessor<'a, S> { |
83 | fn tombstone() -> Event { | 92 | pub(super) fn new(sink: S, text: &'a str, tokens: &'a[Token], events: &'a mut [Event]) -> EventProcessor<'a, S> { |
84 | Event::Start { kind: TOMBSTONE, forward_parent: None } | 93 | EventProcessor { |
94 | sink, | ||
95 | text_pos: 0.into(), | ||
96 | text, | ||
97 | token_pos: 0, | ||
98 | tokens, | ||
99 | events | ||
100 | } | ||
85 | } | 101 | } |
86 | let eat_ws = |idx: &mut usize, builder: &mut S| { | 102 | |
87 | while let Some(token) = tokens.get(*idx) { | 103 | pub(super) fn process(mut self) -> S { |
88 | if !token.kind.is_trivia() { | 104 | fn tombstone() -> Event { |
89 | break; | 105 | Event::Start { kind: TOMBSTONE, forward_parent: None } |
90 | } | ||
91 | builder.leaf(token.kind, token.len); | ||
92 | *idx += 1 | ||
93 | } | 106 | } |
94 | }; | 107 | let mut depth = 0; |
108 | let mut forward_parents = Vec::new(); | ||
95 | 109 | ||
96 | let events: &mut [Event] = &mut events; | 110 | for i in 0..self.events.len() { |
97 | let mut depth = 0; | 111 | match mem::replace(&mut self.events[i], tombstone()) { |
98 | let mut forward_parents = Vec::new(); | 112 | Event::Start { |
99 | let mut next_tok_idx = 0; | 113 | kind: TOMBSTONE, .. |
100 | for i in 0..events.len() { | 114 | } => (), |
101 | match mem::replace(&mut events[i], tombstone()) { | ||
102 | Event::Start { | ||
103 | kind: TOMBSTONE, .. | ||
104 | } => (), | ||
105 | 115 | ||
106 | Event::Start { kind, forward_parent } => { | 116 | Event::Start { kind, forward_parent } => { |
107 | forward_parents.push(kind); | 117 | forward_parents.push(kind); |
108 | let mut idx = i; | 118 | let mut idx = i; |
109 | let mut fp = forward_parent; | 119 | let mut fp = forward_parent; |
110 | while let Some(fwd) = fp { | 120 | while let Some(fwd) = fp { |
111 | idx += fwd as usize; | 121 | idx += fwd as usize; |
112 | fp = match mem::replace(&mut events[idx], tombstone()) { | 122 | fp = match mem::replace(&mut self.events[idx], tombstone()) { |
113 | Event::Start { | 123 | Event::Start { |
114 | kind, | 124 | kind, |
115 | forward_parent, | 125 | forward_parent, |
116 | } => { | 126 | } => { |
117 | forward_parents.push(kind); | 127 | forward_parents.push(kind); |
118 | forward_parent | 128 | forward_parent |
119 | }, | 129 | }, |
120 | _ => unreachable!(), | 130 | _ => unreachable!(), |
121 | }; | 131 | }; |
132 | } | ||
133 | for kind in forward_parents.drain(..).rev() { | ||
134 | if depth > 0 { | ||
135 | self.eat_ws(); | ||
136 | } | ||
137 | depth += 1; | ||
138 | self.sink.start_internal(kind); | ||
139 | } | ||
122 | } | 140 | } |
123 | for kind in forward_parents.drain(..).rev() { | 141 | Event::Finish => { |
124 | if depth > 0 { | 142 | depth -= 1; |
125 | eat_ws(&mut next_tok_idx, builder); | 143 | if depth == 0 { |
144 | self.eat_ws(); | ||
126 | } | 145 | } |
127 | depth += 1; | 146 | |
128 | builder.start_internal(kind); | 147 | self.sink.finish_internal(); |
129 | } | 148 | } |
130 | } | 149 | Event::Token { |
131 | Event::Finish => { | 150 | kind, |
132 | depth -= 1; | 151 | mut n_raw_tokens, |
133 | if depth == 0 { | 152 | } => { |
134 | eat_ws(&mut next_tok_idx, builder); | 153 | self.eat_ws(); |
154 | let mut len = 0.into(); | ||
155 | for _ in 0..n_raw_tokens { | ||
156 | len += self.tokens[self.token_pos].len; | ||
157 | } | ||
158 | self.leaf(kind, len, n_raw_tokens as usize); | ||
135 | } | 159 | } |
136 | 160 | Event::Error { msg } => self.sink.error(msg, self.text_pos), | |
137 | builder.finish_internal(); | ||
138 | } | 161 | } |
139 | Event::Token { | 162 | } |
140 | kind, | 163 | self.sink |
141 | mut n_raw_tokens, | 164 | } |
142 | } => { | 165 | |
143 | eat_ws(&mut next_tok_idx, builder); | 166 | fn eat_ws(&mut self) { |
144 | let mut len = 0.into(); | 167 | while let Some(&token) = self.tokens.get(self.token_pos) { |
145 | for _ in 0..n_raw_tokens { | 168 | if !token.kind.is_trivia() { |
146 | len += tokens[next_tok_idx].len; | 169 | break; |
147 | next_tok_idx += 1; | ||
148 | } | ||
149 | builder.leaf(kind, len); | ||
150 | } | 170 | } |
151 | Event::Error { msg } => builder.error(msg), | 171 | self.leaf(token.kind, token.len, 1); |
152 | } | 172 | } |
153 | } | 173 | } |
174 | |||
175 | fn leaf(&mut self, kind: SyntaxKind, len: TextUnit, n_tokens: usize) { | ||
176 | let range = TextRange::offset_len(self.text_pos, len); | ||
177 | let text: SmolStr = self.text[range].into(); | ||
178 | self.text_pos += len; | ||
179 | self.token_pos += n_tokens; | ||
180 | self.sink.leaf(kind, text); | ||
181 | } | ||
154 | } | 182 | } |