1use std::cell::Cell;
2
3use crate::syntax::{
4 buildctx::BuildCtx,
5 cst::{
6 kind::TreeKind,
7 tree::{Node, NodeHandle},
8 },
9 diagnostic::Severity,
10 lexer::token::{Token, TokenKind},
11 location::Span,
12};
13
14use super::token::{Tt, TtSet};
15
16#[derive(Debug, Clone, Copy)]
17enum EventKind {
18 Open { kind: TreeKind, next: u32 },
19 Close,
20}
21
22const CHAIN_END: u32 = u32::MAX;
23
24#[derive(Debug, Clone, Copy)]
25struct Event {
26 token: u32,
27 kind: EventKind,
28}
29
30const EVENT_IGNORE: u32 = u32::MAX;
31
32#[derive(Debug, Clone, Copy)]
33pub struct OpenHandle(u32);
34#[derive(Debug, Clone, Copy)]
35pub struct CloseHandle(u32);
36
37const MAX_PARSER_LOOKUPS: u32 = 256;
38
39pub struct Parser<'ctx> {
40 ctx: &'ctx mut BuildCtx,
41 tokens: Vec<Token>,
42 token_idx: u32,
43 events: Vec<Event>,
44 fuel: Cell<u32>,
45}
46
47impl<'ctx> Parser<'ctx> {
48 pub fn new(ctx: &'ctx mut BuildCtx, tokens: Vec<Token>) -> Self {
49 Self {
50 ctx,
51 tokens,
52 token_idx: 0,
53 events: Vec::new(),
54 fuel: Cell::new(MAX_PARSER_LOOKUPS),
55 }
56 }
57
58 pub fn make_tree(&mut self) -> Vec<Node> {
59 let mut stack = Vec::new();
60 let mut output = Vec::with_capacity(self.tokens.len() + self.events.len());
61 let mut tokens = self.tokens.drain(..);
62 let mut token_idx = 0;
63
64 for event in self.events.iter() {
65 if event.token == EVENT_IGNORE {
66 continue;
67 }
68
69 for _ in token_idx..event.token {
71 output.push(Node::Token(
72 tokens
73 .next()
74 .expect("Event token index exceeds number of tokens"),
75 ));
76 }
77 token_idx = event.token;
78
79 match event.kind {
80 EventKind::Open { mut kind, mut next } => loop {
81 stack.push(output.len());
82 output.push(Node::Open {
83 kind,
84 close: NodeHandle(u32::MAX),
85 });
86
87 if next != CHAIN_END {
88 assert_eq!(self.events[next as usize].token, EVENT_IGNORE);
89 (kind, next) = if let EventKind::Open { kind, next } =
90 self.events[next as usize].kind
91 {
92 (kind, next)
93 } else {
94 panic!("Open event chained to a non-Open event")
95 }
96 } else {
97 break;
98 }
99 },
100 EventKind::Close => {
101 let open_idx = stack.pop().expect("Too many close events");
102 let close_idx = output.len();
103
104 let Node::Open { kind, close } = &mut output[open_idx] else {
105 panic!("stack points to non-Open node");
106 };
107
108 *close = NodeHandle(close_idx as u32);
109 let kind = *kind;
110
111 output.push(Node::Close {
112 kind,
113 open: NodeHandle(open_idx as u32),
114 });
115 }
116 }
117 }
118
119 assert!(stack.is_empty());
120
121 output
122 }
123
124 fn burn(&self) {
125 if self.fuel.get() == 0 {
126 panic!("Parser is stuck at {:?}", self.pos())
127 }
128 self.fuel.set(self.fuel.get() - 1);
129 }
130
131 fn push_event(&mut self, kind: EventKind) {
132 self.events.push(Event {
133 token: self.token_idx,
134 kind,
135 });
136 }
137
138 #[must_use]
139 pub fn open(&mut self) -> OpenHandle {
140 let handle = OpenHandle(self.events.len() as u32);
141 self.push_event(EventKind::Open {
142 kind: TreeKind::Error,
143 next: CHAIN_END,
144 });
145 handle
146 }
147
148 pub fn close(&mut self, handle: OpenHandle, new_kind: TreeKind) -> CloseHandle {
149 let EventKind::Open { kind, .. }: &mut EventKind = &mut self.events[handle.0 as usize].kind
150 else {
151 panic!("close called on Close event")
152 };
153
154 *kind = new_kind;
155
156 self.push_event(EventKind::Close);
157 CloseHandle(handle.0)
158 }
159
160 pub fn open_before(&mut self, handle: CloseHandle) -> OpenHandle {
161 let new_evt_idx = self.events.len();
162 let prev_evt_idx = handle.0 as usize;
163
164 let Event { token, kind } = self.events[prev_evt_idx];
165
166 self.events.push(Event {
167 token: EVENT_IGNORE,
168 kind,
169 });
170
171 self.events[prev_evt_idx] = Event {
172 token,
173 kind: EventKind::Open {
174 kind: TreeKind::Error,
175 next: new_evt_idx as u32,
176 },
177 };
178
179 OpenHandle(handle.0)
180 }
181
182 pub fn wrap(&mut self, handle: CloseHandle, kind: TreeKind) -> CloseHandle {
183 let h = self.open_before(handle);
184 self.close(h, kind)
185 }
186
187 fn peek_raw(&self) -> Option<&Token> {
188 self.tokens.get(self.token_idx as usize)
189 }
190
191 pub fn peek_kind<'inp: 'out, 'out>(&'inp mut self) -> Option<&'out TokenKind> {
192 self.burn();
193
194 while let Some(tok) = self.peek_raw() {
195 if tok.kind.significant() {
196 break;
197 }
198 self.advance();
199 }
200
201 self.peek_raw().map(|t| &t.kind)
202 }
203
204 pub fn peek(&mut self) -> Tt {
205 self.peek_kind()
206 .map_or(Tt::Eof, |t| Tt::from_kind(t).expect("Token is significant"))
207 }
208
209 pub fn nth_raw(&mut self, ofs: usize) -> Option<Tt> {
212 self.tokens
213 .get(self.token_idx as usize + ofs)
214 .map_or(Some(Tt::Eof), |t| Tt::from_kind(&t.kind))
215 }
216
217 pub fn nth(&mut self, mut ofs: usize) -> Tt {
218 let mut raw_ofs = 0;
219
220 loop {
221 match self.nth_raw(raw_ofs) {
222 Some(tt) if ofs == 0 => return tt,
223 Some(_) => ofs -= 1,
224 None => (),
225 }
226 raw_ofs += 1;
227 }
228 }
229
230 pub fn nth_is(&mut self, ofs: usize, ty: impl Into<Tt>) -> bool {
231 self.nth(ofs) == ty.into()
232 }
233
234 pub fn advance(&mut self) {
235 assert!(!self.eof());
236 self.fuel.set(MAX_PARSER_LOOKUPS);
237 self.token_idx += 1;
238 }
239
240 pub fn eof(&self) -> bool {
241 self.token_idx == self.tokens.len() as u32
242 }
243
244 pub fn at(&mut self, ty: impl Into<Tt>) -> bool {
245 self.peek() == ty.into()
246 }
247
248 pub fn at_set(&mut self, tys: &TtSet) -> bool {
249 tys.contains(self.peek())
250 }
251
252 pub fn at_id(&mut self, str: &str) -> bool {
253 matches!(self.peek_kind(), Some(TokenKind::Ident(id)) if id == str)
254 }
255
256 pub fn eof_or(&mut self, ty: impl Into<Tt>) -> bool {
257 self.at(ty) || self.eof()
258 }
259
260 pub fn eat(&mut self, ty: impl Into<Tt>) -> bool {
261 if self.at(ty) {
262 self.advance();
263 true
264 } else {
265 false
266 }
267 }
268
269 pub fn advance_error(&mut self, message: impl Into<String>) -> CloseHandle {
270 let h = self.open();
271 self.error(message);
272 if !self.eof() {
273 self.advance();
274 }
275 self.close(h, TreeKind::Error)
276 }
277
278 pub fn error_empty(&mut self, message: impl Into<String>) -> CloseHandle {
279 let h = self.open();
280 self.error(message);
281 self.close(h, TreeKind::Error)
282 }
283
284 fn pos(&self) -> Span {
285 self.tokens
286 .get(self.token_idx as usize)
287 .map_or(Span::empty_at(self.ctx.origins.root().end_pos()), |t| {
288 t.span.empty_at_start()
289 })
290 }
291
292 pub fn error(&mut self, message: impl Into<String>) {
293 self.ctx
294 .diagnostics
295 .push(self.pos(), Severity::Error, "blues-lsp", message.into());
296 }
297
298 pub fn expect(&mut self, ty: impl Into<Tt>) {
299 let ty = ty.into();
300 if self.eat(ty) {
301 return;
302 }
303
304 self.error(format!("Expected {}", ty));
305 }
306
307 pub fn assert(&mut self, ty: impl Into<Tt>) {
308 let ty = ty.into();
309 assert_eq!(self.peek(), ty);
310 self.advance();
311 }
312
313 pub fn kind_of(&self, handle: CloseHandle) -> TreeKind {
314 match self.events[handle.0 as usize].kind {
315 EventKind::Open { kind, .. } => kind,
316 EventKind::Close => unreachable!(),
317 }
318 }
319}