----- 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 >> <, 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
