From 79a31f87b668f9ef67a8cd6bc7826031fe3be18e Mon Sep 17 00:00:00 2001 From: Kjetil Orbekk Date: Sun, 19 Nov 2023 17:34:43 -0500 Subject: lisp testing --- lisp/src/parser.rs | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 lisp/src/parser.rs (limited to 'lisp/src/parser.rs') diff --git a/lisp/src/parser.rs b/lisp/src/parser.rs new file mode 100644 index 0000000..e36bdf7 --- /dev/null +++ b/lisp/src/parser.rs @@ -0,0 +1,77 @@ +use chumsky::prelude::*; + +use crate::ast::Val; + +pub fn parser<'a>() -> impl Parser, Error = Simple> { + recursive(|val| { + let string = just('"') + .ignore_then(none_of('"').repeated()) + .then_ignore(just('"')) + .collect::() + .map(Val::String) + .padded(); + + let atom = filter(|c: &char| c.is_alphanumeric()) + .map(Some) + .chain::(filter(|c: &char| c.is_alphanumeric()).repeated()) + .collect::() + .map(Val::Atom) + .padded(); + + let number = just('-') + .or_not() + .chain::(text::int(10)) + .collect::() + .from_str() + .unwrapped() + .map(Val::I64) + .labelled("number"); + + choice(( + string, // + number, + atom, + val.delimited_by(just('('), just(')')).map(Val::List), + )) + .repeated() + }) + .then_ignore(end()) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn parse_atom() { + assert_eq!( + Ok(vec!(Val::Atom("foo".to_string()))), + parser().parse("foo") + ); + } + + #[test] + fn parse_string() { + assert_eq!( + Ok(vec!(Val::String("foo".to_string()))), + parser().parse("\"foo\"") + ); + } + + #[test] + fn parse_i64() { + assert_eq!(Ok(vec!(Val::I64(123))), parser().parse("123")); + assert_eq!(Ok(vec!(Val::I64(-643))), parser().parse("-643")); + } + + #[test] + fn parse_list() { + assert_eq!( + Ok(vec!(Val::List(vec!( + Val::Atom("a".to_string()), + Val::Atom("b".to_string()) + )))), + parser().parse("(a b)") + ); + } +} -- cgit v1.2.3