use crate::errors::DiagResult;
use std::cmp::max;
use std::collections::VecDeque;
use std::io::Read;
pub trait Reader {
fn peek(&mut self, offset: usize) -> Option<char>;
fn consume(&mut self, amount: usize);
fn clear(&mut self);
fn to_string(&self) -> String;
}
pub trait Lexer<T> {
fn next_token<'td>(&mut self) -> DiagResult<'td, T>;
}
pub struct AccumulatingReader {
rd: Box<dyn Read>,
buf: Vec<u8>,
base: usize,
pos: usize,
tail: usize,
}
impl AccumulatingReader {
pub fn new(rd: Box<dyn Read>) -> AccumulatingReader {
AccumulatingReader {
rd: rd,
buf: Vec::new(),
base: 0,
pos: 0,
tail: 0,
}
}
pub fn refill(&mut self, mut min_len: usize) {
if self.base > 0 {
for i in 0..(self.tail - self.base) {
self.buf[i] = self.buf[self.base + i]
}
self.pos -= self.base;
self.tail -= self.base;
min_len -= self.base;
self.base = 0;
}
assert!(self.base == 0);
let cur_len = self.buf.len();
if min_len > cur_len {
let new_len = max(cur_len * 2, 32);
self.buf.resize(new_len, 0);
}
assert!(self.buf.len() >= min_len);
while min_len > self.tail {
let nread = {
let dst = &mut self.buf[self.tail..];
let nread = self.rd.read(dst).unwrap();
nread
};
if nread == 0 {
break;
}
self.tail += nread;
}
}
pub fn slice(&self) -> &[u8] {
&self.buf[self.base..self.pos]
}
pub fn rem_slice(&self) -> &[u8] {
&self.buf[self.base..]
}
}
impl Reader for AccumulatingReader {
fn peek(&mut self, off: usize) -> Option<char> {
let idx = self.pos + off;
if idx >= self.tail {
self.refill(idx + 1)
}
let idx = self.pos + off;
if idx < self.tail {
Some(self.buf[idx] as char)
} else {
None
}
}
fn consume(&mut self, amt: usize) {
self.pos += amt
}
fn clear(&mut self) {
self.base = self.pos
}
fn to_string(&self) -> String {
String::from_utf8(self.slice().to_vec()).unwrap()
}
}
pub struct StringReader<'tdata> {
iter: Box<dyn Iterator<Item = char> + 'tdata>,
buf: Vec<char>,
base: usize,
pos: usize,
tail: usize,
}
impl<'tdata> StringReader<'tdata> {
pub fn new(data: &'tdata str) -> StringReader<'tdata> {
StringReader {
iter: Box::new(data.chars()),
buf: Vec::new(),
base: 0,
pos: 0,
tail: 0,
}
}
fn refill(&mut self, mut min_len: usize) {
if self.base > 0 {
for i in 0..(self.tail - self.base) {
self.buf[i] = self.buf[self.base + i]
}
self.pos -= self.base;
self.tail -= self.base;
min_len -= self.base;
self.base = 0;
}
assert!(self.base == 0);
let cur_len = self.buf.len();
if min_len > cur_len {
let new_len = max(cur_len * 2, 32);
self.buf.resize(new_len, 0 as char);
}
assert!(self.buf.len() >= min_len);
while min_len > self.tail {
match self.iter.next() {
Some(c) => {
self.buf[self.tail] = c;
self.tail += 1;
}
None => break,
}
}
}
}
impl<'tdata> Reader for StringReader<'tdata> {
fn peek(&mut self, offset: usize) -> Option<char> {
let idx = self.pos + offset;
if idx >= self.tail {
self.refill(idx + 1)
}
let idx = self.pos + offset;
if idx < self.tail {
Some(self.buf[idx])
} else {
None
}
}
fn consume(&mut self, amount: usize) {
self.pos += amount;
}
fn clear(&mut self) {
self.base = self.pos;
}
fn to_string(&self) -> String {
let mut s = String::new();
for c in self.buf[self.base..self.pos].iter() {
s.push(*c);
}
s
}
}
pub struct StackedLexer<T> {
stack: Vec<Box<dyn Lexer<T>>>,
eof: T,
}
impl<T> StackedLexer<T> {
pub fn new(eof: T) -> StackedLexer<T> {
StackedLexer {
stack: Vec::new(),
eof: eof,
}
}
pub fn push(&mut self, lexer: Box<dyn Lexer<T>>) {
self.stack.push(lexer);
}
}
impl<T: Clone + PartialEq> Lexer<T> for StackedLexer<T> {
fn next_token<'td>(&mut self) -> DiagResult<'td, T> {
loop {
let token = if let Some(lexer) = self.stack.last_mut() {
lexer.next_token()?
} else {
return Ok(self.eof.clone());
};
if token == self.eof {
self.stack.pop();
continue;
} else {
return Ok(token);
}
}
}
}
pub struct BufferedLexer<T> {
inner: Box<dyn Lexer<T>>,
eof: T,
buffer: VecDeque<T>,
done: bool,
}
impl<T: Clone + PartialEq> BufferedLexer<T> {
pub fn new(inner: Box<dyn Lexer<T>>, eof: T) -> BufferedLexer<T> {
BufferedLexer {
inner: inner,
eof: eof,
buffer: VecDeque::new(),
done: false,
}
}
pub fn peek<'td>(&mut self, offset: usize) -> DiagResult<'td, &T> {
while !self.done && self.buffer.len() <= offset {
let token = self.inner.next_token()?;
if token == self.eof {
self.done = true;
}
self.buffer.push_back(token);
}
Ok(self.buffer.get(offset).unwrap_or(&self.eof))
}
#[allow(unused_variables)]
pub fn push(&mut self, token: T) {
unimplemented!();
}
pub fn pop<'td>(&mut self) -> DiagResult<'td, T> {
if self.buffer.is_empty() && !self.done {
self.inner.next_token()
} else {
Ok(self
.buffer
.pop_front()
.expect("pop() called on drained BufferedLexer"))
}
}
pub fn inner(&self) -> &dyn Lexer<T> {
&*self.inner
}
pub fn inner_mut(&mut self) -> &mut dyn Lexer<T> {
&mut *self.inner
}
}