X-Git-Url: https://harishankar.org/repos/?p=evpf.git;a=blobdiff_plain;f=src%2Fmain.rs;h=2154ba56b87f1926be18214671d33833f0652a84;hp=c911ca230dd8ccd5191f0a585dbd9fa2881fef0e;hb=ebba3951aa13d2668bc684680f557b8cbbda8b20;hpb=8c424fbdf4baf3e27f63b2526def89ddf4ac1b83 diff --git a/src/main.rs b/src/main.rs index c911ca2..2154ba5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,28 @@ use std::io; use std::io::Write; use regex::Regex; +use ansi_term::Colour; +use ansi_term::Style; +use std::env; +const ILLEGAL_EXP : &'static str = "Illegal Expression"; +const ERR_PARSING_NOT_MATCH : &'static str = "Error parsing expression! \ + Must be a number or operator (+,-,* or /)"; +const ERR_POSTFIX_INCOMPLETE : &'static str = "Postfix expression incomplete!"; +const ERR_FLUSHING : &'static str = "Error flushing!"; +const ERR_READING_LINE : &'static str = "Error reading line!"; +const HELP_TEXT : [&str ; 4] = + ["Type an expression in postfix style to evaluate.", + "Example: 4 5 + 12 -", + "Supported operators: +, -, *, /", + "Type q, Q to quit" + ]; + +const RESULT : &'static str = "Result"; +const ERROR : &'static str = "Error"; +const ERROR_HELP : &'static str = "Type ? or h or H for help"; + +// Describe an operator - one of add, subtract, multiply or divide enum Operator { ADD, SUB, @@ -21,13 +42,13 @@ fn get_result (t : &mut Vec, op : Operator) -> Result { // if nothing - panic with error let n1 = t.pop (); if n1.is_none () { - return Err ("Illegal expression".to_string()); + return Err (ILLEGAL_EXP.to_string()); } // pop the stack for the first operand // if nothing - panic with error let n2 = t.pop (); if n2.is_none () { - return Err ("Illegal expression!".to_string()); + return Err (ILLEGAL_EXP.to_string()); } let num1 = n1.unwrap().value; @@ -97,8 +118,7 @@ fn evaluate (expr : &str, match_num : ®ex::Regex) -> Result { } // if word doesn't match either operator or number then panic. else { - return Err ("Error parsing expression! \ - Must be a number or operator (+,-,* or /)".to_string()); + return Err (ERR_PARSING_NOT_MATCH.to_string()); } } } @@ -106,7 +126,7 @@ fn evaluate (expr : &str, match_num : ®ex::Regex) -> Result { if ops.len () > 1 { // if the stack has more than one value, it means that the postfix // expression is not complete - so display the stack status - return Err ("Postfix expression incomplete!".to_string()); + return Err (ERR_POSTFIX_INCOMPLETE.to_string()); } else { // stack has only one item which is the result so display it let res = ops[0].value; @@ -115,42 +135,86 @@ fn evaluate (expr : &str, match_num : ®ex::Regex) -> Result { } fn main() { - // get a line from input and evaluate it - let mut expr = String::new (); + + let args : Vec = env::args().collect (); // regular expression to match a number let match_num = Regex::new (r"^\d+?\.*?\d*?$").unwrap (); - // loop until a blank line is received - loop { - expr.clear (); - print!("evpf>"); - io::stdout().flush ().expect ("Error flushing!"); - // read a line of text - io::stdin().read_line (&mut expr).expect ("Error reading line!"); - // trim the text - let expr = expr.trim (); - - if expr == "q" || expr == "Q" { - // quit if the expression is q or Qs - break; - } else if expr == "?" || expr == "h" || expr == "H" { - // display help text - println! ("Type an expression in postfix style to evaluate."); - println! ("Example: 4 5 + 12 -"); - println! ("Supported operators: +, -, *, /"); - println! ("Type q, Q to quit"); - continue; - } else if expr == "" { - // continue without proceeding - continue; + + if args.len () > 1 { + // if arguments are provided run in command line mode - i.e. print the + // result and exit + let mut expr = String::new (); + let mut i = 0; + // create the expression string to evaluate + for arg in args.iter() { + if i > 0 { + expr.push_str (&arg); + expr.push_str (" "); + } + i += 1; } - + // evaluate the result let res = evaluate (&expr, &match_num); + // if Result is OK then print the result in green if res.is_ok () { - println! ("Result: {}", res.unwrap()); - } - else { - eprintln! ("Error: {}", res.unwrap_err()); - eprintln! ("Type ? or h or H for help"); + let restxt = format! ("{}: {}", RESULT, + res.unwrap()); + println! ("{}", Colour::Green.paint (restxt)); + } else { + // print the error in purple + let errtxt = format! ("{}: {}", ERROR, + res.unwrap_err()); + eprintln! ("{}", Colour::Purple.paint (errtxt)); + } + + } else { + // if arguments are not provided run in interactive mode - + // display a prompt and get the expression + // repeat until the user quits + + // get a line from input and evaluate it + let mut expr = String::new (); + + // loop until a blank line is received + loop { + expr.clear (); + print!("{}", Style::new().bold().paint("evpf>")); + io::stdout().flush ().expect (ERR_FLUSHING); + // read a line of text + io::stdin().read_line (&mut expr).expect (ERR_READING_LINE); + // trim the text + let expr = expr.trim (); + + if expr == "q" || expr == "Q" { + // quit if the expression is q or Qs + break; + } else if expr == "?" || expr == "h" || expr == "H" { + // display help text + for text in HELP_TEXT.iter() { + println! ("{}", Colour::Cyan.paint(*text)); + } + + continue; + } else if expr == "" { + // continue without proceeding + continue; + } + + // Evaluate result + let res = evaluate (&expr, &match_num); + + // if Result is OK then print the result in green + if res.is_ok () { + let restxt = format! ("{}: {}", RESULT, + res.unwrap()); + println! ("{}", Colour::Green.paint (restxt)); + } else { + // print the error in purple + let errtxt = format! ("{}: {}", ERROR, + res.unwrap_err()); + eprintln! ("{}", Colour::Purple.paint (errtxt)); + eprintln! ("{}", Colour::Purple.paint (ERROR_HELP)); + } } } }