3 //extern crate regex_macros;
8 use types::{MalVal,MalRet,ErrString,ErrMalVal,
9 _nil,_true,_false,_int,symbol,string,list,vector,hash_mapv,
10 err_str,err_string,err_val};
12 use super::printer::unescape_str;
14 #[deriving(Show, Clone)]
21 fn next(&mut self) -> Option<String> {
22 if self.position < self.tokens.len() {
24 Some(self.tokens[self.position-1].to_string())
29 fn peek(&self) -> Option<String> {
30 if self.position < self.tokens.len() {
31 Some(self.tokens[self.position].to_string())
38 fn tokenize(str :String) -> Vec<String> {
39 let mut results = vec![];
41 let re = match Pcre::compile(r###"[\s,]*(~@|[\[\]{}()'`~^@]|"(?:\\.|[^\\"])*"|;.*|[^\s\[\]{}('"`,;)]*)"###) {
42 Err(_) => { fail!("failed to compile regex") },
46 let mut it = re.matches(str.as_slice());
48 let opt_m = it.next();
49 if opt_m.is_none() { break; }
50 let m = opt_m.unwrap();
51 if m.group(1) == "" { break; }
52 if m.group(1).starts_with(";") { continue; }
54 results.push((*m.group(1)).to_string());
59 fn read_atom(rdr : &mut Reader) -> MalRet {
60 let otoken = rdr.next();
61 //println!("read_atom: {}", otoken);
62 if otoken.is_none() { return err_str("read_atom underflow"); }
63 let stoken = otoken.unwrap();
64 let token = stoken.as_slice();
65 if regex!(r"^-?[0-9]+$").is_match(token) {
66 let num : Option<int> = from_str(token);
67 Ok(_int(num.unwrap()))
68 } else if regex!(r#"^".*"$"#).is_match(token) {
69 let new_str = token.slice(1,token.len()-1);
70 Ok(string(unescape_str(new_str)))
71 } else if token == "nil" {
73 } else if token == "true" {
75 } else if token == "false" {
82 fn read_seq(rdr : &mut Reader, start: &str, end: &str) -> Result<Vec<MalVal>,String> {
83 let otoken = rdr.next();
85 return Err("read_atom underflow".to_string());
87 let stoken = otoken.unwrap();
88 let token = stoken.as_slice();
90 return Err("expected '".to_string() + start.to_string() + "'".to_string());
93 let mut ast_vec : Vec<MalVal> = vec![];
95 let otoken = rdr.peek();
97 return Err("expected '".to_string() + end.to_string() + "', got EOF".to_string());
99 let stoken = otoken.unwrap();
100 let token = stoken.as_slice();
101 if token == end { break; }
103 match read_form(rdr) {
104 Ok(mv) => ast_vec.push(mv),
105 Err(ErrString(es)) => return Err(es),
106 Err(ErrMalVal(_)) => return Err("read_seq exception".to_string()),
114 fn read_list(rdr : &mut Reader) -> MalRet {
115 match read_seq(rdr, "(", ")") {
116 Ok(seq) => Ok(list(seq)),
117 Err(es) => err_string(es),
121 fn read_vector(rdr : &mut Reader) -> MalRet {
122 match read_seq(rdr, "[", "]") {
123 Ok(seq) => Ok(vector(seq)),
124 Err(es) => err_string(es),
128 fn read_hash_map(rdr : &mut Reader) -> MalRet {
129 match read_seq(rdr, "{", "}") {
130 Ok(seq) => hash_mapv(seq),
131 Err(es) => err_string(es),
135 fn read_form(rdr : &mut Reader) -> MalRet {
136 let otoken = rdr.peek();
137 //println!("read_form: {}", otoken);
138 let stoken = otoken.unwrap();
139 let token = stoken.as_slice();
143 match read_form(rdr) {
144 Ok(f) => Ok(list(vec![symbol("quote"), f])),
150 match read_form(rdr) {
151 Ok(f) => Ok(list(vec![symbol("quasiquote"), f])),
157 match read_form(rdr) {
158 Ok(f) => Ok(list(vec![symbol("unquote"), f])),
164 match read_form(rdr) {
165 Ok(f) => Ok(list(vec![symbol("splice-unquote"), f])),
170 ")" => err_str("unexected ')'"),
171 "(" => read_list(rdr),
173 "]" => err_str("unexected ']'"),
174 "[" => read_vector(rdr),
176 "}" => err_str("unexected '}'"),
177 "{" => read_hash_map(rdr),
183 pub fn read_str(str :String) -> MalRet {
184 let tokens = tokenize(str);
185 if tokens.len() == 0 {
186 // any malval as the error slot means empty line
187 return err_val(_nil())
189 //println!("tokens: {}", tokens);
190 let rdr = &mut Reader{tokens: tokens, position: 0};