Created
July 17, 2018 15:10
-
-
Save ShigekiKarita/fa06db7173fbfc0fd8bc21fb5f802bd6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| based on https://github.com/zick/OCamLisp/blob/master/ocamlisp.ml | |
| */ | |
| enum Obj<'a> { | |
| Nil, | |
| Num(i32), | |
| Sym(&'a str), | |
| Error(&'a str), | |
| Cons(&'a Obj<'a>, &'a Obj<'a>), | |
| Subr(&'a Fn(Obj<'a>) -> Obj<'a>), | |
| Expr(&'a Obj<'a>, &'a Obj<'a>, &'a Obj<'a>) | |
| } | |
| impl<'a> std::fmt::Debug for Obj<'a> { | |
| fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | |
| match self { | |
| Obj::Nil => write!(f, "Nil"), | |
| Obj::Num(i) => write!(f, "Num({})", i), | |
| Obj::Sym(s) => write!(f, "Str({})", s), | |
| Obj::Error(s) => write!(f, "Error({})", s), | |
| // Obj::Cons(a, b) => write!(f, "Cons({}, {})", a, b), | |
| // Obj::Subr(f) => write!(f, "Subr"), | |
| // Obj::Expr(a, b, c) => write!(f, "Expr({}, {}, {})", a, b, c), | |
| _ => write!(f, "<cannot display>") | |
| } | |
| } | |
| } | |
| fn str_pair(st: &str) -> (Option<char>, Option<&str>) { | |
| let hd = st.chars().next(); | |
| let tl = match hd { | |
| Some(c) if st.len() > c.len_utf8() => Some(&st[c.len_utf8() ..]), | |
| _ => None | |
| }; | |
| (hd, tl) | |
| } | |
| fn read_quote(s: &str) -> (Obj, Option<&str>) { | |
| let (elm, next) = read(s); | |
| use Obj::*; | |
| (Cons(&Sym("quote"), &Cons(&Box::new(elm), &Nil)), next) | |
| } | |
| // fn read_list | |
| fn read(s: &str) -> (Obj, Option<&str>) { | |
| let st = s.trim_left(); | |
| use Obj::Error; | |
| match str_pair(st) { | |
| (None, _) => (Error("empty input"), None), | |
| (Some(c), rest) => match c { | |
| '\\' => match rest { | |
| Some(srest) => read_quote(srest), | |
| None => read_quote(""), | |
| } | |
| '(' => { println!("Error {}", st); (Error("invarid syntax"), None) }, | |
| // ')' => read_list(rest, Obj::Nil), | |
| _ => (Error("not implmented"), None) //read_atom(st) | |
| } | |
| _ => (Error("unknown parse error"), None) | |
| } | |
| } | |
| fn tokenize(s: &str) -> Obj { | |
| if s.len() > 0 { | |
| let (head, tail) = s.split_at(1); | |
| match head { | |
| "(" => println!("LPAR"), | |
| ")" => println!("RPAR"), | |
| " " => println!("SPACE"), | |
| _ => println!("<{}>", head) | |
| } | |
| tokenize(tail); | |
| } | |
| Obj::Nil | |
| } | |
| fn test() { | |
| assert_eq!(" \r \ta bc\t".trim_left(), "a bc\t"); | |
| assert_eq!(str_pair(" abc"), (Some('a'), Some("bc"))); | |
| assert_eq!(str_pair(" あbc"), (Some('あ'), Some("bc"))); | |
| assert_eq!(str_pair(" あ"), (Some('あ'), None)); | |
| assert_eq!(str_pair(" "), (None, None)); | |
| } | |
| fn main() { | |
| test(); | |
| let test1 = "(+ 1 1)"; | |
| // println!("{:#?}", test1.split(" ")); | |
| println!("{:#?}", tokenize(test1)); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment