Basic evaluator functionality
Interpreter now works for simple arithmetic expressions
This commit is contained in:
parent
1c23329656
commit
819fb3f58f
@ -4,27 +4,77 @@ struct Evaluator {
|
|||||||
ast: AST
|
ast: AST
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Evaluator {
|
pub type EvaluatorResult<T> = Result<T, EvaluatorError>;
|
||||||
pub fn run(&mut self) -> String {
|
|
||||||
while self.ast.can_reduce() {
|
struct EvaluatorError {
|
||||||
self.ast.reduce();
|
err: String
|
||||||
}
|
}
|
||||||
|
|
||||||
format!("{}", self.ast)
|
impl Evaluator {
|
||||||
|
pub fn run(self) -> String {
|
||||||
|
match reduce_full(self.ast) {
|
||||||
|
Err(e) => format!("{}", e.err),
|
||||||
|
Ok(ast) => format!("{}", ast)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AST {
|
impl AST {
|
||||||
fn can_reduce(&self) -> bool {
|
fn can_reduce(&self) -> bool {
|
||||||
false
|
use parser::AST::*;
|
||||||
|
match self {
|
||||||
|
&Number(_) => false,
|
||||||
|
&Name(_) => false,
|
||||||
|
_ => true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reduce(&mut self) {
|
fn reduce_full(ast: AST) -> EvaluatorResult<AST> {
|
||||||
|
let mut ast = ast;
|
||||||
|
while ast.can_reduce() {
|
||||||
|
ast = try!(reduce_step(ast));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ast)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reduce_step(ast: AST) -> EvaluatorResult<AST> {
|
||||||
|
use parser::AST::*;
|
||||||
|
match ast {
|
||||||
|
BinOp(left, op, right) => {
|
||||||
|
let left = try!(reduce_full(*left));
|
||||||
|
let op = try!(reduce_full(*op));
|
||||||
|
let right = try!(reduce_full(*right));
|
||||||
|
match (left, op, right) {
|
||||||
|
(Number(l), Name(op), Number(r)) => {
|
||||||
|
match &op[..] {
|
||||||
|
"+" => Ok(Number(l + r)),
|
||||||
|
"-" => Ok(Number(l - r)),
|
||||||
|
"*" => Ok(Number(l * r)),
|
||||||
|
"/" => {
|
||||||
|
if r == 0.0 {
|
||||||
|
Err(EvaluatorError { err: format!("Divide by zero") })
|
||||||
|
} else {
|
||||||
|
Ok(Number(l / r))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err(EvaluatorError { err: format!("Bad BinOp operator") })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err(EvaluatorError {
|
||||||
|
err: format!("Bad arguments for BinOp")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Number(_) => Ok(ast),
|
||||||
|
Name(_) => Ok(ast),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn evaluate(ast: AST) -> String {
|
pub fn evaluate(ast: AST) -> String {
|
||||||
let mut ev = Evaluator { ast: ast };
|
let ev = Evaluator { ast: ast };
|
||||||
ev.run()
|
ev.run()
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,11 @@ pub enum AST {
|
|||||||
|
|
||||||
impl fmt::Display for AST {
|
impl fmt::Display for AST {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}", "GENERIC DISPLAY")
|
match self {
|
||||||
|
&AST::Number(ref n) => write!(f, "{}", n),
|
||||||
|
&AST::Name(ref s) => write!(f, "{}", s),
|
||||||
|
astnode => write!(f, "UNEXPANDED AST NODE: {:?}", astnode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user