Skip to main content
CFDL

This is a specification page.

It defines CFDL normatively — complete, exact, and written for people implementing against it. If you are building a model, Reference covers the same ground at the altitude of the work.

This grammar is intentionally pragmatic for v0.1: it captures the surface syntax needed by the Core spec. It is suitable as the basis for a hand-written parser or parser-generator input after minor adaptation (token rules, whitespace/comment handling).


1) Lexical tokens (informative)

Implementations MUST support:

  • Whitespace: spaces, tabs, newlines (ignored except as separators)
  • Line comments: // ... to end of line
  • Block comments: /* ... */

Recommended tokens:

  • IDENT → [A-Za-z_][A-Za-z0-9_]*
  • QNAME → IDENT ('.' IDENT)*
  • STRING → "..." with escapes
  • INT → digits with optional _ separators
  • DECIMAL → digits . digits with optional _
  • DATE → YYYY-MM or YYYY-MM-DD

2) Grammar

The formal EBNF grammar is maintained as a standalone file for use with grammar tooling (railroad diagram generators, parser generators, etc.):

📄 Download the grammar (EBNF)


3) Notes & implementation guidance (informative)

  1. Line breaks are not significant; blocks and keywords provide structure.
  2. money_lit is syntactic sugar; implementations should normalize to Money with currency.
  3. DATE accepts YYYY-MM and YYYY-MM-DD; normalize YYYY-MM to YYYY-MM-01 during parsing.
  4. schedule_opts are order-independent; parsers should accept any order.
  5. activate contract / deactivate contract were removed: a contract is a collection of streams, and one switch cannot express forbearance or an early termination. Gate the streams a contract produced by name, or with active in state.
  6. The event latch was removed. An event fires on each occurrence (rising edge), and a schedule clause supplies occurrences that when then filters. There is no once keyword: once-ness is declared, as a singular schedule or a topology with no way back. Implementations MUST NOT carry a hidden "has fired" flag — the latch was memory living outside the machine, unjournaled and undeclarable.
  7. Arrival actions are set on entity-relative FIELD names only, never status. Entry actions (on enter <state>) run before the taken edge's actions, and both run on every traversal — including one caused by a named event's status write.