diff --git a/fall-2024/soft-skills/Ethics/.~lock.Ethics - Thanawin Pattanaphol.odt# b/fall-2024/soft-skills/Ethics/.~lock.Ethics - Thanawin Pattanaphol.odt# deleted file mode 100644 index c54dd00..0000000 --- a/fall-2024/soft-skills/Ethics/.~lock.Ethics - Thanawin Pattanaphol.odt# +++ /dev/null @@ -1 +0,0 @@ -,winsdominoes,fedora,14.12.2024 11:59,file:///home/winsdominoes/.var/app/org.libreoffice.LibreOffice/config/libreoffice/4; \ No newline at end of file diff --git a/fall-2024/soft-skills/Ethics/Ethics - Thanawin Pattanaphol.odt b/fall-2024/soft-skills/Ethics/Ethics - Thanawin Pattanaphol.odt index 44649eb..30c31b4 100644 Binary files a/fall-2024/soft-skills/Ethics/Ethics - Thanawin Pattanaphol.odt and b/fall-2024/soft-skills/Ethics/Ethics - Thanawin Pattanaphol.odt differ diff --git a/fall-2024/soft-skills/Ethics/Ethics - Thanawin Pattanaphol.pdf b/fall-2024/soft-skills/Ethics/Ethics - Thanawin Pattanaphol.pdf new file mode 100644 index 0000000..7d9efb7 Binary files /dev/null and b/fall-2024/soft-skills/Ethics/Ethics - Thanawin Pattanaphol.pdf differ diff --git a/fall-2024/soft-skills/Proactiveness/Proactiveness - Thanawin Pattanaphol.odt b/fall-2024/soft-skills/Proactiveness/Proactiveness - Thanawin Pattanaphol.odt new file mode 100644 index 0000000..949a569 Binary files /dev/null and b/fall-2024/soft-skills/Proactiveness/Proactiveness - Thanawin Pattanaphol.odt differ diff --git a/fall-2024/soft-skills/Proactiveness/Proactiveness - Thanawin Pattanaphol.pdf b/fall-2024/soft-skills/Proactiveness/Proactiveness - Thanawin Pattanaphol.pdf new file mode 100644 index 0000000..ffbbc53 Binary files /dev/null and b/fall-2024/soft-skills/Proactiveness/Proactiveness - Thanawin Pattanaphol.pdf differ diff --git a/fall-2024/soft-skills/Professionalism/Professionalism - Thanawin Pattanaphol.odt b/fall-2024/soft-skills/Professionalism/Professionalism - Thanawin Pattanaphol.odt new file mode 100644 index 0000000..c71d4bd Binary files /dev/null and b/fall-2024/soft-skills/Professionalism/Professionalism - Thanawin Pattanaphol.odt differ diff --git a/fall-2024/soft-skills/Professionalism/Professionalism - Thanawin Pattanaphol.pdf b/fall-2024/soft-skills/Professionalism/Professionalism - Thanawin Pattanaphol.pdf new file mode 100644 index 0000000..d576698 Binary files /dev/null and b/fall-2024/soft-skills/Professionalism/Professionalism - Thanawin Pattanaphol.pdf differ diff --git a/fall-2024/soft-skills/Self-Learning/Self-Learning - Thanawin Pattanaphol.odt b/fall-2024/soft-skills/Self-Learning/Self-Learning - Thanawin Pattanaphol.odt new file mode 100644 index 0000000..ec3d316 Binary files /dev/null and b/fall-2024/soft-skills/Self-Learning/Self-Learning - Thanawin Pattanaphol.odt differ diff --git a/fall-2024/soft-skills/Self-Learning/Self-Learning - Thanawin Pattanaphol.pdf b/fall-2024/soft-skills/Self-Learning/Self-Learning - Thanawin Pattanaphol.pdf new file mode 100644 index 0000000..184e87c Binary files /dev/null and b/fall-2024/soft-skills/Self-Learning/Self-Learning - Thanawin Pattanaphol.pdf differ diff --git a/fall-2024/soft-skills/Teamwork/Teamwork - Thanawin Pattanaphol.odt b/fall-2024/soft-skills/Teamwork/Teamwork - Thanawin Pattanaphol.odt new file mode 100644 index 0000000..8eaa284 Binary files /dev/null and b/fall-2024/soft-skills/Teamwork/Teamwork - Thanawin Pattanaphol.odt differ diff --git a/fall-2024/soft-skills/Teamwork/Teamwork - Thanawin Pattanaphol.pdf b/fall-2024/soft-skills/Teamwork/Teamwork - Thanawin Pattanaphol.pdf new file mode 100644 index 0000000..ab4fb83 Binary files /dev/null and b/fall-2024/soft-skills/Teamwork/Teamwork - Thanawin Pattanaphol.pdf differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/._eval b/spring-2025/sen-109/00020/eval/__MACOSX/._eval new file mode 100755 index 0000000..eb62a54 Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/._eval differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/._.DS_Store b/spring-2025/sen-109/00020/eval/__MACOSX/eval/._.DS_Store new file mode 100644 index 0000000..a5b28df Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/._.DS_Store differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/._.idea b/spring-2025/sen-109/00020/eval/__MACOSX/eval/._.idea new file mode 100755 index 0000000..5829a1f Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/._.idea differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/._Cargo.toml b/spring-2025/sen-109/00020/eval/__MACOSX/eval/._Cargo.toml new file mode 100644 index 0000000..b274884 Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/._Cargo.toml differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/._src b/spring-2025/sen-109/00020/eval/__MACOSX/eval/._src new file mode 100755 index 0000000..134bf95 Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/._src differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/.idea/._.gitignore b/spring-2025/sen-109/00020/eval/__MACOSX/eval/.idea/._.gitignore new file mode 100644 index 0000000..7a38672 Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/.idea/._.gitignore differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/.idea/._eval.iml b/spring-2025/sen-109/00020/eval/__MACOSX/eval/.idea/._eval.iml new file mode 100644 index 0000000..46cd8b7 Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/.idea/._eval.iml differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/.idea/._modules.xml b/spring-2025/sen-109/00020/eval/__MACOSX/eval/.idea/._modules.xml new file mode 100644 index 0000000..0449522 Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/.idea/._modules.xml differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/.idea/._vcs.xml b/spring-2025/sen-109/00020/eval/__MACOSX/eval/.idea/._vcs.xml new file mode 100644 index 0000000..9ba1bfe Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/.idea/._vcs.xml differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/.idea/._workspace.xml b/spring-2025/sen-109/00020/eval/__MACOSX/eval/.idea/._workspace.xml new file mode 100644 index 0000000..c105a93 Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/.idea/._workspace.xml differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/._.DS_Store b/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/._.DS_Store new file mode 100644 index 0000000..a5b28df Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/._.DS_Store differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/._main.rs b/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/._main.rs new file mode 100644 index 0000000..a13a95a Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/._main.rs differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/._parsemath b/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/._parsemath new file mode 100755 index 0000000..94c3363 Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/._parsemath differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/parsemath/._ast.rs b/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/parsemath/._ast.rs new file mode 100644 index 0000000..37c9bcf Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/parsemath/._ast.rs differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/parsemath/._mod.rs b/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/parsemath/._mod.rs new file mode 100644 index 0000000..cc72d1b Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/parsemath/._mod.rs differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/parsemath/._parser.rs b/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/parsemath/._parser.rs new file mode 100644 index 0000000..cb7184e Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/parsemath/._parser.rs differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/parsemath/._token.rs b/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/parsemath/._token.rs new file mode 100644 index 0000000..42eaf41 Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/parsemath/._token.rs differ diff --git a/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/parsemath/._tokenizer.rs b/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/parsemath/._tokenizer.rs new file mode 100644 index 0000000..d149bbd Binary files /dev/null and b/spring-2025/sen-109/00020/eval/__MACOSX/eval/src/parsemath/._tokenizer.rs differ diff --git a/spring-2025/sen-109/00020/eval/eval/.idea/.gitignore b/spring-2025/sen-109/00020/eval/eval/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/spring-2025/sen-109/00020/eval/eval/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/spring-2025/sen-109/00020/eval/eval/.idea/eval.iml b/spring-2025/sen-109/00020/eval/eval/.idea/eval.iml new file mode 100644 index 0000000..cf84ae4 --- /dev/null +++ b/spring-2025/sen-109/00020/eval/eval/.idea/eval.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/spring-2025/sen-109/00020/eval/eval/.idea/modules.xml b/spring-2025/sen-109/00020/eval/eval/.idea/modules.xml new file mode 100644 index 0000000..f0c1a8c --- /dev/null +++ b/spring-2025/sen-109/00020/eval/eval/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/spring-2025/sen-109/00020/eval/eval/.idea/vcs.xml b/spring-2025/sen-109/00020/eval/eval/.idea/vcs.xml new file mode 100644 index 0000000..d843f34 --- /dev/null +++ b/spring-2025/sen-109/00020/eval/eval/.idea/vcs.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/spring-2025/sen-109/00020/eval/eval/Cargo.toml b/spring-2025/sen-109/00020/eval/eval/Cargo.toml new file mode 100644 index 0000000..f813e8c --- /dev/null +++ b/spring-2025/sen-109/00020/eval/eval/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "expression-eval" +version = "0.1.0" +authors = ["cmkl"] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/spring-2025/sen-109/00020/eval/eval/src/main.rs b/spring-2025/sen-109/00020/eval/eval/src/main.rs new file mode 100644 index 0000000..6907f7c --- /dev/null +++ b/spring-2025/sen-109/00020/eval/eval/src/main.rs @@ -0,0 +1,44 @@ +/// This is the main command-line application for arithmetic expression evaluator +// Standard library +use std::io; + +// code for arithmetic expression evaluation is in parsemath module +mod parsemath; +use parsemath::ast; +use parsemath::parser::{ParseError, Parser}; + +// Function to invoke Parser and evaluate expression +fn evaluate(expr: String) -> Result { + let expr = expr.split_whitespace().collect::(); // remove whitespace chars + let mut math_parser = Parser::new(&expr)?; + let ast = math_parser.parse()?; + println!("The generated AST is {:?}", ast); + + Ok(ast::eval(ast)?) +} + +// Main function reads arithmetic expression from command-line and displays result and error. +// It calls the evaluate function to perform computation. + +fn main() { + println!("Hello! Welcome to Arithmetic expression evaluator."); + println!("You can calculate value for expression such as 2*3+(4-5)+2^3/4. "); + println!("Allowed numbers: positive, negative and decimals."); + println!("Supported operations: Add, Subtract, Multiply, Divide, PowerOf(^). "); + println!("Enter your arithmetic expression below:"); + loop { + let mut input = String::new(); + match io::stdin().read_line(&mut input) { + Ok(_) => { + match evaluate(input) { + Ok(val) => println!("The computed number is {}\n", val), + Err(_) => { + println!("Error in evaluating expression. Please enter valid expression\n"); + } + }; + } + + Err(error) => println!("error: {}", error), + } + } +} diff --git a/spring-2025/sen-109/00020/eval/eval/src/parsemath/ast.rs b/spring-2025/sen-109/00020/eval/eval/src/parsemath/ast.rs new file mode 100644 index 0000000..9a3e154 --- /dev/null +++ b/spring-2025/sen-109/00020/eval/eval/src/parsemath/ast.rs @@ -0,0 +1,64 @@ +/// This program contains list of valid AST nodes that can be constructed and also evaluates an AST to compute a value +// Standard lib +use std::error; + +//structs + +// List of allowed AST nodes that can be constructed by Parser +// Tokens can be arithmetic operators or a Number +#[derive(Debug, Clone, PartialEq)] +pub enum Node { + // WARNING: Bitwise And and Or operation only works on integer value + And(Box, Box), + Or(Box, Box), + + Add(Box, Box), + Subtract(Box, Box), + Multiply(Box, Box), + Divide(Box, Box), + Caret(Box, Box), + Negative(Box), + Number(f64), +} + +// Given an AST, calculate the numeric value. +pub fn eval(expr: Node) -> Result> { + use self::Node::*; + match expr { + Number(i) => Ok(i), + Add(expr1, expr2) => Ok(eval(*expr1)? + eval(*expr2)?), + + // TODO: complete the match expression to evaluate the numeric value + _ => panic!() + } +} + +//Unit tests +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_expr1() { + use crate::parsemath::parser::Parser; + + let ast = Parser::new("1+2-3").unwrap().parse().unwrap(); + let value = eval(ast).unwrap(); + assert_eq!(value, 0.0); + } + #[test] + fn test_expr2() { + use crate::parsemath::parser::Parser; + + let ast = Parser::new("3+2-1*5/4").unwrap().parse().unwrap(); + let value = eval(ast).unwrap(); + assert_eq!(value, 3.75); + } + #[test] + fn test_expr3() { + use crate::parsemath::parser::Parser; + + let ast = Parser::new("3+3 | 4").unwrap().parse().unwrap(); + let value = eval(ast).unwrap(); + assert_eq!(value, 6.0); + } +} diff --git a/spring-2025/sen-109/00020/eval/eval/src/parsemath/mod.rs b/spring-2025/sen-109/00020/eval/eval/src/parsemath/mod.rs new file mode 100644 index 0000000..dba3699 --- /dev/null +++ b/spring-2025/sen-109/00020/eval/eval/src/parsemath/mod.rs @@ -0,0 +1,5 @@ +/// Module Parsemath +pub mod ast; +pub mod parser; +pub mod token; +pub mod tokenizer; diff --git a/spring-2025/sen-109/00020/eval/eval/src/parsemath/parser.rs b/spring-2025/sen-109/00020/eval/eval/src/parsemath/parser.rs new file mode 100644 index 0000000..518912a --- /dev/null +++ b/spring-2025/sen-109/00020/eval/eval/src/parsemath/parser.rs @@ -0,0 +1,174 @@ +/// This program reads tokens returned by Tokenizer and converts them into AST. +// Standard lib +use std::fmt; + +// Internal modules +use super::ast::Node; +use super::token::{OperPrec, Token}; +use super::tokenizer::Tokenizer; + +//Structs and constants + +// Parser struct +pub struct Parser<'a> { + tokenizer: Tokenizer<'a>, + current_token: Token, +} + +// Public methods of Parser + +impl<'a> Parser<'a> { + // Create a new instance of Parser + pub fn new(expr: &'a str) -> Result { + let mut lexer = Tokenizer::new(expr); + let cur_token = match lexer.next() { + Some(token) => token, + None => return Err(ParseError::InvalidOperator("Invalid character".into())), + }; + Ok(Parser { + tokenizer: lexer, + current_token: cur_token, + }) + } + + // Take an arithmetic expression as input and return an AST + + pub fn parse(&mut self) -> Result { + let ast = self.generate_ast(OperPrec::DefaultZero); + match ast { + // TODO: Replace this with proper handling of return value from generate_ast result + _ => panic!() + } + } +} + +// Private methods of Parser + +impl<'a> Parser<'a> { + // Retrieve the next token from arithmetic expression and set it to current_token field in Parser struct + fn get_next_token(&mut self) -> Result<(), ParseError> { + let next_token = match self.tokenizer.next() { + Some(token) => token, + None => return Err(ParseError::InvalidOperator("Invalid character".into())), + }; + self.current_token = next_token; + Ok(()) + } + + // Main workhorse method that is called recursively + + fn generate_ast(&mut self, oper_prec: OperPrec) -> Result { + let mut left_expr = self.parse_number()?; + + while oper_prec < self.current_token.get_oper_prec() { + if self.current_token == Token::EOF { + break; + } + let right_expr = self.convert_token_to_node(left_expr.clone())?; + left_expr = right_expr; + } + Ok(left_expr) + } + + // Construct AST node for numbers, taking into account negative prefixes while handling parenthesis + + fn parse_number(&mut self) -> Result { + let token = self.current_token.clone(); + match token { + Token::Subtract => { + self.get_next_token()?; + let expr = self.generate_ast(OperPrec::Negative)?; + Ok(Node::Negative(Box::new(expr))) + } + Token::Num(i) => { + self.get_next_token()?; + Ok(Node::Number(i)) + } + Token::LeftParen => { + self.get_next_token()?; + + // TODO: Replace the following code to check for matching parenthesis; + // also convert (x)(y) to x times y + let expr = self.generate_ast(OperPrec::DefaultZero)?; + Ok(expr) + } + _ => Err(ParseError::UnableToParse("Unable to parse".to_string())), + } + } + + // Check for balancing parenthesis + fn check_paren(&mut self, expected: Token) -> Result<(), ParseError> { + if expected == self.current_token { + self.get_next_token()?; + Ok(()) + } else { + Err(ParseError::InvalidOperator(format!( + "Expected {:?}, got {:?}", + expected, self.current_token + ))) + } + } + + // Construct Operator AST nodes + fn convert_token_to_node(&mut self, left_expr: Node) -> Result { + match self.current_token { + Token::Add => { + self.get_next_token()?; + //Get right-side expression + let right_expr = self.generate_ast(OperPrec::AddSub)?; + Ok(Node::Add(Box::new(left_expr), Box::new(right_expr))) + } + // TODO: Complete the node construction for other tokens + + _ => Err(ParseError::InvalidOperator(format!( + "Please enter valid operator {:?}", + self.current_token + ))), + } + } +} + +// Custom error handler for Parser +#[derive(Debug)] +pub enum ParseError { + UnableToParse(String), + InvalidOperator(String), +} + +impl fmt::Display for ParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match &self { + ParseError::UnableToParse(e) => write!(f, "Error in evaluating {}", e), + ParseError::InvalidOperator(e) => write!(f, "Error in evaluating {}", e), + } + } +} + +// Handle error thrown from AST module + +impl From> for ParseError { + fn from(_evalerr: Box) -> Self { + ParseError::UnableToParse("Unable to parse".into()) + } +} + +// Unit tests + +#[cfg(test)] +mod tests { + use super::*; + use crate::parsemath::ast::Node::{Add, Or, Number}; + #[test] + fn test_addition() { + let mut parser = Parser::new("1+2").unwrap(); + let expected = Add(Box::new(Number(1.0)), Box::new(Number(2.0))); + assert_eq!(parser.parse().unwrap(), expected); + } + + #[test] + fn test_bitwise_or() { + let mut parser = Parser::new("6|2").unwrap(); + let expected = Or(Box::new(Number(6.0)), Box::new(Number(2.0))); + assert_eq!(parser.parse().unwrap(), expected); + } +} diff --git a/spring-2025/sen-109/00020/eval/eval/src/parsemath/token.rs b/spring-2025/sen-109/00020/eval/eval/src/parsemath/token.rs new file mode 100644 index 0000000..bd70900 --- /dev/null +++ b/spring-2025/sen-109/00020/eval/eval/src/parsemath/token.rs @@ -0,0 +1,48 @@ +/// This contains enum for list of Tokens, and handles Operator precedence rules. + +// List of valid tokens that can be constructed from arithmetic expression by Tokenizer + +#[derive(Debug, PartialEq, Clone)] +pub enum Token { + And, // & + Or, // | + Add, // + + Subtract, // - + Multiply, // * + Divide, // / + Caret, // ^ + LeftParen, // ( + RightParen, // ) + Num(f64), // 12.34 + EOF, +} + +// Order of operators as per operator precedence rules (low to high) + +#[derive(Debug, PartialEq, PartialOrd)] +/// Defines all the OperPrec levels, from lowest to highest. +pub enum OperPrec { + DefaultZero, + AndOr, + AddSub, + MulDiv, + Power, + Negative, +} + +// This contains methods to retrieve operator precedence for a given arithmetic operator + +impl Token { + pub fn get_oper_prec(&self) -> OperPrec { + use self::OperPrec::*; + use self::Token::*; + match *self { + And | Or => AndOr, + Add | Subtract => AddSub, + Multiply | Divide => MulDiv, + Caret => Power, + + _ => DefaultZero, + } + } +} diff --git a/spring-2025/sen-109/00020/eval/eval/src/parsemath/tokenizer.rs b/spring-2025/sen-109/00020/eval/eval/src/parsemath/tokenizer.rs new file mode 100644 index 0000000..7e76a82 --- /dev/null +++ b/spring-2025/sen-109/00020/eval/eval/src/parsemath/tokenizer.rs @@ -0,0 +1,70 @@ +/// This module reads characters in arithmetic expression and converts them to tokens. +/// The allowed tokens are defined in ast module. +// Standard lib +use std::iter::Peekable; +use std::str::Chars; + +//Other internal modules +use super::token::Token; + +// Other structs + +// Tokenizer struct contains a Peekable iterator on the arithmetic expression +pub struct Tokenizer<'a> { + expr: Peekable>, +} + +// Constructs a new instance of Tokenizer +impl<'a> Tokenizer<'a> { + pub fn new(new_expr: &'a str) -> Self { + Tokenizer { + expr: new_expr.chars().peekable(), + } + } +} + +// Implement Iterator trait for Tokenizer struct. +// With this, we can use next() method on tokenizer to retrieve the next token from arithmetic expression + +impl<'a> Iterator for Tokenizer<'a> { + type Item = Token; + + fn next(&mut self) -> Option { + let next_char = self.expr.next(); + + match next_char { + Some('0'..='9') => { + // TODO: Iterate & peeking through the next characters to create Num token + // Make sure to return None if the value is not parsable + None + }, + + // TODO: return the appropriate tokens for available symbols + + None => Some(Token::EOF), + Some(_) => None, + } + } +} + +// Unit tests +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_positive_integer() { + let mut tokenizer = Tokenizer::new("34"); + assert_eq!(tokenizer.next().unwrap(), Token::Num(34.0)) + } + #[test] + fn test_decimal_number() { + let mut tokenizer = Tokenizer::new("34.5"); + assert_eq!(tokenizer.next().unwrap(), Token::Num(34.5)) + } + #[test] + fn test_invalid_char() { + let mut tokenizer = Tokenizer::new("#$%"); + assert_eq!(tokenizer.next(), None); + } +}