Skip to content

Commit

Permalink
feat: implement integers parser (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
sor4chi authored Jun 28, 2024
1 parent 7c5a35c commit 7858d0a
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod parser;
pub mod tokenizer;
26 changes: 26 additions & 0 deletions src/parser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use crate::tokenizer::Token;

const INTEGER_ASCII: &str = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";

fn parse_integer(indicator: Token) -> usize {
assert!(matches!(indicator, Token::Integer(_)));
let mut result = 0;
for c in indicator.to_string().chars() {
let index = INTEGER_ASCII.find(c).unwrap();
result = result * INTEGER_ASCII.len() + index;
}
result
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_parse_integer() {
assert_eq!(INTEGER_ASCII.len(), 94);
let input = Token::Integer("/6".to_string());
let expected = 1337;
assert_eq!(parse_integer(input), expected);
}
}
95 changes: 95 additions & 0 deletions src/tokenizer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use std::iter::Peekable;
use std::vec::IntoIter;

pub type PeekableIter<T> = Peekable<IntoIter<T>>;

#[derive(Debug, PartialEq)]
pub enum Token {
Integer(String),
Unknown(String),
}

impl Token {
pub fn to_string(&self) -> String {
match self {
Token::Integer(value) => value.to_string(),
Token::Unknown(value) => value.to_string(),
}
}
}

struct Tokenizer {
input: PeekableIter<char>,
}

impl Tokenizer {
pub fn new(input: &str) -> Tokenizer {
Tokenizer {
input: input.chars().collect::<Vec<char>>().into_iter().peekable(),
}
}

pub fn tokenize(&mut self) -> Vec<Token> {
let mut tokens = vec![];
while let Some(&c) = self.input.peek() {
match c {
'I' => tokens.push(self.tokenize_integer()),
' ' => {
self.input.next();
}
_ => tokens.push(self.tokenize_unknown()),
}
}
tokens
}

fn tokenize_integer(&mut self) -> Token {
let mut value = String::new();
while let Some(&c) = self.input.peek() {
match c {
'I' => {
self.input.next();
continue;
}
' ' => break,
_ => {
value.push(c);
self.input.next();
}
}
}
Token::Integer(value)
}

fn tokenize_unknown(&mut self) -> Token {
let mut value = String::new();
while let Some(&c) = self.input.peek() {
match c {
' ' => break,
_ => {
value.push(c);
self.input.next();
}
}
}
Token::Unknown(value)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_tokenize() {
let input = "I/6 + I5";
let expected = vec![
Token::Integer("/6".to_string()),
Token::Unknown("+".to_string()),
Token::Integer("5".to_string()),
];
let mut tokenizer = Tokenizer::new(input);
let result = tokenizer.tokenize();
assert_eq!(result, expected);
}
}

0 comments on commit 7858d0a

Please sign in to comment.