Skip to main content

blues_lsp/syntax/parser/
state.rs

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            // Emit all tokens leading up to event
70            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    /// Get token kind `ofs` tokens from cursor
210    /// This does *not* skip non-significant tokens!
211    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}