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}