69 lines
1.4 KiB
Rust
69 lines
1.4 KiB
Rust
const MIN_CHAR: char = ' '; // ASCII code: 32
|
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
pub struct Char {
|
|
value: char,
|
|
pos: Pos,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
pub struct Pos {
|
|
pub index: usize,
|
|
pub line: usize,
|
|
pub col: usize,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
|
pub struct Token {
|
|
pub pos: Pos,
|
|
pub value: String,
|
|
}
|
|
|
|
impl Char {
|
|
pub fn new(value: char, pos: Pos) -> Result<Self, char> {
|
|
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
|
|
}
|
|
}
|
|
|
|
impl Pos {
|
|
pub fn new(index: usize, line: usize, col: usize) -> Self {
|
|
Self { index, line, col }
|
|
}
|
|
}
|
|
|
|
impl Default for Pos {
|
|
fn default() -> Self {
|
|
Self::new(0, 1, 1)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn valid_invalid_chars() {
|
|
let pos = Pos::default();
|
|
|
|
assert_eq!(Char::new('\0', pos), Err('\0'));
|
|
assert_eq!(Char::new('\t', pos), Err('\t'));
|
|
assert_eq!(Char::new('\r', pos), Err('\r'));
|
|
|
|
assert_eq!(Char::new(' ', pos), Ok(Char { value: ' ', pos }));
|
|
assert_eq!(Char::new('\n', pos), Ok(Char { value: '\n', pos }));
|
|
assert_eq!(Char::new('a', pos), Ok(Char { value: 'a', pos }));
|
|
}
|
|
}
|