Cleanup, added more operators

pull/2/head
Mark 2023-03-19 20:32:49 -07:00
parent a4506e775a
commit 579f7f2ece
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
4 changed files with 159 additions and 99 deletions

View File

@ -2,7 +2,6 @@ use std::io;
use std::io::Write; use std::io::Write;
//use std::io::Read; //use std::io::Read;
use std::sync::Arc; use std::sync::Arc;
use std::collections::VecDeque;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use termcolor::{ use termcolor::{
@ -13,7 +12,7 @@ use termcolor::{
WriteColor WriteColor
}; };
pub mod tokenize; mod parser;
const PROMPT_PREFIX: &str = "==> "; 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>) -> tokenize::Token,
) -> Result<tokenize::Token, ()> {
// 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<tokenize::Token> = 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<tokenize::Token> = match g {
tokenize::Token::Group(ref mut x) => x,
_ => panic!()
};
let mut new: VecDeque<tokenize::Token> = 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<tokenize::Token> = 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 {
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 {
tokenize::Token::Add(v)
}
fn main() -> Result<(), std::io::Error> { fn main() -> Result<(), std::io::Error> {
let mut stdout = StandardStream::stdout(ColorChoice::Always); let mut stdout = StandardStream::stdout(ColorChoice::Always);
@ -167,7 +79,7 @@ fn main() -> Result<(), std::io::Error> {
// Tokenize input. // Tokenize input.
// Fail if we encounter invalid characters. // Fail if we encounter invalid characters.
let exp = match tokenize::tokenize(&input) { let mut exp = match parser::tokenize::tokenize(&input) {
Ok(v) => v, Ok(v) => v,
Err(_) => { Err(_) => {
continue; continue;
@ -180,12 +92,9 @@ fn main() -> Result<(), std::io::Error> {
stdout.reset()?; stdout.reset()?;
write!(stdout, "Got {input}\n\n\n")?; write!(stdout, "Got {input}\n\n\n")?;
//writeln!(stdout, "Tokenized: {exp:#?}")?; parser::treefold::treefold(&mut exp).expect("Could not fold");
writeln!(stdout, "Tokenized: {exp:#?}")?;
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, "Exiting.")?; writeln!(stdout, "Exiting.")?;

2
src/parser.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod tokenize;
pub mod treefold;

View File

@ -9,15 +9,19 @@ pub enum Token {
Negative, Negative,
Factorial, Factorial,
Group(VecDeque<Token>), // Will be expanded during tree folding Group(VecDeque<Token>), // 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), Number(String),
Word(String), Word(String),
// Only used in tree // Only used in tree
Mult(VecDeque<Token>), Multiply(VecDeque<Token>),
Add(VecDeque<Token>) Divide(VecDeque<Token>),
Add(VecDeque<Token>),
Subtract(VecDeque<Token>),
Fac(VecDeque<Token>),
Neg(VecDeque<Token>)
} }

145
src/parser/treefold.rs Normal file
View File

@ -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>) -> 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<Token> = match g {
Token::Group(ref mut x) => x,
_ => panic!()
};
let mut new: VecDeque<Token> = 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<Token> = 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<Token> = 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<Token> = 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 { Token::Multiply(v) }
fn is_add(t: &Token) -> bool {
match t {
Token::Operator(s) => {s == "+"},
_ => false
}
}
fn new_add(v: VecDeque<Token>) -> Token { Token::Add(v) }
fn is_div(t: &Token) -> bool {
match t {
Token::Operator(s) => {s == "/"},
_ => false
}
}
fn new_div(v: VecDeque<Token>) -> Token { Token::Divide(v) }
fn is_sub(t: &Token) -> bool {
match t {
Token::Operator(s) => {s == "-"},
_ => false
}
}
fn new_sub(v: VecDeque<Token>) -> Token { Token::Subtract(v) }
fn is_fac(t: &Token) -> bool {
match t {
Token::Factorial => true,
_ => false
}
}
fn new_fac(v: VecDeque<Token>) -> Token { Token::Fac(v) }
fn is_neg(t: &Token) -> bool {
match t {
Token::Negative => true,
_ => false
}
}
fn new_neg(v: VecDeque<Token>) -> 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(())
}