1
0
forked from bonsai/harakit

rpn(1): rewrote parser for the second time

This commit is contained in:
Emma Tebibyte 2024-02-02 15:35:36 -07:00
parent 4cb5e8e2b0
commit fb2a164507
Signed by untrusted user: emma
GPG Key ID: 06FA419A1698C270

View File

@ -67,7 +67,7 @@ enum CalcType {
Floor, Floor,
Modulo, Modulo,
Val(f64), Val(f64),
Empty, Invalid,
} }
impl From<&str> for CalcType { impl From<&str> for CalcType {
@ -83,7 +83,7 @@ impl From<&str> for CalcType {
_ => { _ => {
match value.parse::<f64>() { match value.parse::<f64>() {
Ok(x) => Val(x), Ok(x) => Val(x),
Err(_) => Empty, Err(_) => Invalid,
} }
}, },
} }
@ -104,7 +104,7 @@ impl Display for CalcType {
Val(x) => { Val(x) => {
y = x.to_string(); &y y = x.to_string(); &y
}, },
Empty => "", Invalid => "",
}) })
} }
} }
@ -122,6 +122,7 @@ impl Display for EvaluationError {
// repeating and it seems this can give it to me // repeating and it seems this can give it to me
const PRECISION_MOD: f64 = 0.9 + f64::EPSILON * 100.0; const PRECISION_MOD: f64 = 0.9 + f64::EPSILON * 100.0;
fn eval( fn eval(
input: &str, input: &str,
initial_stack: VecDeque<f64>, initial_stack: VecDeque<f64>,
@ -135,64 +136,45 @@ fn eval(
} }
// Split the input into tokens. // Split the input into tokens.
let toks = input.split(' ').collect::<Vec<&str>>(); let mut toks: VecDeque<CalcType> = input
.split(' ')
.map(|t| CalcType::from(t))
.collect();
let mut ops: VecDeque<CalcType> = VecDeque::new(); let mut ops: VecDeque<CalcType> = VecDeque::new();
for tok in toks { while let Some(n) = toks.pop_back() {
let x: CalcType = match CalcType::from(tok) { match n {
Empty => { Val(v) => stack.push_back(v),
Invalid => {
return Err(EvaluationError { return Err(EvaluationError {
message: format!("{}: Invalid token", tok), message: format!("{}: Invalid token", n)
}) })
}, },
x => x, op => {
}; ops.push_back(op);
oper = true;
match x { let vals = (
Val(v) => stack.push_back(v), stack.pop_back(),
_ => ops.push_back(x), stack.pop_back(),
} );
}
for op in &ops { if let (Some(x), Some(y)) = vals {
match op { match op {
Val(_) => { Add => stack.push_back(y + x),
return Err(EvaluationError { message: format!( Subtract => stack.push_back(y - x),
"{}: Unexpected value in the operator stack.", Multiply => stack.push_back(y * x),
op, Divide => stack.push_back(y / x),
)}); Power => stack.push_back(x.powf(y)),
}, Floor => stack.push_back((y / x).floor()),
_ => { Modulo => stack.push_back(y % x),
_ => {},
if stack.len() < 2 { };
} else {
return Err(EvaluationError { return Err(EvaluationError {
message: format!("{}: Unexpected operation.", op) message: format!("{}: Unexpected operation.", op)
}) })
} }
if stack.len() > ops.len() + 1 {
return Err(
EvaluationError { message: format!("Syntax error.")}
);
}
oper = true;
let (x, y) = (
stack.pop_back().unwrap(),
stack.pop_back().unwrap(),
);
match op {
Add => stack.push_back(y + x),
Subtract => stack.push_back(y - x),
Multiply => stack.push_back(y * x),
Divide => stack.push_back(y / x),
Power => stack.push_back(x.powf(y)),
Floor => stack.push_back((y / x).floor()),
Modulo => stack.push_back(y % x),
_ => {},
};
}, },
}; };
} }
@ -240,6 +222,7 @@ fn main() -> ExitCode {
let input = argv let input = argv
.iter() .iter()
.skip(1) .skip(1)
.rev()
.map(|x| x.to_owned()) .map(|x| x.to_owned())
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(" "); .join(" ");