Skip to content

Instantly share code, notes, and snippets.

@ShigekiKarita
Created July 17, 2018 15:10
Show Gist options
  • Select an option

  • Save ShigekiKarita/fa06db7173fbfc0fd8bc21fb5f802bd6 to your computer and use it in GitHub Desktop.

Select an option

Save ShigekiKarita/fa06db7173fbfc0fd8bc21fb5f802bd6 to your computer and use it in GitHub Desktop.
/**
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