Skip to main content

sim_codec_algol/parse/
state.rs

1//! Parse cursor state for the Algol codec: `ParseCx` holds the spanned token
2//! stream and offers peek/advance/lookahead operations over it.
3
4use sim_kernel::{Error, Result};
5
6use super::tokenize::SpannedToken;
7
8/// Cursor over a spanned Algol token stream, driving the Pratt parser with
9/// peek, advance, and lookahead operations.
10pub struct ParseCx {
11    tokens: Vec<SpannedToken>,
12    index: usize,
13}
14
15impl ParseCx {
16    /// Creates a cursor positioned at the first of `tokens`.
17    pub fn new(tokens: Vec<SpannedToken>) -> Self {
18        Self { tokens, index: 0 }
19    }
20
21    /// Returns the current token without consuming it, or `None` at end of
22    /// input.
23    pub fn peek(&self) -> Option<&SpannedToken> {
24        self.tokens.get(self.index)
25    }
26
27    /// Consumes and returns the current token, or `None` at end of input.
28    pub fn advance(&mut self) -> Option<SpannedToken> {
29        let token = self.tokens.get(self.index).cloned()?;
30        self.index += 1;
31        Some(token)
32    }
33
34    /// Consumes the current token, erroring if the stream is exhausted.
35    pub fn next_required(&mut self) -> Result<SpannedToken> {
36        self.advance()
37            .ok_or_else(|| Error::Eval("unexpected end of algol input".to_owned()))
38    }
39
40    /// Returns `true` once every token has been consumed.
41    pub fn is_empty(&self) -> bool {
42        self.index >= self.tokens.len()
43    }
44}