use crate::error::LexError;
use crate::lexer::{PartiqlLexer, Spanned, Token};
use partiql_source_map::location::ByteOffset;
use std::collections::VecDeque;
pub(crate) type BufferedToken<'input> = (Spanned<Token<'input>, ByteOffset>, &'input str);
pub(crate) struct TokenParser<'input, 'tracker> {
lexer: PartiqlLexer<'input, 'tracker>,
buffered: VecDeque<BufferedToken<'input>>,
consumed_c: usize,
}
const TOKEN_BUFFER_INIT_CAPACITY: usize = 20;
impl<'input, 'tracker> TokenParser<'input, 'tracker> {
pub fn new(lexer: PartiqlLexer<'input, 'tracker>) -> Self {
Self {
lexer,
buffered: VecDeque::with_capacity(TOKEN_BUFFER_INIT_CAPACITY),
consumed_c: 0,
}
}
#[inline]
pub fn consume(&mut self) -> Option<Result<(), Spanned<LexError<'input>, ByteOffset>>> {
match self.buffer(1) {
Some(Ok(_)) => {
self.consumed_c += 1;
Some(Ok(()))
}
other => other,
}
}
#[inline]
pub fn unconsume(&mut self) {
self.consumed_c = self.consumed_c.saturating_sub(1);
}
#[inline]
pub fn flush_1(&mut self) -> Option<BufferedToken<'input>> {
self.consumed_c = self.consumed_c.saturating_sub(1);
self.buffered.pop_front()
}
#[inline]
pub fn unflush_1(&mut self, tok: Option<BufferedToken<'input>>) {
if let Some(t) = tok {
self.buffered.push_front(t);
self.consumed_c += 1;
}
}
#[inline]
pub fn flush(&mut self) -> Vec<BufferedToken<'input>> {
let len = std::mem::replace(&mut self.consumed_c, 0);
self.buffered.drain(0..len).collect()
}
#[inline]
pub fn unflush(&mut self, toks: Vec<BufferedToken<'input>>) {
self.consumed_c += toks.len();
for tok in toks.into_iter().rev() {
self.buffered.push_front(tok);
}
}
#[inline]
pub fn expect(&mut self, target: &Token) -> Result<(), Spanned<LexError<'input>, ByteOffset>> {
match self.peek_n(0) {
Some(((_, tok, _), _)) if target == tok => {
self.consumed_c += 1;
Ok(())
}
_ => Err((0.into(), LexError::Unknown, 0.into())),
}
}
#[inline]
pub fn peek_n(&mut self, i: usize) -> Option<&BufferedToken<'input>> {
self.buffer(i + 1);
self.get(i)
}
#[inline]
fn get(&mut self, i: usize) -> Option<&BufferedToken<'input>> {
self.buffered.get(self.consumed_c + i)
}
#[inline]
fn buffer(&mut self, upto: usize) -> Option<Result<(), Spanned<LexError<'input>, ByteOffset>>> {
while upto > self.buffered.len() - self.consumed_c {
if let Some(tok) = self.lexer.next_internal() {
match tok {
Ok(tok) => self.buffered.push_back((tok, self.lexer.slice())),
Err(e) => return Some(Err(e)),
}
} else {
return None;
}
}
Some(Ok(()))
}
}