forked from bonsai/harakit
rpn(1): rewrote parser for the second time
This commit is contained in:
parent
4cb5e8e2b0
commit
fb2a164507
83
src/rpn.rs
83
src/rpn.rs
@ -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(" ");
|
||||||
|
Loading…
Reference in New Issue
Block a user