]> git.lizzy.rs Git - rust.git/blob - src/parser/mod.rs
0f8f2ce0cc7126e4581ec14a691fe9b4715e7ac3
[rust.git] / src / parser / mod.rs
1 use {File, FileBuilder, Sink, SyntaxKind, Token};
2
3 use syntax_kinds::*;
4 use tree::TOMBSTONE;
5
6 mod event_parser;
7 use self::event_parser::Event;
8
9 /// Parse a sequence of tokens into the representative node tree
10 pub fn parse(text: String, tokens: &[Token]) -> File {
11     let events = event_parser::parse(&text, tokens);
12     from_events_to_file(text, tokens, events)
13 }
14
15 fn from_events_to_file(text: String, tokens: &[Token], events: Vec<Event>) -> File {
16     let mut builder = FileBuilder::new(text);
17     let mut idx = 0;
18
19     let mut holes = Vec::new();
20     let mut forward_parents = Vec::new();
21
22     for (i, event) in events.iter().enumerate() {
23         if holes.last() == Some(&i) {
24             holes.pop();
25             continue;
26         }
27
28         match event {
29             &Event::Start {
30                 kind: TOMBSTONE, ..
31             } => (),
32
33             &Event::Start { .. } => {
34                 forward_parents.clear();
35                 let mut idx = i;
36                 loop {
37                     let (kind, fwd) = match events[idx] {
38                         Event::Start {
39                             kind,
40                             forward_parent,
41                         } => (kind, forward_parent),
42                         _ => unreachable!(),
43                     };
44                     forward_parents.push((idx, kind));
45                     if let Some(fwd) = fwd {
46                         idx += fwd as usize;
47                     } else {
48                         break;
49                     }
50                 }
51                 for &(idx, kind) in forward_parents.iter().into_iter().rev() {
52                     builder.start_internal(kind);
53                     holes.push(idx);
54                 }
55                 holes.pop();
56             }
57             &Event::Finish => {
58                 while idx < tokens.len() {
59                     let token = tokens[idx];
60                     if is_insignificant(token.kind) {
61                         idx += 1;
62                         builder.leaf(token.kind, token.len);
63                     } else {
64                         break;
65                     }
66                 }
67                 builder.finish_internal()
68             }
69             &Event::Token {
70                 kind: _,
71                 mut n_raw_tokens,
72             } => loop {
73                 let token = tokens[idx];
74                 if !is_insignificant(token.kind) {
75                     n_raw_tokens -= 1;
76                 }
77                 idx += 1;
78                 builder.leaf(token.kind, token.len);
79                 if n_raw_tokens == 0 {
80                     break;
81                 }
82             },
83             &Event::Error { ref message } => builder.error().message(message.clone()).emit(),
84         }
85     }
86     builder.finish()
87 }
88
89 fn is_insignificant(kind: SyntaxKind) -> bool {
90     match kind {
91         WHITESPACE | COMMENT => true,
92         _ => false,
93     }
94 }