1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use std::fmt;
use std::io::Read;
use std::path::Path;
use std::fs::File;
use super::Instruction;
pub use self::error::Error;
#[derive(Debug)]
pub struct Program {
asl: Vec<Instruction>,
}
impl Program {
pub fn parse(source: &str) -> Result<Program, Error> {
let mut asl = Vec::new();
let mut count = 0usize;
let mut stack = Vec::new();
for c in source.chars() {
let instruction = match c {
'>' => Instruction::IncPtr,
'<' => Instruction::DecPtr,
'+' => Instruction::IncVal,
'-' => Instruction::DecVal,
'.' => Instruction::Output,
',' => Instruction::Input,
'[' => {
stack.push(count);
Instruction::SkipForward(0)
},
']' => {
let open_pc = match stack.pop() {
Some(o) => o,
None => return Err(Error::MissingOpenBracket(count))
};
let open = asl.get_mut(open_pc).expect("in");
*open = Instruction::SkipForward(count);
Instruction::SkipBackward(open_pc)
},
_ => continue,
};
count += 1;
asl.push(instruction);
}
if !stack.is_empty() {
return Err(Error::MissingCloseBracket(stack.len()))
}
Ok(Program {
asl: asl
})
}
pub fn get(&self, iptr: usize) -> Option<Instruction> {
self.asl.get(iptr).map(|i| *i)
}
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Program, Error> {
let mut file = try!(File::open(path));
let mut source = String::new();
try!(file.read_to_string(&mut source));
Program::parse(&source)
}
}
impl fmt::Display for Program {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut string = String::new();
for i in &self.asl {
string = format!("{}{}", string, i);
}
write!(f, "{}", string)
}
}
mod error;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn program() {
let program = Program::from_file("fixtures/helloworld.b");
assert!(program.is_ok());
}
#[test]
fn equal_brackets() {
let program = Program::parse("[[]]");
assert!(program.is_ok());
}
#[test]
fn more_open_brackets() {
let program = Program::parse("[[[]]");
assert!(program.is_err());
}
#[test]
fn more_close_brackets() {
let program = Program::parse("[[]]]");
assert!(program.is_err());
}
}