diff options
Diffstat (limited to 'lisp')
-rw-r--r-- | lisp/.envrc | 2 | ||||
-rw-r--r-- | lisp/Cargo.toml | 7 | ||||
-rw-r--r-- | lisp/flake.lock | 96 | ||||
-rw-r--r-- | lisp/src/ast.rs | 7 | ||||
-rw-r--r-- | lisp/src/lib.rs | 16 | ||||
-rw-r--r-- | lisp/src/parser.rs | 77 |
6 files changed, 205 insertions, 0 deletions
diff --git a/lisp/.envrc b/lisp/.envrc index 3550a30..7f44580 100644 --- a/lisp/.envrc +++ b/lisp/.envrc @@ -1 +1,3 @@ +export RUST_LOG=info +export RUST_BACKTRACE=1 use flake diff --git a/lisp/Cargo.toml b/lisp/Cargo.toml new file mode 100644 index 0000000..06b3eff --- /dev/null +++ b/lisp/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "lisp" +version = "0.1.0" +edition = "2021" + +[dependencies] +chumsky = "0.9.3" diff --git a/lisp/flake.lock b/lisp/flake.lock new file mode 100644 index 0000000..8a334fc --- /dev/null +++ b/lisp/flake.lock @@ -0,0 +1,96 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1681202837, + "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1700272409, + "narHash": "sha256-Mge6iOvomplBsvQ47sIeVAwAUGSVXH4qCW4pLUt/qMI=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "8e5e424b1c059e9ccf5db6a652458e30de05fa3a", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1681358109, + "narHash": "sha256-eKyxW4OohHQx9Urxi7TQlFBTDWII+F+x2hklDOQPB50=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "96ba1c52e54e74c3197f4d43026b3f3d92e83ff9", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1700360261, + "narHash": "sha256-8fRSHx5osjDELHSL7OHEfj/cOh8q+B7M9EF/yPR3bw8=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "45066cb0b2505d8da581be8432a16238c867f199", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/lisp/src/ast.rs b/lisp/src/ast.rs new file mode 100644 index 0000000..8cac963 --- /dev/null +++ b/lisp/src/ast.rs @@ -0,0 +1,7 @@ +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Val { + Atom(String), + List(Vec<Self>), + I64(i64), + String(String), +} diff --git a/lisp/src/lib.rs b/lisp/src/lib.rs new file mode 100644 index 0000000..60d0a4e --- /dev/null +++ b/lisp/src/lib.rs @@ -0,0 +1,16 @@ +pub mod parser; +pub mod ast; + +pub fn my_fn() -> bool { + true +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + assert!(my_fn()); + } +} 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)") + ); + } +} |