Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/parser/src/output.rs')
| -rw-r--r-- | crates/parser/src/output.rs | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/crates/parser/src/output.rs b/crates/parser/src/output.rs new file mode 100644 index 0000000000..b613df029f --- /dev/null +++ b/crates/parser/src/output.rs @@ -0,0 +1,76 @@ +//! See [`Output`] + +use crate::SyntaxKind; + +/// Output of the parser -- a DFS traversal of a concrete syntax tree. +/// +/// Use the [`Output::iter`] method to iterate over traversal steps and consume +/// a syntax tree. +/// +/// In a sense, this is just a sequence of [`SyntaxKind`]-colored parenthesis +/// interspersed into the original [`crate::Input`]. The output is fundamentally +/// coordinated with the input and `n_input_tokens` refers to the number of +/// times [`crate::Input::push`] was called. +#[derive(Default)] +pub struct Output { + /// 32-bit encoding of events. If LSB is zero, then that's an index into the + /// error vector. Otherwise, it's one of the thee other variants, with data encoded as + /// + /// |16 bit kind|8 bit n_input_tokens|4 bit tag|4 bit leftover| + /// + event: Vec<u32>, + error: Vec<String>, +} + +pub enum Step<'a> { + Token { kind: SyntaxKind, n_input_tokens: u8 }, + Enter { kind: SyntaxKind }, + Exit, + Error { msg: &'a str }, +} + +impl Output { + pub fn iter(&self) -> impl Iterator<Item = Step<'_>> { + self.event.iter().map(|&event| { + if event & 0b1 == 0 { + return Step::Error { msg: self.error[(event as usize) >> 1].as_str() }; + } + let tag = ((event & 0x0000_00F0) >> 4) as u8; + match tag { + 0 => { + let kind: SyntaxKind = (((event & 0xFFFF_0000) >> 16) as u16).into(); + let n_input_tokens = ((event & 0x0000_FF00) >> 8) as u8; + Step::Token { kind, n_input_tokens } + } + 1 => { + let kind: SyntaxKind = (((event & 0xFFFF_0000) >> 16) as u16).into(); + Step::Enter { kind } + } + 2 => Step::Exit, + _ => unreachable!(), + } + }) + } + + pub(crate) fn token(&mut self, kind: SyntaxKind, n_tokens: u8) { + let e = ((kind as u16 as u32) << 16) | ((n_tokens as u32) << 8) | (0 << 4) | 1; + self.event.push(e) + } + + pub(crate) fn enter_node(&mut self, kind: SyntaxKind) { + let e = ((kind as u16 as u32) << 16) | (1 << 4) | 1; + self.event.push(e) + } + + pub(crate) fn leave_node(&mut self) { + let e = 2 << 4 | 1; + self.event.push(e) + } + + pub(crate) fn error(&mut self, error: String) { + let idx = self.error.len(); + self.error.push(error); + let e = (idx as u32) << 1; + self.event.push(e); + } +} |