Hi Remi,

Thanks for the field report. I am pleased your list of "pro" is longer than 
your list of "cons".

As for your first "cons", the warning you are looking for is 
-Xlint:dangling-doc-comments, which will report all doc comments which are not 
attached to a documentable declaration. which will be the case for any `///` 
lines that become separated from any later `///` lines by an intervening `//`. 
The warning has been available since the introduction of Markdown support.

-- Jon


On Fri, Jun 19, 2026, at 2:28 PM, Remi Forax wrote:
> Hello,
> over the last few months, I've developed a small library called LazyLR 
> (runtime grammar parsers) and because it requires Java 25, I use the markdown 
> doc-comments introduced by JEP 467.
> 
> The overall experience is great, it's better than the traditional 
> doc-comments that mix documentation and HTML tags.
> 
> Here is my field trip report:
> 
> Pro:
>   - /// really shine to write one line doc for private methods, the visual 
> overhead is minimal compared to /** ... */
>   - /// does not requires escaping, even /// inside a /// is correctly 
> recognized
>   - Markdown is a better format than HTML for the documentation (especially 
> lists and tables)
>   - A blank line in markdown is really a blank line, unlike in HTML, so the 
> the doc comments are closer to the rendered javadoc (What you see is closer 
> to what you get)
>   - Code snippets using three backticks (```java) are easier to use than 
> <pre> (no &lt;, no escaping needed)
> 
> Cons:
>   - If you have 100 lines of /// and one of then is a //, the javadoc will 
> skip all the lines before the '//' without a warning.
>     It should be great if javadoc could emit a warning in that case.
>   - Inline backtick `, are hard to read so it's easy to miss the ending 
> backtick,
>     Again, here, I think I would like a warning if there is no end backtick 
> at the end of the line
> 
> regards,
> Rémi
> 
> Here is a full example:
>   
> https://github.com/forax/lazylr/blob/master/src/main/java/com/github/forax/lazylr/package-info.java
> 
> /// # Lazy LR — A Lightweight Runtime LR(1) Parser Library
> ///
> /// This package provides all the building blocks to define a context-free 
> grammar,
> /// tokenize raw text, and parse token streams into structured results at 
> runtime,
> /// without a separate code-generation step.
> ///
> /// ## Core Concepts
> ///
> /// A [com.github.forax.lazylr.Grammar] is a validated set of
> /// [com.github.forax.lazylr.Production] rules plus a
> /// start [com.github.forax.lazylr.NonTerminal].
> /// Productions are built from two kinds of [com.github.forax.lazylr.Symbol]s:
> /// [com.github.forax.lazylr.Terminal] (a concrete token, e.g. `"+"` or 
> `"num"`)
> /// and [com.github.forax.lazylr.NonTerminal] (an abstract construct, e.g. 
> `"E"`).
> ///
> /// [com.github.forax.lazylr.MetaGrammar] lets you describe tokens, 
> precedence,
> /// and productions in a compact text instead of building Java objects 
> programmaticaly:
> ///
> /// ```java
> /// var mg = MetaGrammar.load("""
> ///     tokens {
> ///       num: /[0-9]+/
> ///       /[ ]+/
> ///     }
> ///     precedence {
> ///       left:  '+'
> ///       left:  '*'
> ///       right: '^'
> ///     }
> ///     grammar {
> ///       E: num
> ///       E: E '+' E
> ///       E: E '*' E
> ///       E: E '^' E   %prec '^'
> ///     }
> ///     """);
> /// ```
> ///
> /// The text has three optional sections:
> /// - **`tokens`**: named terminals (`name: /regex/`) and unnamed
> ///   skip patterns (`/regex/`).
> /// - **`precedence`**: `left:` or `right:` lines, lowest first,
> ///   multiple terminals per line share the same level.
> /// - **`grammar`**: BNF-style rules; quoted literals like `'+'` are
> ///   auto-registered as terminals.
> ///   Lines with no right-hand side are epsilon productions,
> ///   `%prec TOKEN` overrides a production's default precedence.
> ///
> /// ## Typical Usage
> ///
> /// ```java
> /// // 1. Load the grammar
> /// MetaGrammar mg = MetaGrammar.load(grammarText);
> ///
> /// // 2. Optionally verify for conflicts
> /// mg.verify();
> ///
> /// // 3. Parse and evaluate
> /// String inputText = ...
> /// var result = mg.parse(inputText, new MyVisitor());
> /// ```
> ///
> /// ## Key Classes
> /// [com.github.forax.lazylr.LALRVerifier] performs a full offline LALR(1)
> /// analysis and can print the complete state automaton with conflict markers.
> /// This is the class used by [com.github.forax.lazylr.MetaGrammar#verify()].
> ///
> /// [com.github.forax.lazylr.Lexer] converts a `CharSequence` into
> /// a lazy `Iterator<Terminal>` using a longest-match rule, ties
> /// broken by declaration order.
> ///
> /// [com.github.forax.lazylr.Parser] implements a lazy LR(1) algorithm:
> /// states are computed on demand.
> /// Shift/reduce conflicts are resolved via a 
> [com.github.forax.lazylr.Precedence] map;
> /// unresolved conflicts cause a [com.github.forax.lazylr.ParsingException]
> /// during parsing.
> /// A call to 
> [com.github.forax.lazylr.MetaGrammar#parse(java.lang.CharSequence, 
> com.github.forax.lazylr.Visitor)()]
> /// creates a lexer and a parser.
> ///
> /// [com.github.forax.lazylr.Visitor] maps terminal and productions to 
> typechecked methods.
> /// When a terminal is shifted, the corresponding terminal method is called.
> /// When a production is reduced, the production method is called with the 
> values
> /// of the symbols of the production in left-to-right order.
> /// 
> [com.github.forax.lazylr.Visitor#reflect(java.lang.invoke.MethodHandles.Lookup,
>  com.github.forax.lazylr.Visitor)]
> /// creates an evaluator from a visitor using reflection.
> ///
> /// [com.github.forax.lazylr.Evaluator] maps parse events to a result
> /// of type `T`: `evaluate(Terminal)` is called on every shift,
> /// `evaluate(Production, List<T>)` on every reduction.
> /// For event-driven use without a result, prefer 
> [com.github.forax.lazylr.ParserListener].
> ///
> /// ## Thread Safety
> /// All classes are immutable and thread-safe except 
> [com.github.forax.lazylr.Parser],
> /// which is stateful and bound to the thread that uses it.
> ///
> /// [com.github.forax.lazylr.MetaGrammar] is thread-safe and can be shared 
> globally.
> ///
> /// For concurrent workloads, you can share a 
> [com.github.forax.lazylr.ParserFactory]
> /// and call [com.github.forax.lazylr.ParserFactory#createParser()]
> /// once per thread.
> ///
> /// @see com.github.forax.lazylr.Terminal
> /// @see com.github.forax.lazylr.Production
> /// @see com.github.forax.lazylr.Grammar
> /// @see com.github.forax.lazylr.MetaGrammar
> /// @see com.github.forax.lazylr.Visitor
> 
> 

Reply via email to