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,54 +136,30 @@ 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 => {
return Err(EvaluationError {
message: format!("{}: Invalid token", tok),
})
},
x => x,
};
match x {
Val(v) => stack.push_back(v), Val(v) => stack.push_back(v),
_ => ops.push_back(x), Invalid => {
}
}
for op in &ops {
match op {
Val(_) => {
return Err(EvaluationError { message: format!(
"{}: Unexpected value in the operator stack.",
op,
)});
},
_ => {
if stack.len() < 2 {
return Err(EvaluationError { return Err(EvaluationError {
message: format!("{}: Unexpected operation.", op) message: format!("{}: Invalid token", n)
}) })
} },
op => {
if stack.len() > ops.len() + 1 { ops.push_back(op);
return Err(
EvaluationError { message: format!("Syntax error.")}
);
}
oper = true; oper = true;
let (x, y) = ( let vals = (
stack.pop_back().unwrap(), stack.pop_back(),
stack.pop_back().unwrap(), stack.pop_back(),
); );
if let (Some(x), Some(y)) = vals {
match op { match op {
Add => stack.push_back(y + x), Add => stack.push_back(y + x),
Subtract => stack.push_back(y - x), Subtract => stack.push_back(y - x),
@ -193,6 +170,11 @@ fn eval(
Modulo => stack.push_back(y % x), Modulo => stack.push_back(y % x),
_ => {}, _ => {},
}; };
} else {
return Err(EvaluationError {
message: format!("{}: Unexpected operation.", op)
})
}
}, },
}; };
} }
@ -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(" ");