Lean 4’s parser is fully extensible. You can introduce new syntax rules at any point in a file and immediately use them in subsequent code. TheDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/leanprover/lean4/llms.txt
Use this file to discover all available pages before exploring further.
syntax command defines the grammar, while macro_rules or elab/elab_rules give it meaning. This page covers the full surface of Lean 4’s syntax extension API.
The syntax Command
The syntax command declares a new grammar rule without assigning semantics. It registers a parser for a syntax category (term, tactic, command, doElem, or a user-defined category).
Syntax node with a fresh syntax node kind (derived from the current namespace and name).
Parser Combinators
The grammar pattern insyntax is built from combinators. The most important ones are:
| Combinator | Meaning |
|---|---|
ident | An identifier |
num | A numeric literal |
str | A string literal |
term | Any term |
tactic | Any tactic |
"keyword" | A literal token |
p,* | Zero or more p comma-separated |
p,+ | One or more p comma-separated |
p* | Zero or more p |
p+ | One or more p |
p? | Optional p |
(p) | Grouping |
p \<|\> q | Ordered choice |
sepBy(p, sep) | General separated list |
ppSpace | Pretty-printer space hint |
colGt | Indentation: column greater than enclosing |
Syntax Categories
Lean uses several built-in syntax categories:| Category | Used for |
|---|---|
term | Expressions |
tactic | Tactics inside by blocks |
command | Top-level declarations |
doElem | Statements inside do blocks |
attr | Attribute syntax (inside @[…]) |
stx | Raw syntax fragments |
declare_syntax_cat:
Syntax Priority
When multiple syntax rules could parse the same input, Lean uses priority to choose. Higher priority wins. The default priority isdefault (1000).
elab: Inline Elaborator
The elab command combines syntax declaration and elaborator in a single step, analogously to how macro combines syntax + macro_rules:
elab_rules: Pattern-Matching Elaborator
elab_rules is the elaboration counterpart to macro_rules. It pattern-matches on the expanded syntax:
syntax + macro_rules vs syntax + elab
syntax + macro_rules: pure syntax transformation
syntax + macro_rules: pure syntax transformation
Use this when the meaning of your construct can be expressed entirely in terms of existing Lean syntax. The macro runs before elaboration; no type information is available.
syntax + elab: full elaborator
syntax + elab: full elaborator
Use this when you need access to types, the environment, or you need to produce
Expr directly. Elaborators run in TermElabM and have the full meta-programming API.Complete Example: A Custom assert Command
This example defines an assert command that type-checks an expression against True or False at compile time and logs the result:
Naming Syntax Nodes
By default, the syntax kind is derived automatically from the namespace. You can assign an explicit name with(name := myName):
@[command_elab myModuleDebug] from a different file.
Syntax in do Notation
Extending doElem lets you add new statements to do blocks: