mirror of https://github.com/rm-dr/daisy
Cleanup, added more operators
parent
a4506e775a
commit
579f7f2ece
99
src/main.rs
99
src/main.rs
|
@ -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.")?;
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod tokenize;
|
||||||
|
pub mod treefold;
|
|
@ -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>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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(())
|
||||||
|
}
|
Loading…
Reference in New Issue