Skip to main content

meta_language/
language_parser.rs

1use crate::{
2    LinkNetwork, ParseConfiguration, docx_parser, language_catalog, lino_parser, pdf_parser,
3    structured_text_parser, tree_sitter_adapter,
4};
5
6/// Parser boundary that produces lossless links networks for source text.
7pub trait LanguageParser {
8    /// Parses `text` using the requested language label.
9    fn parse_source(
10        &self,
11        text: &str,
12        language: &str,
13        configuration: ParseConfiguration,
14    ) -> LinkNetwork;
15}
16
17/// Built-in parser registry used by [`LinkNetwork::parse`].
18#[derive(Clone, Copy, Debug, Default)]
19pub struct BuiltInLanguageParser;
20
21impl LanguageParser for BuiltInLanguageParser {
22    fn parse_source(
23        &self,
24        text: &str,
25        language: &str,
26        configuration: ParseConfiguration,
27    ) -> LinkNetwork {
28        if let Some(network) = parse_builtin_grammar(text, language, configuration) {
29            return network;
30        }
31
32        // Lean has a statically linked tree-sitter frontend. A build-time ABI
33        // mismatch is an implementation error, not permission to silently
34        // relabel its lexical fallback as a grammar CST.
35        if language.eq_ignore_ascii_case("lean") || language.eq_ignore_ascii_case("lean4") {
36            return tree_sitter_adapter::parse(text, language, configuration)
37                .expect("the built-in Lean tree-sitter grammar must initialize");
38        }
39
40        if let Some(network) = tree_sitter_adapter::parse(text, language, configuration) {
41            return network;
42        }
43
44        LinkNetwork::parse_lossless_text(text, language, configuration)
45    }
46}
47
48fn parse_builtin_grammar(
49    text: &str,
50    language: &str,
51    configuration: ParseConfiguration,
52) -> Option<LinkNetwork> {
53    let entry = language_catalog::language_entry(language)?;
54    match entry.name.as_str() {
55        "LiNo" => Some(lino_parser::parse(text, language, configuration)),
56        "txt" => Some(structured_text_parser::parse_plain(
57            text,
58            language,
59            configuration,
60        )),
61        "PDF" => Some(pdf_parser::parse(text, language, configuration)),
62        "DOCX" => Some(docx_parser::parse(text, language, configuration)),
63        _ if entry.family == "natural" => Some(structured_text_parser::parse_natural(
64            text,
65            language,
66            configuration,
67        )),
68        _ => None,
69    }
70}