aboutsummaryrefslogtreecommitdiff
path: root/src/parser_impl
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser_impl')
-rw-r--r--src/parser_impl/event.rs54
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.
10use std::mem;
10use { 11use {
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
80pub(super) fn process<'a, S: Sink<'a>>(builder: &mut S, tokens: &[Token], events: Vec<Event>) { 81
81 let mut next_tok_idx = 0; 82pub(super) fn process<'a, S: Sink<'a>>(builder: &mut S, tokens: &[Token], mut events: Vec<Event>) {
83 fn tombstone() -> Event {
84 Event::Start { kind: TOMBSTONE, forward_parent: None }
85 }
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}