Anonymous user
Arithmetic evaluation: Difference between revisions
Formatting had broken something
(Rust implementation) |
(Formatting had broken something) |
||
Line 5,062:
=={{header|Rust}}==
<lang rust>//! Simple calculator parser and evaluator
/// Binary operator
Line 5,069 ⟶ 5,070:
Substract,
Multiply,
Divide
}
Line 5,077 ⟶ 5,078:
Value(f64),
SubNode(Box<Node>),
Binary(Operator, Box<Node>,
}
/// parse a string into a node
pub fn parse(txt
let chars = txt.chars().filter(|c| *c != ' ').collect();
parse_expression(&chars, 0).map(|(_,
}
/// parse an expression into a node, keeping track of the position in the character vector
fn parse_expression(chars: &Vec<char>, pos: usize) -> Option<(usize,
match parse_start(chars, pos) {
Some((new_pos, first)) =>
if let Some((new_pos3,
}▼
None => Some((new_pos,first)),
}
None => None,
}
Line 5,105 ⟶ 5,109:
fn combine(op: Operator, first: Node, second: Node) -> Node {
match second {
Node::Binary(op2,
} else {▼
▲ Node::Binary(op2, Box::new(combine(op, first, *v21)), v22)
▲ } else {
},▼
▲ Node::Binary(op, Box::new(first), Box::new(Node::Binary(op2, v21, v22)))
▲ }
▲ }
▲ _ => Node::Binary(op, Box::new(first), Box::new(second)),
}
}
Line 5,118 ⟶ 5,120:
/// a precedence rank for operators
fn precedence(op: &Operator) -> usize {
match op
Operator::Multiply | Operator::Divide => 2,
_ => 1
}
}
/// try to parse from the start of an expression (either a parenthesis or a value)
fn parse_start(chars: &Vec<char>, pos: usize) -> Option<(usize,
match start_parenthesis(chars, pos)
Some (new_pos) => {
let r = parse_expression(chars, new_pos);
end_parenthesis(chars, r)
},
None => parse_value(chars, pos),
}
Line 5,136 ⟶ 5,138:
/// match a starting parentheseis
fn start_parenthesis(chars: &Vec<char>, pos: usize) -> Option<usize>
if pos
Some(pos
} else {
None
Line 5,145 ⟶ 5,147:
/// match an end parenthesis, if successful will create a sub node contained the wrapped expression
fn end_parenthesis(chars: &Vec<char>, wrapped
match wrapped {
Some((pos, node)) => if pos<chars.len() && chars[pos] == ')' {
} else {
None
},
▲ }
None => None,
}
Line 5,159:
/// parse a value: an decimal with an optional minus sign
fn parse_value(chars: &Vec<char>, pos: usize) -> Option<(usize,
let mut new_pos = pos;
if new_pos
new_pos = new_pos
}
while new_pos
{▼
}
if new_pos
if let Ok(v) = dbg!(chars[pos..new_pos].iter().collect::<String>()).parse() {
Some((new_pos,
} else {
None
Line 5,182 ⟶ 5,180:
/// parse an operator
fn parse_operator(chars: &Vec<char>, pos: usize) -> Option<(usize,
if pos
let ops_with_char = vec!
for (ch,op) in ops_with_char
];▼
if chars[pos] == ch {
return Some((pos
}
}
}
None
}
/// eval a string
pub fn eval(txt
match parse(txt) {
Some(t) => eval_term(&t),
None => panic!("Cannot parse {}",
}
}
Line 5,213 ⟶ 5,206:
Node::Value(v) => *v,
Node::SubNode(t) => eval_term(t),
Node::Binary(Operator::Add,
Node::Binary(Operator::Substract,
Node::Binary(Operator::Multiply,
Node::Binary(Operator::Divide,
}
}
Line 5,225 ⟶ 5,218:
#[test]
fn test_eval()
assert_eq!(2.0,
assert_eq!(4.0,
assert_eq!(11.0
assert_eq!(2.0, eval("2*3-4"));
assert_eq!(3.0, eval("1+2*3-4"));
assert_eq!(89.0
assert_eq!(14.0, eval("2 * (3 -1) + 2 * 5"));
assert_eq!(7000.0, eval("2 * (3 + (4 * 5 + (6 * 7) * 8) - 9) * 10"));
assert_eq!(-9.0
assert_eq!(1.5, eval("1 - 5 * 2 / 20 + 1"));
assert_eq!(3.5, eval("2 * (3 + ((5) / (7 - 11)))"));
}
}
|