Added sin function and expression printing

pull/2/head
Mark 2023-03-29 10:40:33 -07:00
parent 3d5dcf0694
commit 3126b4c616
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
2 changed files with 171 additions and 14 deletions

View File

@ -80,13 +80,13 @@ fn main() -> Result<(), std::io::Error> {
if let Key::Char(q) = c.as_ref().unwrap() { if let Key::Char(q) = c.as_ref().unwrap() {
match q { match q {
'\n' => { '\n' => {
let s = pb.enter(); let in_str = pb.enter();
write!(stdout, "\r\n")?; write!(stdout, "\r\n")?;
if s == "" { break; } if in_str == "" { break; }
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
RawTerminal::suspend_raw_mode(&stdout)?; RawTerminal::suspend_raw_mode(&stdout)?;
let g = parser::parse(&s); let g = parser::parse(&in_str);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
RawTerminal::activate_raw_mode(&stdout)?; RawTerminal::activate_raw_mode(&stdout)?;
@ -94,14 +94,22 @@ fn main() -> Result<(), std::io::Error> {
Ok(g) => { Ok(g) => {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
RawTerminal::suspend_raw_mode(&stdout)?; RawTerminal::suspend_raw_mode(&stdout)?;
let out_str = g.print();
let g = evaluate::evaluate(g); let g = evaluate::evaluate(g);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
RawTerminal::activate_raw_mode(&stdout)?; RawTerminal::activate_raw_mode(&stdout)?;
write!(
stdout, " {}{}=>{}{} {}\r\n",
style::Bold, color::Fg(color::Magenta),
style::Reset, color::Fg(color::Reset),
out_str
)?;
match g { match g {
Ok(Token::Number(v)) => { Ok(Token::Number(v)) => {
write!( write!(
stdout, "\r\n {}{}={} {v}{}\r\n\n", stdout, "\n {}{}={} {v}{}\r\n\n",
style::Bold, style::Bold,
color::Fg(color::Green), color::Fg(color::Green),
style::Reset, style::Reset,
@ -111,7 +119,7 @@ fn main() -> Result<(), std::io::Error> {
Err(_) => { Err(_) => {
write!( write!(
stdout, "\r\n {}{}Mathematical Error: {}Failed to evaluate expression.is{}\r\n\n", stdout, "\n {}{}Mathematical Error: {}Failed to evaluate expression.{}\r\n\n",
style::Bold, style::Bold,
color::Fg(color::Red), color::Fg(color::Red),
style::Reset, style::Reset,

View File

@ -16,7 +16,22 @@ pub enum Token {
} }
impl Token { impl Token {
pub fn print(&self) -> String {
match self {
Token::Number(v) => v.to_string(),
Token::Constant(_,s) => s.clone(),
Token::Operator(o,a) => o.print(a)
}
}
#[inline(always)] #[inline(always)]
pub fn get_args(&self) -> Option<&VecDeque<Token>> {
match self {
Token::Operator(_, ref a) => Some(a),
_ => None
}
}
#[inline(always)] #[inline(always)]
pub fn get_args_mut(&mut self) -> Option<&mut VecDeque<Token>> { pub fn get_args_mut(&mut self) -> Option<&mut VecDeque<Token>> {
@ -57,18 +72,137 @@ pub enum Operator {
Add, Add,
Divide, Divide,
Multiply, Multiply,
ImplicitMultiply,
Modulo, // Mod invoked with % Modulo, // Mod invoked with %
Negative, Negative,
Power,
Sqrt, Sqrt,
ImplicitMultiply,
Power,
Factorial, Factorial,
Function(String),
// Not accessible from prompt // Not accessible from prompt
Flip, Flip,
} }
impl Operator { impl Operator {
#[inline(always)]
fn add_parens_to_arg(&self, arg: &Token) -> String {
let mut astr: String = arg.print();
if let Token::Operator(o,_) = arg {
if o.as_int() < self.as_int() {
astr = format!("({})", astr);
}
}
return astr;
}
pub fn print(&self, args: &VecDeque<Token>) -> String {
match self {
Operator::ImplicitMultiply |
Operator::Sqrt |
Operator::Divide |
Operator::Flip |
Operator::Subtract => { panic!() }
Operator::Negative => {
return format!("-{}", self.add_parens_to_arg(&args[0]));
},
Operator::ModuloLong => {
return format!(
"{} mod {}",
self.add_parens_to_arg(&args[0]),
self.add_parens_to_arg(&args[1])
);
},
Operator::Modulo => {
return format!(
"{} % {}",
self.add_parens_to_arg(&args[0]),
self.add_parens_to_arg(&args[1])
);
},
Operator::Power => {
return format!(
"{}^{}",
self.add_parens_to_arg(&args[0]),
self.add_parens_to_arg(&args[1])
);
},
Operator::Factorial => {
return format!("{}!", self.add_parens_to_arg(&args[0]));
},
Operator::Add => {
let a = &args[0];
let mut b = &args[1];
let mut sub = false;
if let Token::Operator(o,ar) = b {
if let Operator::Negative = o {
sub = true;
b = &ar[0];
}
}
let (b, sub) = (b, sub);
if sub {
return format!("{} - {}", self.add_parens_to_arg(a), self.add_parens_to_arg(b));
} else {
return format!("{} + {}", self.add_parens_to_arg(a), self.add_parens_to_arg(b));
}
},
Operator::Multiply => {
let a = &args[0];
let mut b = &args[1];
let mut div = false;
if let Token::Operator(o,ar) = b {
if let Operator::Flip = o {
div = true;
b = &ar[0];
}
}
let (b, div) = (b, div);
let mut astr: String = a.print();
if let Token::Operator(o,_) = a {
if o.as_int() < self.as_int() {
astr = format!("({})", astr);
}
}
let mut bstr: String = b.print();
if let Token::Operator(o,_) = b {
if o.as_int() < self.as_int() {
bstr = format!("({})", astr);
}
}
if div {
return format!("{} ÷ {}", astr, bstr);
} else {
return format!("{} × {}", astr, bstr);
}
},
Operator::Function(s) => {
return format!("{}({})", s, args[0].print());
}
};
}
#[inline(always)] #[inline(always)]
pub fn from_string(s: &str) -> Option<Operator> { pub fn from_string(s: &str) -> Option<Operator> {
match s { match s {
@ -83,6 +217,7 @@ impl Operator {
"^"|"**" => {Some( Operator::Power )}, "^"|"**" => {Some( Operator::Power )},
"!" => {Some( Operator::Factorial )}, "!" => {Some( Operator::Factorial )},
"sqrt"|"rt"|"" => {Some( Operator::Sqrt )}, "sqrt"|"rt"|"" => {Some( Operator::Sqrt )},
"sin" => {Some( Operator::Function(String::from("sin")) )}
_ => None _ => None
} }
} }
@ -93,6 +228,7 @@ impl Operator {
Operator::Negative Operator::Negative
| Operator::Factorial | Operator::Factorial
| Operator::Sqrt | Operator::Sqrt
| Operator::Function(_)
=> false, => false,
_ => true _ => true
} }
@ -103,6 +239,7 @@ impl Operator {
match self { match self {
Operator::Negative Operator::Negative
| Operator::Sqrt | Operator::Sqrt
| Operator::Function(_)
=> false, => false,
_ => true _ => true
} }
@ -154,16 +291,15 @@ impl Operator {
Operator::ImplicitMultiply Operator::ImplicitMultiply
=> { Token::Operator(Operator::Multiply, args) }, => { Token::Operator(Operator::Multiply, args) },
Operator::ModuloLong Operator::Function(_)
=> { Token::Operator(Operator::Modulo, args) }, | Operator::Factorial
Operator::Factorial
| Operator::Negative | Operator::Negative
| Operator::Flip | Operator::Flip
| Operator::Add | Operator::Add
| Operator::Multiply | Operator::Multiply
| Operator::Modulo | Operator::Modulo
| Operator::Power | Operator::Power
| Operator::ModuloLong
=> { Token::Operator(self, args) }, => { Token::Operator(self, args) },
} }
} }
@ -174,7 +310,6 @@ impl Operator{
match self { match self {
Operator::ImplicitMultiply | Operator::ImplicitMultiply |
Operator::Sqrt | Operator::Sqrt |
Operator::ModuloLong |
Operator::Divide | Operator::Divide |
Operator::Subtract => { panic!() } Operator::Subtract => { panic!() }
@ -223,7 +358,8 @@ impl Operator{
return Ok(Token::Number(prod)); return Ok(Token::Number(prod));
}, },
Operator::Modulo => { Operator::ModuloLong
| Operator::Modulo => {
if args.len() != 2 {panic!()}; if args.len() != 2 {panic!()};
let a = args[0].as_number(); let a = args[0].as_number();
let b = args[1].as_number(); let b = args[1].as_number();
@ -271,6 +407,19 @@ impl Operator{
return Ok(Token::Number(prod)); return Ok(Token::Number(prod));
} else { panic!(); } } else { panic!(); }
}, },
Operator::Function(s) => {
match &s[..] {
"sin" => {
if args.len() != 1 {panic!()};
let a = args[0].as_number();
let Token::Number(v) = a else {panic!()};
return Ok(Token::Number(v.sin()));
}
_ => panic!()
}
}
}; };
} }