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",
"enum_dispatch",
"flate2",
"improvise-formula",
"indexmap",
"pest",
"pest_derive",
@ -750,6 +751,14 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "improvise-formula"
version = "0.1.0-rc2"
dependencies = [
"anyhow",
"serde",
]
[[package]]
name = "indexmap"
version = "2.14.0"

View File

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

View File

@ -1,8 +1,10 @@
# Repository Map (LLM Reference)
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.
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
```rust
// src/formula/ast.rs
// crates/improvise-formula/src/ast.rs
pub enum Expr {
Number(f64),
Ref(String), // reference to an item name
@ -172,7 +174,7 @@ pub struct Formula {
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>
```
@ -383,11 +385,11 @@ Lines / tests / path — grouped by layer.
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
77 / 0t formula/ast.rs Expr, BinOp, AggFunc, Formula, Filter (data only)
5 / 0t formula/mod.rs
776 / 35t crates/improvise-formula/src/parser.rs Recursive descent parser → Formula AST
77 / 0t crates/improvise-formula/src/ast.rs Expr, BinOp, AggFunc, Formula, Filter (data only)
5 / 0t crates/improvise-formula/src/lib.rs
```
### 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)]
mod tests {
use super::parse_formula;
use crate::formula::{AggFunc, BinOp, Expr};
use crate::{AggFunc, BinOp, Expr};
#[test]
fn parse_simple_subtraction() {

View File

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