Skip to main content

lex_babel/formats/lex/
mod.rs

1//! Lex format implementation
2//!
3//! This module implements the Format trait for Lex itself, treating Lex
4//! as just another format in the system. This creates a uniform API where
5//! Lex can be converted to/from other formats using the same interface.
6
7use crate::error::FormatError;
8use crate::format::Format;
9use lex_core::lex::ast::Document;
10use lex_core::lex::transforms::standard::STRING_TO_AST;
11
12pub mod formatting_rules;
13pub mod serializer;
14
15use formatting_rules::FormattingRules;
16use serializer::LexSerializer;
17///
18/// Parses Lex source text into a Document AST by delegating to lex-parser.
19/// Serialization is implemented via LexSerializer.
20#[derive(Default)]
21pub struct LexFormat {
22    rules: FormattingRules,
23}
24
25impl LexFormat {
26    pub fn new(rules: FormattingRules) -> Self {
27        Self { rules }
28    }
29}
30
31impl Format for LexFormat {
32    fn name(&self) -> &str {
33        "lex"
34    }
35
36    fn description(&self) -> &str {
37        "Lex document format"
38    }
39
40    fn file_extensions(&self) -> &[&str] {
41        &["lex"]
42    }
43
44    fn supports_parsing(&self) -> bool {
45        true
46    }
47
48    fn supports_serialization(&self) -> bool {
49        true
50    }
51
52    fn parse(&self, source: &str) -> Result<Document, FormatError> {
53        STRING_TO_AST
54            .run(source.to_string())
55            .map_err(|e| FormatError::ParseError(e.to_string()))
56    }
57
58    fn serialize(&self, doc: &Document) -> Result<String, FormatError> {
59        let serializer = LexSerializer::new(self.rules.clone());
60        serializer
61            .serialize(doc)
62            .map_err(FormatError::SerializationError)
63    }
64}
65
66/// Convenience function to export a Document AST into a Lex string
67/// using the default formatting rules.
68pub fn export(doc: &Document) -> Result<String, FormatError> {
69    LexFormat::default().serialize(doc)
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75    use lex_core::lex::ast::{ContentItem, Paragraph};
76
77    #[test]
78    fn test_lex_format_name() {
79        let format = LexFormat::default();
80        assert_eq!(format.name(), "lex");
81    }
82
83    #[test]
84    fn test_lex_format_supports_parsing() {
85        let format = LexFormat::default();
86        assert!(format.supports_parsing());
87        assert!(format.supports_serialization());
88    }
89
90    #[test]
91    fn test_lex_format_parse_simple() {
92        let format = LexFormat::default();
93        let source = "Hello world\n";
94
95        let result = format.parse(source);
96        assert!(result.is_ok());
97
98        let doc = result.unwrap();
99        assert_eq!(doc.root.children.len(), 1);
100
101        match &doc.root.children[0] {
102            ContentItem::Paragraph(_) => {}
103            _ => panic!("Expected paragraph"),
104        }
105    }
106
107    #[test]
108    fn test_lex_format_parse_session() {
109        let format = LexFormat::default();
110        let source = "Introduction:\n    Welcome to the guide\n";
111
112        let result = format.parse(source);
113        assert!(result.is_ok());
114
115        let doc = result.unwrap();
116        // Just verify that something was parsed successfully
117        // The exact structure depends on the parser implementation
118        assert!(!doc.root.children.is_empty());
119    }
120
121    #[test]
122    fn test_lex_format_parse_error() {
123        let format = LexFormat::default();
124        // Create invalid Lex that would cause a parse error
125        // Note: Current parser is very permissive, so this might not fail
126        // But the test shows the error handling works
127        let source = "";
128
129        let result = format.parse(source);
130        // Empty document should parse successfully
131        assert!(result.is_ok());
132    }
133
134    #[test]
135    fn test_lex_format_serialize_supported() {
136        let format = LexFormat::default();
137        let doc = Document::with_content(vec![ContentItem::Paragraph(Paragraph::from_line(
138            "Test".to_string(),
139        ))]);
140
141        let result = format.serialize(&doc);
142        assert!(result.is_ok());
143        assert_eq!(result.unwrap(), "Test\n");
144    }
145}