Skip to content

Instantly share code, notes, and snippets.

@JEG2
Created August 15, 2014 18:53
Show Gist options
  • Save JEG2/f57212afa30bd7a48d7c to your computer and use it in GitHub Desktop.
Save JEG2/f57212afa30bd7a48d7c to your computer and use it in GitHub Desktop.
An early stab at writing some Rust. I have questions.
use std::fmt;
use std::os;
struct Stack {
numbers: Vec<f64>
}
impl Stack {
fn new() -> Stack {
Stack{numbers: vec![]}
}
fn is_empty(&self) -> bool {
self.numbers.is_empty()
}
fn push(&mut self, number: f64) {
self.numbers.push(number);
}
fn result(&self) -> f64 {
*self.numbers.last().expect("Stack empty.")
}
fn add(&mut self) { self._do_binary_operation(|l, r| l + r); }
fn subtract(&mut self) { self._do_binary_operation(|l, r| l - r); }
fn multiply(&mut self) { self._do_binary_operation(|l, r| l * r); }
fn divide(&mut self) { self._do_binary_operation(|l, r| l / r); }
fn _do_binary_operation(&mut self, operation: |f64, f64| -> f64) {
let r = self.numbers.pop().expect("Stack underflow.");
let l = self.numbers.pop().expect("Stack underflow.");
self.numbers.push(operation(l, r));
}
}
impl fmt::Show for Stack {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut s = String::new();
let mut i = self.numbers.len();
for number in self.numbers.iter() {
i -= 1;
s = s.add(&format!("{}: {}\n", i, number));
}
s.pop_char();
write!(f, "{}", s)
}
}
struct Tokenizer<'a> {
tokens: Vec<&'a str>,
i: uint
}
impl<'a> Tokenizer<'a> {
fn new(expression: &str) -> Tokenizer {
Tokenizer{
tokens: expression.split(|c: char| c.is_whitespace()).collect(),
i: 0
}
}
fn has_next_token(&self) -> bool {
self.i < self.tokens.len()
}
fn next_token(&mut self) -> &str {
if !self.has_next_token() { fail!("Tokens exhausted.") }
let token = self.tokens[self.i];
self.i += 1;
token
}
}
struct RPNCalculator<'a> {
stack: Stack,
tokens: Tokenizer<'a>
}
impl<'a> RPNCalculator<'a> {
fn new(stack: Stack, tokens: Tokenizer) -> RPNCalculator {
RPNCalculator{stack: stack, tokens: tokens}
}
fn calculate(&mut self) -> f64 {
while self.tokens.has_next_token() {
let token = self.tokens.next_token();
if !self.stack.is_empty() {
println!("{}", self.stack);
}
println!("T: {}\n", token);
match token {
"+" => { self.stack.add(); }
"-" => { self.stack.subtract(); }
"*" => { self.stack.multiply(); }
"/" => { self.stack.divide(); }
n => { self.stack.push(from_str(n).expect("Not a number.")); }
}
}
if !self.stack.is_empty() {
println!("{}\n", self.stack);
}
self.stack.result()
}
}
fn main() {
let expression = os::args();
let stack = Stack::new();
let tokenizer = Tokenizer::new(expression[1].as_slice());
let mut calculator = RPNCalculator::new(stack, tokenizer);
println!("{}", calculator.calculate());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment