2023-07-27 20:17:44 +02:00
|
|
|
use crate::{
|
|
|
|
lexer::{FullToken, Token},
|
2023-07-27 22:01:50 +02:00
|
|
|
parser::Parse,
|
2023-07-27 20:17:44 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
pub struct TokenStream<'a, 'b> {
|
|
|
|
ref_position: Option<&'b mut usize>,
|
|
|
|
tokens: &'a [FullToken],
|
|
|
|
pub position: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'b> TokenStream<'a, 'b> {
|
|
|
|
pub fn from(tokens: &'a [FullToken]) -> Self {
|
|
|
|
TokenStream {
|
|
|
|
ref_position: None,
|
|
|
|
tokens,
|
|
|
|
position: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn expect(&mut self, token: Token) -> Result<(), ()> {
|
|
|
|
if let Some(peeked) = self.peek() {
|
2023-07-27 21:25:13 +02:00
|
|
|
if token == peeked {
|
2023-07-27 20:17:44 +02:00
|
|
|
self.position += 1;
|
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err(())
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Err(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn next(&mut self) -> Option<Token> {
|
|
|
|
let value = if self.tokens.len() < self.position {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(self.tokens[self.position].token.clone())
|
|
|
|
};
|
|
|
|
self.position += 1;
|
|
|
|
value
|
|
|
|
}
|
|
|
|
|
2023-07-27 21:25:13 +02:00
|
|
|
pub fn peek(&mut self) -> Option<Token> {
|
2023-07-27 20:17:44 +02:00
|
|
|
if self.tokens.len() < self.position {
|
|
|
|
None
|
|
|
|
} else {
|
2023-07-27 21:25:13 +02:00
|
|
|
Some(self.tokens[self.position].token.clone())
|
2023-07-27 20:17:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-27 22:01:50 +02:00
|
|
|
pub fn parse<T: Parse>(&mut self) -> Result<T, ()> {
|
2023-07-27 20:17:44 +02:00
|
|
|
let mut ref_pos = self.position;
|
|
|
|
|
|
|
|
let position = self.position;
|
|
|
|
let clone = TokenStream {
|
|
|
|
ref_position: Some(&mut ref_pos),
|
|
|
|
tokens: self.tokens,
|
|
|
|
position,
|
|
|
|
};
|
|
|
|
|
|
|
|
match T::parse(clone) {
|
|
|
|
Ok(res) => {
|
|
|
|
self.position = ref_pos.max(self.position);
|
|
|
|
Ok(res)
|
|
|
|
}
|
|
|
|
Err(e) => Err(e),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for TokenStream<'_, '_> {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
if let Some(ref_pos) = &mut self.ref_position {
|
|
|
|
**ref_pos = self.position;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|