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