diff options
author | Kjetil Orbekk <kj@orbekk.com> | 2023-11-19 17:34:43 -0500 |
---|---|---|
committer | Kjetil Orbekk <kj@orbekk.com> | 2023-11-19 17:34:59 -0500 |
commit | 79a31f87b668f9ef67a8cd6bc7826031fe3be18e (patch) | |
tree | 0fc311198a30e37bb519bc1433e33def47bfb14f /lisp/src/parser.rs | |
parent | d5a1aa8daaf1371d6b0032636c5c668dea581a3b (diff) |
lisp testing
Diffstat (limited to 'lisp/src/parser.rs')
-rw-r--r-- | lisp/src/parser.rs | 77 |
1 files changed, 77 insertions, 0 deletions
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<char, Vec<Val>, Error = Simple<char>> { + recursive(|val| { + let string = just('"') + .ignore_then(none_of('"').repeated()) + .then_ignore(just('"')) + .collect::<String>() + .map(Val::String) + .padded(); + + let atom = filter(|c: &char| c.is_alphanumeric()) + .map(Some) + .chain::<char, _, _>(filter(|c: &char| c.is_alphanumeric()).repeated()) + .collect::<String>() + .map(Val::Atom) + .padded(); + + let number = just('-') + .or_not() + .chain::<char, _, _>(text::int(10)) + .collect::<String>() + .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)") + ); + } +} |