1 use std::borrow::ToOwned;
2 use types::MalError::{ErrString, ErrMalVal};
3 use types::{MalVal, MalRet,
4 _nil, _true, _false, _int, symbol, string, list, vector, hash_mapv,
5 err_str, err_string, err_val};
6 use super::printer::unescape_str;
8 #[derive(Debug, Clone)]
15 fn next(&mut self) -> Option<String> {
16 if self.position < self.tokens.len() {
18 Some(self.tokens[self.position-1].to_string())
23 fn peek(&self) -> Option<String> {
24 if self.position < self.tokens.len() {
25 Some(self.tokens[self.position].to_string())
32 fn tokenize(str: String) -> Vec<String> {
33 let mut results = vec![];
34 let re = regex!(r###"[\s,]*(~@|[\[\]{}()'`~^@]|"(?:\\.|[^\\"])*"|;.*|[^\s\[\]{}('"`,;)]*)"###);
35 for cap in re.captures_iter(&str) {
36 let group = cap.at(1).unwrap_or("");
37 if group == "" { break; }
38 if group.starts_with(";") { continue; }
39 results.push(group.to_owned());
44 fn read_atom(rdr : &mut Reader) -> MalRet {
45 let otoken = rdr.next();
46 //println!("read_atom: {}", otoken);
47 if otoken.is_none() { return err_str("read_atom underflow"); }
48 let stoken = otoken.unwrap();
49 let token = &stoken[..];
50 if regex!(r"^-?[0-9]+$").is_match(token) {
51 let num : Option<isize> = token.parse().ok();
52 Ok(_int(num.unwrap()))
53 } else if regex!(r#"^".*"$"#).is_match(token) {
54 let new_str = &token[1..token.len()-1];
55 Ok(string(unescape_str(new_str)))
56 } else if regex!(r#"^:"#).is_match(token) {
57 Ok(string(format!("\u{29e}{}", &token[1..])))
58 } else if token == "nil" {
60 } else if token == "true" {
62 } else if token == "false" {
69 fn read_seq(rdr : &mut Reader, start: &str, end: &str) -> Result<Vec<MalVal>,String> {
70 let otoken = rdr.next();
72 return Err("read_atom underflow".to_string());
74 let stoken = otoken.unwrap();
75 let token = &stoken[..];
77 return Err(format!("expected '{}'", start))
80 let mut ast_vec : Vec<MalVal> = vec![];
82 let otoken = rdr.peek();
84 return Err(format!("expected '{}', got EOF", end));
86 let stoken = otoken.unwrap();
87 let token = &stoken[..];
88 if token == end { break; }
90 match read_form(rdr) {
91 Ok(mv) => ast_vec.push(mv),
92 Err(ErrString(es)) => return Err(es),
93 Err(ErrMalVal(_)) => return Err("read_seq exception".to_string()),
101 fn read_list(rdr : &mut Reader) -> MalRet {
102 match read_seq(rdr, "(", ")") {
103 Ok(seq) => Ok(list(seq)),
104 Err(es) => err_string(es),
108 fn read_vector(rdr : &mut Reader) -> MalRet {
109 match read_seq(rdr, "[", "]") {
110 Ok(seq) => Ok(vector(seq)),
111 Err(es) => err_string(es),
115 fn read_hash_map(rdr : &mut Reader) -> MalRet {
116 match read_seq(rdr, "{", "}") {
117 Ok(seq) => hash_mapv(seq),
118 Err(es) => err_string(es),
122 fn read_form(rdr : &mut Reader) -> MalRet {
123 let otoken = rdr.peek();
124 //println!("read_form: {}", otoken);
125 let stoken = otoken.unwrap();
126 let token = &stoken[..];
130 match read_form(rdr) {
131 Ok(f) => Ok(list(vec![symbol("quote"), f])),
137 match read_form(rdr) {
138 Ok(f) => Ok(list(vec![symbol("quasiquote"), f])),
144 match read_form(rdr) {
145 Ok(f) => Ok(list(vec![symbol("unquote"), f])),
151 match read_form(rdr) {
152 Ok(f) => Ok(list(vec![symbol("splice-unquote"), f])),
158 match read_form(rdr) {
160 match read_form(rdr) {
161 Ok(f) => Ok(list(vec![symbol("with-meta"), f, meta])),
170 match read_form(rdr) {
171 Ok(f) => Ok(list(vec![symbol("deref"), f])),
176 ")" => err_str("unexected ')'"),
177 "(" => read_list(rdr),
179 "]" => err_str("unexected ']'"),
180 "[" => read_vector(rdr),
182 "}" => err_str("unexected '}'"),
183 "{" => read_hash_map(rdr),
189 pub fn read_str(str :String) -> MalRet {
190 let tokens = tokenize(str);
191 if tokens.len() == 0 {
192 // any malval as the error slot means empty line
193 return err_val(_nil())
195 //println!("tokens: {}", tokens);
196 let rdr = &mut Reader{tokens: tokens, position: 0};