Overview
The grammar is split into two layers, matching the implementation in newcode/parser.py and newcode/expr.py:
Everything a human writes in New Code is a score. The conductor writes the score; the compiler plays it. Everything the compiler writes in New Code is also a score — the syntax is shared, the semantics are the same.
EBNF Conventions
| Notation | Meaning |
|---|---|
| A ::= B | A is defined as B |
| A | B | One of A or B |
| A? | Optional A |
| A* | Zero or more of A |
| A+ | One or more of A |
| ( A B ) | Grouping |
| "lit" | A literal token |
| UPPERCASE | Terminal symbols |
| lowercase | Non-terminal symbols |
Lexical Structure
Source and whitespace
source ::= ( line NEWLINE )*
NEWLINE ::= "\r\n" | "\n"
whitespace ::= " " | "\t"
comment ::= "※" any*
Identifiers
IDENT ::= ( LETTER | "_" ) ( LETTER | DIGIT | "_" )*
DOTTED_IDENT ::= IDENT ( "." IDENT )*
LETTER ::= "A".."Z" | "a".."z"
DIGIT ::= "0".."9"
Numeric literals
NUMBER ::= SIGN? ( FLOAT | INT ) EXPONENT?
SIGN ::= "+" | "-"
INT ::= DIGIT+
FLOAT ::= DIGIT+ "." DIGIT* | "." DIGIT+
EXPONENT ::= ("e" | "E") SIGN? DIGIT+
String literals
STRING ::= "\"" STRING_CHAR* "\""
| "'" STRING_CHAR* "'"
INTENT_STR ::= "「" any* "」"
INTENT_STR is the bracketed string form used in intent, forbid, and ensure clauses. Regular strings use ASCII quotes; intent strings use the Japanese corner brackets.
Top-Level Declarations
Module
module_decl ::= "module" DOTTED_IDENT NEWLINE
intent_clause?
forbid_clause?
ensure_clause?
module_body
module_body ::= ( import_decl
| extern_decl
| fn_decl
| process_decl
| let_decl
| export_decl )*
Import
import_decl ::= "import" DOTTED_IDENT ( "as" IDENT )?
| "import" DOTTED_IDENT ".{" name_list "}"
Extern Python block
extern_decl ::= "extern" "python" "{" python_source "}"
Function declaration
fn_decl ::= "fn" IDENT params_list "→" type_expr NEWLINE
intent_clause
forbid_clause
ensure_clause
requires_clause*
guard_clause*
bind_expr
params_list ::= "(" ( param ( "," param )* )? ")"
param ::= IDENT ":" type_expr
Process declaration
process_decl ::= "process" IDENT ":" type_expr NEWLINE
intent_clause
emits_clause
consumes_clause*
bind_expr
Let binding
let_decl ::= "let" IDENT ( ":" type_expr )? "=" expr
Body binding
bind_expr ::= "≔" expr
| ":=" expr
| "≔" "??" (* a hole — compiler fills from intent *)
Intent Clauses
intent_clause ::= "intent:" ":" INTENT_STR NEWLINE
forbid_clause ::= "forbid:" ":" INTENT_STR NEWLINE
ensure_clause ::= "ensure:" ":" INTENT_STR NEWLINE
requires_clause ::= "requires" ":" expr NEWLINE
emits_clause ::= "emits" ":" type_expr "at" NUMBER ("Hz" | "kHz")? NEWLINE
consumes_clause ::= "consumes" ":" IDENT "<" IDENT ">" NEWLINE
guard_clause ::= "guard" ":" expr NEWLINE
Clause indentation: All clauses in a function declaration must be indented at least one level beyond the fn keyword. The body (≔) must be at the same indentation level as the clauses.
Expression Layer
The expression layer is parsed by newcode/expr.py and is invoked on every let RHS, every explicit body, and every REPL expression.
Let-in
let_expr ::= "let" IDENT ( ":" type_expr )? "=" expr "in" expr
| "let" IDENT ( ":" type_expr )? "=" expr NEWLINE expr
Lambda
lambda_expr ::= "\" IDENT+ "->" expr
| "λ" IDENT+ "↦" expr
Block
block_expr ::= "{" statement* expr "}"
statement ::= let_decl NEWLINE
Conditional
if_expr ::= "if" expr "then" expr "else" expr
Both branches must yield a value of the same type. if without else is a parse error.
Case expression
case_expr ::= "case" expr "of" NEWLINE
( pattern "when" expr? "↦" expr NEWLINE )+
Fold
fold_expr ::= expr "fold" "with" expr "from" expr
| expr "fold-min" "by" IDENT
Record and list literals
record_expr ::= "{" ( IDENT ":" expr ( "," IDENT ":" expr )* )? "}"
list_expr ::= "[" ( expr ( "," expr )* )? "]"
Python escape
python_expr ::= "python" "{" python_source "}"
Binary and unary expressions
expr ::= expr "⊕" expr
| expr "⊚" expr
| expr "⇝" expr
| expr "‖" expr
| expr "▶" expr
| expr "∥" expr
| expr "↺" "by" NUMBER TIME_UNIT
| expr "▷◁" expr
| "⟪" expr "," expr "⟫"
| "⌊" expr "⌉"
| "⌊" expr "⌉_amp"
| "⌊" expr "⌉_freq"
| "⌊" expr "⌉_rms"
| expr "⁻"
| expr "?"
| "◈" "(" expr "," expr ")"
| expr "(" arg_list? ")" (* function application *)
| atom
Waveform literal
wave_literal ::= "⟨" expr "," expr "," expr "," shape_expr "⟩"
shape_expr ::= IDENT
| "pulse" "(" expr ")"
| "noise" "(" expr ")"
| "{" IDENT "↦" expr "}" (* shape literal *)
Literals
| Kind | Form | Example |
|---|---|---|
| Waveform | ⟨ f, A, φ, σ ⟩ | ⟨ 440, 1.0, 0, sine ⟩ |
| Scalar | Decimal, optional exponent | 3.14 · 6.022e23 |
| Shape | { t ↦ expr } | { t ↦ tanh(sin(2π·t)) } |
| String (intent) | 「...」 | 「identify the nearest signature」 |
| String (general) | "..." or '...' | "libsndfile" |
| Boolean | true / false / True / False | true |
| List | [ expr, ... ] | [concert_a, silence] |
| Record | { key: expr, ... } | { f: 440, A: 1.0 } |
Type Expressions
type_expr ::= "𝕎"
| "𝕎*"
| "ℝ"
| "shape"
| "proc" "<" type_expr ">"
| "stream" "<" type_expr ">"
| "fault" "<" IDENT ">"
| "⌊" type_expr "⌉"
| "⟨" type_expr "▷◁" type_expr "⟩"
| "[" type_expr "]"
| "(" type_expr "," type_expr ")"
| "{" ( IDENT ":" type_expr )+ "}"
| "fn" "(" type_expr_list ")" "→" type_expr
| type_expr "|" type_expr
| IDENT
Patterns
pattern ::= "⟨" pat_component "," pat_component "," pat_component "," pat_component "⟩"
| "fault" "<" IDENT ">" "(" pattern "," pattern ")"
| "⌊" pattern "⌉"
| "⟨" pattern "▷◁" pattern "⟩"
| "[" pattern ( "," pattern )* "]"
| IDENT (* variable binding *)
| "_" (* wildcard *)
| NUMBER
| STRING
pat_component ::= IDENT (* bind component to name *)
| "_" (* ignore component *)
| shape_expr (* match on specific shape *)
| NUMBER (* match on literal value *)
Reserved Words
Top-level declaration keywords
fn let process module import extern export
Clause keywords
intent forbid ensure requires emits consumes guard
Expression-layer keywords
let in if then else and or not
match with do end
case of when fold
true false True False
Type keywords
fn proc stream fault shape record collapse
Built-in shape names
sine sq square tri triangle saw sawtooth pulse noise
Reserved symbols
| Symbol | Role |
|---|---|
| 𝕎 ℝ | Type glyphs |
| ⊕ ⊚ ⁻ ⇝ ⟪·,·⟫ ▷◁ ◈ ‖ ⌊·⌉ | Operators |
| ▶ ∥ ↺ | Process combinators |
| ⟨ ⟩ | Waveform literal delimiters |
| ↦ | Maps-to (lambda and shape literals) |
| ≔ := | Definition / body bind |
| ?? | Hole placeholder |
| ※ | Line comment |
| 《 》 | Block comment delimiters |
| 「 」 | Intent string delimiters |
Unicode note: All reserved symbols are fixed Unicode code points. The parser does not accept ASCII substitutes for most symbols except := for ≔, \ for λ, and -> for ↦ in lambda expressions.