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//! - Annotation references: [::label]
27//! - Footnotes: [42]
28//! - Session references: [#2.1]
29//! - URLs: [https://example.com]
30//! - File paths: [./path/to/file]
31//! - TK placeholders: [TK] or [TK-identifier]
32//! - General references: [Section Title]
33//!
34//! Inline elements have these properties:
35//! - Clear start and end markers (single character tokens)
36//! - Can be nested (except literal types)
37//! - Cannot break parent element boundaries
38//! - No space allowed between marker and content
39//!
40//! Token Specifications
41//!
42//! Each inline type is defined by an InlineSpec that specifies:
43//! - The kind of inline element (from InlineKind enum)
44//! - Start and end tokens (characters)
45//! - Whether it's literal (no nested parsing inside)
46//! - Optional post-processing callback for complex logic
47//!
48//! Citation Parsing
49//!
50//! Citations are a specialized form of reference that follow academic citation format.
51//! The reference token [target] is post-processed to detect citations starting with @.
52//! Citation parsing is handled by [crate::lex::inlines::citations] which extracts:
53//! - Multiple citation keys (separated by ; or ,)
54//! - Optional page locators (p. or pp. followed by page ranges)
55//! - Page ranges in various formats: single pages, ranges, or lists
56
57/// The type of inline element
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
59pub enum InlineKind {
60 /// Strong/bold text: *text*
61 Strong,
62 /// Emphasized/italic text: _text_
63 Emphasis,
64 /// Inline code: `text` (literal, no nested inlines)
65 Code,
66 /// Mathematical notation: #formula# (literal, no nested inlines)
67 Math,
68 /// Reference (link, citation, footnote): \[target\] (literal, no nested inlines)
69 Reference,
70}
71
72impl std::fmt::Display for InlineKind {
73 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74 match self {
75 InlineKind::Strong => write!(f, "strong"),
76 InlineKind::Emphasis => write!(f, "emphasis"),
77 InlineKind::Code => write!(f, "code"),
78 InlineKind::Math => write!(f, "math"),
79 InlineKind::Reference => write!(f, "reference"),
80 }
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 #[test]
89 fn test_inline_kind_display() {
90 assert_eq!(format!("{}", InlineKind::Strong), "strong");
91 assert_eq!(format!("{}", InlineKind::Emphasis), "emphasis");
92 assert_eq!(format!("{}", InlineKind::Code), "code");
93 assert_eq!(format!("{}", InlineKind::Math), "math");
94 assert_eq!(format!("{}", InlineKind::Reference), "reference");
95 }
96
97 #[test]
98 fn test_inline_kind_equality() {
99 assert_eq!(InlineKind::Strong, InlineKind::Strong);
100 assert_ne!(InlineKind::Strong, InlineKind::Emphasis);
101 assert_ne!(InlineKind::Code, InlineKind::Math);
102 }
103}