summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjetil Orbekk <kj@orbekk.com>2023-11-19 17:34:43 -0500
committerKjetil Orbekk <kj@orbekk.com>2023-11-19 17:34:59 -0500
commit79a31f87b668f9ef67a8cd6bc7826031fe3be18e (patch)
tree0fc311198a30e37bb519bc1433e33def47bfb14f
parentd5a1aa8daaf1371d6b0032636c5c668dea581a3b (diff)
lisp testing
-rw-r--r--lisp/.envrc2
-rw-r--r--lisp/Cargo.toml7
-rw-r--r--lisp/flake.lock96
-rw-r--r--lisp/src/ast.rs7
-rw-r--r--lisp/src/lib.rs16
-rw-r--r--lisp/src/parser.rs77
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)")
+ );
+ }
+}