diff options
author | Aleksey Kladov <[email protected]> | 2018-01-12 17:32:37 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-01-12 17:32:37 +0000 |
commit | ca0c5ea38b623422e1a25388817e224c2c4f4ae2 (patch) | |
tree | f4b3c05e35020ff6dcd3cef7fbf890bbce03c9e5 | |
parent | 15ae9026cf270d898cad16678032a5460e77404c (diff) |
Support tree rebalancing
-rw-r--r-- | src/parser/event_parser/grammar/items.rs | 11 | ||||
-rw-r--r-- | src/parser/event_parser/mod.rs | 5 | ||||
-rw-r--r-- | src/parser/event_parser/parser.rs | 20 | ||||
-rw-r--r-- | src/parser/mod.rs | 41 | ||||
-rw-r--r-- | tests/data/parser/ok/0011_outer_attribute.txt | 38 |
5 files changed, 86 insertions, 29 deletions
diff --git a/src/parser/event_parser/grammar/items.rs b/src/parser/event_parser/grammar/items.rs index 522986ed0..725f04d1e 100644 --- a/src/parser/event_parser/grammar/items.rs +++ b/src/parser/event_parser/grammar/items.rs | |||
@@ -32,6 +32,7 @@ fn mod_contents_item(p: &mut Parser) { | |||
32 | } | 32 | } |
33 | 33 | ||
34 | fn item(p: &mut Parser) -> bool { | 34 | fn item(p: &mut Parser) -> bool { |
35 | let attrs_start = p.mark(); | ||
35 | attributes::outer_attributes(p); | 36 | attributes::outer_attributes(p); |
36 | visibility(p); | 37 | visibility(p); |
37 | // node_if(p, USE_KW, USE_ITEM, use_item) | 38 | // node_if(p, USE_KW, USE_ITEM, use_item) |
@@ -41,11 +42,17 @@ fn item(p: &mut Parser) -> bool { | |||
41 | // || unsafe trait, impl | 42 | // || unsafe trait, impl |
42 | // || node_if(p, FN_KW, FN_ITEM, fn_item) | 43 | // || node_if(p, FN_KW, FN_ITEM, fn_item) |
43 | // || node_if(p, TYPE_KW, TYPE_ITEM, type_item) | 44 | // || node_if(p, TYPE_KW, TYPE_ITEM, type_item) |
44 | node_if(p, [EXTERN_KW, CRATE_KW], EXTERN_CRATE_ITEM, extern_crate_item) | 45 | let item_start = p.mark(); |
46 | let item_parsed = node_if(p, [EXTERN_KW, CRATE_KW], EXTERN_CRATE_ITEM, extern_crate_item) | ||
45 | || node_if(p, MOD_KW, MOD_ITEM, mod_item) | 47 | || node_if(p, MOD_KW, MOD_ITEM, mod_item) |
46 | || node_if(p, USE_KW, USE_ITEM, use_item) | 48 | || node_if(p, USE_KW, USE_ITEM, use_item) |
47 | || node_if(p, STRUCT_KW, STRUCT_ITEM, struct_item) | 49 | || node_if(p, STRUCT_KW, STRUCT_ITEM, struct_item) |
48 | || node_if(p, FN_KW, FN_ITEM, fn_item) | 50 | || node_if(p, FN_KW, FN_ITEM, fn_item); |
51 | |||
52 | if item_parsed && attrs_start != item_start { | ||
53 | p.forward_parent(attrs_start, item_start); | ||
54 | } | ||
55 | item_parsed | ||
49 | } | 56 | } |
50 | 57 | ||
51 | fn struct_item(p: &mut Parser) { | 58 | fn struct_item(p: &mut Parser) { |
diff --git a/src/parser/event_parser/mod.rs b/src/parser/event_parser/mod.rs index 87b317c84..c89a3ebe7 100644 --- a/src/parser/event_parser/mod.rs +++ b/src/parser/event_parser/mod.rs | |||
@@ -5,7 +5,10 @@ mod parser; | |||
5 | 5 | ||
6 | #[derive(Debug)] | 6 | #[derive(Debug)] |
7 | pub(crate) enum Event { | 7 | pub(crate) enum Event { |
8 | Start { kind: SyntaxKind }, | 8 | Start { |
9 | kind: SyntaxKind, | ||
10 | forward_parent: Option<u32>, | ||
11 | }, | ||
9 | Finish, | 12 | Finish, |
10 | Token { | 13 | Token { |
11 | kind: SyntaxKind, | 14 | kind: SyntaxKind, |
diff --git a/src/parser/event_parser/parser.rs b/src/parser/event_parser/parser.rs index 8bc382b12..14c0efe2d 100644 --- a/src/parser/event_parser/parser.rs +++ b/src/parser/event_parser/parser.rs | |||
@@ -22,6 +22,9 @@ pub(crate) struct Parser<'t> { | |||
22 | #[derive(Debug, Clone, Copy,PartialEq, Eq)] | 22 | #[derive(Debug, Clone, Copy,PartialEq, Eq)] |
23 | pub(crate) struct Pos(u32); | 23 | pub(crate) struct Pos(u32); |
24 | 24 | ||
25 | #[derive(Debug, Clone, Copy,PartialEq, Eq)] | ||
26 | pub(crate) struct Mark(u32); | ||
27 | |||
25 | impl<'t> Parser<'t> { | 28 | impl<'t> Parser<'t> { |
26 | pub(crate) fn new(text: &'t str, raw_tokens: &'t [Token]) -> Parser<'t> { | 29 | pub(crate) fn new(text: &'t str, raw_tokens: &'t [Token]) -> Parser<'t> { |
27 | let mut tokens = Vec::new(); | 30 | let mut tokens = Vec::new(); |
@@ -47,6 +50,21 @@ impl<'t> Parser<'t> { | |||
47 | } | 50 | } |
48 | } | 51 | } |
49 | 52 | ||
53 | pub(crate) fn mark(&self) -> Mark { | ||
54 | Mark(self.events.len() as u32) | ||
55 | } | ||
56 | |||
57 | pub(crate) fn forward_parent(&mut self, child: Mark, parent: Mark) { | ||
58 | assert!(child.0 < parent.0); | ||
59 | let diff = parent.0 - child.0; | ||
60 | match self.events[child.0 as usize] { | ||
61 | Event::Start { ref mut forward_parent, .. } => { | ||
62 | *forward_parent = Some(diff); | ||
63 | } | ||
64 | _ => unreachable!() | ||
65 | } | ||
66 | } | ||
67 | |||
50 | pub(crate) fn pos(&self) -> Pos { | 68 | pub(crate) fn pos(&self) -> Pos { |
51 | Pos(self.pos as u32) | 69 | Pos(self.pos as u32) |
52 | } | 70 | } |
@@ -71,7 +89,7 @@ impl<'t> Parser<'t> { | |||
71 | } | 89 | } |
72 | 90 | ||
73 | pub(crate) fn start(&mut self, kind: SyntaxKind) { | 91 | pub(crate) fn start(&mut self, kind: SyntaxKind) { |
74 | self.event(Event::Start { kind }); | 92 | self.event(Event::Start { kind, forward_parent: None }); |
75 | } | 93 | } |
76 | 94 | ||
77 | pub(crate) fn finish(&mut self) { | 95 | pub(crate) fn finish(&mut self) { |
diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 742755142..c08d32d08 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs | |||
@@ -18,10 +18,39 @@ fn from_events_to_file( | |||
18 | ) -> File { | 18 | ) -> File { |
19 | let mut builder = FileBuilder::new(text); | 19 | let mut builder = FileBuilder::new(text); |
20 | let mut idx = 0; | 20 | let mut idx = 0; |
21 | for event in events { | 21 | |
22 | let mut holes = Vec::new(); | ||
23 | let mut forward_parents = Vec::new(); | ||
24 | |||
25 | for (i, event) in events.iter().enumerate() { | ||
26 | if holes.last() == Some(&i) { | ||
27 | holes.pop(); | ||
28 | continue | ||
29 | } | ||
30 | |||
22 | match event { | 31 | match event { |
23 | Event::Start { kind } => builder.start_internal(kind), | 32 | &Event::Start { kind, forward_parent } => { |
24 | Event::Finish => { | 33 | forward_parents.clear(); |
34 | let mut idx = i; | ||
35 | loop { | ||
36 | let (kind, fwd) = match events[idx] { | ||
37 | Event::Start { kind, forward_parent } => (kind, forward_parent), | ||
38 | _ => unreachable!(), | ||
39 | }; | ||
40 | forward_parents.push((idx, kind)); | ||
41 | if let Some(fwd) = fwd { | ||
42 | idx += fwd as usize; | ||
43 | } else { | ||
44 | break; | ||
45 | } | ||
46 | } | ||
47 | for &(idx, kind) in forward_parents.iter().into_iter().rev() { | ||
48 | builder.start_internal(kind); | ||
49 | holes.push(idx); | ||
50 | } | ||
51 | holes.pop(); | ||
52 | } | ||
53 | &Event::Finish => { | ||
25 | while idx < tokens.len() { | 54 | while idx < tokens.len() { |
26 | let token = tokens[idx]; | 55 | let token = tokens[idx]; |
27 | if is_insignificant(token.kind) { | 56 | if is_insignificant(token.kind) { |
@@ -33,7 +62,7 @@ fn from_events_to_file( | |||
33 | } | 62 | } |
34 | builder.finish_internal() | 63 | builder.finish_internal() |
35 | }, | 64 | }, |
36 | Event::Token { kind, mut n_raw_tokens } => loop { | 65 | &Event::Token { kind, mut n_raw_tokens } => loop { |
37 | let token = tokens[idx]; | 66 | let token = tokens[idx]; |
38 | if !is_insignificant(token.kind) { | 67 | if !is_insignificant(token.kind) { |
39 | n_raw_tokens -= 1; | 68 | n_raw_tokens -= 1; |
@@ -44,8 +73,8 @@ fn from_events_to_file( | |||
44 | break; | 73 | break; |
45 | } | 74 | } |
46 | }, | 75 | }, |
47 | Event::Error { message } => builder.error().message(message).emit(), | 76 | &Event::Error { ref message } => |
48 | 77 | builder.error().message(message.clone()).emit(), | |
49 | } | 78 | } |
50 | } | 79 | } |
51 | builder.finish() | 80 | builder.finish() |
diff --git a/tests/data/parser/ok/0011_outer_attribute.txt b/tests/data/parser/ok/0011_outer_attribute.txt index a790f4095..0f69b1f66 100644 --- a/tests/data/parser/ok/0011_outer_attribute.txt +++ b/tests/data/parser/ok/0011_outer_attribute.txt | |||
@@ -1,23 +1,23 @@ | |||
1 | FILE@[0; 35) | 1 | FILE@[0; 35) |
2 | ATTR@[0; 13) | 2 | FN_ITEM@[0; 35) |
3 | POUND@[0; 1) | 3 | ATTR@[0; 13) |
4 | L_BRACK@[1; 2) | 4 | POUND@[0; 1) |
5 | META_ITEM@[2; 11) | 5 | L_BRACK@[1; 2) |
6 | IDENT@[2; 5) | 6 | META_ITEM@[2; 11) |
7 | L_PAREN@[5; 6) | 7 | IDENT@[2; 5) |
8 | META_ITEM@[6; 10) | 8 | L_PAREN@[5; 6) |
9 | IDENT@[6; 10) | 9 | META_ITEM@[6; 10) |
10 | R_PAREN@[10; 11) | 10 | IDENT@[6; 10) |
11 | R_BRACK@[11; 12) | 11 | R_PAREN@[10; 11) |
12 | WHITESPACE@[12; 13) | 12 | R_BRACK@[11; 12) |
13 | ATTR@[13; 23) | 13 | WHITESPACE@[12; 13) |
14 | POUND@[13; 14) | 14 | ATTR@[13; 23) |
15 | L_BRACK@[14; 15) | 15 | POUND@[13; 14) |
16 | META_ITEM@[15; 21) | 16 | L_BRACK@[14; 15) |
17 | IDENT@[15; 21) | 17 | META_ITEM@[15; 21) |
18 | R_BRACK@[21; 22) | 18 | IDENT@[15; 21) |
19 | WHITESPACE@[22; 23) | 19 | R_BRACK@[21; 22) |
20 | FN_ITEM@[23; 35) | 20 | WHITESPACE@[22; 23) |
21 | FN_KW@[23; 25) | 21 | FN_KW@[23; 25) |
22 | WHITESPACE@[25; 26) | 22 | WHITESPACE@[25; 26) |
23 | IDENT@[26; 29) | 23 | IDENT@[26; 29) |