nautilus-schema
Schema language parser, validator, IR builder, and formatter for the Nautilus ORM.
Overview
This crate implements the full processing pipeline for .nautilus schema files:
- Lex — Converts source text into typed tokens with byte-offset span tracking.
- Parse — Recursive descent parser builds a strongly-typed [
ast::Schema] AST. - Validate — Multi-pass semantic validator resolves types, relations, and constraints, emitting a fully resolved [
ir::SchemaIr]. - Format — Renders an AST back to canonical source text (idempotent).
Editor tooling (LSP, CLI) can use the one-shot [analyze] function which runs all four stages and returns structured diagnostics.
Features
- Parser — datasources, generators, models, enums, all field types, all attributes, error recovery
- Validator — duplicate name detection, unknown type resolution, relation integrity, default value type checking, physical name collision detection
- IR — fully resolved intermediate representation with logical and physical names
- Analysis API —
analyze(),completion(),hover(),goto_definition()for editor integration - Formatter — canonical output, column-aligned, idempotent
- Visitor — trait-based AST traversal with default walk implementations
- Span Tracking — every AST node carries byte-offset spans for precise diagnostics
- Error Recovery — parser continues after errors to surface multiple issues at once
Quick Start
Add to your Cargo.toml:
[]
= { = "../nautilus-schema" }
One-shot analysis
The recommended entry point. Runs lex → parse → validate in a single call and collects every diagnostic:
use analyze;
let result = analyze;
for diag in &result.diagnostics
if let Some = &result.ir
Validate and obtain the IR directly
use ;
let mut lexer = new;
let mut tokens = Vecnew;
loop
let ast = new.parse_schema?;
let ir = validate_schema?;
println!;
Editor tooling API
The analysis module exposes higher-level functions for LSP servers and CLI tools:
use ;
// Completions at a byte offset
let items = completion;
// Hover documentation at a byte offset
if let Some = hover
// Jump to the declaration a symbol at a byte offset refers to
if let Some = goto_definition
Formatting
format_schema renders an AST back to canonical, column-aligned source text:
use ;
let result = analyze;
if let Some = &result.ast
Visitor Pattern
Implement custom visitors for AST traversal and analysis:
use ;
Common Visitor Patterns
Collecting Information:
Finding Specific Patterns:
Validation:
Schema Language
Supported Declarations
Datasource:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
Generator:
generator client {
provider = "nautilus-client-rs"
output = "../generated" // Optional
interface = "async" // default: sync
}
Enum:
enum Role {
USER
ADMIN
MODERATOR
}
Model:
model User {
id Int @id @default(autoincrement())
email String @unique
username String @map("user_name")
role Role @default(USER)
createdAt DateTime @default(now())
posts Post[]
@@map("users")
@@index([email])
}
Field Types
Scalar Types:
String,Boolean,Int,BigInt,FloatDateTime,Bytes,Json,UuidDecimal(precision, scale)- e.g.,Decimal(10, 2)
User Types:
- Model references:
Post,User - Enum references:
Role,Status
Modifiers:
?- optional/nullable field[]- array/one-to-many relation
Field Attributes
@id- Primary key@unique- Unique constraint@default(expr)- Default value- Functions:
autoincrement(),uuid(),now() - Literals:
0,"DEFAULT",true - Enum values:
USER,ACTIVE
- Functions:
@map("physical_name")- Physical column name@relation(...)- Foreign key relationshipuser User @relation( fields: [userId], references: [id], onDelete: Cascade, onUpdate: Restrict )
Model Attributes
@@map("table_name")- Physical table name@@id([field1, field2])- Composite primary key@@unique([field1, field2])- Composite unique constraint@@index([field1, field2])- Database index, you can also specify the index types
Error Handling
The analyze function collects all diagnostics in one pass. Each Diagnostic
carries a byte-offset span that can be converted to line/column:
use ;
let result = analyze;
for diag in &result.diagnostics
For the lower-level SchemaError type, each variant with a span exposes
format_with_file(filepath, source) which emits the standard
filepath:line:column: message format recognised by VS Code.
Examples
Run the bundled examples:
Grammar
See GRAMMAR.md for the complete EBNF grammar specification.
Key grammar structures:
Schema ::= Declaration* EOF
Declaration ::= DatasourceDecl | GeneratorDecl | ModelDecl | EnumDecl
ModelDecl ::= 'model' Ident '{' (FieldDecl | ModelAttribute)* '}'
FieldDecl ::= Ident FieldType FieldModifier? FieldAttribute*
FieldType ::= ScalarType | 'Decimal' '(' Number ',' Number ')' | UserType
Expr ::= Literal | FunctionCall | Array | Ident
Testing
Run all tests:
Run specific test suites:
Test coverage:
- 57 unit tests embedded in each module
- 17 integration tests for the analysis API (
analysis_tests.rs) - 14 integration tests for the IR builder (
ir_tests.rs) - 23 integration tests for the lexer (
lexer_tests.rs) - 16 integration tests for the parser (
parser_tests.rs) - 24 integration tests for the validator (
validation_tests.rs) - 12 integration tests for the visitor (
visitor_tests.rs)
Documentation
Generate and view documentation:
Documentation includes:
- Module-level overviews
- Comprehensive API docs
- Usage examples
- Grammar reference
Architecture
nautilus-schema/
├── src/
│ ├── lib.rs # Public API re-exports
│ ├── span.rs # Byte-offset source location types
│ ├── token.rs # Token types
│ ├── lexer.rs # Tokenizer
│ ├── ast.rs # Syntax AST node definitions
│ ├── parser.rs # Recursive descent parser with error recovery
│ ├── error.rs # SchemaError and Result alias
│ ├── diagnostic.rs # Severity + Diagnostic (stable public contract)
│ ├── validator.rs # Multi-pass semantic validator
│ ├── ir.rs # Validated intermediate representation
│ ├── visitor.rs # Visitor trait and walk helpers
│ ├── formatter.rs # Canonical source formatter
│ └── analysis.rs # analyze / completion / hover / goto_definition
├── tests/
│ ├── lexer_tests.rs # 23 lexer integration tests
│ ├── parser_tests.rs # 16 parser integration tests
│ ├── validation_tests.rs # 24 validator integration tests
│ ├── ir_tests.rs # 14 IR builder integration tests
│ ├── visitor_tests.rs # 12 visitor integration tests
│ └── analysis_tests.rs # 17 analysis API integration tests
├── examples/
│ ├── tokenize_schema.rs
│ ├── parse_schema.rs
│ └── visitor_demo.rs
├── GRAMMAR.md # EBNF grammar specification
└── README.md
Usage within the project
nautilus-lsp— usesanalyze,completion,hover,goto_definition, andformat_schemato implement the language server.nautilus-codegen— callsvalidate_schemato obtain theSchemaIrfrom which it generates Rust types and SQL.nautilus-cli— callsanalyzeto surface diagnostics andformat_schemafor the format command.
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
Contributing
This is part of the Nautilus ORM project. See the main repository for contribution guidelines.