Filter input chars

This commit is contained in:
Alex Kotov 2023-04-02 15:02:15 +04:00
parent 16ad2c2d3a
commit 4f2d50e9b8
Signed by: kotovalexarian
GPG Key ID: 553C0EBBEB5D5F08
3 changed files with 50 additions and 15 deletions

View File

@ -1,10 +1,16 @@
use crate::models::{Char, Pos}; use crate::models::{Char, Pos};
pub use std::io::{Error, Result};
use std::io::BufRead; use std::io::BufRead;
use std::vec::IntoIter; use std::vec::IntoIter;
pub type Result = std::result::Result<Char, Error>;
#[derive(Debug)]
pub enum Error {
IO(std::io::Error),
InvalidChar(char),
}
pub struct Input<'a> { pub struct Input<'a> {
read: &'a mut dyn BufRead, read: &'a mut dyn BufRead,
fin: bool, fin: bool,
@ -12,6 +18,18 @@ pub struct Input<'a> {
pos: Pos, pos: Pos,
} }
impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Self {
Self::IO(err)
}
}
impl From<char> for Error {
fn from(chr: char) -> Self {
Self::InvalidChar(chr)
}
}
impl<'a> Input<'a> { impl<'a> Input<'a> {
pub fn new(read: &'a mut dyn BufRead) -> Self { pub fn new(read: &'a mut dyn BufRead) -> Self {
Self { Self {
@ -27,7 +45,7 @@ impl<'a> Input<'a> {
} }
impl Iterator for Input<'_> { impl Iterator for Input<'_> {
type Item = Result<Char>; type Item = Result;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.fin { if self.fin {
@ -35,10 +53,13 @@ impl Iterator for Input<'_> {
} }
if let Some(chr) = self.iter.next() { if let Some(chr) = self.iter.next() {
let result = Some(Ok(Char::new(chr, self.pos))); let chr = Char::new(chr, self.pos);
self.pos.index += 1; self.pos.index += 1;
self.pos.col += 1; self.pos.col += 1;
return result; return match chr {
Err(chr) => Some(Err(chr.into())),
Ok(chr) => Some(Ok(chr)),
};
} }
let mut buffer = String::new(); let mut buffer = String::new();
@ -53,7 +74,7 @@ impl Iterator for Input<'_> {
} }
Err(err) => { Err(err) => {
self.fin = true; self.fin = true;
Some(Err(err)) Some(Err(err.into()))
} }
} }
} }
@ -64,7 +85,7 @@ mod tests {
use super::*; use super::*;
fn chr(value: char, index: usize, line: usize, col: usize) -> Char { fn chr(value: char, index: usize, line: usize, col: usize) -> Char {
Char::new(value, Pos::new(index, line, col)) Char::new(value, Pos::new(index, line, col)).unwrap()
} }
#[test] #[test]

View File

@ -1,12 +1,12 @@
use crate::input::{self, Input}; use crate::input::{self, Input};
use crate::models::{Char, Pos, Token}; use crate::models::{Pos, Token};
use crate::tokenizer::Tokenizer; use crate::tokenizer::Tokenizer;
pub type Result = std::result::Result<Token, Error>; pub type Result = std::result::Result<Token, Error>;
pub struct Lexer<'a> { pub struct Lexer<'a> {
input: Input<'a>, input: Input<'a>,
cur: Option<input::Result<Char>>, cur: Option<input::Result>,
pos: Pos, pos: Pos,
tokenizer: Tokenizer, tokenizer: Tokenizer,
} }
@ -47,14 +47,14 @@ impl Iterator for Lexer<'_> {
Ok(chr) => { Ok(chr) => {
let chr = *chr; let chr = *chr;
self.cur = self.input.next(); self.cur = self.input.next();
match self.tokenizer.iter(Some(chr.value)) { match self.tokenizer.iter(Some(chr.value())) {
None => self.next(), None => self.next(),
Some(value) => { Some(value) => {
let token = Token { let token = Token {
value, value,
pos: self.pos, pos: self.pos,
}; };
self.pos = chr.pos; self.pos = chr.pos();
Some(Ok(token)) Some(Ok(token))
} }
} }

View File

@ -1,7 +1,9 @@
const MIN_CHAR: char = ' '; // ASCII code: 32
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Char { pub struct Char {
pub value: char, value: char,
pub pos: Pos, pos: Pos,
} }
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
@ -18,8 +20,20 @@ pub struct Token {
} }
impl Char { impl Char {
pub fn new(value: char, pos: Pos) -> Self { pub fn new(value: char, pos: Pos) -> Result<Self, char> {
Self { value, pos } if value >= MIN_CHAR || value == ' ' || value == '\n' {
Ok(Self { value, pos })
} else {
Err(value)
}
}
pub fn value(&self) -> char {
self.value
}
pub fn pos(&self) -> Pos {
self.pos
} }
} }