Refactor/scanner/1 #26

Merged
bazaah merged 2 commits from refactor/scanner/1 into master 2021-09-07 17:32:27 +00:00
5 changed files with 3 additions and 241 deletions

4
Cargo.lock generated
View File

@ -11,9 +11,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.40"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
checksum = "28ae2b3dec75a406790005a200b1bd89785afc02517a00ca99ecfe093ee9e6cf"
[[package]]
name = "atoi"

View File

@ -7,9 +7,8 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1"
atoi = "0.4"
[dev-dependencies]
anyhow = "1"
pretty_assertions = "0.7"

View File

@ -1,2 +0,0 @@
pub type Error = anyhow::Error;
pub type Result<T> = std::result::Result<T, Error>;

View File

@ -3,6 +3,5 @@
mod error;
mod queue;
mod reader;
mod scanner;
mod token;

View File

@ -1,234 +0,0 @@
use std::collections::VecDeque;
use anyhow::bail;
use crate::error::Result;
#[derive(Debug)]
struct Reader<I>
{
src: I,
buffer: VecDeque<char>,
column: usize,
mark: usize,
reset_column: bool,
}
impl<I> Reader<I>
where
I: Iterator<Item = Result<char>>,
{
pub fn new(src: I) -> Self
{
Self {
src,
buffer: VecDeque::new(),
column: 0,
mark: 0,
reset_column: false,
}
}
/// Number of chars seen so far
pub fn mark(&self) -> usize
{
self.mark
}
/// How deep into a line we currently are
pub fn column(&self) -> usize
{
self.column
}
/// Reserve amt chars, returning an error if it could
/// not reserve the requested amount
pub fn reserve_exact(&mut self, amt: usize) -> Result<()>
{
let reserved = self.reserve(amt)?;
if reserved != amt
{
bail!("only reserved {}/{} chars @{}", reserved, amt, self.mark());
}
Ok(())
}
/// Attempt to reserve up to amt chars, returning the
/// actual number added
pub fn reserve(&mut self, amt: usize) -> Result<usize>
{
let mut done = 0;
while done < amt
{
match self.src.next()
{
Some(Ok(c)) => self.buffer.push_front(c),
Some(Err(e)) => return Err(e),
None => return Ok(done),
}
done += 1;
}
Ok(done)
}
fn next_char(&mut self) -> Result<Option<char>>
{
match self.read_one()?
{
Some(c) =>
{
// We hit a line end previously, reset column size
if self.reset_column
{
self.reset_column = false;
self.column = 0;
}
// We just hit a line end, arm column reset
if c == '\n'
{
self.reset_column = true;
}
self.column += 1;
self.mark += 1;
Ok(Some(c))
},
None => Ok(None),
}
}
fn read_one(&mut self) -> Result<Option<char>>
{
match self.buffer.is_empty()
{
true => self.src.next().transpose(),
false => Ok(self.buffer.pop_back()),
}
}
}
impl<I> Iterator for Reader<I>
where
I: Iterator<Item = Result<char>>,
{
type Item = Result<char>;
fn next(&mut self) -> Option<Self::Item>
{
self.next_char().transpose()
}
}
#[cfg(test)]
mod tests
{
use pretty_assertions::{assert_eq, assert_ne};
use super::*;
macro_rules! data {
($data:expr) => {
$data.chars().map(Ok)
};
() => {
"1234567890".chars().map(Ok)
};
}
#[test]
fn amount()
{
let data = data!();
let r = Reader::new(data);
assert_eq!(r.into_iter().count(), 10);
}
#[test]
fn reserve()
{
let data = data!();
let mut r = Reader::new(data);
let amount = r.reserve(20).expect("impossible to error");
assert_ne!(amount, 20);
assert_eq!(amount, 10);
}
#[test]
fn reserve_partial()
{
let data = data!();
let mut r = Reader::new(data);
let amount = r.reserve(5).expect("impossible to error");
assert_eq!(amount, 5);
}
#[test]
fn reserve_one()
{
let data = data!();
let mut r = Reader::new(data);
let amount = r.reserve(1).expect("impossible to error");
assert_eq!(amount, 1);
}
#[test]
fn reserve_zero()
{
let data = data!();
let mut r = Reader::new(data);
let amount = r.reserve(0).expect("impossible to error");
assert_eq!(amount, 0);
}
#[test]
fn column()
{
let data = data!("abc\nefg\nhijkl");
let expected = vec![1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 5];
let mut r = Reader::new(data);
assert_eq!(r.column(), 0);
for indent in expected
{
let c = r.next().unwrap().expect("impossible to error");
assert_eq!(r.column(), indent, "@ char: {}, mark: {}", c, r.mark());
}
}
#[test]
fn mark()
{
let data = data!();
let expected = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let mut r = Reader::new(data);
assert_eq!(r.mark(), 0);
for mark in expected
{
let c = r.next().unwrap().expect("impossible to error");
assert_eq!(r.mark(), mark, "@ char: {}, mark: {}", c, r.mark());
}
}
}