aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/parsing/parser_impl.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/parsing/parser_impl.rs')
-rw-r--r--crates/ra_syntax/src/parsing/parser_impl.rs199
1 files changed, 199 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/parsing/parser_impl.rs b/crates/ra_syntax/src/parsing/parser_impl.rs
new file mode 100644
index 000000000..c639d83e8
--- /dev/null
+++ b/crates/ra_syntax/src/parsing/parser_impl.rs
@@ -0,0 +1,199 @@
1mod event;
2mod input;
3
4use std::cell::Cell;
5
6use crate::{
7 SmolStr,
8 syntax_node::syntax_error::{ParseError, SyntaxError},
9 parsing::{
10 lexer::Token,
11 parser_api::Parser,
12 parser_impl::{
13 event::{Event, EventProcessor},
14 input::{InputPosition, ParserInput},
15 },
16}};
17
18use crate::SyntaxKind::{self, EOF, TOMBSTONE};
19
20pub(crate) trait Sink {
21 type Tree;
22
23 /// Adds new leaf to the current branch.
24 fn leaf(&mut self, kind: SyntaxKind, text: SmolStr);
25
26 /// Start new branch and make it current.
27 fn start_branch(&mut self, kind: SyntaxKind);
28
29 /// Finish current branch and restore previous
30 /// branch as current.
31 fn finish_branch(&mut self);
32
33 fn error(&mut self, error: SyntaxError);
34
35 /// Complete tree building. Make sure that
36 /// `start_branch` and `finish_branch` calls
37 /// are paired!
38 fn finish(self) -> Self::Tree;
39}
40
41/// Parse a sequence of tokens into the representative node tree
42pub(crate) fn parse_with<S: Sink>(
43 sink: S,
44 text: &str,
45 tokens: &[Token],
46 parser: fn(&mut Parser),
47) -> S::Tree {
48 let mut events = {
49 let input = input::ParserInput::new(text, tokens);
50 let parser_impl = ParserImpl::new(&input);
51 let mut parser_api = Parser(parser_impl);
52 parser(&mut parser_api);
53 parser_api.0.into_events()
54 };
55 EventProcessor::new(sink, text, tokens, &mut events).process().finish()
56}
57
58/// Implementation details of `Parser`, extracted
59/// to a separate struct in order not to pollute
60/// the public API of the `Parser`.
61pub(crate) struct ParserImpl<'t> {
62 parser_input: &'t ParserInput<'t>,
63 pos: InputPosition,
64 events: Vec<Event>,
65 steps: Cell<u32>,
66}
67
68impl<'t> ParserImpl<'t> {
69 fn new(inp: &'t ParserInput<'t>) -> ParserImpl<'t> {
70 ParserImpl {
71 parser_input: inp,
72 pos: InputPosition::new(),
73 events: Vec::new(),
74 steps: Cell::new(0),
75 }
76 }
77
78 fn into_events(self) -> Vec<Event> {
79 assert_eq!(self.nth(0), EOF);
80 self.events
81 }
82
83 pub(super) fn current2(&self) -> Option<(SyntaxKind, SyntaxKind)> {
84 let c1 = self.parser_input.kind(self.pos);
85 let c2 = self.parser_input.kind(self.pos + 1);
86 if self.parser_input.token_start_at(self.pos + 1)
87 == self.parser_input.token_start_at(self.pos) + self.parser_input.token_len(self.pos)
88 {
89 Some((c1, c2))
90 } else {
91 None
92 }
93 }
94
95 pub(super) fn current3(&self) -> Option<(SyntaxKind, SyntaxKind, SyntaxKind)> {
96 let c1 = self.parser_input.kind(self.pos);
97 let c2 = self.parser_input.kind(self.pos + 1);
98 let c3 = self.parser_input.kind(self.pos + 2);
99 if self.parser_input.token_start_at(self.pos + 1)
100 == self.parser_input.token_start_at(self.pos) + self.parser_input.token_len(self.pos)
101 && self.parser_input.token_start_at(self.pos + 2)
102 == self.parser_input.token_start_at(self.pos + 1)
103 + self.parser_input.token_len(self.pos + 1)
104 {
105 Some((c1, c2, c3))
106 } else {
107 None
108 }
109 }
110
111 /// Get the syntax kind of the nth token.
112 pub(super) fn nth(&self, n: u32) -> SyntaxKind {
113 let steps = self.steps.get();
114 assert!(steps <= 10_000_000, "the parser seems stuck");
115 self.steps.set(steps + 1);
116
117 self.parser_input.kind(self.pos + n)
118 }
119
120 pub(super) fn at_kw(&self, t: &str) -> bool {
121 self.parser_input.token_text(self.pos) == t
122 }
123
124 /// Start parsing right behind the last event.
125 pub(super) fn start(&mut self) -> u32 {
126 let pos = self.events.len() as u32;
127 self.push_event(Event::tombstone());
128 pos
129 }
130
131 /// Advances the parser by one token unconditionally.
132 pub(super) fn bump(&mut self) {
133 let kind = self.nth(0);
134 if kind == EOF {
135 return;
136 }
137 self.do_bump(kind, 1);
138 }
139
140 pub(super) fn bump_remap(&mut self, kind: SyntaxKind) {
141 if self.nth(0) == EOF {
142 // TODO: panic!?
143 return;
144 }
145 self.do_bump(kind, 1);
146 }
147
148 pub(super) fn bump_compound(&mut self, kind: SyntaxKind, n: u8) {
149 self.do_bump(kind, n);
150 }
151
152 fn do_bump(&mut self, kind: SyntaxKind, n_raw_tokens: u8) {
153 self.pos += u32::from(n_raw_tokens);
154 self.push_event(Event::Token { kind, n_raw_tokens });
155 }
156
157 /// Append one Error event to the back of events.
158 pub(super) fn error(&mut self, msg: String) {
159 self.push_event(Event::Error { msg: ParseError(msg) })
160 }
161
162 /// Complete an event with appending a `Finish` event.
163 pub(super) fn complete(&mut self, pos: u32, kind: SyntaxKind) {
164 match self.events[pos as usize] {
165 Event::Start { kind: ref mut slot, .. } => {
166 *slot = kind;
167 }
168 _ => unreachable!(),
169 }
170 self.push_event(Event::Finish);
171 }
172
173 /// Ignore the dummy `Start` event.
174 pub(super) fn abandon(&mut self, pos: u32) {
175 let idx = pos as usize;
176 if idx == self.events.len() - 1 {
177 match self.events.pop() {
178 Some(Event::Start { kind: TOMBSTONE, forward_parent: None }) => (),
179 _ => unreachable!(),
180 }
181 }
182 }
183
184 /// Save the relative distance of a completed event to its forward_parent.
185 pub(super) fn precede(&mut self, pos: u32) -> u32 {
186 let new_pos = self.start();
187 match self.events[pos as usize] {
188 Event::Start { ref mut forward_parent, .. } => {
189 *forward_parent = Some(new_pos - pos);
190 }
191 _ => unreachable!(),
192 }
193 new_pos
194 }
195
196 fn push_event(&mut self, event: Event) {
197 self.events.push(event)
198 }
199}