Skip to content

Instantly share code, notes, and snippets.

@kirjavascript
Created November 4, 2018 11:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kirjavascript/636805ddc9dd80c577623bcb6a261f7d to your computer and use it in GitHub Desktop.
Save kirjavascript/636805ddc9dd80c577623bcb6a261f7d to your computer and use it in GitHub Desktop.
#[derive(Debug, Clone, PartialEq)]
enum Token {
Op(char),
Num(f64),
}
fn prec(op: char) -> usize {
match op {
'*' | '/' => 3,
'+' | '-' => 2,
'(' => 1,
_ => panic!("unsupported operation"),
}
}
fn main() {
// let input = " 1.5 + 23 * 7 + (4 * 7)".to_string().replace(" ", "");
// let input = "1 + 2".to_string().replace(" ", "");
let input = &std::env::args().collect::<Vec<_>>()[1..].join("");
// parse to tokens
let mut tokens = vec![];
let mut num = "".to_owned();
for c in input.chars() {
match c {
'0'..='9' | '.' => {
num.push(c);
},
_ => {
if !num.is_empty() {
tokens.push(Token::Num(num.parse().expect("incorrect number format")));
num.clear();
}
tokens.push(Token::Op(c));
},
}
}
if !num.is_empty() {
tokens.push(Token::Num(num.parse().expect("incorrect number format")));
}
// convert to rpn
let mut postfix_list = Vec::new();
let mut opstack = Vec::new();
for token in tokens {
match token {
Token::Num(_) => {
postfix_list.push(token);
},
Token::Op(op) => match op {
'(' => {
opstack.push(op);
},
')' => {
let mut top = opstack.pop().expect("empty opstack");
while top != '(' {
postfix_list.push(Token::Op(top));
top = opstack.pop().expect("empty opstack");
}
},
_ => {
while !opstack.is_empty() &&
prec(*opstack.last().unwrap()) >= prec(op) {
postfix_list.push(Token::Op(opstack.pop().unwrap()));
}
opstack.push(op);
},
},
}
}
while !opstack.is_empty() {
postfix_list.push(Token::Op(opstack.pop().unwrap()));
}
// evaluate
let mut stack = Vec::new();
for token in postfix_list {
match token {
Token::Num(num) => {
stack.push(num);
},
Token::Op(op) => {
let (op1, op2) = (
stack.pop().unwrap(),
stack.pop().unwrap(),
);
let result = match op {
'+' => op1 + op2,
'-' => op1 - op2,
'/' => op1 / op2,
'*' => op1 * op2,
_ => panic!("unsupported operator"),
};
stack.push(result);
},
}
}
println!("{:#?}", stack.pop().expect("something fucked up"));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment