Skip to content

Hello! 👋 My name is Nathan Weir. This is a fun personal project for using AI to build a bespoke, domain-specific programming language. It is not a serious, professional project. This site and the language itself are largely generated via Claude Code. If you find yourself programming with Weir, have fun - but use at your own risk!

Grammar

This page describes Weir’s grammar informally. Weir uses S-expression syntax — all code is parenthesized prefix notation with extensions for collection literals, type annotations, and keywords.

TokenUsage
( )S-expressions (code, function calls, definitions)
[ ]Vector literals
{ }Hash-map literals
KindExamplesDescription
Identifierfoo, add, spawn-enemy, set!Function/variable names. May contain -, ?, !, <, >, =
Integer42, -7, 0Default type i64
Float3.14, -0.5, 1e10Default type f64
String"hello", "line\n"UTF-8, with escape sequences
Keyword:name, :health, :posColon-prefixed, used as map keys and named arguments
Type variable'a, 'b, 'elemQuote-prefixed, used in type expressions
Booleantrue, falseBoolean literals
;; Line comment — everything after ; to end of line

Spaces, tabs, newlines, and commas are all whitespace. Commas are ignored (can be used for readability in collections).

A Weir source file is a sequence of top-level items:

program ::= item*
item ::= defn | deftype | defstruct | defclass | instance
| defmacro | declare | import | extern-c | expr
defn ::= '(' 'defn' name param* [':' type] body+ ')'
| '(' 'pub' 'defn' name param* [':' type] body+ ')'
param ::= '(' name ':' type ')'
| '(' 'mut' name ':' type ')'
| '(' struct-destructure ':' type ')'
deftype ::= '(' 'deftype' ['(' name type-var* ')' | name] constructor+ ')'
constructor ::= name ;; no-data variant
| '(' name type+ ')' ;; variant with data
defstruct ::= '(' 'defstruct' name field+ ')'
field ::= '(' name ':' type ')'
defclass ::= '(' 'defclass' [constraints] '(' name type-var+ ')' method+ ')'
method ::= '(' name ':' type ')'
constraints ::= '(' '=>' constraint+ ... ')'
constraint ::= '(' class-name type-var ')'
instance ::= '(' 'instance' [constraints] '(' class-name type+ ')' defn+ ')'
import ::= '(' 'import' module-path import-spec ')'
import-spec ::= '(' name+ ')' ;; specific names
| ':as' name ;; alias
| ':all' ;; everything
extern-c ::= '(' 'extern' '"C"' defn+ ')'
expr ::= literal | name | call | let | if | cond | match
| when | unless | fn | do | set! | unsafe | ann
| field-access | vector-lit | map-lit | threading
call ::= '(' expr expr* ')'
let ::= '(' 'let' '(' binding+ ')' body+ ')'
binding ::= '(' name expr ')'
| '(' 'mut' name expr ')'
| '(' '(' name ':' type ')' expr ')'
| '(' struct-destructure expr ')'
if ::= '(' 'if' expr expr [expr] ')'
cond ::= '(' 'cond' cond-clause+ ')'
cond-clause ::= '(' expr expr ')'
| '(' 'else' expr ')'
match ::= '(' 'match' expr match-arm+ ')'
match-arm ::= '(' pattern expr ')'
when ::= '(' 'when' expr body+ ')'
unless ::= '(' 'unless' expr body+ ')'
fn ::= '(' 'fn' '(' param* ')' [':' type] body+ ')'
do ::= '(' 'do' expr+ ')'
set! ::= '(' 'set!' name expr ')'
unsafe ::= '(' 'unsafe' body+ ')'
ann ::= '(' 'ann' type expr ')'
field-access ::= '.' name
vector-lit ::= '[' expr* ']'
map-lit ::= '{' (keyword expr)* '}'
threading ::= '(' '->' expr form+ ')'
| '(' '->>' expr form+ ')'
pattern ::= '_' ;; wildcard
| name ;; variable binding or no-data variant
| literal ;; literal match
| '(' name pattern* ')' ;; constructor pattern
| '{' (':' name [name])* '}' ;; struct destructure
type ::= name ;; simple type: i64, String, Bool
| type-var ;; 'a, 'b
| '(' 'Fn' '[' type* ']' type ')' ;; function type
| '(' name type+ ')' ;; type application: (Option i64)
| 'Ptr' ;; raw pointer (FFI)

A tree-sitter grammar for syntax highlighting is available at tree-sitter-weir/ in the repository. This provides accurate parsing for editor integration.

Terminal window
cd tree-sitter-weir && tree-sitter generate
cd tree-sitter-weir && tree-sitter test