use crate::lexer::{Token, TokenKind};
pub struct Stream<'a> {
tokens: &'a [Token],
pos: usize,
furthest: usize,
}
impl<'a> Stream<'a> {
pub fn new(tokens: &'a [Token]) -> Self {
Stream {
tokens,
pos: 0,
furthest: 0,
}
}
pub fn pos(&self) -> usize {
self.pos
}
pub fn furthest(&self) -> usize {
self.furthest
}
pub fn set(&mut self, pos: usize) {
self.pos = pos;
}
fn advance_to(&mut self, pos: usize) {
self.pos = pos;
if pos > self.furthest {
self.furthest = pos;
}
}
pub fn at_end(&self) -> bool {
self.pos >= self.tokens.len()
}
pub fn peek(&self) -> Option<&Token> {
self.tokens.get(self.pos)
}
pub fn at(&self, pos: usize) -> Option<&Token> {
self.tokens.get(pos)
}
pub fn bump(&mut self) -> Option<&Token> {
if self.pos < self.tokens.len() {
self.advance_to(self.pos + 1);
self.tokens.get(self.pos - 1)
} else {
None
}
}
pub fn eat(&mut self, kind: &TokenKind) -> Option<String> {
match self.tokens.get(self.pos) {
Some(t) if &t.kind == kind => {
let v = t.value.clone();
self.advance_to(self.pos + 1);
Some(v)
}
_ => None,
}
}
pub fn eat_keyword(&mut self, name: &str) -> Option<String> {
match self.tokens.get(self.pos) {
Some(Token {
kind: TokenKind::Keyword(k),
value,
}) if k == name => {
let v = value.clone();
self.advance_to(self.pos + 1);
Some(v)
}
_ => None,
}
}
pub fn ws0(&mut self) {
while let Some(Token {
kind: TokenKind::Ws,
..
}) = self.tokens.get(self.pos)
{
self.advance_to(self.pos + 1);
}
}
pub fn ws1(&mut self) -> bool {
let start = self.pos;
self.ws0();
self.pos > start
}
}