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
119
120
121
122
123
124
125
126
|
//#![feature(phase)]
//#[phase(plugin)]
//extern crate regex_macros;
//extern crate regex;
extern crate pcre;
use std::rc::Rc;
use types::{MalVal,MalRet,Nil,True,False,Int,Strn,Sym,List};
use self::pcre::Pcre;
use super::printer::unescape_str;
#[deriving(Show, Clone)]
struct Reader {
tokens : Vec<String>,
position : uint,
}
impl Reader {
fn next(&mut self) -> Option<String> {
if self.position < self.tokens.len() {
self.position += 1;
Some(self.tokens[self.position-1].to_string())
} else {
None
}
}
fn peek(&self) -> Option<String> {
if self.position < self.tokens.len() {
Some(self.tokens[self.position].to_string())
} else {
None
}
}
}
fn tokenize(str :String) -> Vec<String> {
let mut results = vec![];
let re = match Pcre::compile(r###"[\s,]*(~@|[\[\]{}()'`~^@]|"(?:\\.|[^\\"])*"|;.*|[^\s\[\]{}('"`,;)]*)"###) {
Err(_) => { fail!("failed to compile regex") },
Ok(re) => re
};
let mut it = re.matches(str.as_slice());
loop {
let opt_m = it.next();
if opt_m.is_none() { break; }
let m = opt_m.unwrap();
if m.group(1) == "" { break; }
results.push((*m.group(1)).to_string());
}
results
}
fn read_atom(rdr : &mut Reader) -> MalRet {
let otoken = rdr.next();
//println!("read_atom: {}", otoken);
if otoken.is_none() { return Err("read_atom underflow".to_string()); }
let stoken = otoken.unwrap();
let token = stoken.as_slice();
if regex!(r"^-?[0-9]+$").is_match(token) {
let num : Option<int> = from_str(token);
Ok(Rc::new(Int(num.unwrap())))
} else if regex!(r#"^".*"$"#).is_match(token) {
let new_str = token.slice(1,token.len()-1);
Ok(Rc::new(Strn(unescape_str(new_str))))
} else if token == "nil" {
Ok(Rc::new(Nil))
} else if token == "true" {
Ok(Rc::new(True))
} else if token == "false" {
Ok(Rc::new(False))
} else {
Ok(Rc::new(Sym(String::from_str(token))))
}
}
fn read_list(rdr : &mut Reader) -> MalRet {
let otoken = rdr.next();
if otoken.is_none() { return Err("read_atom underflow".to_string()); }
let stoken = otoken.unwrap();
let token = stoken.as_slice();
if token != "(" { return Err("expected '('".to_string()); }
let mut ast_vec : Vec<MalVal> = vec![];
loop {
let otoken = rdr.peek();
if otoken.is_none() { return Err("expected ')', got EOF".to_string()); }
let stoken = otoken.unwrap();
let token = stoken.as_slice();
if token == ")" { break; }
match read_form(rdr) {
Ok(mv) => ast_vec.push(mv),
Err(e) => return Err(e),
}
}
rdr.next();
//ast_vec.push(Rc::new(Nil));
Ok(Rc::new(List(ast_vec)))
}
fn read_form(rdr : &mut Reader) -> MalRet {
let otoken = rdr.peek();
//println!("read_form: {}", otoken);
let stoken = otoken.unwrap();
let token = stoken.as_slice();
match token {
")" => Err("unexected ')'".to_string()),
"(" => read_list(rdr),
_ => read_atom(rdr)
}
}
pub fn read_str(str :String) -> MalRet {
let tokens = tokenize(str);
if tokens.len() == 0 {
return Err("<empty line>".to_string());
}
//println!("tokens: {}", tokens);
let rdr = &mut Reader{tokens: tokens, position: 0};
read_form(rdr)
}
|