lexpr

Rust library for parsing, representing, and printing Lisp S-expressions.

Library
Cargo
v0.2.7
200stars
MIT OR Apache-2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
36/100Needs Attention
Development Activity0
Maintenance0
Community64
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
82/100Excellent
Architecture84
Code Quality85
Innovation80
Learning Curve78

lexpr is a Rust library for working with S-expressions — the parenthesized data notation of the Lisp family. It provides the lexpr::Value type for representing S-expression data in memory, a sexp! macro for embedding literal S-expressions directly in Rust source, and a configurable parser and printer that support several Lisp dialects (Scheme, Emacs Lisp, Common Lisp).

A companion crate, serde-lexpr, integrates lexpr with Serde so arbitrary Rust data structures can be serialized to and deserialized from S-expressions, much like serde_json does for JSON.

What You Get

  • A lexpr::Value type representing the full range of S-expression data, including cons cells and lists
  • A configurable parser and printer with per-dialect syntax options (Scheme, Emacs Lisp, Common Lisp)
  • The sexp! macro for embedding S-expression literals directly in Rust code
  • Optional Serde integration via the serde-lexpr crate for (de)serializing Rust types

Common Use Cases

  • Reading and writing configuration or data files in an S-expression format
  • Interoperating with Lisp/Scheme tooling that exchanges data as S-expressions
  • Serializing Rust data structures to a human-readable Lisp-style format via Serde

Under The Hood

Architecture - lexpr-rs is a Cargo workspace of three crates: lexpr (the public library), serde-lexpr (Serde bindings), and lexpr-macros (an internal proc-macro crate implementing sexp!). Inside the lexpr crate, the core Value type is built from submodules for number, cons, datum, and value, with dedicated parse/ and print/ module trees plus a syntax module that captures dialect-specific reader/printer options. The parser is driven by these syntax settings so the same engine reads multiple Lisp flavors.

Tech Stack - Pure Rust, edition 2021, MSRV 1.56. Runtime dependencies are lean — itoa and ryu for fast integer and float formatting — with the sexp! macro pulled in optionally via lexpr-macros. Testing uses criterion for benchmarks and quickcheck/rand for property-based tests.

Code Quality - The codebase is substantial (~340 KB of Rust) and thoroughly tested, combining unit tests, a tests.rs suite, and QuickCheck property tests, with CI and Codecov coverage reporting. Much of the parsing/printing structure is adapted from the well-regarded serde_json and serde_yaml projects, lending it a proven design.

API Design - The API mirrors serde_json closely: a central Value enum, a literal macro (sexp! vs json!), and separate parser/printer entry points, so the learning curve is gentle for Serde-ecosystem users. Dialect configuration is explicit through the syntax options, making the multi-Lisp support discoverable rather than magical.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search