/* … */ Is a Comment, It Nests, and It Is Not a Doc CommentStatus: Superseded by ADR-307 — its D1-D3 are D1-D3 there Date: September 19, 2026 Target Version: Nikaia 0.0.10 Related: ADR-296 (a grammar’s vocabulary page), Part I chapter 2 (a comment)
A comment began with // and ran to the end of the line, and that was the
only form: /* … */ did not parse. A line comment is enough for a sentence
beside a statement and not for commenting out a block of code while
debugging, for a paragraph above a function, or for a note inside an
argument list — the three places a reader reaches for /* … */ and finds
it in C, Rust, JavaScript and every language between.
/* opens a comment that */ closes, across lines, anywhere whitespace may stand.A block comment may stand wherever whitespace may: between any two tokens,
inside an argument list, inside a grammar { … } block, across as many
lines as it needs. It is whitespace to the parser, as a line comment is.
A /* inside a string literal is text, not a comment; a // inside a block
comment is comment, not a second comment.
/* a /* b */ c */ is one comment that ends at the second */, as in Rust:
a block of code that already holds a block comment can be commented out
without hunting for the inner close. An unclosed block comment is a parse
error reported at the /* that opened it — the place the reader must fix,
not the end of the file where the parser gave up.
/** … */ and /*! … */ are block comments and nothing more.The language has no doc comment (ADR-291’s page says the same
of ///), and this record does not add one by the back door: a comment
that begins with two stars is a comment. What a doc comment would be — a
sentence the ledger carries and the prompt bundle reads — is a decision of
its own, in docs/open-decisions.md.
COMMENT, with the nesting
count and the error at the opening.All of it. BLOCK_COMMENT stands beside COMMENT in WS, which is the only
place a comment can be said — the generator puts WS between the tokens of every
syntactic rule, so a block comment stands wherever whitespace may. It nests,
because the step inside it tries the nested comment before the plain character. A
/* inside a string literal is text with no help needed: STRING is a lexical
rule, so no implicit whitespace runs between its characters and the comment rule
is never asked. /** and /*! are comments, and nothing is carried into the
generated Rust.
Two things the building settled that the record did not name.
The rule’s steps hand back a char they have no use for. Two alternatives of
different value types make the generator write a unit conversion, which
clippy::unused_unit refuses, so the nested arm answers with a space — which is
what a comment is to the parser anyway.
The error at the opening is not the grammar’s to give. The cut fires where the
input ran out, which is the end of the file: a comment that swallowed the rest of
a program fails at its last byte, and a caret there points at nothing. The
opening may be thousands of bytes behind. So the offset is found by scanning,
on a parse that has already failed with */ missing, and the scan is the reading
the lexer does — a " opens a string until its unescaped close, a // runs to
the end of its line, /* and */ count against each other. The condition is the
grammar’s own, which is what keeps the one thing the scan cannot read — a /*
inside a dsl … eod or a grammar { … } block, where it is text — from turning a
good message into a wrong one.
Six tests in crates/nikaia/tests/block_comments.rs: the nested comment inside
an argument list, /* inside a string, a // inside a block comment (the case a
scan that read line comments everywhere would get wrong, because the close is
behind one), the unclosed comment at its opening and at the outer opening
where a nested one is what is missing, /** and /*!, and division.