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}