----- Original Message -----
> From: "Pavel Rappo" <[email protected]>
> To: "Remi Forax" <[email protected]>
> Cc: "core-libs-dev" <[email protected]>
> Sent: Friday, June 19, 2026 5:24:26 PM
> Subject: Re: [External] : Markdown doc comments

> Rémi, why don't you bring it to javadoc-dev?

Hi Pavel,
I did not know that there was a javadoc-dev, so sorry for the noise.

regards,
Rémi

> 
> On Fri, Jun 19, 2026 at 4:09 PM Remi Forax <[email protected]> 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