This is the authoritative grammar as implemented in
src/sense_lang/parser.py
and src/sense_lang/lexer.py. It’s kept in sync with the source, not
aspirational — if a construct isn’t here, it isn’t implemented.Layout tokens
Blocks are indentation, not braces. The lexer producesNEWLINE, INDENT,
and DEDENT tokens from leading whitespace (spaces only — a leading tab is
a SenseSyntaxError) before the parser ever runs; see
Indentation-Sensitive Lexing for the
algorithm. Newlines and indentation are both suppressed inside ( ) / [ ].
Full grammar
How the parser resolves ambiguity
A function declaration itself is unambiguous —def is a dedicated
keyword, so a call expression (square(5)) is never confused with a
declaration. (A leftover square(x) returns Int: with no def — the
syntax’s first, since-replaced shape — is specifically detected and
raises an error naming def, rather than a generic parse failure; see
Functions.)
Three other constructs still share a token prefix with something else,
resolved by lookahead rather than a dedicated keyword:
A
capability_path segment accepts any keyword’s own lexeme, not just
IDENT — a capability path (model.anthropic, payment.execute, …) is
a free-form dotted namespace label, not a Sense variable, so reserving a
word as a language keyword (model, action, tool, …) must not
retroactively break an already-established capability name that happens
to use it.Keywords
File extension and comments
Sense source files use.sns. Comments start with # and run to end of
line; there’s no block-comment syntax.
Continue
Builtins reference
Every built-in function, with signatures.
Error reference
The error hierarchy and when each one fires.

