diff --git a/src/main.rs b/src/main.rs index f032633..a8362cc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,6 @@ use std::io; use std::io::Write; //use std::io::Read; use std::sync::Arc; -use std::collections::VecDeque; use std::sync::atomic::{AtomicBool, Ordering}; use termcolor::{ @@ -13,7 +12,7 @@ use termcolor::{ WriteColor }; -pub mod tokenize; +mod parser; const PROMPT_PREFIX: &str = "==> "; @@ -61,93 +60,6 @@ fn prompt( } -fn treefold( - mut exp: tokenize::Token, // Must be a group - check: fn(&tokenize::Token) -> bool, - op_type: u8, - new_token: fn(VecDeque) -> tokenize::Token, -) -> Result { - - // Groups to process - let mut t_vec: VecDeque<&mut tokenize::Token> = VecDeque::with_capacity(32); - t_vec.push_back(&mut exp); - - let mut out: Option = None; - - while t_vec.len() > 0 { - - // The group we're currently working with - let g: &mut tokenize::Token = t_vec.pop_front().unwrap(); - let g_inner: &mut VecDeque = match g { - tokenize::Token::Group(ref mut x) => x, - _ => panic!() - }; - - let mut new: VecDeque = VecDeque::with_capacity(8); - - // Build new group array - while g_inner.len() > 0 { - let t: tokenize::Token = match g_inner.pop_front() { - Some(o) => o, - None => break - }; - - if check(&t) { - match op_type { - 0 => {}, - 1 => {}, - 2 => { - let mut last: tokenize::Token = new.pop_back().unwrap(); - let mut next: tokenize::Token = g_inner.pop_front().unwrap().clone(); - - // TODO: append to t_vec, do this without recursion. - if let tokenize::Token::Group(_) = last { - last = treefold(last, check, op_type, new_token).unwrap(); - } - if let tokenize::Token::Group(_) = next { - next = treefold(next, check, op_type, new_token).unwrap(); - } - - let mut new_token_args: VecDeque = VecDeque::with_capacity(2); - new_token_args.push_back(last); - new_token_args.push_back(next); - new.push_back(new_token(new_token_args)); - }, - _ => panic!() - }; - } else { - new.push_back(t.clone()); - } - } - - *g_inner = new; - } - return Ok(exp); -} - - -fn is_mult(t: &tokenize::Token) -> bool { - match t { - tokenize::Token::Operator(s) => {s == "*"}, - _ => false - } -} - -fn new_mult(v: VecDeque) -> tokenize::Token { - tokenize::Token::Mult(v) -} - -fn is_add(t: &tokenize::Token) -> bool { - match t { - tokenize::Token::Operator(s) => {s == "+"}, - _ => false - } -} - -fn new_add(v: VecDeque) -> tokenize::Token { - tokenize::Token::Add(v) -} - fn main() -> Result<(), std::io::Error> { let mut stdout = StandardStream::stdout(ColorChoice::Always); @@ -167,7 +79,7 @@ fn main() -> Result<(), std::io::Error> { // Tokenize input. // Fail if we encounter invalid characters. - let exp = match tokenize::tokenize(&input) { + let mut exp = match parser::tokenize::tokenize(&input) { Ok(v) => v, Err(_) => { continue; @@ -180,12 +92,9 @@ fn main() -> Result<(), std::io::Error> { stdout.reset()?; write!(stdout, "Got {input}\n\n\n")?; - //writeln!(stdout, "Tokenized: {exp:#?}")?; + parser::treefold::treefold(&mut exp).expect("Could not fold"); - - let mut q = treefold(exp, is_mult, 2, new_mult).unwrap(); - q = treefold(q, is_add, 2, new_add).unwrap(); - writeln!(stdout, "{q:#?}")?; + writeln!(stdout, "Tokenized: {exp:#?}")?; } writeln!(stdout, "Exiting.")?; diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..26e9e57 --- /dev/null +++ b/src/parser.rs @@ -0,0 +1,2 @@ +pub mod tokenize; +pub mod treefold; \ No newline at end of file diff --git a/src/tokenize.rs b/src/parser/tokenize.rs similarity index 93% rename from src/tokenize.rs rename to src/parser/tokenize.rs index adb2407..4b57833 100644 --- a/src/tokenize.rs +++ b/src/parser/tokenize.rs @@ -9,15 +9,19 @@ pub enum Token { Negative, Factorial, Group(VecDeque), // Will be expanded during tree folding - Operator(String), // Will become Ops during tree folding + Operator(String), // Will become Ops during tree folding - // Used in both. + // Used in both Number(String), Word(String), // Only used in tree - Mult(VecDeque), - Add(VecDeque) + Multiply(VecDeque), + Divide(VecDeque), + Add(VecDeque), + Subtract(VecDeque), + Fac(VecDeque), + Neg(VecDeque) } diff --git a/src/parser/treefold.rs b/src/parser/treefold.rs new file mode 100644 index 0000000..f926a4b --- /dev/null +++ b/src/parser/treefold.rs @@ -0,0 +1,145 @@ +use std::collections::VecDeque; + +use crate::parser::tokenize::Token; + +fn treefold_one( + exp: &mut Token, // Must be a group + check: fn(&Token) -> bool, + op_type: u8, + new_token: fn(VecDeque) -> Token, +) -> Result<(), ()> { + + // Groups to process + let mut t_vec: VecDeque<&mut Token> = VecDeque::with_capacity(32); + t_vec.push_back(exp); + + while t_vec.len() > 0 { + + // The group we're currently working with + let g: &mut Token = t_vec.pop_front().unwrap(); + let g_inner: &mut VecDeque = match g { + Token::Group(ref mut x) => x, + _ => panic!() + }; + + let mut new: VecDeque = VecDeque::with_capacity(8); + + // Build new group array + while g_inner.len() > 0 { + let t: Token = match g_inner.pop_front() { + Some(o) => o, + None => break + }; + + if check(&t) { + match op_type { + 0 => { + let mut last: Token = new.pop_back().unwrap(); + + if let Token::Group(_) = last { + treefold_one(&mut last, check, op_type, new_token).unwrap(); + } + + let mut new_token_args: VecDeque = VecDeque::with_capacity(1); + new_token_args.push_back(last); + new.push_back(new_token(new_token_args)); + }, + 1 => { + let mut next: Token = g_inner.pop_front().unwrap().clone(); + + if let Token::Group(_) = next { + treefold_one(&mut next, check, op_type, new_token).unwrap(); + } + + let mut new_token_args: VecDeque = VecDeque::with_capacity(1); + new_token_args.push_back(next); + new.push_back(new_token(new_token_args)); + }, + 2 => { + let mut last: Token = new.pop_back().unwrap(); + let mut next: Token = g_inner.pop_front().unwrap().clone(); + + // TODO: append to t_vec, do this without recursion. + if let Token::Group(_) = last { + treefold_one(&mut last, check, op_type, new_token).unwrap(); + } + if let Token::Group(_) = next { + treefold_one(&mut next, check, op_type, new_token).unwrap(); + } + + let mut new_token_args: VecDeque = VecDeque::with_capacity(2); + new_token_args.push_back(last); + new_token_args.push_back(next); + new.push_back(new_token(new_token_args)); + }, + _ => panic!() + }; + } else { + new.push_back(t.clone()); + } + } + + *g_inner = new; + } + + Ok(()) +} + + +fn is_mult(t: &Token) -> bool { + match t { + Token::Operator(s) => {s == "*"}, + _ => false + } +} +fn new_mult(v: VecDeque) -> Token { Token::Multiply(v) } + +fn is_add(t: &Token) -> bool { + match t { + Token::Operator(s) => {s == "+"}, + _ => false + } +} +fn new_add(v: VecDeque) -> Token { Token::Add(v) } + +fn is_div(t: &Token) -> bool { + match t { + Token::Operator(s) => {s == "/"}, + _ => false + } +} +fn new_div(v: VecDeque) -> Token { Token::Divide(v) } + +fn is_sub(t: &Token) -> bool { + match t { + Token::Operator(s) => {s == "-"}, + _ => false + } +} +fn new_sub(v: VecDeque) -> Token { Token::Subtract(v) } + +fn is_fac(t: &Token) -> bool { + match t { + Token::Factorial => true, + _ => false + } +} +fn new_fac(v: VecDeque) -> Token { Token::Fac(v) } + +fn is_neg(t: &Token) -> bool { + match t { + Token::Negative => true, + _ => false + } +} +fn new_neg(v: VecDeque) -> Token { Token::Neg(v) } + +pub fn treefold(exp: &mut Token) -> Result<(), ()> { + treefold_one(exp, is_fac, 0, new_fac)?; + treefold_one(exp, is_neg, 1, new_neg)?; + treefold_one(exp, is_mult, 2, new_mult)?; + treefold_one(exp, is_div, 2, new_div)?; + treefold_one(exp, is_add, 2, new_add)?; + treefold_one(exp, is_sub, 2, new_sub)?; + Ok(()) +} \ No newline at end of file