daml-parser
A lossless lexer, layout resolver, and parser for the Daml smart-contract language, in pure Rust with zero external dependencies.
Part of the daml-tools workspace.
This is the shared foundation under both
daml-lint (a static analyzer) and
daml-fmt (a code formatter). The pipeline is:
lexer → layout → parse
(tokens (Haskell (typed AST with a
+ trivia) offside byte Span on every node)
rule)
Lossless by design
The lexer records every comment and whitespace run as trivia
(lexer::lex_with_trivia), so the original bytes can be reconstructed exactly
(lexer::render_lossless, ast_span::render_from_ast). One tree serves two
very different readers:
- the linter ignores trivia and reads meaning;
- the formatter keeps trivia and re-prints layout — if it dropped a comment it would eat your code, so losslessness is not optional.
This is the same shape the grown-up tools use (rust-analyzer, ruff, biome): one parser, one lossless tree, many consumers.
Usage
[]
= "0.1"
use parse_module;
let = parse_module;
assert!;
Public modules
| Module | What it gives you |
|---|---|
lexer |
tokenizer, trivia, Tok/Token, Pos, lossless reconstruction |
layout |
offside-rule resolution into virtual { ; } tokens |
parse |
parse_module → typed AST + diagnostics |
ast |
the syntax tree types, byte Span on every node |
ast_span |
render_from_ast, the byte-span losslessness oracle |
Stability
daml-parser is pre-1.0. The supported public entry points are the modules
listed above, with parse::parse_module as the normal start. The AST is public
so tools can inspect parser output; downstream code should prefer parser-created
trees over manual construction. Breaking public API changes use 0.x minor bumps,
and patch releases should stay compatible. cargo-semver-checks is a soft CI
signal until the first crates.io baseline exists.
License
AGPL-3.0-only. See LICENSE.