Nexus logo

Nexus

One grammar file in. One standalone Zig module out: a DFA lexer, an LALR(1) parser, and a verified semantic layer.

View on GitHub Read the Docs

How It Works

Write one grammar file: the tokens as regular expressions, the syntax as LALR(1) rules, and next to each rule the tree it builds. When the language needs layout or keyword classification, add a Zig lang module. Nexus writes one Zig module you can vendor: a DFA lexer, an LALR(1) parser and, with @schema, a verified semantic layer. No runtime library, no allocation while lexing, the same bytes on every run.

calc.grammartokens, rules, trees
→
nexuschecks and generates
→
parser.ziglexer, parser, tree API

Example

A calculator with let statements: a schema for its tree, comments kept aside as trivia, and an operator-precedence chain. The same grammar is the tour in the README, where the test suite generates, compiles and runs it.

calc.grammar Input
@lexer

tokens
    ident, number, let
    eq, plus, minus, star, slash, lparen, rparen
    newline, comment, eof, err

'#' [^\n]*                 → comment
'\n'                       → newline
'='                        → eq
'+'                        → plus
'-'                        → minus
'*'                        → star
'/'                        → slash
'('                        → lparen
')'                        → rparen
[0-9]+                     → number
"let"                      → let
[a-zA-Z_][a-zA-Z0-9_]*     → ident
.                          → err

@parser

@schema
    program    ...stmts
    let        name:leaf value
    "+", "-"   left right
    "*", "/"   left right
    neg        value
    num        value:leaf
    var        name:leaf

@trivia COMMENT

program! = stmts                            → (program ...1)

stmts    = stmt                             → (1)
         | stmts NEWLINE stmt               → (...1 3)
         | stmts NEWLINE                    → 1

stmt     = LET name:IDENT "=" value:expr    → (let)
         | expr

expr     = @infix

atom     = NUMBER                           → (num 1)
         | IDENT                            → (var 1)
         | "-" value:atom                   → (neg)
         | "(" expr ")"                     → 2

@infix atom
    "+" left, "-" left
    "*" left, "/" left
terminal Generate
$ nexus calc.grammar src/parser.zig
Reading grammar from calc.grammar
   Lexer: 14 tokens, 13 rules, 16 DFA states
   Parser: 5 rules, 1 start symbols
   Generated: 23 symbols, 18 rules, 31 states
Generated: src/parser.zig

The input let x = 1 + 2 * 3 # seven parses to (let `x` (+ (num `1`) (* (num `2`) (num `3`)))), and a compiler reads it by role (ir.Let.value(node)), with a source span for every node. Had an action built a node the schema does not allow, generation would have failed with file:line:col: error: naming the rule.


Key Features

Verified Semantic Layer

With @schema, every node kind has named, typed roles. Generation proves every rule builds nodes of the declared shape and generates the accessors.

A Real Lexer Generator

Patterns compile to one minimized DFA, emitted as direct-coded Zig with guards, trailing context, zero-width tokens and SIMD scans. Tokens are 8 bytes and zero-copy.

Conflict Manifest

Every remaining LALR(1) conflict is declared in @conflicts with a reason. Any change fails generation and prints the manifest ready to paste.

Tolerant Parsing

Syntax errors name what was expected, trivia keeps its positions, and parseTolerant repairs a broken buffer from a generated table.

Nothing Silent

A dead lexer rule, an unreachable rule or a value an action drops is a located error, and nothing is written.

Self-Hosting

Nexus parses its grammar files with a parser it generates from its own schema-mode grammar.


Validated Languages

Rig, MUMPS (the language of VistA: pattern mode, dot levels, context-sensitive commands), a Ruby subset, Slash, Nexis (a Clojure reader) and Nexus's own grammar files: each grammar generates, compiles and parses its cases in the test suite. The README's table gives their sizes, states and declared conflicts.