New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bools #2

Merged
merged 2 commits into from Feb 9, 2018
Jump to file or symbol
Failed to load files and symbols.
+80 −50
Diff settings

Always

Just for now

Copy path View file
@@ -1,8 +1,8 @@
use token::{Token, Opcode};
use token::{Token, Opcode, Type};
use runtime_error::RuntimeError;
pub fn eval(tokens: Vec<Token>) -> Result<isize, RuntimeError> {
pub fn eval(tokens: Vec<Token>) -> Result<Type, RuntimeError> {
// shift reduce parsing
// two operations
@@ -79,10 +79,10 @@ fn reduce<'a>(stack: &mut Vec<Token>) {
fn reduce_addition(stack: &mut Vec<Token>) -> Result<Token, RuntimeError> {
let operands = unwrap_operand_tokens(stack);
match operands {
Ok(operand_vec) => Ok(Token::Operand(
Ok(operand_vec) => Ok(Token::Operand(Type::Integer(
operand_vec
.iter()
.fold(0, |sum, value| sum + value))),
.fold(0, |sum, value| sum + value)))),
Err(_) => Err(RuntimeError{})
}
}
@@ -93,10 +93,10 @@ fn reduce_subtraction(stack: &mut Vec<Token>) -> Result<Token, RuntimeError> {
Ok(mut operand_vec) =>{
let initial_positive_option = operand_vec.pop();
if let Some(initial_positive) = initial_positive_option {
Ok(Token::Operand(
Ok(Token::Operand(Type::Integer(
operand_vec
.iter()
.fold(initial_positive, |sum, value| sum - value)))
.fold(initial_positive, |sum, value| sum - value))))
} else {
Err(RuntimeError{})
}
@@ -108,10 +108,10 @@ fn reduce_subtraction(stack: &mut Vec<Token>) -> Result<Token, RuntimeError> {
fn reduce_multiplication(stack: &mut Vec<Token>) -> Result<Token, RuntimeError> {
let operands = unwrap_operand_tokens(stack);
match operands {
Ok(operand_vec) => Ok(Token::Operand(
Ok(operand_vec) => Ok(Token::Operand(Type::Integer(
operand_vec
.iter()
.fold(1, |prod, value| prod * value))),
.fold(1, |prod, value| prod * value)))),
Err(_) => Err(RuntimeError{})
}
}
@@ -122,10 +122,10 @@ fn reduce_division(stack: &mut Vec<Token>) -> Result<Token, RuntimeError> {
Ok(mut operand_vec) =>{
let initial_numerator_option = operand_vec.pop();
if let Some(initial_numerator) = initial_numerator_option {
Ok(Token::Operand(
Ok(Token::Operand(Type::Integer(
operand_vec
.iter()
.fold(initial_numerator, |numerator, value| numerator / value)))
.fold(initial_numerator, |numerator, value| numerator / value))))
} else {
Err(RuntimeError{})
}
@@ -136,7 +136,7 @@ fn reduce_division(stack: &mut Vec<Token>) -> Result<Token, RuntimeError> {
fn unwrap_operand_tokens(tokens: &Vec<Token>) -> Result<Vec<isize>, RuntimeError> {
let result : Vec<isize> = tokens.iter().filter_map(|t| match *t {
Token::Operand(val) => Some(val),
Token::Operand(Type::Integer(val)) => Some(val),
_ => None,
})
.collect();
@@ -150,11 +150,11 @@ fn unwrap_operand_tokens(tokens: &Vec<Token>) -> Result<Vec<isize>, RuntimeError
#[test]
fn it_adds_arrays() {
let mut array = vec![
Token::Operand(1),
Token::Operand(2),
Token::Operand(3)
Token::Operand(Type::Integer(1)),
Token::Operand(Type::Integer(2)),
Token::Operand(Type::Integer(3))
];
let expected = Token::Operand(6);
let expected = Token::Operand(Type::Integer(6));
let actual = reduce_addition(&mut array).expect("Unexpected addition failure");
assert!(expected == actual);
}
@@ -164,11 +164,11 @@ fn it_evals_simple_stacks() {
let tokens = vec![
Token::LeftParen,
Token::Operator(Opcode::Add),
Token::Operand(2),
Token::Operand(3),
Token::Operand(Type::Integer(2)),
Token::Operand(Type::Integer(3)),
Token::RightParen
];
let expected = 5;
let expected = Type::Integer(5);
let actual = eval(tokens).expect("Failed to eval valid simple addition");
assert!(expected == actual, "Eval failed on simple addition");
}
@@ -178,11 +178,11 @@ fn it_evals_simple_stacks_with_subtract() {
let tokens = vec![
Token::LeftParen,
Token::Operator(Opcode::Subtract),
Token::Operand(2),
Token::Operand(3),
Token::Operand(Type::Integer(2)),
Token::Operand(Type::Integer(3)),
Token::RightParen
];
let expected = -1;
let expected = Type::Integer(-1);
let actual = eval(tokens).expect("Failed to eval valid simple addition");
assert!(expected == actual, "Eval failed on simple addition");
}
@@ -192,16 +192,16 @@ fn it_handles_nested_addition() {
let tokens = vec![
Token::LeftParen,
Token::Operator(Opcode::Add),
Token::Operand(2),
Token::Operand(3),
Token::Operand(Type::Integer(2)),
Token::Operand(Type::Integer(3)),
Token::LeftParen,
Token::Operator(Opcode::Add),
Token::Operand(1),
Token::Operand(2),
Token::Operand(Type::Integer(1)),
Token::Operand(Type::Integer(2)),
Token::RightParen,
Token::RightParen
];
let expected = 8;
let expected = Type::Integer(8);
let actual = eval(tokens).expect("Failed to eval nested addition");
assert!(expected == actual, "Eval incorrect on nested addition");
}
@@ -211,16 +211,16 @@ fn it_handles_nested_addition_with_subrtraction() {
let tokens = vec![
Token::LeftParen,
Token::Operator(Opcode::Add),
Token::Operand(2),
Token::Operand(3),
Token::Operand(Type::Integer(2)),
Token::Operand(Type::Integer(3)),
Token::LeftParen,
Token::Operator(Opcode::Subtract),
Token::Operand(1),
Token::Operand(2),
Token::Operand(Type::Integer(1)),
Token::Operand(Type::Integer(2)),
Token::RightParen,
Token::RightParen
];
let expected = 4;
let expected = Type::Integer(4);
let actual = eval(tokens).expect("Failed to eval nested addition");
assert!(expected == actual, "Eval incorrect on nested addition with subraction");
}
@@ -230,27 +230,27 @@ fn it_handles_nested_nonses_with_all_ops() {
let tokens = vec![
Token::LeftParen,
Token::Operator(Opcode::Add),
Token::Operand(2),
Token::Operand(3),
Token::Operand(Type::Integer(2)),
Token::Operand(Type::Integer(3)),
Token::LeftParen,
Token::Operator(Opcode::Subtract),
Token::Operand(1),
Token::Operand(2),
Token::Operand(Type::Integer(1)),
Token::Operand(Type::Integer(2)),
Token::RightParen,
Token::LeftParen,
Token::Operator(Opcode::Multiply),
Token::LeftParen,
Token::Operator(Opcode::Divide),
Token::Operand(4),
Token::Operand(2),
Token::Operand(Type::Integer(4)),
Token::Operand(Type::Integer(2)),
Token::RightParen,
Token::Operand(3),
Token::Operand(Type::Integer(3)),
Token::RightParen,
Token::RightParen
];
// (+ 2 3 (- 1 2)(* (/ 4 2) 3)) == 10
let expected = 10;
let expected = Type::Integer(10);
let actual = eval(tokens).expect("Failed to eval complex expression");
assert!(expected == actual, "failed to get correct result for complex expression");
}
Copy path View file
@@ -1,6 +1,6 @@
use nom;
use token::{Token,Opcode};
use token::{Token,Opcode,Type};
use tokenization_error::TokenizationError;
use std::str;
@@ -32,15 +32,31 @@ named!(division_sign<&[u8], Token>,
do_parse!(tag!("/") >> (Token::Operator(Opcode::Divide)))
);
named!(operand<&[u8], Token>,
named!(bool_literal_true<&[u8], Token>,
do_parse!(alt!(tag!("#t") | tag!("true")) >> (Token::Operand(Type::Bool(true))))
);
named!(bool_literal_false<&[u8], Token>,
do_parse!(alt!(tag!("#f") | tag!("false")) >> (Token::Operand(Type::Bool(false))))
);
named!(integer_literal<&[u8], Token>,
map!(nom::digit, parse_string_to_operand)
);
named!(operand<&[u8], Token>,
alt!(
bool_literal_true |
bool_literal_false |
integer_literal
)
);
fn parse_string_to_operand(slice: &[u8]) -> Token {
// I believe `unwrap()` is OK because the nom macro digit! shouldn't match anything
// that doesn't parse as an int.
let string = str::from_utf8(slice).unwrap();
Token::Operand(string.parse::<isize>().unwrap())
Token::Operand(Type::Integer(string.parse::<isize>().unwrap()))
}
named!(single_token<&[u8], Token>,
@@ -73,8 +89,8 @@ fn test_several_tokens() {
let expected = vec![
Token::LeftParen,
Token::Operator(Opcode::Add),
Token::Operand(3),
Token::Operand(4),
Token::Operand(Type::Integer(3)),
Token::Operand(Type::Integer(4)),
Token::RightParen
];
@@ -88,8 +104,8 @@ fn test_several_tokens_with_long_numeric_token() {
let expected = vec![
Token::LeftParen,
Token::Operator(Opcode::Add),
Token::Operand(3),
Token::Operand(40_424),
Token::Operand(Type::Integer(3)),
Token::Operand(Type::Integer(40_424)),
Token::RightParen
];
@@ -104,7 +120,7 @@ fn test_single_token() {
#[test]
fn test_single_numeric_token() {
assert!(single_token(&b"4"[..]).to_result().expect("failed to parse token (") == Token::Operand(4isize));
assert!(single_token(&b"4"[..]).to_result().expect("failed to parse token (") == Token::Operand(Type::Integer(4isize)));
}
#[test]
@@ -139,5 +155,5 @@ fn division_sign_parser() {
#[test]
fn operand_parser() {
assert!(operand(&b"123"[..]).to_result().expect("failed to parse numeric operand") == Token::Operand(123isize));
assert!(operand(&b"123"[..]).to_result().expect("failed to parse numeric operand") == Token::Operand(Type::Integer(123isize)));
}
Copy path View file
@@ -5,14 +5,19 @@ pub enum Token {
LeftParen,
RightParen,
Operator(Opcode),
Operand(isize)
Operand(Type),
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Opcode {
Add, Subtract, Multiply, Divide,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Type {
Bool(bool), Integer(isize)
}
impl fmt::Display for Opcode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
@@ -30,7 +35,16 @@ impl fmt::Display for Token {
Token::LeftParen => write!(f, "Token:LeftParen"),
Token::RightParen => write!(f, "Token:RightParen"),
Token::Operator(code) => write!(f, "Token:Operator:{}", code),
Token::Operand(value) => write!(f, "Token:Operand:{}", value),
Token::Operand(operand) => write!(f, "Token:Operand:{}", operand),
}
}
}
impl fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Type::Bool(b) => write!(f, "Bool:{}",b),
Type::Integer(int) => write!(f, "Integer:{}",int),
}
}
}
ProTip! Use n and p to navigate between commits in a pull request.