Skip to main content

lex_core/lex/token/
inline.rs

1//! Inline token types and specifications
2//!
3//!     This module defines the token types for inline parsing. Inline elements are span-based
4//!     elements that can start and end at arbitrary positions within text content. Unlike the
5//!     line-based tokens (core and line), inline tokens operate at the character level and can
6//!     be nested within each other.
7//!
8//!     For the complete inline grammar specification, see specs/v1/grammar-inline.lex.
9//!
10//!     Related token modules:
11//!     - [core](super::core) - Character and word-level tokens from the logos lexer
12//!     - [line](super::line) - Line-based tokens for the main parser
13//!
14//! Inline Token Types
15//!
16//!     These are the inline element types supported by lex:
17//!
18//!         - Strong: *text* (bold/emphasis)
19//!         - Emphasis: _text_ (italic)
20//!         - Code: `text` (monospace, literal)
21//!         - Math: #formula# (mathematical notation, literal)
22//!         - Reference: [target] (links, citations, footnotes)
23//!
24//!     References support multiple subtypes including:
25//!         - Citations: [@key] or [@key1; @key2, pp. 42-45]
26//!         - Footnotes: [^label] or [42]
27//!         - Session references: [#2.1]
28//!         - URLs: [https://example.com]
29//!         - File paths: [./path/to/file]
30//!         - TK placeholders: [TK] or [TK-identifier]
31//!         - General references: [Section Title]
32//!
33//!     Inline elements have these properties:
34//!     - Clear start and end markers (single character tokens)
35//!     - Can be nested (except literal types)
36//!     - Cannot break parent element boundaries
37//!     - No space allowed between marker and content
38//!
39//! Token Specifications
40//!
41//!     Each inline type is defined by an InlineSpec that specifies:
42//!     - The kind of inline element (from InlineKind enum)
43//!     - Start and end tokens (characters)
44//!     - Whether it's literal (no nested parsing inside)
45//!     - Optional post-processing callback for complex logic
46//!
47//! Citation Parsing
48//!
49//!     Citations are a specialized form of reference that follow academic citation format.
50//!     The reference token [target] is post-processed to detect citations starting with @.
51//!     Citation parsing is handled by [crate::lex::inlines::citations] which extracts:
52//!     - Multiple citation keys (separated by ; or ,)
53//!     - Optional page locators (p. or pp. followed by page ranges)
54//!     - Page ranges in various formats: single pages, ranges, or lists
55
56/// The type of inline element
57#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
58pub enum InlineKind {
59    /// Strong/bold text: *text*
60    Strong,
61    /// Emphasized/italic text: _text_
62    Emphasis,
63    /// Inline code: `text` (literal, no nested inlines)
64    Code,
65    /// Mathematical notation: #formula# (literal, no nested inlines)
66    Math,
67    /// Reference (link, citation, footnote): \[target\] (literal, no nested inlines)
68    Reference,
69}
70
71impl std::fmt::Display for InlineKind {
72    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73        match self {
74            InlineKind::Strong => write!(f, "strong"),
75            InlineKind::Emphasis => write!(f, "emphasis"),
76            InlineKind::Code => write!(f, "code"),
77            InlineKind::Math => write!(f, "math"),
78            InlineKind::Reference => write!(f, "reference"),
79        }
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86
87    #[test]
88    fn test_inline_kind_display() {
89        assert_eq!(format!("{}", InlineKind::Strong), "strong");
90        assert_eq!(format!("{}", InlineKind::Emphasis), "emphasis");
91        assert_eq!(format!("{}", InlineKind::Code), "code");
92        assert_eq!(format!("{}", InlineKind::Math), "math");
93        assert_eq!(format!("{}", InlineKind::Reference), "reference");
94    }
95
96    #[test]
97    fn test_inline_kind_equality() {
98        assert_eq!(InlineKind::Strong, InlineKind::Strong);
99        assert_ne!(InlineKind::Strong, InlineKind::Emphasis);
100        assert_ne!(InlineKind::Code, InlineKind::Math);
101    }
102}