diff options
Diffstat (limited to 'src/parser_impl')
-rw-r--r-- | src/parser_impl/event.rs | 54 |
1 files changed, 25 insertions, 29 deletions
diff --git a/src/parser_impl/event.rs b/src/parser_impl/event.rs index 4c97b1bea..9fd56b996 100644 --- a/src/parser_impl/event.rs +++ b/src/parser_impl/event.rs | |||
@@ -7,6 +7,7 @@ | |||
7 | //! tree builder: the parser produces a stream of events like | 7 | //! tree builder: the parser produces a stream of events like |
8 | //! `start node`, `finish node`, and `FileBuilder` converts | 8 | //! `start node`, `finish node`, and `FileBuilder` converts |
9 | //! this stream to a real tree. | 9 | //! this stream to a real tree. |
10 | use std::mem; | ||
10 | use { | 11 | use { |
11 | lexer::Token, | 12 | lexer::Token, |
12 | parser_impl::Sink, | 13 | parser_impl::Sink, |
@@ -77,8 +78,11 @@ pub(crate) enum Event { | |||
77 | }, | 78 | }, |
78 | } | 79 | } |
79 | 80 | ||
80 | pub(super) fn process<'a, S: Sink<'a>>(builder: &mut S, tokens: &[Token], events: Vec<Event>) { | 81 | |
81 | let mut next_tok_idx = 0; | 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 | } | ||
82 | let eat_ws = |idx: &mut usize, builder: &mut S| { | 86 | let eat_ws = |idx: &mut usize, builder: &mut S| { |
83 | while let Some(token) = tokens.get(*idx) { | 87 | while let Some(token) = tokens.get(*idx) { |
84 | if !token.kind.is_trivia() { | 88 | if !token.kind.is_trivia() { |
@@ -89,50 +93,42 @@ pub(super) fn process<'a, S: Sink<'a>>(builder: &mut S, tokens: &[Token], events | |||
89 | } | 93 | } |
90 | }; | 94 | }; |
91 | 95 | ||
96 | let events: &mut [Event] = &mut events; | ||
92 | let mut depth = 0; | 97 | let mut depth = 0; |
93 | let mut holes = Vec::new(); | ||
94 | let mut forward_parents = Vec::new(); | 98 | let mut forward_parents = Vec::new(); |
95 | 99 | let mut next_tok_idx = 0; | |
96 | for (i, event) in events.iter().enumerate() { | 100 | for i in 0..events.len() { |
97 | if holes.last() == Some(&i) { | 101 | match mem::replace(&mut events[i], tombstone()) { |
98 | holes.pop(); | 102 | Event::Start { |
99 | continue; | ||
100 | } | ||
101 | |||
102 | match event { | ||
103 | &Event::Start { | ||
104 | kind: TOMBSTONE, .. | 103 | kind: TOMBSTONE, .. |
105 | } => (), | 104 | } => (), |
106 | 105 | ||
107 | &Event::Start { .. } => { | 106 | Event::Start { kind, forward_parent } => { |
108 | forward_parents.clear(); | 107 | forward_parents.push(kind); |
109 | let mut idx = i; | 108 | let mut idx = i; |
110 | loop { | 109 | let mut fp = forward_parent; |
111 | let (kind, fwd) = match events[idx] { | 110 | while let Some(fwd) = fp { |
111 | idx += fwd as usize; | ||
112 | fp = match mem::replace(&mut events[idx], tombstone()) { | ||
112 | Event::Start { | 113 | Event::Start { |
113 | kind, | 114 | kind, |
114 | forward_parent, | 115 | forward_parent, |
115 | } => (kind, forward_parent), | 116 | } => { |
117 | forward_parents.push(kind); | ||
118 | forward_parent | ||
119 | }, | ||
116 | _ => unreachable!(), | 120 | _ => unreachable!(), |
117 | }; | 121 | }; |
118 | forward_parents.push((idx, kind)); | ||
119 | if let Some(fwd) = fwd { | ||
120 | idx += fwd as usize; | ||
121 | } else { | ||
122 | break; | ||
123 | } | ||
124 | } | 122 | } |
125 | for &(idx, kind) in forward_parents.iter().into_iter().rev() { | 123 | for kind in forward_parents.drain(..).rev() { |
126 | if depth > 0 { | 124 | if depth > 0 { |
127 | eat_ws(&mut next_tok_idx, builder); | 125 | eat_ws(&mut next_tok_idx, builder); |
128 | } | 126 | } |
129 | depth += 1; | 127 | depth += 1; |
130 | builder.start_internal(kind); | 128 | builder.start_internal(kind); |
131 | holes.push(idx); | ||
132 | } | 129 | } |
133 | holes.pop(); | ||
134 | } | 130 | } |
135 | &Event::Finish => { | 131 | Event::Finish => { |
136 | depth -= 1; | 132 | depth -= 1; |
137 | if depth == 0 { | 133 | if depth == 0 { |
138 | eat_ws(&mut next_tok_idx, builder); | 134 | eat_ws(&mut next_tok_idx, builder); |
@@ -140,7 +136,7 @@ pub(super) fn process<'a, S: Sink<'a>>(builder: &mut S, tokens: &[Token], events | |||
140 | 136 | ||
141 | builder.finish_internal(); | 137 | builder.finish_internal(); |
142 | } | 138 | } |
143 | &Event::Token { | 139 | Event::Token { |
144 | kind, | 140 | kind, |
145 | mut n_raw_tokens, | 141 | mut n_raw_tokens, |
146 | } => { | 142 | } => { |
@@ -152,7 +148,7 @@ pub(super) fn process<'a, S: Sink<'a>>(builder: &mut S, tokens: &[Token], events | |||
152 | } | 148 | } |
153 | builder.leaf(kind, len); | 149 | builder.leaf(kind, len); |
154 | } | 150 | } |
155 | &Event::Error { ref msg } => builder.error(msg.clone()), | 151 | Event::Error { msg } => builder.error(msg), |
156 | } | 152 | } |
157 | } | 153 | } |
158 | } | 154 | } |