read_quotes/
read_quotes.rsuse clojure_reader::edn::{self, Edn};
fn wrap_quote(edn: Edn<'_>) -> Edn<'_> {
match edn {
Edn::Symbol(s) => s.strip_prefix('\'').map_or(Edn::Symbol(s), |stripped| {
Edn::List(vec![Edn::Symbol("quote"), Edn::Symbol(stripped)])
}),
Edn::List(mut edn) => {
edn.reverse();
let mut list = vec![];
while let Some(e) = edn.pop() {
if e == Edn::Symbol("'") {
list.push(Edn::List(vec![Edn::Symbol("quote"), wrap_quote(edn.pop().unwrap())]));
} else {
list.push(wrap_quote(e));
}
}
return Edn::List(list);
}
_ => edn,
}
}
fn quotify(s: &str) -> Edn<'_> {
let (edn, rest) = edn::read(s).unwrap();
let edn = if edn == Edn::Symbol("'") {
Edn::List(vec![Edn::Symbol("quote"), edn::read_string(rest).unwrap()])
} else {
edn
};
let edn = wrap_quote(edn);
edn
}
fn main() {
let quoted = quotify("'(foo (bar '(a 'b)))");
assert_eq!(format!("{quoted}"), "(quote (foo (bar (quote (a (quote b))))))");
let quoted = quotify("(foo '(a))");
assert_eq!(format!("{quoted}"), "(foo (quote (a)))");
let quoted = quotify("'(foo the 'bar)");
assert_eq!(format!("{quoted}"), "(quote (foo the (quote bar)))");
let quoted = quotify("(foo the 'bar)");
assert_eq!(format!("{quoted}"), "(foo the (quote bar))");
let quoted = quotify("(foo the bar)");
assert_eq!(format!("{quoted}"), "(foo the bar)");
}
#[test]
fn run() {
main();
}