Expand description
Controlled-natural-language (CNL) <-> formula translation (Phase 4).
This is a controlled natural language: a small, fixed, deterministic grammar, not open-English NLP. No LLMs, no external services.
§Grammar (EBNF-ish)
sentence = [ subject copula ] expr [ "." ]
subject = measure-name (* ignored; RHS is what we return *)
copula = "equals" | "is"
expr = term { ("plus" | "+" | "minus" | "-") term }
term = factor { ("times" | "*" | "divided" "by" | "/") factor }
factor = number
| agg-call
| measure-ref
| "(" expr ")"
agg-call = ("the")? ("sum"|"average"|"min"|"max") "of" measure-ref
measure-ref= measure-name { dim-phrase }
dim-phrase = "over" cat-list (* aggregate over: DimensionSpec.over *)
| ("by" | "for" "each") cat-list (* keep/group: DimensionSpec.by *)
cat-list = category-name { "and" category-name }§Function-id mapping (built-in registry)
| phrase | FuncId |
|---|---|
sum of | 1 |
average of | 2 |
min of | 3 |
max of | 4 |
§Design choices
- The subject + copula (
Revenue equals,Revenue is) is parsed and discarded: the returned [Formula] is only the right-hand-side [Expr]. The target measure is a property of where the formula is stored, not of the expression tree. - A dimension phrase binds to the nearest preceding measure reference,
populating that
Ref’s [DimensionSpec] (over-> aggregate over,by/for each-> keep).exceptis not surfaced by the grammar.
Structs§
- NlContext
- Name-resolution context: measures and categories looked up by name.
Enums§
Constants§
- FUNC_
AVERAGE - FUNC_
MAX - FUNC_
MIN - FUNC_
SUM - MAX_
PARSE_ DEPTH - Bound on parser recursion (paren nesting) plus binary-operator nodes, so
both the parser and anything that later walks the AST recursively
(describe, serialize, drop) stay far from the stack limit on hostile input.
Matches
improv_core_model’s formula-parser limit.
Functions§
- describe_
formula - Render a [
Formula] back into a controlled English sentence. - parse_
nl_ formula - Parse a controlled sentence into a [
Formula] (its right-hand-side Expr).