diff options
-rw-r--r-- | crates/libsyntax2/src/algo/walk.rs | 33 |
1 files changed, 13 insertions, 20 deletions
diff --git a/crates/libsyntax2/src/algo/walk.rs b/crates/libsyntax2/src/algo/walk.rs index a50ec2a09..d8797c453 100644 --- a/crates/libsyntax2/src/algo/walk.rs +++ b/crates/libsyntax2/src/algo/walk.rs | |||
@@ -1,4 +1,7 @@ | |||
1 | use SyntaxNodeRef; | 1 | use { |
2 | SyntaxNodeRef, | ||
3 | algo::generate, | ||
4 | }; | ||
2 | 5 | ||
3 | pub fn preorder<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = SyntaxNodeRef<'a>> { | 6 | pub fn preorder<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = SyntaxNodeRef<'a>> { |
4 | walk(root).filter_map(|event| match event { | 7 | walk(root).filter_map(|event| match event { |
@@ -14,32 +17,22 @@ pub enum WalkEvent<'a> { | |||
14 | } | 17 | } |
15 | 18 | ||
16 | pub fn walk<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = WalkEvent<'a>> { | 19 | pub fn walk<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = WalkEvent<'a>> { |
17 | let mut done = false; | 20 | generate(Some(WalkEvent::Enter(root)), |pos| { |
18 | ::itertools::unfold(WalkEvent::Enter(root), move |pos| { | 21 | let next = match *pos { |
19 | if done { | ||
20 | return None; | ||
21 | } | ||
22 | let res = *pos; | ||
23 | *pos = match *pos { | ||
24 | WalkEvent::Enter(node) => match node.first_child() { | 22 | WalkEvent::Enter(node) => match node.first_child() { |
25 | Some(child) => WalkEvent::Enter(child), | 23 | Some(child) => WalkEvent::Enter(child), |
26 | None => WalkEvent::Exit(node), | 24 | None => WalkEvent::Exit(node), |
27 | }, | 25 | }, |
28 | WalkEvent::Exit(node) => { | 26 | WalkEvent::Exit(node) => { |
29 | if node == root { | 27 | match node.next_sibling() { |
30 | done = true; | 28 | Some(sibling) => WalkEvent::Enter(sibling), |
31 | WalkEvent::Exit(node) | 29 | None => match node.parent() { |
32 | } else { | 30 | Some(node) => WalkEvent::Exit(node), |
33 | match node.next_sibling() { | 31 | None => return None, |
34 | Some(sibling) => WalkEvent::Enter(sibling), | 32 | }, |
35 | None => match node.parent() { | ||
36 | Some(node) => WalkEvent::Exit(node), | ||
37 | None => WalkEvent::Exit(node), | ||
38 | }, | ||
39 | } | ||
40 | } | 33 | } |
41 | } | 34 | } |
42 | }; | 35 | }; |
43 | Some(res) | 36 | Some(next) |
44 | }) | 37 | }) |
45 | } | 38 | } |