use logos::*;
use super::lexer::RantToken;
use std::ops::Range;
use crate::InternalString;
pub struct RantTokenReader<'source> {
lexer: Lexer<'source, RantToken>,
peeked: Option<(RantToken, Range<usize>)>,
}
impl<'source> RantTokenReader<'source> {
pub fn new(src: &'source str) -> Self {
Self {
lexer: RantToken::lexer(src),
peeked: None,
}
}
pub fn next(&mut self) -> Option<(RantToken, Range<usize>)> {
self.peeked.take().or_else(|| self.lexer.next().map(|token| (token, self.lexer.span())))
}
pub fn skip_one(&mut self) {
self.next();
}
pub fn eat_where<F: FnOnce(Option<&(RantToken, Range<usize>)>) -> bool>(&mut self, predicate: F) -> bool {
if predicate(self.peek()) {
self.skip_one();
return true
}
false
}
pub fn take_where<F: FnOnce(Option<&(RantToken, Range<usize>)>) -> bool>(&mut self, predicate: F) -> Option<(RantToken, Range<usize>)> {
if predicate(self.peek()) {
self.next()
} else {
None
}
}
pub fn last_token_string(&self) -> InternalString {
InternalString::from(self.lexer.slice())
}
pub fn next_solid(&mut self) -> Option<(RantToken, Range<usize>)> {
loop {
match self.next() {
Some((RantToken::Whitespace, _)) => continue,
Some((token, span)) => return Some((token, span)),
None => return None
}
}
}
pub fn skip_ws(&mut self) {
while let Some((RantToken::Whitespace, _)) = self.peek() {
self.next();
}
}
pub fn last_token_pos(&self) -> usize {
self.lexer.span().start
}
pub fn last_token_span(&self) -> Range<usize> {
self.lexer.span()
}
pub fn peek(&mut self) -> Option<&(RantToken, Range<usize>)> {
if self.peeked.is_some() {
return self.peeked.as_ref();
}
let token = self.next();
self.peeked = token;
self.peeked.as_ref()
}
}