use crate::primitive::is_trivia;
use super::{position::PositionTokenIter, PositionedToken};
use itertools::{peek_nth, PeekNth};
use skullbrain_lexer::{PunctuationKind, TokenKind};
pub(super) struct Sequence<'input> {
raw_iter: PeekNth<PositionTokenIter<'input>>,
delimiter_stack: Vec<TokenKind>,
}
pub(crate) struct PeekSequence<'a, 'input> {
iter: &'a mut Sequence<'input>,
peek_index: usize,
}
impl Iterator for Sequence<'_> {
type Item = PositionedToken;
fn next(&mut self) -> Option<Self::Item> {
if self.is_blocked_by_outer_delimiter() {
None
} else {
self.next_raw()
}
}
}
impl<'input> Sequence<'input> {
pub(super) fn new(input: &'input str) -> Self {
Self {
raw_iter: peek_nth(PositionTokenIter::new(input)),
delimiter_stack: vec![TokenKind::Punctuation(PunctuationKind::Dot)],
}
}
pub(super) fn next_raw(&mut self) -> Option<<Self as Iterator>::Item> {
self.raw_iter.next()
}
pub(super) fn peek_raw(&mut self) -> Option<&<Self as Iterator>::Item> {
self.raw_iter.peek()
}
pub(super) fn peek(&mut self) -> Option<&<Self as Iterator>::Item> {
if self.is_blocked_by_outer_delimiter() {
None
} else {
self.peek_raw()
}
}
}
impl Sequence<'_> {
pub(super) fn push_delimited(&mut self, closing: TokenKind) {
self.delimiter_stack.push(closing);
}
fn is_blocked_by_outer_delimiter(&mut self) -> bool {
let Some(token) = self.raw_iter.peek() else {
return false;
};
let Some(active_closer) = self.delimiter_stack.last() else {
return false;
};
token.kind().is(active_closer)
}
pub(super) fn resume_normal_tokenstream(&mut self) {
self.delimiter_stack
.pop()
.expect("Failed to resume normal tokenstream since stack was empty");
}
}
impl<'a, 'input> PeekSequence<'a, 'input> {
pub(super) const fn new(iter: &'a mut Sequence<'input>) -> Self {
Self {
iter,
peek_index: 0,
}
}
pub(crate) fn peek_next(&mut self) -> Option<&PositionedToken> {
loop {
if self.iter.is_blocked_by_outer_delimiter() {
break None;
} else if let Some(item) = self.iter.raw_iter.peek_nth(self.peek_index) {
if !is_trivia(item.kind()) {
self.peek_index += 1;
return self.iter.raw_iter.peek_nth(self.peek_index - 1);
}
self.peek_index += 1;
} else {
break None;
}
}
}
pub(crate) fn peek_next_is(&mut self, kind: &TokenKind) -> bool {
self.peek_next().is_some_and(|i| i.kind().is(kind))
}
#[deprecated]
pub(crate) fn revert_by_one(&mut self) {
self.peek_index = self.peek_index.saturating_sub(1)
}
}