forked from bonsai/harakit
rpn(1): rewrote parser for the second time
This commit is contained in:
parent
4cb5e8e2b0
commit
fb2a164507
67
src/rpn.rs
67
src/rpn.rs
@ -67,7 +67,7 @@ enum CalcType {
|
||||
Floor,
|
||||
Modulo,
|
||||
Val(f64),
|
||||
Empty,
|
||||
Invalid,
|
||||
}
|
||||
|
||||
impl From<&str> for CalcType {
|
||||
@ -83,7 +83,7 @@ impl From<&str> for CalcType {
|
||||
_ => {
|
||||
match value.parse::<f64>() {
|
||||
Ok(x) => Val(x),
|
||||
Err(_) => Empty,
|
||||
Err(_) => Invalid,
|
||||
}
|
||||
},
|
||||
}
|
||||
@ -104,7 +104,7 @@ impl Display for CalcType {
|
||||
Val(x) => {
|
||||
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
|
||||
const PRECISION_MOD: f64 = 0.9 + f64::EPSILON * 100.0;
|
||||
|
||||
|
||||
fn eval(
|
||||
input: &str,
|
||||
initial_stack: VecDeque<f64>,
|
||||
@ -135,54 +136,30 @@ fn eval(
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
for tok in toks {
|
||||
let x: CalcType = match CalcType::from(tok) {
|
||||
Empty => {
|
||||
return Err(EvaluationError {
|
||||
message: format!("{}: Invalid token", tok),
|
||||
})
|
||||
},
|
||||
x => x,
|
||||
};
|
||||
|
||||
match x {
|
||||
while let Some(n) = toks.pop_back() {
|
||||
match n {
|
||||
Val(v) => stack.push_back(v),
|
||||
_ => ops.push_back(x),
|
||||
}
|
||||
}
|
||||
|
||||
for op in &ops {
|
||||
match op {
|
||||
Val(_) => {
|
||||
return Err(EvaluationError { message: format!(
|
||||
"{}: Unexpected value in the operator stack.",
|
||||
op,
|
||||
)});
|
||||
},
|
||||
_ => {
|
||||
|
||||
if stack.len() < 2 {
|
||||
Invalid => {
|
||||
return Err(EvaluationError {
|
||||
message: format!("{}: Unexpected operation.", op)
|
||||
message: format!("{}: Invalid token", n)
|
||||
})
|
||||
}
|
||||
|
||||
if stack.len() > ops.len() + 1 {
|
||||
return Err(
|
||||
EvaluationError { message: format!("Syntax error.")}
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
op => {
|
||||
ops.push_back(op);
|
||||
oper = true;
|
||||
|
||||
let (x, y) = (
|
||||
stack.pop_back().unwrap(),
|
||||
stack.pop_back().unwrap(),
|
||||
let vals = (
|
||||
stack.pop_back(),
|
||||
stack.pop_back(),
|
||||
);
|
||||
|
||||
if let (Some(x), Some(y)) = vals {
|
||||
match op {
|
||||
Add => stack.push_back(y + x),
|
||||
Subtract => stack.push_back(y - x),
|
||||
@ -193,6 +170,11 @@ fn eval(
|
||||
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
|
||||
.iter()
|
||||
.skip(1)
|
||||
.rev()
|
||||
.map(|x| x.to_owned())
|
||||
.collect::<Vec<String>>()
|
||||
.join(" ");
|
||||
|
Loading…
Reference in New Issue
Block a user