--- /dev/null
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "crust"
+version = "0.1.0"
+dependencies = [
+ "lazy_static",
+ "regex",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "memchr"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+
+[[package]]
+name = "regex"
+version = "1.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
--- /dev/null
+mod stack;
+use lazy_static::lazy_static;
+use regex::Regex;
+use std::io;
+
+#[derive(Debug)]
+enum JoyVal {
+ True,
+ False,
+ List(stack::List<JoyVal>),
+ Int(i64),
+ Sym(String),
+}
+
+fn tokenize(str: &str) -> JoyVal {
+ lazy_static! {
+ static ref RE: Regex = Regex::new(
+ r"(?x)
+ (?P<true>true)\b
+ | (?P<false>false)\b
+ | (?P<lbracket>\[)
+ | (?P<rbracket>\])
+ | (?P<int>\d+)
+ | (?P<atom>[^\s+\[\]]+) "
+ )
+ .unwrap();
+ }
+
+ let mut frame = vec![];
+ let mut stack = vec![];
+ for cap in RE.captures_iter(str) {
+ // Is this better than the if/elif/else chain below?
+ // More importantly, how would I go about figuring that out?
+ match cap.name("true") {
+ Some(_) => {
+ frame.push(JoyVal::True);
+ continue;
+ }
+ None => {}
+ }
+ // Is there a better way to do this?
+ //if cap.name("true") != None {
+ // println!("T");
+ //} else
+ if cap.name("false") != None {
+ frame.push(JoyVal::False);
+ } else if cap.name("lbracket") != None {
+ stack.push(frame);
+ frame = vec![];
+ } else if cap.name("rbracket") != None {
+ let v = frame;
+ frame = stack.pop().expect("Extra closing bracket.");
+ frame.push(JoyVal::List(stack::List::vec_to_list(v)));
+ } else if cap.name("int") != None {
+ frame.push(JoyVal::Int(cap[0].parse().unwrap()));
+ } else if cap.name("atom") != None {
+ frame.push(JoyVal::Sym(String::from(&cap[0])));
+ } else {
+ println!("wtf");
+ }
+ }
+ JoyVal::List(stack::List::vec_to_list(frame))
+}
+
+fn joy(mut s: stack::List<JoyVal>, mut e: stack::List<JoyVal>) -> stack::List<JoyVal> {
+ while !e.empty() {
+ let term = e.head().expect("How!?");
+ e = e.tail();
+ match term {
+ JoyVal::True => { s = s.push(JoyVal::True) }
+ JoyVal::False => { s = s.push(JoyVal::False) }
+ JoyVal::List(_) => { s = s.push(term) }
+ JoyVal::Int(_) => { s = s.push(term) }
+ JoyVal::Sym(_) => { s = s.push(term) }
+ }
+ }
+ s
+}
+
+fn main() {
+ println!("Enter a number:");
+ let mut n = String::new();
+ let m = io::stdin().read_line(&mut n).expect("WTF?");
+ println!("{:?}", tokenize(&n));
+ println!("Entered: {} {}", m, n);
+}
--- /dev/null
+// https://rust-unofficial.github.io/too-many-lists/third.html
+use std::rc::Rc;
+
+#[derive(Debug)]
+pub struct List<T> {
+ head: Link<T>,
+}
+
+type Link<T> = Option<Rc<Node<T>>>;
+
+#[derive(Debug)]
+struct Node<T> {
+ elem: T,
+ next: Link<T>,
+}
+
+impl<T> List<T> {
+ pub fn new() -> Self {
+ List { head: None }
+ }
+ pub fn push(&self, elem: T) -> List<T> {
+ List {
+ head: Some(Rc::new(Node {
+ elem: elem,
+ next: self.head.clone(),
+ })),
+ }
+ }
+ pub fn tail(&self) -> List<T> {
+ List {
+ head: self.head.as_ref().and_then(|node| node.next.clone()),
+ }
+ }
+ pub fn head(&self) -> Option<&T> {
+ self.head.as_ref().map(|node| &node.elem)
+ }
+ pub fn iter(&self) -> Iter<'_, T> {
+ Iter {
+ next: self.head.as_deref(),
+ }
+ }
+ pub fn vec_to_list(v: Vec<T>) -> List<T> {
+ let mut list = List::new();
+ for t in v.into_iter().rev() {
+ list = list.push(t);
+ }
+ list
+ }
+ pub fn empty(&self) -> bool {
+ match self.head {
+ Some(_) => false,
+ None => true
+ }
+ }
+}
+
+impl<T> Drop for List<T> {
+ fn drop(&mut self) {
+ let mut head = self.head.take();
+ while let Some(node) = head {
+ if let Ok(mut node) = Rc::try_unwrap(node) {
+ head = node.next.take();
+ } else {
+ break;
+ }
+ }
+ }
+}
+
+pub struct Iter<'a, T> {
+ next: Option<&'a Node<T>>,
+}
+
+impl<'a, T> Iterator for Iter<'a, T> {
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.next.map(|node| {
+ self.next = node.next.as_deref();
+ &node.elem
+ })
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::List;
+
+ #[test]
+ fn basics() {
+ let list = List::new();
+ assert_eq!(list.head(), None);
+ assert_eq!(list.empty(), true);
+
+ let list = list.push(1).push(2).push(3);
+ assert_eq!(list.empty(), false);
+ assert_eq!(list.head(), Some(&3));
+
+ let list = list.tail();
+ assert_eq!(list.head(), Some(&2));
+
+ let list = list.tail();
+ assert_eq!(list.head(), Some(&1));
+
+ let list = list.tail();
+ assert_eq!(list.head(), None);
+
+ // Make sure empty tail works
+ let list = list.tail();
+ assert_eq!(list.head(), None);
+ }
+
+ #[test]
+ fn iter() {
+ let list = List::new().push(1).push(2).push(3);
+
+ let mut iter = list.iter();
+ assert_eq!(iter.next(), Some(&3));
+ assert_eq!(iter.next(), Some(&2));
+ assert_eq!(iter.next(), Some(&1));
+ }
+
+ #[test]
+ fn v2l() {
+ let v = vec![1, 2, 3];
+ let list = List::vec_to_list(v);
+
+ let mut iter = list.iter();
+ assert_eq!(iter.next(), Some(&1));
+ assert_eq!(iter.next(), Some(&2));
+ assert_eq!(iter.next(), Some(&3));
+ }
+}