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}