Skip to main content

texform/
parser.rs

1use texform_core::parse::{self, ContextItem, ParseConfig};
2
3use crate::parse_result::ParseResult;
4
5#[derive(Clone, Debug)]
6pub struct Parser {
7    inner: parse::ParseContext,
8    default_config: ParseConfig,
9}
10
11pub struct ParserBuilder {
12    inner: parse::ParseContextBuilder,
13    default_config: ParseConfig,
14}
15
16#[derive(Debug)]
17pub struct ParserBuildError(parse::ParseContextBuildError);
18
19impl std::fmt::Display for ParserBuildError {
20    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21        match &self.0 {
22            parse::ParseContextBuildError::PackageLoad(error) => error.fmt(f),
23            parse::ParseContextBuildError::InvalidContextItem { name, source } => {
24                write!(f, "invalid context item {name}: {source}")
25            }
26        }
27    }
28}
29
30impl std::error::Error for ParserBuildError {}
31
32impl Parser {
33    pub fn builder() -> ParserBuilder {
34        ParserBuilder {
35            inner: parse::ParseContext::builder(),
36            default_config: ParseConfig::default(),
37        }
38    }
39
40    /// Parse a LaTeX formula with this parser's default configuration.
41    ///
42    /// The standalone [`Parser`] default is [`ParseConfig::LENIENT`]. Use
43    /// [`parse_with`](Self::parse_with) to override per call.
44    pub fn parse(&self, src: &str) -> ParseResult {
45        ParseResult::from_core(self.inner.parse(src, &self.default_config))
46    }
47
48    pub fn parse_with(&self, src: &str, config: &ParseConfig) -> ParseResult {
49        ParseResult::from_core(self.inner.parse(src, config))
50    }
51
52    pub fn lookup_command(
53        &self,
54        name: &str,
55        mode: parse::ContentMode,
56    ) -> Option<&parse::ActiveCommandRecord> {
57        self.inner.lookup_command(name, mode)
58    }
59
60    pub fn lookup_explicit_command(
61        &self,
62        name: &str,
63        mode: parse::ContentMode,
64    ) -> Option<&parse::ActiveCommandRecord> {
65        self.inner.lookup_explicit_command(name, mode)
66    }
67
68    pub fn lookup_character(
69        &self,
70        name: &str,
71        mode: parse::ContentMode,
72    ) -> Option<&parse::ActiveCharacterRecord> {
73        self.inner.lookup_character(name, mode)
74    }
75
76    pub fn lookup_env(
77        &self,
78        name: &str,
79        mode: parse::ContentMode,
80    ) -> Option<&parse::ActiveEnvironmentRecord> {
81        self.inner.lookup_env(name, mode)
82    }
83
84    pub fn is_delimiter_control(&self, name: &str) -> bool {
85        self.inner.is_delimiter_control(name)
86    }
87
88    pub fn knows_command_name(&self, name: &str) -> bool {
89        self.inner.knows_command_name(name)
90    }
91
92    pub fn knows_env_name(&self, name: &str) -> bool {
93        self.inner.knows_env_name(name)
94    }
95
96    pub fn knows_character_name(&self, name: &str) -> bool {
97        self.inner.knows_character_name(name)
98    }
99
100    pub(crate) fn inner(&self) -> &parse::ParseContext {
101        &self.inner
102    }
103
104    pub fn default_parse_config(&self) -> &ParseConfig {
105        &self.default_config
106    }
107}
108
109impl ParserBuilder {
110    pub fn packages(mut self, packages: &[&str]) -> Self {
111        self.inner = self.inner.packages(packages);
112        self
113    }
114
115    pub fn empty_knowledge(mut self) -> Self {
116        self.inner = parse::ParseContextBuilder::empty();
117        self
118    }
119
120    pub fn default_parse_config(mut self, config: ParseConfig) -> Self {
121        self.default_config = config;
122        self
123    }
124
125    pub fn item(mut self, item: impl Into<ContextItem>) -> Self {
126        self.inner = self.inner.insert_item(item);
127        self
128    }
129
130    pub fn insert_item(self, item: impl Into<ContextItem>) -> Self {
131        self.item(item)
132    }
133
134    pub fn remove_command(mut self, name: impl Into<String>) -> Self {
135        self.inner = self.inner.remove_command(name);
136        self
137    }
138
139    pub fn remove_environment(mut self, name: impl Into<String>) -> Self {
140        self.inner = self.inner.remove_environment(name);
141        self
142    }
143
144    pub fn remove_delimiter_control(mut self, name: impl Into<String>) -> Self {
145        self.inner = self.inner.remove_delimiter_control(name);
146        self
147    }
148
149    pub fn build(self) -> Result<Parser, ParserBuildError> {
150        Ok(Parser {
151            inner: self.inner.build().map_err(ParserBuildError)?,
152            default_config: self.default_config,
153        })
154    }
155}