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