aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/parser/event_parser/grammar/items.rs11
-rw-r--r--src/parser/event_parser/mod.rs5
-rw-r--r--src/parser/event_parser/parser.rs20
-rw-r--r--src/parser/mod.rs41
-rw-r--r--tests/data/parser/ok/0011_outer_attribute.txt38
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
34fn item(p: &mut Parser) -> bool { 34fn 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
51fn struct_item(p: &mut Parser) { 58fn 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)]
7pub(crate) enum Event { 7pub(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)]
23pub(crate) struct Pos(u32); 23pub(crate) struct Pos(u32);
24 24
25#[derive(Debug, Clone, Copy,PartialEq, Eq)]
26pub(crate) struct Mark(u32);
27
25impl<'t> Parser<'t> { 28impl<'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 @@
1FILE@[0; 35) 1FILE@[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)