marginalia
Trivia-preserving parsing and formatting for logos + lalrpop grammars.
marginalia plugs into the standard Rust parsing stack and keeps comments and blank lines around
the AST, so you can write a formatter for your language without losing the user's notes.
The crate has three layers, all in one place:
TriviaLexeradapts anyIterator<Item = Result<(usize, Tok, usize), E>>and records line, block, and blank-line trivia in aTriviaTablewhile the parser sees only semantic tokens.marginalia::attachplaces those trivia events on AST node spans as leading, trailing, or dangling comments.marginalia::prettyis a smallDocIR with explicit trivia slots that the renderer resolves against aCommentMap.
The shape of an integration:
use TriviaLexer;
use ;
use ;
let raw = my_logos_lexer;
let mut lex = new;
let program = new.parse?;
let table = lex.into_table;
let map = attach;
let doc = program.doc;
let formatted = render;
The lexer must yield Result<(usize, Tok, usize), E> and Tok must implement
marginalia::Classify so marginalia knows which tokens are comments.
Classify, Trivia, TriviaTable, and CommentMap are all generic over a kind enum K (default
BuiltinKind = Line | Block). A language that needs richer categories supplies its own enum and an
impl Classify<MyKind> for MyTok. The renderer requires K: TriviaClass so it knows which trailing
comments terminate a line.
Example
examples/calc is a 200-line calculator language with full lex + parse + format
roundtrip and comment preservation. Read it end-to-end as the canonical integration template:
License
This project is licensed under the MIT License. See the LICENSE file for details.