diff options
Diffstat (limited to 'src/parser_impl/mod.rs')
-rw-r--r-- | src/parser_impl/mod.rs | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/src/parser_impl/mod.rs b/src/parser_impl/mod.rs new file mode 100644 index 000000000..b58094be3 --- /dev/null +++ b/src/parser_impl/mod.rs | |||
@@ -0,0 +1,155 @@ | |||
1 | mod event; | ||
2 | mod input; | ||
3 | |||
4 | use { | ||
5 | grammar, | ||
6 | lexer::Token, | ||
7 | parser_api::Parser, | ||
8 | parser_impl::{ | ||
9 | event::{process, Event}, | ||
10 | input::{InputPosition, ParserInput}, | ||
11 | }, | ||
12 | TextUnit, | ||
13 | }; | ||
14 | |||
15 | use SyntaxKind::{self, EOF, TOMBSTONE}; | ||
16 | |||
17 | pub(crate) trait Sink { | ||
18 | type Tree; | ||
19 | |||
20 | fn new(text: String) -> Self; | ||
21 | |||
22 | fn leaf(&mut self, kind: SyntaxKind, len: TextUnit); | ||
23 | fn start_internal(&mut self, kind: SyntaxKind); | ||
24 | fn finish_internal(&mut self); | ||
25 | fn error(&mut self, err: String); | ||
26 | fn finish(self) -> Self::Tree; | ||
27 | } | ||
28 | |||
29 | /// Parse a sequence of tokens into the representative node tree | ||
30 | pub(crate) fn parse<S: Sink>(text: String, tokens: &[Token]) -> S::Tree { | ||
31 | let events = { | ||
32 | let input = input::ParserInput::new(&text, tokens); | ||
33 | let parser_impl = ParserImpl::new(&input); | ||
34 | let mut parser_api = Parser(parser_impl); | ||
35 | grammar::file(&mut parser_api); | ||
36 | parser_api.0.into_events() | ||
37 | }; | ||
38 | let mut sink = S::new(text); | ||
39 | process(&mut sink, tokens, events); | ||
40 | sink.finish() | ||
41 | } | ||
42 | |||
43 | /// Implementation details of `Parser`, extracted | ||
44 | /// to a separate struct in order not to pollute | ||
45 | /// the public API of the `Parser`. | ||
46 | pub(crate) struct ParserImpl<'t> { | ||
47 | inp: &'t ParserInput<'t>, | ||
48 | |||
49 | pos: InputPosition, | ||
50 | events: Vec<Event>, | ||
51 | } | ||
52 | |||
53 | impl<'t> ParserImpl<'t> { | ||
54 | pub(crate) fn new(inp: &'t ParserInput<'t>) -> ParserImpl<'t> { | ||
55 | ParserImpl { | ||
56 | inp, | ||
57 | |||
58 | pos: InputPosition::new(), | ||
59 | events: Vec::new(), | ||
60 | } | ||
61 | } | ||
62 | |||
63 | pub(crate) fn into_events(self) -> Vec<Event> { | ||
64 | assert_eq!(self.nth(0), EOF); | ||
65 | self.events | ||
66 | } | ||
67 | |||
68 | pub(super) fn nth(&self, n: u32) -> SyntaxKind { | ||
69 | self.inp.kind(self.pos + n) | ||
70 | } | ||
71 | |||
72 | pub(super) fn at_kw(&self, t: &str) -> bool { | ||
73 | self.inp.text(self.pos) == t | ||
74 | } | ||
75 | |||
76 | pub(super) fn start(&mut self) -> u32 { | ||
77 | let pos = self.events.len() as u32; | ||
78 | self.event(Event::Start { | ||
79 | kind: TOMBSTONE, | ||
80 | forward_parent: None, | ||
81 | }); | ||
82 | pos | ||
83 | } | ||
84 | |||
85 | pub(super) fn bump(&mut self) { | ||
86 | let kind = self.nth(0); | ||
87 | if kind == EOF { | ||
88 | return; | ||
89 | } | ||
90 | self.do_bump(kind); | ||
91 | } | ||
92 | |||
93 | pub(super) fn bump_remap(&mut self, kind: SyntaxKind) { | ||
94 | if self.nth(0) == EOF { | ||
95 | // TODO: panic!? | ||
96 | return; | ||
97 | } | ||
98 | self.do_bump(kind); | ||
99 | } | ||
100 | |||
101 | fn do_bump(&mut self, kind: SyntaxKind) { | ||
102 | self.pos += 1; | ||
103 | self.event(Event::Token { | ||
104 | kind, | ||
105 | n_raw_tokens: 1, | ||
106 | }); | ||
107 | } | ||
108 | |||
109 | pub(super) fn error(&mut self, msg: String) { | ||
110 | self.event(Event::Error { msg }) | ||
111 | } | ||
112 | |||
113 | pub(super) fn complete(&mut self, pos: u32, kind: SyntaxKind) { | ||
114 | match self.events[pos as usize] { | ||
115 | Event::Start { | ||
116 | kind: ref mut slot, .. | ||
117 | } => { | ||
118 | *slot = kind; | ||
119 | } | ||
120 | _ => unreachable!(), | ||
121 | } | ||
122 | self.event(Event::Finish); | ||
123 | } | ||
124 | |||
125 | pub(super) fn abandon(&mut self, pos: u32) { | ||
126 | let idx = pos as usize; | ||
127 | if idx == self.events.len() - 1 { | ||
128 | match self.events.pop() { | ||
129 | Some(Event::Start { | ||
130 | kind: TOMBSTONE, | ||
131 | forward_parent: None, | ||
132 | }) => (), | ||
133 | _ => unreachable!(), | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | |||
138 | pub(super) fn precede(&mut self, pos: u32) -> u32 { | ||
139 | let new_pos = self.start(); | ||
140 | match self.events[pos as usize] { | ||
141 | Event::Start { | ||
142 | ref mut forward_parent, | ||
143 | .. | ||
144 | } => { | ||
145 | *forward_parent = Some(new_pos - pos); | ||
146 | } | ||
147 | _ => unreachable!(), | ||
148 | } | ||
149 | new_pos | ||
150 | } | ||
151 | |||
152 | fn event(&mut self, event: Event) { | ||
153 | self.events.push(event) | ||
154 | } | ||
155 | } | ||