smt_scope/formatter/
defns_const.rs

1use crate::NonMaxU32;
2
3use super::{defns::*, ConversionError, FormatterParseError};
4
5#[derive(Debug)]
6pub struct TermDisplayConst<'a> {
7    pub matcher: MatcherConst<'a>,
8    pub formatter: FormatterConst<'a>,
9}
10
11impl TryFrom<TermDisplayConst<'_>> for TermDisplay {
12    type Error = ConversionError;
13    fn try_from(t: TermDisplayConst) -> Result<Self, Self::Error> {
14        let matcher = Matcher::try_from(t.matcher)?;
15        let formatter = Formatter::try_from(t.formatter)?;
16        Self::new(matcher, formatter)
17    }
18}
19
20#[derive(Debug)]
21pub struct MatcherConst<'a> {
22    pub data: &'a str,
23    pub children: Option<NonMaxU32>,
24    pub kind: MatcherKindConst,
25}
26
27#[derive(Debug)]
28pub enum MatcherKindConst {
29    Exact,
30    Regex,
31}
32
33impl TryFrom<MatcherConst<'_>> for Matcher {
34    type Error = regex::Error;
35    fn try_from(m: MatcherConst<'_>) -> Result<Self, Self::Error> {
36        let kind = match m.kind {
37            MatcherKindConst::Exact => MatcherKind::Exact(m.data.to_string()),
38            MatcherKindConst::Regex => {
39                MatcherKind::Regex(RegexMatcher::new(format!("^(?:{})$", m.data))?)
40            }
41        };
42        Ok(Matcher {
43            children: m.children,
44            kind,
45        })
46    }
47}
48
49#[derive(Debug)]
50pub struct FormatterConst<'a> {
51    /// How strongly does the formatter bind its output from the left? Bracketed
52    /// outputs generally have a higher binding power than non-bracketed ones.
53    /// For example `{ ... }` can have a higher binding power, while `... + ...`
54    /// would typically have a lower binding power.
55    pub bind_power: BindPowerPair,
56
57    /// The formatter's output
58    pub outputs: [Option<SubFormatterConst<'a>>; 64],
59}
60
61impl TryFrom<FormatterConst<'_>> for Formatter {
62    type Error = FormatterParseError;
63    fn try_from(f: FormatterConst<'_>) -> Result<Self, Self::Error> {
64        let outputs: Vec<_> = f
65            .outputs
66            .into_iter()
67            .map_while(|o| o)
68            .map(SubFormatter::try_from)
69            .collect::<Result<_, _>>()?;
70        let mut self_ = Self {
71            bind_power: f.bind_power,
72            outputs,
73            max_capture: None,
74        };
75        self_.calculate_max_capture();
76        Ok(self_)
77    }
78}
79
80impl<'a> FormatterConst<'a> {
81    /// Shallow max capture calculation.
82    pub const fn max_capture(&self) -> Option<NonMaxU32> {
83        let mut max_capture = None::<NonMaxU32>;
84        let mut idx = 0;
85        while idx < self.outputs.len() {
86            let Some(output) = &self.outputs[idx] else {
87                break;
88            };
89            if let SubFormatterConst::Capture(idx) = output {
90                max_capture = match max_capture {
91                    Some(max) if max.get() >= idx.get() => Some(max),
92                    _ => Some(*idx),
93                };
94            }
95            idx += 1;
96        }
97        max_capture
98    }
99}
100
101#[derive(Debug)]
102pub enum SubFormatterConst<'a> {
103    /// A simple string output, will be printed literally.
104    String(SubFormatterString<'a>),
105    Single(SubFormatterSingle),
106    Repeat(SubFormatterRepeatConst<'a>),
107    Capture(NonMaxU32),
108}
109
110impl TryFrom<SubFormatterConst<'_>> for SubFormatter {
111    type Error = FormatterParseError;
112    fn try_from(sub: SubFormatterConst<'_>) -> Result<Self, Self::Error> {
113        let sf = match sub {
114            SubFormatterConst::String(s) => {
115                let c = s.control_deduplicate.then_some(CONTROL_CHARACTER);
116                let data = deduplicate_character(s.data, c);
117                SubFormatter::String(data)
118            }
119            SubFormatterConst::Single(s) => SubFormatter::Single {
120                path: s.path.into(),
121                index: s.index,
122                bind_power: s.bind_power,
123            },
124            SubFormatterConst::Repeat(s) => SubFormatter::Repeat(s.try_into()?),
125            SubFormatterConst::Capture(idx) => SubFormatter::Capture(idx),
126        };
127        Ok(sf)
128    }
129}
130
131impl From<[Option<ChildIndex>; 8]> for ChildPath {
132    fn from(path: [Option<ChildIndex>; 8]) -> Self {
133        ChildPath(path.into_iter().flatten().collect())
134    }
135}
136
137#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
138#[derive(Debug, Clone, PartialEq, Eq)]
139pub struct SubFormatterSingle {
140    pub path: [Option<ChildIndex>; 8],
141    pub index: ChildIndex,
142    /// How strongly does the surrounding context bind the child?
143    pub bind_power: BindPowerPair,
144}
145
146#[derive(Debug)]
147pub struct SubFormatterString<'a> {
148    pub data: &'a str,
149    pub control_deduplicate: bool,
150}
151
152#[derive(Debug)]
153pub struct SubFormatterRepeatConst<'a> {
154    pub range: ChildRange,
155    pub left_sep: SubFormatterRepeatSeparator<'a>,
156    pub middle_sep: SubFormatterRepeatSeparator<'a>,
157    pub right_sep: SubFormatterRepeatSeparator<'a>,
158    pub left: BindPower,
159    pub middle: BindPowerPair,
160    pub right: BindPower,
161}
162
163impl TryFrom<SubFormatterRepeatConst<'_>> for SubFormatterRepeat {
164    type Error = FormatterParseError;
165    fn try_from(sub: SubFormatterRepeatConst<'_>) -> Result<Self, Self::Error> {
166        let left_sep = String::from(sub.left_sep);
167        let left_sep = left_sep.parse::<Formatter>()?;
168        let middle_sep = String::from(sub.middle_sep);
169        let middle_sep = middle_sep.parse::<Formatter>()?;
170        let right_sep = String::from(sub.right_sep);
171        let right_sep = right_sep.parse::<Formatter>()?;
172        Ok(Self {
173            path: sub.range.path.into(),
174            from: sub.range.from,
175            to: sub.range.to,
176            left_sep,
177            middle_sep,
178            right_sep,
179            left: sub.left,
180            middle: sub.middle,
181            right: sub.right,
182        })
183    }
184}
185
186#[derive(Debug)]
187pub struct SubFormatterRepeatSeparator<'a> {
188    /// Does the separator contain `SEPARATOR_CHARACTER`s that should be
189    /// deduplicated?
190    pub separator_deduplicate: bool,
191    pub separator: &'a str,
192}
193
194impl From<SubFormatterRepeatSeparator<'_>> for String {
195    fn from(sep: SubFormatterRepeatSeparator<'_>) -> Self {
196        let c = sep.separator_deduplicate.then_some(SEPARATOR_CHARACTER);
197        deduplicate_character(sep.separator, c)
198    }
199}
200
201impl SubFormatterRepeatSeparator<'static> {
202    pub const fn default() -> Self {
203        Self {
204            separator_deduplicate: false,
205            separator: "",
206        }
207    }
208}
209
210#[derive(Debug)]
211pub struct ChildRange {
212    pub path: [Option<ChildIndex>; 8],
213    pub from: ChildIndex,
214    pub to: ChildIndex,
215}
216
217fn deduplicate_character(s: &str, c: Option<char>) -> String {
218    if let Some(c) = c {
219        let mut to: [u8; 4] = [0; 4];
220        let to = c.encode_utf8(&mut to);
221        s.replace([c, c], to)
222    } else {
223        s.to_string()
224    }
225}