Module Wax_utils.TriviaSource

Parsing context for collecting comments and annotations.

Sourcetype position =
  1. | Line_start
  2. | Inline
Sourcetype kind =
  1. | Line_comment
  2. | Block_comment
  3. | Annotation
Sourcetype trivia =
  1. | Item of {
    1. content : string;
    2. kind : kind;
    }
  2. | Blank_line
Sourcetype entry = {
  1. anchor : int;
  2. trivia : trivia;
  3. position : position;
}
Sourcetype context
Sourcetype associated = {
  1. before : entry list;
  2. within : entry list;
  3. after : entry list;
}
Sourceval associate : ?only:(Ast.location, unit) Hashtbl.t -> context -> t * entry list

associate ctx associates trivia to locations. The second component holds the leftover comments that no location owns (trailing comments, or every comment when there are no locations); the caller prints them as tail trivia.

only restricts the association to the given set of locations — those the printer will actually look up (see get). Comments that would otherwise attach to a non-emitted node bubble up to an emitted one instead of being lost. Collect the set with a dry printing pass.

Sourceval make : unit -> context

Create a new trivia context.

Sourceval report_item : context -> kind -> string -> unit

report_item ctx kind content reports a comment or an annotation.

Sourceval report_newline : context -> unit

report_newline ctx reports a newline.

Sourceval report_token : context -> int -> unit

report_token ctx pos records that a meaningful token ending at byte pos has been encountered on the current line.

Sourceval with_pos : context -> Ast.location -> 'a -> ('a, Ast.location) Ast.annotated

with_pos ctx loc v wraps v with location loc.

Sourceval drop_in_ranges : context -> (int * int) list -> unit

drop_in_ranges ctx ranges removes every comment whose anchor falls within one of the half-open byte ranges [start, end). Used after conditional specialization splices out a branch: the comments inside the removed source span are discarded rather than re-attaching to a surviving neighbour. The ranges and comments are each sorted once and swept together in a single pass.

Association lookup

Looking up the trivia attached to a location. Rendering it to styled output lives in Styled_printer, which owns the colour theme.

Sourceval dummy_assoc : associated

The empty association (before, within and after all empty).

Sourceval get : ?collect:(Ast.location, unit) Hashtbl.t -> t -> seen:(Ast.location, unit) Hashtbl.t -> Ast.location option -> associated

get trivia ~seen loc returns the trivia associated with loc, with de-duplication: it returns dummy_assoc for None, a missing location, or a location already present in seen; on the first real hit it records the location in seen and returns its association. De-duplication is a no-op for formatters (each parser location occurs once) and prevents a comment from being emitted repeatedly when conversion replicates one source location onto several output nodes.

Sourceval drop_trailing_blank_lines : entry list -> entry list

Drop blank-line entries at the end of the list, so emitted tail trivia does not leave spurious blank lines at the end of the file.

Cross-format translation

The comment text stored by a lexer keeps the source syntax's delimiters (;; …/(; … ;) for WebAssembly, // …//* … */ for Wax). When trivia collected from one format is replayed onto an AST that is printed in the other format (during conversion), the delimiters must be rewritten.

Sourcetype comment_syntax = {
  1. line : string;
    (*

    line-comment prefix, e.g. ";;" or "//"

    *)
  2. block_open : string;
    (*

    block-comment opener, e.g. "(;" or "/*"

    *)
  3. block_close : string;
    (*

    block-comment closer, e.g. ";)" or "*/"

    *)
}
Sourceval wax_syntax : comment_syntax
Sourceval wat_syntax : comment_syntax
Sourceval retarget : src:comment_syntax -> dst:comment_syntax -> t -> entry list -> t * entry list

retarget ~src ~dst trivia tail rewrites every comment's delimiters from the src syntax to the dst syntax (line-comment prefix and block-comment delimiters), leaving blank lines and annotations untouched. Block delimiters are balanced in stored content, so a global swap preserves nesting.