Basic evaluator functionality

Interpreter now works for simple arithmetic expressions
This commit is contained in:
greg 2015-12-30 20:48:59 -08:00
parent 1c23329656
commit 819fb3f58f
2 changed files with 64 additions and 10 deletions

View File

@ -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() {
self.ast.reduce();
}
format!("{}", self.ast) struct EvaluatorError {
err: String
}
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_full(ast: AST) -> EvaluatorResult<AST> {
let mut ast = ast;
while ast.can_reduce() {
ast = try!(reduce_step(ast));
} }
fn reduce(&mut self) { 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()
} }

View File

@ -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)
}
} }
} }