scheme4r/
parser.rs

1use std::vec;
2
3use crate::types::List;
4
5use super::types::Type;
6static VEC_PREFIX: &'static str = "#(";
7static QUOTE_PREFIX: &'static str = "'(";
8static U8VEC_PREFIX: &'static str = "#u8(";
9static PREFIX: &'static str = "(";
10static SUFFIX: &'static str = ")";
11
12pub fn parser(expr: String) -> Result<Type, String> {
13    let e = parse0(expr.trim());
14    println!("parser:{}", e);
15    Ok(e)
16}
17
18fn parse0(expr: &str) -> Type {
19    let is_vec = expr.starts_with(VEC_PREFIX);
20    let is_quote = expr.starts_with(QUOTE_PREFIX);
21    let is_u8_vec = expr.starts_with(U8VEC_PREFIX);
22    let is_push = expr.starts_with(PREFIX) || is_vec || is_u8_vec || is_quote;
23    if is_push {
24        parse_expr(expr)
25    } else {
26        parse_atom(expr).unwrap()
27    }
28}
29
30fn parse_expr(expr: &str) -> Type {
31    let mut stack = Vec::new();
32    let mut next = true;
33    let mut exp = expr;
34    while next {
35        exp = exp.trim();
36        let is_vec = exp.starts_with(VEC_PREFIX);
37        let is_quote = exp.starts_with(QUOTE_PREFIX);
38        let is_u8_vec = exp.starts_with(U8VEC_PREFIX);
39        let is_push = exp.starts_with(PREFIX) || is_vec || is_u8_vec || is_quote;
40        let index = if is_u8_vec {
41            4
42        } else if is_vec || is_quote {
43            2
44        } else {
45            1
46        };
47        let next_exp = &exp[index..];
48        let to_index = get_to_index(next_exp);
49        next = next_exp.find(SUFFIX) != None;
50        let sub_exp = &next_exp[..to_index];
51        // print!("sub_exp:{} next_exp:{} is_push:{} to_index:{}" , sub_exp, next_exp, is_push, to_index);
52        if is_push {
53            if is_u8_vec {
54                let v = parse_vec(sub_exp)
55                    .iter()
56                    .map(|x| as_u8(x))
57                    .collect::<Vec<u8>>();
58                stack.push(Type::u8vector_of(v));
59            } else if is_vec {
60                stack.push(Type::vector_of(parse_vec(sub_exp)));
61            } else if is_quote {
62                let v = parse_vec(sub_exp);
63                let mut vec = vec![Type::symbol("quote")];
64                vec.push(Type::expr_of(v));
65                stack.push(Type::Lists(List::of_quote(vec)));
66            } else {
67                stack.push(Type::expr_of(parse_vec(sub_exp)));
68            }
69        } else {
70            let brother = stack.pop().unwrap();
71            if stack.is_empty() {
72                stack.push(brother);
73            } else {
74                let mut parent = stack.pop().unwrap();
75                match &mut parent {
76                    Type::Lists(p) => {
77                        if p.is_quote() {
78                            if let Type::Lists(d) = p.get_data().get_mut(1).unwrap() {
79                                d.push(brother);
80                                d.push_vec(parse_vec(sub_exp));
81                            }else{
82                                // skip error
83                            }
84                        } else {
85                            p.push(brother);
86                            p.push_vec(parse_vec(sub_exp));
87                        }
88                    }
89                    Type::Vectors(p) => {
90                        p.push(brother);
91                        p.push_vec(parse_vec(sub_exp));
92                    }
93                    Type::ByteVectors(p) => {
94                        p.push(as_u8(&brother));
95                        let v = parse_vec(sub_exp)
96                            .iter()
97                            .map(|x| as_u8(x))
98                            .collect::<Vec<u8>>();
99                        p.push_vec(v);
100                    }
101                    _ => {}
102                }
103                stack.push(parent);
104            }
105        }
106
107        // println!("stack: {}", stack.len());
108        // println!("-----");
109        // print!("old-exp:{}to_index:{}",exp, to_index);
110        exp = exp[to_index + index..].trim();
111        // println!("exp:{}",exp)
112    }
113    stack.pop().unwrap()
114}
115
116fn get_to_index(next_exp: &str) -> usize {
117    // println!("________________________________________________________________{}", next_exp);
118    let pre0 = next_exp.find(PREFIX);
119    let pre1 = next_exp.find(VEC_PREFIX);
120    let pre2 = next_exp.find(U8VEC_PREFIX);
121    let pre3 = next_exp.find(QUOTE_PREFIX);
122    // min
123    let mut t = vec![pre0, pre1, pre2, pre3]
124        .iter()
125        .filter(|x| x.is_some())
126        .map(|x| x.unwrap())
127        .collect::<Vec<usize>>();
128    t.sort();
129    let pre = t.get(0);
130    let suf = next_exp.find(SUFFIX);
131    if suf != None {
132        let suf_index = suf.unwrap();
133        if pre != None {
134            let pre_index = pre.unwrap();
135            if *pre_index < suf_index {
136                *pre_index
137            } else {
138                suf_index
139            }
140        } else {
141            suf_index
142        }
143    } else {
144        0
145    }
146}
147
148fn parse_vec(exp: &str) -> Vec<Type> {
149    rep_str(exp.to_string())
150        .trim()
151        .split_whitespace()
152        .map(|s| parse_atom(s).unwrap())
153        .collect()
154}
155
156// fn parse_vec(exp: &str) -> Vec<Type> {
157//     parse_vec0(exp, false)
158// }
159
160fn rep_str(str: String) -> String {
161    if let Some(i) = str.find("'") {
162        let sub = &str[i + 1..];
163        if let Some(j) = sub.find("'") {
164            let s = &sub[..j].replace(" ", "\\u0009");
165            let mut all_str = String::new();
166            let right_str = &str[..i + 1];
167            let left_str = &sub[j..];
168            all_str.push_str(right_str);
169            all_str.push_str(s);
170            all_str.push_str(rep_str(left_str.to_string()).as_str());
171            return all_str;
172        }
173        return str;
174    } else {
175        return str;
176    }
177}
178
179fn parse_atom(s: &str) -> Result<Type, String> {
180    let t: Type = match s {
181        "nil" => Type::Nil,
182        "#t" => Type::Booleans(true),
183        "#f" => Type::Booleans(false),
184        _ => {
185            if s.starts_with("'") {
186                Type::expr_of(vec![Type::symbol("quote"), parse0(&s.replace("'", ""))])
187            } else if s.starts_with("\"") && s.ends_with("\"") && s.len() > 2 {
188                Type::string_of(
189                    s[1..s.len() - 1]
190                        .replace("\\u0009", " ")
191                        .replace("\\r", "\r")
192                        .replace("\\n", "\n")
193                        .to_string(),
194                )
195            } else if s.starts_with("#\\") && s.len() == 2 {
196                Type::character_of(s.chars().nth(2).unwrap())
197            } else if s.starts_with(U8VEC_PREFIX) && s.len() > 4 {
198                let v = parse0(&s.replace(U8VEC_PREFIX, "("));
199                let r = match v {
200                    Type::Lists(v) => v.data(),
201                    _ => vec![v],
202                };
203                Type::u8vector_of(r.iter().map(|x| as_u8(x)).collect::<Vec<u8>>())
204            } else if s.starts_with(VEC_PREFIX) && s.len() > 2 {
205                let v = parse0(&s.replace(VEC_PREFIX, "("));
206                let r = match v {
207                    Type::Lists(v) => v.data(),
208                    _ => vec![v],
209                };
210                Type::vector_of(r)
211            } else if s.parse::<isize>().is_ok() {
212                Type::integer_of(s.parse::<isize>().unwrap())
213            } else if s.parse::<f64>().is_ok() {
214                Type::float_of(s.parse::<f64>().unwrap())
215            } else if s.starts_with(",@") {
216                if s.len() > 2 {
217                    Type::expr_of(vec![
218                        Type::symbol_of(",@".to_string()),
219                        Type::symbol_of(s[2..].to_string()),
220                    ])
221                } else {
222                    Type::symbol_of(s.to_string())
223                }
224            } else {
225                peel_onions(s, vec![",", "'"])
226            }
227        }
228    };
229    Ok(t)
230}
231
232fn peel_onions(s: &str, keys: Vec<&str>) -> Type {
233    for key in keys {
234        if s.starts_with(key) && s.len() > key.len() {
235            return Type::expr_of(vec![
236                Type::Symbols(key.to_string()),
237                Type::Symbols(s[key.len()..].to_string()),
238            ]);
239        }
240    }
241    Type::Symbols(s.to_string())
242}
243
244fn as_u8(v: &Type) -> u8 {
245    match v {
246        Type::Numbers(v) => *v as u8,
247        Type::Characters(v) => *v as u8,
248        _ => 0,
249    }
250}