refactor(formula): extract formula parser into separate crate

Extract the formula AST and parser into a dedicated `improvise-formula`
crate and convert the project into a Cargo workspace.

The root crate now re-exports `improvise-formula` as `crate::formula` to
maintain backward compatibility for internal callers. The repository map is
updated to reflect the new crate structure.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (gemma-4-31B-it-UD-Q4_K_XL.gguf)
This commit is contained in:
Edward Langley
2026-04-14 01:49:16 -07:00
parent 8b7b45587b
commit f02d905aac
8 changed files with 35 additions and 9 deletions

9
Cargo.lock generated
View File

@ -737,6 +737,7 @@ dependencies = [
"dirs", "dirs",
"enum_dispatch", "enum_dispatch",
"flate2", "flate2",
"improvise-formula",
"indexmap", "indexmap",
"pest", "pest",
"pest_derive", "pest_derive",
@ -750,6 +751,14 @@ dependencies = [
"unicode-width", "unicode-width",
] ]
[[package]]
name = "improvise-formula"
version = "0.1.0-rc2"
dependencies = [
"anyhow",
"serde",
]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.14.0" version = "2.14.0"

View File

@ -1,3 +1,6 @@
[workspace]
members = [".", "crates/improvise-formula"]
[package] [package]
name = "improvise" name = "improvise"
version = "0.1.0-rc2" version = "0.1.0-rc2"
@ -15,6 +18,7 @@ name = "improvise"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
improvise-formula = { path = "crates/improvise-formula" }
ratatui = "0.30" ratatui = "0.30"
crossterm = "0.29" crossterm = "0.29"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }

View File

@ -1,8 +1,10 @@
# Repository Map (LLM Reference) # Repository Map (LLM Reference)
Terminal pivot-table modeling app. Rust, Ratatui TUI, command/effect architecture. Terminal pivot-table modeling app. Rust, Ratatui TUI, command/effect architecture.
Crate `improvise` v0.1.0-rc2, Apache-2.0, edition 2024. Cargo workspace, Apache-2.0, edition 2024. Root package `improvise` v0.1.0-rc2.
Library + binary crate: `src/lib.rs` exports public modules, `src/main.rs` is the CLI entry. Library + binary crate: `src/lib.rs` exports public modules, `src/main.rs` is the CLI entry.
Sub-crates live under `crates/`:
- `crates/improvise-formula/` — formula parser, AST (`Expr`, `BinOp`, `AggFunc`, `Formula`, `Filter`), `parse_formula`. Re-exported as `crate::formula` from the main crate via `pub use improvise_formula as formula;`.
--- ---
@ -153,7 +155,7 @@ pub enum CategoryKind { Regular, VirtualIndex, VirtualDim, VirtualMeasure, Label
### Formula System ### Formula System
```rust ```rust
// src/formula/ast.rs // crates/improvise-formula/src/ast.rs
pub enum Expr { pub enum Expr {
Number(f64), Number(f64),
Ref(String), // reference to an item name Ref(String), // reference to an item name
@ -172,7 +174,7 @@ pub struct Formula {
pub filter: Option<Filter>, // WHERE clause pub filter: Option<Filter>, // WHERE clause
} }
// src/formula/parser.rs // crates/improvise-formula/src/parser.rs
pub fn parse_formula(raw: &str, target_category: &str) -> Result<Formula> pub fn parse_formula(raw: &str, target_category: &str) -> Result<Formula>
``` ```
@ -383,11 +385,11 @@ Lines / tests / path — grouped by layer.
6 / 0t model/mod.rs 6 / 0t model/mod.rs
``` ```
### Formula layer ### Formula layer (sub-crate `improvise-formula` under `crates/`)
``` ```
461 / 29t formula/parser.rs Recursive descent parser → Formula AST 776 / 35t crates/improvise-formula/src/parser.rs Recursive descent parser → Formula AST
77 / 0t formula/ast.rs Expr, BinOp, AggFunc, Formula, Filter (data only) 77 / 0t crates/improvise-formula/src/ast.rs Expr, BinOp, AggFunc, Formula, Filter (data only)
5 / 0t formula/mod.rs 5 / 0t crates/improvise-formula/src/lib.rs
``` ```
### View layer ### View layer

View File

@ -0,0 +1,11 @@
[package]
name = "improvise-formula"
version = "0.1.0-rc2"
edition = "2024"
description = "Formula parser and AST for improvise"
license = "Apache-2.0"
repository = "https://github.com/fiddlerwoaroof/improvise"
[dependencies]
anyhow = "1"
serde = { version = "1", features = ["derive"] }

View File

@ -460,7 +460,7 @@ fn parse_comparison(tokens: &[Token], pos: &mut usize) -> Result<Expr> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::parse_formula; use super::parse_formula;
use crate::formula::{AggFunc, BinOp, Expr}; use crate::{AggFunc, BinOp, Expr};
#[test] #[test]
fn parse_simple_subtraction() { fn parse_simple_subtraction() {

View File

@ -1,7 +1,7 @@
pub mod command; pub mod command;
pub mod draw; pub mod draw;
pub mod format; pub mod format;
pub mod formula; pub use improvise_formula as formula;
pub mod import; pub mod import;
pub mod model; pub mod model;
pub mod persistence; pub mod persistence;