From ae36284d60b828869ede5a77343ccb307046b69a Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sat, 3 Aug 2019 15:22:01 +0800 Subject: Fix clippy lints --- src/error/mod.rs | 20 +++------ src/format/mod.rs | 23 ++++------ src/lex/mod.rs | 127 ++++++++++++++++++++++++++-------------------------- src/main.rs | 112 ++++++++++++++++++++++----------------------- src/parse/mod.rs | 44 ++++++++---------- src/readline/mod.rs | 66 +++++++++++++-------------- 6 files changed, 187 insertions(+), 205 deletions(-) diff --git a/src/error/mod.rs b/src/error/mod.rs index 9ac6816..ec2b555 100644 --- a/src/error/mod.rs +++ b/src/error/mod.rs @@ -13,23 +13,17 @@ pub enum CalcError { pub enum Math { DivideByZero, OutOfBounds, - UnknownBase + UnknownBase, } pub fn handler(e: CalcError) -> String { match e { - CalcError::Math(math_err) => { - match math_err { - Math::DivideByZero => format!("Math Error: Divide by zero error!"), - Math::OutOfBounds => format!("Domain Error: Out of bounds!"), - Math::UnknownBase => format!("Base too large! Accepted ranges: 0 - 36") - } + CalcError::Math(math_err) => match math_err { + Math::DivideByZero => "Math Error: Divide by zero error!".to_string(), + Math::OutOfBounds => "Domain Error: Out of bounds!".to_string(), + Math::UnknownBase => "Base too large! Accepted ranges: 0 - 36".to_string(), }, - CalcError::Syntax(details) => { - format!("Syntax Error: {}", details) - }, - CalcError::Parser(details) => { - format!("Parser Error: {}", details) - } + CalcError::Syntax(details) => format!("Syntax Error: {}", details), + CalcError::Parser(details) => format!("Parser Error: {}", details), } } diff --git a/src/format/mod.rs b/src/format/mod.rs index 3e3ade2..45673d7 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -1,12 +1,8 @@ extern crate num; use num::{BigInt, FromPrimitive, ToPrimitive}; +use crate::error::{CalcError, Math}; use crate::CONFIGURATION; -use crate::error::{ - CalcError, - Math -}; - pub fn autobalance_parens(input: &str) -> Result { let mut balanced = String::from(input); @@ -25,7 +21,7 @@ pub fn autobalance_parens(input: &str) -> Result { balanced.push_str(&extras[..]); Ok(balanced) } else if left_parens < right_parens { - return Err(CalcError::Syntax("Mismatched parentheses!".into())) + Err(CalcError::Syntax("Mismatched parentheses!".into())) } else { Ok(balanced) } @@ -39,10 +35,10 @@ fn radix_fmt(number: f64, obase: usize) -> Result { match (number.is_infinite(), number.is_sign_positive()) { (true, true) => return Ok("inf".to_string()), (true, false) => return Ok("-inf".to_string()), - _ => () + _ => (), } - if number.is_nan(){ + if number.is_nan() { return Ok("nan".to_string()); } @@ -53,7 +49,7 @@ fn radix_fmt(number: f64, obase: usize) -> Result { let mut obase_int = String::new(); let obaseb = BigInt::from_usize(obase).unwrap(); - while &integral >= &obaseb { + while integral >= obaseb { obase_int.push(table[(&integral % &obaseb).to_usize().unwrap()]); integral /= &obaseb; } @@ -81,7 +77,7 @@ fn radix_fmt(number: f64, obase: usize) -> Result { fn thousand_sep(inp: &str) -> String { let mut result_string = String::new(); - for (i,c) in inp.to_string().chars().rev().enumerate() { + for (i, c) in inp.to_string().chars().rev().enumerate() { if i % 3 == 0 && i != 0 && c.to_string() != "-" { result_string.push(','); } @@ -92,11 +88,10 @@ fn thousand_sep(inp: &str) -> String { pub fn pprint(ans: f64) { let ans_string = radix_fmt(ans, CONFIGURATION.base).unwrap(); - let ans_vector: Vec<&str> = ans_string.split(".").collect(); + let ans_vector: Vec<&str> = ans_string.split('.').collect(); match ans_vector.len() { 1 => println!("{:>10}", thousand_sep(ans_vector[0])), - 2 => println!("{:>10}.{}", thousand_sep(ans_vector[0]),ans_vector[1]), - _ => unreachable!("N-nani?!") + 2 => println!("{:>10}.{}", thousand_sep(ans_vector[0]), ans_vector[1]), + _ => unreachable!("N-nani?!"), } } - diff --git a/src/lex/mod.rs b/src/lex/mod.rs index c82c17e..48e07be 100644 --- a/src/lex/mod.rs +++ b/src/lex/mod.rs @@ -7,10 +7,7 @@ use std::collections::HashMap; use crate::CONFIGURATION; -use crate::error::{ - CalcError, - Math -}; +use crate::error::{CalcError, Math}; #[derive(Debug, Copy, Clone, PartialEq)] pub struct Operator { @@ -21,22 +18,22 @@ pub struct Operator { } impl Operator { - fn token_from_op(token: char, - operation: fn(f64, f64) -> f64, - precedence: u8, - is_left_associative: bool) -> Token { - Token::Operator( - Operator { - token, - operation, - precedence, - is_left_associative - } - ) + fn token_from_op( + token: char, + operation: fn(f64, f64) -> f64, + precedence: u8, + is_left_associative: bool, + ) -> Token { + Token::Operator(Operator { + token, + operation, + precedence, + is_left_associative, + }) } pub fn operate(self, x: f64, y: f64) -> Result { if self.token == '/' && y == 0. { - return Err(CalcError::Math(Math::DivideByZero)) + Err(CalcError::Math(Math::DivideByZero)) } else { Ok((self.operation)(x, y)) } @@ -51,31 +48,25 @@ pub struct Function { impl Function { fn token_from_fn(token: String, relation: fn(f64) -> f64) -> Token { - Token::Function( - Function { - token, - relation - } - ) + Token::Function(Function { token, relation }) } pub fn apply(self, arg: f64) -> Result { let result = (self.relation)(arg); if !result.is_finite() { - return Err(CalcError::Math(Math::OutOfBounds)); + Err(CalcError::Math(Math::OutOfBounds)) } else { Ok(result) } } } - #[derive(Debug, Clone, PartialEq)] pub enum Token { Operator(Operator), Num(f64), Function(Function), LParen, - RParen + RParen, } lazy_static! { @@ -128,8 +119,8 @@ lazy_static! { }; } -fn factorial (n: f64) -> f64 { - n.signum() * (1.. n.abs() as u64 +1).fold(1, |p, n| p*n) as f64 +fn factorial(n: f64) -> f64 { + n.signum() * (1..=n.abs() as u64).fold(1, |p, n| p * n) as f64 } pub fn lexer(input: &str, prev_ans: f64) -> Result, CalcError> { @@ -141,22 +132,34 @@ pub fn lexer(input: &str, prev_ans: f64) -> Result, CalcError> { for letter in input.chars() { match letter { '0'...'9' | '.' => { - if char_vec.len() > 0 { - if let Some(_) = FUNCTIONS.get(&char_vec[..]) { - return Err(CalcError::Syntax(format!("Function '{}' expected parentheses", char_vec))) + if !char_vec.is_empty() { + if FUNCTIONS.get(&char_vec[..]).is_some() { + return Err(CalcError::Syntax(format!( + "Function '{}' expected parentheses", + char_vec + ))); } else { - return Err(CalcError::Syntax(format!("Unexpected character '{}'", char_vec))) + return Err(CalcError::Syntax(format!( + "Unexpected character '{}'", + char_vec + ))); } } num_vec.push(letter); - last_char_is_op = false; - }, + last_char_is_op = false; + } '_' => { - if char_vec.len() > 0 { - if let Some(_) = FUNCTIONS.get(&char_vec[..]) { - return Err(CalcError::Syntax(format!("Function '{}' expected parentheses", char_vec))) + if !char_vec.is_empty() { + if FUNCTIONS.get(&char_vec[..]).is_some() { + return Err(CalcError::Syntax(format!( + "Function '{}' expected parentheses", + char_vec + ))); } else { - return Err(CalcError::Syntax(format!("Unexpected character '{}'", char_vec))) + return Err(CalcError::Syntax(format!( + "Unexpected character '{}'", + char_vec + ))); } } let parse_num = num_vec.parse::().ok(); @@ -165,7 +168,7 @@ pub fn lexer(input: &str, prev_ans: f64) -> Result, CalcError> { result.push(OPERATORS.get(&'*').unwrap().clone()); num_vec.clear(); } - last_char_is_op = false; + last_char_is_op = false; result.push(Token::Num(prev_ans)); } 'a'...'z' | 'A'...'Z' => { @@ -177,7 +180,7 @@ pub fn lexer(input: &str, prev_ans: f64) -> Result, CalcError> { } char_vec.push(letter); last_char_is_op = false; - }, + } '+' | '-' => { let op_token = OPERATORS.get(&letter).unwrap().clone(); let parse_num = num_vec.parse::().ok(); @@ -194,27 +197,32 @@ pub fn lexer(input: &str, prev_ans: f64) -> Result, CalcError> { result.push(op_token); } else if last_char_is_op { result.push(Token::LParen); - result.push(Token::Num((letter.to_string() + "1").parse::().unwrap())); + result.push(Token::Num( + (letter.to_string() + "1").parse::().unwrap(), + )); result.push(Token::RParen); result.push(Operator::token_from_op('*', |x, y| x * y, 10, true)); } - }, + } '/' | '*' | '%' | '^' | '!' => { drain_stack(&mut num_vec, &mut char_vec, &mut result); let operator_token: Token = OPERATORS.get(&letter).unwrap().clone(); result.push(operator_token); - last_char_is_op = true; + last_char_is_op = true; if letter == '!' { result.push(Token::Num(1.)); - last_char_is_op = false; + last_char_is_op = false; } - }, - '(' => { - if char_vec.len() > 0 { + } + '(' => { + if !char_vec.is_empty() { if let Some(res) = FUNCTIONS.get(&char_vec[..]) { result.push(res.clone()); } else { - return Err(CalcError::Syntax(format!("Unknown function '{}'", char_vec))) + return Err(CalcError::Syntax(format!( + "Unknown function '{}'", + char_vec + ))); } char_vec.clear(); } else { @@ -226,26 +234,19 @@ pub fn lexer(input: &str, prev_ans: f64) -> Result, CalcError> { } } - if let Some(x) = result.last() { - match x { - Token::RParen => { - result.push(OPERATORS.get(&'*').unwrap().clone()); - }, - _ => {} - }; + if let Some(Token::RParen) = result.last() { + result.push(OPERATORS.get(&'*').unwrap().clone()); } result.push(Token::LParen); - last_char_is_op = true; - }, + last_char_is_op = true; + } ')' => { drain_stack(&mut num_vec, &mut char_vec, &mut result); result.push(Token::RParen); - last_char_is_op = false; - }, - ' ' => {}, - _ => { - return Err(CalcError::Syntax(format!("Unexpected token: '{}'", letter))) + last_char_is_op = false; } + ' ' => {} + _ => return Err(CalcError::Syntax(format!("Unexpected token: '{}'", letter))), } } // println!("{:?}", result); @@ -266,7 +267,7 @@ fn drain_stack(num_vec: &mut String, char_vec: &mut String, result: &mut Vec f64 { if is_radian { - return x + x } else { x.to_radians() } diff --git a/src/main.rs b/src/main.rs index c3f3342..140150c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,26 +6,26 @@ /* imports */ // std use std::f64; -use std::path::PathBuf; use std::fs::create_dir_all; +use std::path::PathBuf; // modules -mod lex; -mod parse; mod error; mod format; +mod lex; +mod parse; mod readline; +use crate::error::{handler, CalcError}; +use crate::format::*; use crate::lex::*; use crate::parse::*; -use crate::error::{ CalcError, handler }; -use crate::format::*; use crate::readline::*; // extern crates -use rustyline::error::ReadlineError; -use clap::{Arg, App}; +use clap::{App, Arg}; +use directories::{ProjectDirs, UserDirs}; use lazy_static::lazy_static; -use directories::{ ProjectDirs, UserDirs }; +use rustyline::error::ReadlineError; /* end of imports */ @@ -33,7 +33,7 @@ struct Configuration { radian_mode: bool, fix: usize, base: usize, - input: String + input: String, } lazy_static! { @@ -41,7 +41,7 @@ lazy_static! { } fn main() { - if CONFIGURATION.input.len() > 0 { + if !CONFIGURATION.input.is_empty() { // command mode // let evaled = eval_math_expression(&CONFIGURATION.input[..], 0f64); match evaled { @@ -49,11 +49,11 @@ fn main() { Err(e) => { eprintln!("{}", handler(e)); std::process::exit(1); - }, + } }; } else { // REPL mode // - // create fancy readline + // create fancy readline let mut rl = create_readline(); // previous answer @@ -65,7 +65,7 @@ fn main() { let mut history_path = PathBuf::from(eva_data_dir); match create_dir_all(eva_data_dir) { Ok(_) => history_path.push("history.txt"), - Err(_) => history_path = PathBuf::from(UserDirs::new().unwrap().home_dir()), + Err(_) => history_path = PathBuf::from(UserDirs::new().unwrap().home_dir()), }; if rl.load_history(history_path.as_path()).is_err() { @@ -86,17 +86,15 @@ fn main() { } Err(e) => println!("{}", handler(e)), }; - }, + } Err(ReadlineError::Interrupted) => { println!("CTRL-C"); - break - }, - Err(ReadlineError::Eof) => { - break - }, + break; + } + Err(ReadlineError::Eof) => break, Err(err) => { println!("Error: {:?}", err); - break + break; } } } @@ -109,25 +107,33 @@ fn parse_arguments() -> Configuration { .version(env!("CARGO_PKG_VERSION")) .author(env!("CARGO_PKG_AUTHORS")) .about(env!("CARGO_PKG_DESCRIPTION")) - .arg(Arg::with_name("fix") - .short("f") - .long("fix") - .takes_value(true) - .value_name("FIX") - .help("set number of decimal places in the output")) - .arg(Arg::with_name("base") - .short("b") - .long("base") - .takes_value(true) - .value_name("RADIX") - .help("set the radix of calculation output (1 - 36)")) - .arg(Arg::with_name("INPUT") - .help("optional expression string to run eva in command mode") - .index(1)) - .arg(Arg::with_name("radian") - .short("r") - .long("radian") - .help("set eva to radian mode")) + .arg( + Arg::with_name("fix") + .short("f") + .long("fix") + .takes_value(true) + .value_name("FIX") + .help("set number of decimal places in the output"), + ) + .arg( + Arg::with_name("base") + .short("b") + .long("base") + .takes_value(true) + .value_name("RADIX") + .help("set the radix of calculation output (1 - 36)"), + ) + .arg( + Arg::with_name("INPUT") + .help("optional expression string to run eva in command mode") + .index(1), + ) + .arg( + Arg::with_name("radian") + .short("r") + .long("radian") + .help("set eva to radian mode"), + ) .get_matches(); let mut input = String::new(); @@ -136,29 +142,25 @@ fn parse_arguments() -> Configuration { }; Configuration { radian_mode: config.is_present("radian"), - fix: config.value_of("fix") - .unwrap_or("10") - .parse() - .unwrap(), - base: config.value_of("base") - .unwrap_or("10") - .parse() - .unwrap(), - input, + fix: config.value_of("fix").unwrap_or("10").parse().unwrap(), + base: config.value_of("base").unwrap_or("10").parse().unwrap(), + input, } } pub fn eval_math_expression(input: &str, prev_ans: f64) -> Result { let input = input.trim(); let input = input.replace(" ", ""); - if input.len() == 0 { - return Ok(0.) + if input.is_empty() { + return Ok(0.); } - let input = format::autobalance_parens(&input[..])?; - let lexed = lexer(&input[..], prev_ans)?; - let postfixed = to_postfix(lexed)?; - let evaled = eval_postfix(postfixed)?; - let evaled_fixed = format!("{:.*}", CONFIGURATION.fix, evaled).parse::().unwrap(); + let input = format::autobalance_parens(&input[..])?; + let lexed = lexer(&input[..], prev_ans)?; + let postfixed = to_postfix(lexed)?; + let evaled = eval_postfix(postfixed)?; + let evaled_fixed = format!("{:.*}", CONFIGURATION.fix, evaled) + .parse::() + .unwrap(); Ok(evaled_fixed) } diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 5c85172..aa8bd4b 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -2,8 +2,8 @@ * Refer to LICENCE for more information. * */ -use crate::lex::Token; use crate::error::CalcError; +use crate::lex::Token; pub fn to_postfix(tokens: Vec) -> Result, CalcError> { let mut postfixed: Vec = vec![]; @@ -12,7 +12,7 @@ pub fn to_postfix(tokens: Vec) -> Result, CalcError> { match token { Token::Num(_) => { postfixed.push(token); - }, + } Token::Function(_) => { op_stack.push(token); } @@ -34,14 +34,16 @@ pub fn to_postfix(tokens: Vec) -> Result, CalcError> { Token::Function(_) => { postfixed.push(op_stack.pop().unwrap()); } - _ => { unreachable!(); } + _ => { + unreachable!(); + } } } op_stack.push(token); - }, + } Token::LParen => { op_stack.push(token); - }, + } Token::RParen => { let mut push_until_paren: bool = false; while let Some(token) = op_stack.pop() { @@ -69,43 +71,35 @@ pub fn eval_postfix(postfixed: Vec) -> Result { match token { Token::Num(n) => { num_stack.push(n); - }, + } Token::Operator(op) => { if let Some(n2) = num_stack.pop() { if let Some(n1) = num_stack.pop() { num_stack.push(op.operate(n1, n2)?); } else { - return Err( - CalcError::Parser( - format!("Too many operators, Too little operands") - ) - ) + return Err(CalcError::Parser( + "Too many operators, Too little operands".to_string(), + )); } } else { - return Err( - CalcError::Parser( - format!("Too many operators, Too little operands") - ) - ) + return Err(CalcError::Parser( + "Too many operators, Too little operands".to_string(), + )); } - }, + } Token::Function(funct) => { if let Some(arg) = num_stack.pop() { num_stack.push(funct.apply(arg)?) } } - _ => { - unreachable!("wut") - } + _ => unreachable!("wut"), } } if num_stack.len() == 1 { Ok(num_stack.pop().unwrap()) } else { - return Err( - CalcError::Parser( - format!("Too many operators, Too little operands") - ) - ) + Err(CalcError::Parser( + "Too many operators, Too little operands".to_string(), + )) } } diff --git a/src/readline/mod.rs b/src/readline/mod.rs index e9d4b33..41cd742 100644 --- a/src/readline/mod.rs +++ b/src/readline/mod.rs @@ -1,11 +1,11 @@ -use std::borrow::Cow::{self,Owned}; +use std::borrow::Cow::{self, Owned}; +use rustyline::completion::{Completer, FilenameCompleter, Pair}; +use rustyline::config::{Builder, ColorMode, CompletionType, EditMode}; use rustyline::error::ReadlineError; -use rustyline::{ Editor, Context, Helper }; -use rustyline::config::{ Builder, ColorMode, EditMode, CompletionType }; -use rustyline::hint::{ Hinter, HistoryHinter }; -use rustyline::completion::{ FilenameCompleter, Completer, Pair }; use rustyline::highlight::Highlighter; +use rustyline::hint::{Hinter, HistoryHinter}; +use rustyline::{Context, Editor, Helper}; use regex::Regex; @@ -17,7 +17,7 @@ pub struct RLHelper { hinter: HistoryHinter, } -struct LineHighlighter { } +struct LineHighlighter {} impl Highlighter for LineHighlighter { fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> { Owned(format!("\x1b[90m{}\x1b[0m", hint)) @@ -28,14 +28,9 @@ impl Highlighter for LineHighlighter { Ok(_) => { let constants = ["e", "pi"]; let functions = [ - "sin" , "cos" , "tan" , - "csc" , "sec" , "cot" , - "sinh" , "cosh" , "tanh" , - "ln" , "log" , "sqrt" , - "ceil" , "floor" , "rad" , - "deg" , "abs" , "asin" , - "acos" , "atan" , "acsc" , - "asec" , "acot" + "sin", "cos", "tan", "csc", "sec", "cot", "sinh", "cosh", "tanh", "ln", "log", + "sqrt", "ceil", "floor", "rad", "deg", "abs", "asin", "acos", "atan", "acsc", + "asec", "acot", ]; let ops = Regex::new(r"(?P[\+-/\*%\^!])").unwrap(); let mut coloured: String = ops.replace_all(line, "\x1b[33m$o\x1b[0m").into(); @@ -46,14 +41,14 @@ impl Highlighter for LineHighlighter { for f in &functions { coloured = coloured.replace(f, &format!("\x1b[34m{}\x1b[0m", f)); } - Owned(coloured.into()) - }, - Err(_) => Owned(format!("\x1b[31m{}\x1b[0m", line)) + Owned(coloured) + } + Err(_) => Owned(format!("\x1b[31m{}\x1b[0m", line)), } } } -impl Highlighter for RLHelper { +impl Highlighter for RLHelper { fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> { self.highlighter.highlight_hint(hint) } @@ -69,11 +64,11 @@ impl Completer for RLHelper { line: &str, pos: usize, ctx: &Context<'_>, - ) -> Result<(usize, Vec), ReadlineError> { + ) -> Result<(usize, Vec), ReadlineError> { self.completer.complete(line, pos, ctx) } } - + impl Hinter for RLHelper { fn hint(&self, line: &str, a: usize, b: &Context) -> Option { self.hinter.hint(line, a, b) @@ -83,19 +78,20 @@ impl Hinter for RLHelper { impl Helper for RLHelper {} pub fn create_readline() -> Editor { - let config_builder = Builder::new(); - let config = config_builder.color_mode(ColorMode::Enabled) - .edit_mode(EditMode::Emacs) - .history_ignore_space(true) - .completion_type(CompletionType::Circular) - .max_history_size(1000) - .build(); - let mut rl = Editor::with_config(config); - let h = RLHelper { - completer: FilenameCompleter::new(), - highlighter: LineHighlighter {}, - hinter: HistoryHinter {} - }; - rl.set_helper(Some(h)); - return rl; + let config_builder = Builder::new(); + let config = config_builder + .color_mode(ColorMode::Enabled) + .edit_mode(EditMode::Emacs) + .history_ignore_space(true) + .completion_type(CompletionType::Circular) + .max_history_size(1000) + .build(); + let mut rl = Editor::with_config(config); + let h = RLHelper { + completer: FilenameCompleter::new(), + highlighter: LineHighlighter {}, + hinter: HistoryHinter {}, + }; + rl.set_helper(Some(h)); + rl } -- cgit v1.2.3