use std::collections::VecDeque;
use crate::runtime::error::ErrorKind;
use super::lexer::TokenIter;
use super::{token::Token, lexer::Lexer};
use super::error::Error;
pub struct TokenStream<'a> {
pub iter: TokenIter<'a>,
pub next_token: Option<Token>,
pub consumed_tokens: VecDeque<Token>,
pub cached_tokens: VecDeque<Token>,
pub channel: usize,
}
impl<'a> TokenStream<'a> {
pub fn consume(&mut self) -> Result<Token, Error> {
match self.next() {
Some(token) => Ok(token),
None => Err(Error::create_error_without_location(ErrorKind::TokenStreamOutOfRange, "msg")),
}
}
pub fn release(&mut self) -> Result<Token, Error> {
if self.consumed_tokens.len() <= 0 { return Err(Error::create_error_without_location(ErrorKind::ConsumedTokenExhausted, "consumed token exhausted.")) }
if let Some(next_token) = &self.next_token {
self.cached_tokens.push_front(next_token.clone())
}
self.next_token = self.consumed_tokens.pop_back();
Ok(self.next_token.clone().unwrap())
}
pub fn look_ahead(&mut self, n: usize) -> Result<Token, Error> {
if n <= 0 {
return Err(Error::create_error_without_location(ErrorKind::Unknown, "look_ahead should gt 0"));
}
else if n == 1 {
return self.peek_next_token();
}
else {
let n = n - 2;
if n >= self.cached_tokens.len() {
for _ in 0..(n - self.cached_tokens.len() + 2) {
let next_token = loop {
let next_token = self.iter.lexer_match()?;
if next_token.channel == self.channel {
break next_token;
}
};
self.cached_tokens.push_back(next_token);
}
}
return Ok(self.cached_tokens[n].clone());
}
}
pub fn look_back(&mut self, n:usize) -> Result<Token, Error> {
if n <= 0 {
return Err(Error::create_error_without_location(ErrorKind::Unknown, "look back should gt 0"));
}
else if n > self.consumed_tokens.len() {
return Err(Error::create_error_without_location(ErrorKind::ConsumedTokenExhausted, "consumed token exhausted."))
}
Ok(self.consumed_tokens[self.consumed_tokens.len() - n].clone())
}
pub fn peek_next_token(&self) -> Result<Token, Error> {
match &self.next_token {
Some(next_token) => Ok(next_token.clone()),
None => Err(Error::create_error_without_location(ErrorKind::TokenStreamOutOfRange, "msg")),
}
}
pub fn peek_previous_token(&self) -> Result<Token, Error> {
match self.consumed_tokens.back() {
Some(token) => Ok(token.clone()),
None => Err(Error::create_error_without_location(ErrorKind::ConsumedTokenExhausted, "msg")),
}
}
pub fn new(lexer: &'a dyn Lexer, channel: usize) -> Self {
Self {
iter: lexer.iter(),
channel,
consumed_tokens: VecDeque::new(),
cached_tokens: VecDeque::new(),
next_token: Some(Token::start(channel)),
}
}
pub fn reset(&mut self) {
self.consumed_tokens.clear();
self.cached_tokens.clear();
self.iter.reset();
self.next_token = Some(Token::start(self.channel));
}
}
impl Iterator for TokenStream<'_> {
fn next(&mut self) -> Option<Self::Item> {
let current_token = self.next_token.clone();
if let Some(current_token) = current_token {
if self.cached_tokens.len() > 0 {
self.next_token = self.cached_tokens.pop_front();
}
else if current_token.token_type == 1 {
self.next_token = None
}
else {
let next_token = loop {
let next_token = match self.iter.lexer_match() {
Ok(next_token) => next_token,
Err(err) => {
match err.kind {
ErrorKind::LexerScanOverflow => {
Token::new(1, "_STOP", "_STOP",
self.iter.get_current_position(),
self.iter.get_current_position(),
self.iter.token_index,
self.channel,
self.iter.cursor,
self.iter.cursor)
},
_ => { return None; }
}
},
};
if next_token.channel == self.channel {
break next_token;
}
};
self.next_token = Some(next_token);
}
self.consumed_tokens.push_back(current_token.clone());
if self.consumed_tokens.len() > 1024 { self.consumed_tokens.pop_front(); }
Some(current_token)
}
else {
None
}
}
type Item = Token;
}