Skip to main content

libmandoc_rs/
ast.rs

1//! Owned, renderer-neutral syntax data copied from a completed libmandoc parse.
2//!
3//! These types contain no C pointers and remain valid after the parser session
4//! has been released.  They deliberately describe source semantics rather than
5//! imposing a presentation model on downstream renderers.
6
7/// High-level macro package detected by libmandoc.
8#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
9#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub enum MacroSet {
11    /// No supported semantic macro package was detected.
12    None,
13    /// The source uses the semantic mdoc(7) macro package.
14    Mdoc,
15    /// The source uses the traditional man(7) macro package.
16    Man,
17}
18
19/// Renderer-neutral node role copied from the libmandoc syntax tree.
20#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
21#[derive(Clone, Copy, Debug, Eq, PartialEq)]
22pub enum NodeKind {
23    /// Synthetic root containing the complete syntax tree.
24    Root,
25    /// A macro block, such as a section or display.
26    Block,
27    /// The heading or term portion of a block.
28    Head,
29    /// The principal content portion of a block.
30    Body,
31    /// The trailing portion of a block, when the macro defines one.
32    Tail,
33    /// A leaf-level semantic macro invocation.
34    Element,
35    /// Literal source text after roff escape processing.
36    Text,
37    /// A source comment retained by libmandoc.
38    Comment,
39    /// A tbl(7) table node.
40    Table,
41    /// An eqn(7) equation node.
42    Equation,
43}
44
45/// Normalized mdoc list behavior copied independently of upstream enum values.
46#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
47#[derive(Clone, Copy, Debug, Eq, PartialEq)]
48pub enum NormalizedListKind {
49    /// An unordered list whose items carry bullets.
50    Bullet,
51    /// An ordered list whose items carry ordinal markers.
52    Ordered,
53    /// A term-and-description list.
54    Definition,
55    /// A list laid out as aligned columns.
56    Column,
57    /// A marker-free list.
58    Plain,
59}
60
61/// Whether an mdoc display preserves source line layout.
62#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
63#[derive(Clone, Copy, Debug, Eq, PartialEq)]
64pub enum DisplayKind {
65    /// Preserve input line breaks and horizontal whitespace.
66    Literal,
67    /// Reflow content as filled prose.
68    Filled,
69}
70
71/// Normalized font selected by an mdoc `Bf` block.
72#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
73#[derive(Clone, Copy, Debug, Eq, PartialEq)]
74pub enum NormalizedFont {
75    /// Typographic emphasis.
76    Emphasis,
77    /// Literal or fixed-width text.
78    Literal,
79    /// Symbolic text, conventionally rendered in bold.
80    Symbolic,
81}
82
83/// Explicit author layout mode selected by an mdoc `An` control macro.
84#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
85#[derive(Clone, Copy, Debug, Eq, PartialEq)]
86pub enum AuthorMode {
87    /// Render each subsequent author separately.
88    Split,
89    /// Keep subsequent authors in a continuous group.
90    NoSplit,
91}
92
93/// Horizontal alignment retained for one parsed tbl(7) cell.
94#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
95#[derive(Clone, Copy, Debug, Eq, PartialEq)]
96pub enum TableAlignment {
97    /// Align cell content to the left edge.
98    Left,
99    /// Center cell content horizontally.
100    Center,
101    /// Align cell content to the right edge.
102    Right,
103}
104
105/// Owned payload of one cell in a libmandoc table row.
106#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
107#[derive(Clone, Debug, Eq, PartialEq)]
108pub struct TableCell {
109    /// Visible cell content, or `None` for a spanning/empty cell.
110    pub text: Option<String>,
111    /// Number of logical columns occupied by the cell.
112    pub column_span: u16,
113    /// Number of logical rows occupied by the cell.
114    pub row_span: u16,
115    /// Horizontal alignment requested by tbl(7).
116    pub alignment: TableAlignment,
117}
118
119/// Source and renderer flags needed by a lowering or rendering pass.
120#[allow(clippy::struct_excessive_bools)]
121#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
122#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
123pub struct NodeFlags {
124    /// The node was synthesized by libmandoc rather than written explicitly.
125    pub generated: bool,
126    /// The node ends a sentence according to libmandoc punctuation rules.
127    pub sentence_end: bool,
128    /// The node must not contribute visible output.
129    pub no_print: bool,
130    /// The node belongs to a no-fill region that preserves source lines.
131    pub no_fill: bool,
132    /// libmandoc selected this node as a same-document destination.
133    pub deep_link_target: bool,
134    /// libmandoc renders a self-link for this destination.
135    pub permalink: bool,
136    /// This node begins a roff input line (`NODE_LINE`).
137    ///
138    /// Some man macros keep same-line layout arguments and next-line visible
139    /// content in one syntax head, so source-line role is semantic data.
140    pub line_start: bool,
141    /// This text node is opening punctuation and suppresses spacing after it.
142    pub delimiter_open: bool,
143    /// This text node is closing punctuation and suppresses spacing before it.
144    pub delimiter_close: bool,
145}
146
147/// An owned syntax node with no pointers into the C parser.
148#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
149#[derive(Clone, Debug, Eq, PartialEq)]
150pub struct Node {
151    /// Structural role of this node in the libmandoc tree.
152    pub kind: NodeKind,
153    /// Source macro name, without the leading dot, when applicable.
154    pub macro_name: Option<String>,
155    /// Visible text carried by a text node.
156    pub text: Option<String>,
157    /// Canonical same-document tag assigned during libmandoc validation.
158    pub tag: Option<String>,
159    /// One-based source line reported by libmandoc, or zero when unavailable.
160    pub line: u32,
161    /// One-based source column reported by libmandoc, or zero when unavailable.
162    pub column: u32,
163    /// Source and renderer flags attached to the node.
164    pub flags: NodeFlags,
165    /// Normalized list behavior for an mdoc list block.
166    pub list_kind: Option<NormalizedListKind>,
167    /// Fill behavior for an mdoc display block.
168    pub display_kind: Option<DisplayKind>,
169    /// Font selected by an mdoc font block.
170    pub font: Option<NormalizedFont>,
171    /// Author layout mode selected by an mdoc author macro.
172    pub author_mode: Option<AuthorMode>,
173    /// Whether the enclosing list requests compact vertical layout.
174    pub compact: bool,
175    /// Raw normalized display/list offset, including a roff scale suffix.
176    pub offset: Option<String>,
177    /// Normalized mdoc(7) list width, including its roff scale suffix.
178    pub width: Option<String>,
179    /// Cells copied from a tbl(7) row represented by this node.
180    pub table_cells: Vec<TableCell>,
181    /// Normalized eqn(7) expression carried by this node.
182    pub equation: Option<String>,
183    /// Child nodes in source order.
184    pub children: Vec<Self>,
185}
186
187/// Metadata copied from a completed libmandoc parse.
188#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
189#[derive(Clone, Debug, Default, Eq, PartialEq)]
190pub struct Metadata {
191    /// Canonical manual title, normally derived from `TH` or `Dt`.
192    pub title: Option<String>,
193    /// Native manual category such as `1` or `3p`.
194    pub section: Option<String>,
195    /// Manual volume or collection label.
196    pub volume: Option<String>,
197    /// Operating-system label declared by the page.
198    pub os: Option<String>,
199    /// Architecture qualifier declared by the page.
200    pub arch: Option<String>,
201    /// Primary display name extracted from the NAME section.
202    pub name: Option<String>,
203    /// Normalized source date when libmandoc recognized it.
204    pub date: Option<String>,
205    /// Target named by a top-level `.so` alias page.
206    pub alias_target: Option<String>,
207    /// Whether the parsed source produced a document body.
208    pub has_body: bool,
209}
210
211/// Complete owned output of the low-level parser, excluding diagnostics.
212#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
213#[derive(Clone, Debug, Eq, PartialEq)]
214pub struct Document {
215    /// Macro package selected for the source.
216    pub macro_set: MacroSet,
217    /// Metadata validated and normalized by libmandoc.
218    pub metadata: Metadata,
219    /// Root of the owned syntax tree.
220    pub root: Node,
221}