Grammar¶
A policy is a few lines of text such as
test(suspicious) ; act(block): "when suspicious happens, propose
block". This package turns that text (or the same thing built with
Python helpers) into an automaton the runtime can step through. Open
this page when you write policies in code, need to catch a ParseError,
StarHeightError or CompileError (raised for oversized policies and
for ambiguous ones, where one event could lead to two actions), or are
changing the policy language itself.
Public here: parse, evt, act, seq, star, union,
compile_expr, star_height, StarHeightError (top level), plus
ParseError, CompileError and complement from
grounded_decision.grammar. How to write a policy:
Write a policy. How compilation works:
Grammar compile.
ast ¶
height ¶
Star-height of a generalized regular expression.
Family 134 (Lean): every regular language has generalized star-height ≤ 3. This module enforces the bound on the expression the user wrote. It does not rewrite an arbitrary language down to height 3.
StarHeightError ¶
Bases: ValueError
Expression exceeds the allowed generalized star-height.
parse ¶
Policy DSL: text → Expr via Lark LALR.
The kernel after this module is still the catalog-134 algebra (star-height, Thompson NFA, subset DFA). Lark replaces the old regex tokenizer, which silently skipped illegal characters and had no source positions.
Grammar source: policy.lark next to this file.
Examples::
test(apply) ; (test(eligible) ; act(approve) | test(ineligible) ; act(deny))
(test(ping) ; act(ack))*
test("low-risk") | test(high_risk) # comments and quoted names
eps
ParseError ¶
Bases: ValueError
Policy text is not in the DSL (Lark unexpected input, wrapped).
PolicyTransformer ¶
Bases: Transformer[Token, Expr]
Lark tree → frozen Expr.
Callbacks use Lark's default calling convention: each rule callback receives the list of its (already transformed) children.
parse ¶
parse(source: str) -> Expr
Parse a policy string into an Expr.
Raises ParseError with Lark's line/column context. Empty or
whitespace-only input is an error. Comments start with #.
Source code in src/grounded_decision/grammar/parse.py
dfa ¶
Compile a policy expression to a small DFA / Mealy machine.
Actions are markings on states, not input letters. Tests are letters. Complement determinizes and flips accepting bits on the event language, then drops action markings (complement is a language operation).
CompileError ¶
Bases: ValueError
The policy cannot be compiled: past a size limit, or ambiguous.
A policy is ambiguous when one event can lead to two different
actions at once, as in test(e) ; (act(a) | act(b)).
DFA
dataclass
¶
DFA(
states: int,
start: int,
alphabet: tuple[str, ...],
trans: tuple[tuple[int, ...], ...],
actions: tuple[str | None, ...],
accepting: tuple[bool, ...],
dead: int | None = None,
)
Deterministic machine with optional action labels on states.
dead
class-attribute
instance-attribute
¶
The reject sink: the state reached when the policy has no
continuation for an event. None when every event always has one.
compile_expr ¶
Compile a policy expression to a DFA with actions marked on states.
Raises:
| Type | Description |
|---|---|
StarHeightError
|
Star-height exceeds |
CompileError
|
The NFA or DFA exceeds its size cap, or the policy is
ambiguous: one event (or the start) can lead to two different
actions, as in |