flams_stex/quickparse/stex/
structs.rs

1use std::{
2    borrow::Cow,
3    collections::hash_map::Entry,
4    path::{Path, PathBuf},
5};
6
7use flams_ontology::{
8    languages::Language,
9    narration::{paragraphs::ParagraphKind, problems::CognitiveDimension},
10    uris::{
11        ArchiveId, ArchiveURIRef, ArchiveURITrait, ContentURI, ContentURITrait, DocumentURI,
12        ModuleURI, Name, PathURI, PathURITrait, SymbolURI, URIRefTrait,
13    },
14};
15use flams_system::backend::{AnyBackend, Backend};
16use flams_utils::{
17    id_counters::IdCounter,
18    impossible,
19    parsing::ParseStr,
20    prelude::HMap,
21    sourcerefs::{LSPLineCol, SourcePos, SourceRange},
22    vecmap::{VecMap, VecSet},
23};
24use smallvec::SmallVec;
25
26use crate::quickparse::{
27    latex::{
28        rules::{AnyEnv, AnyMacro, DynMacro},
29        Environment, FromLaTeXToken, Group, GroupState, Groups, LaTeXParser, Macro, ParserState,
30    },
31    stex::rules::{IncludeProblemArg, MHGraphicsArg},
32};
33
34use super::{
35    rules::{
36        MathStructureArg, NotationArg, ParagraphArg, ProblemArg, SModuleArg, SymdeclArg, SymdefArg,
37        TextSymdeclArg, VardefArg,
38    },
39    DiagnosticLevel, STeXParseData,
40};
41
42#[allow(clippy::large_enum_variant)]
43#[derive(Debug, serde::Serialize)]
44pub enum STeXToken<Pos: SourcePos> {
45    ImportModule {
46        archive_range: Option<SourceRange<Pos>>,
47        path_range: SourceRange<Pos>,
48        module: ModuleReference,
49        full_range: SourceRange<Pos>,
50        token_range: SourceRange<Pos>,
51    },
52    UseModule {
53        archive_range: Option<SourceRange<Pos>>,
54        path_range: SourceRange<Pos>,
55        module: ModuleReference,
56        full_range: SourceRange<Pos>,
57        token_range: SourceRange<Pos>,
58    },
59    UseStructure {
60        structure: SymbolReference<Pos>,
61        structure_range: SourceRange<Pos>,
62        full_range: SourceRange<Pos>,
63        token_range: SourceRange<Pos>,
64    },
65    SetMetatheory {
66        archive_range: Option<SourceRange<Pos>>,
67        path_range: SourceRange<Pos>,
68        module: ModuleReference,
69        full_range: SourceRange<Pos>,
70        token_range: SourceRange<Pos>,
71    },
72    Inputref {
73        archive: Option<(ArchiveId, SourceRange<Pos>)>,
74        filepath: (std::sync::Arc<str>, SourceRange<Pos>),
75        full_range: SourceRange<Pos>,
76        token_range: SourceRange<Pos>,
77    },
78    IncludeProblem {
79        filepath: (std::sync::Arc<str>, SourceRange<Pos>),
80        archive: Option<(ArchiveId, SourceRange<Pos>)>,
81        full_range: SourceRange<Pos>,
82        token_range: SourceRange<Pos>,
83        args: Vec<IncludeProblemArg<Pos>>,
84    },
85    MHGraphics {
86        filepath: (std::sync::Arc<str>, SourceRange<Pos>),
87        archive: Option<(ArchiveId, SourceRange<Pos>)>,
88        full_range: SourceRange<Pos>,
89        token_range: SourceRange<Pos>,
90        args: Vec<MHGraphicsArg<Pos>>,
91    },
92    MHInput {
93        archive: Option<(ArchiveId, SourceRange<Pos>)>,
94        filepath: (std::sync::Arc<str>, SourceRange<Pos>),
95        full_range: SourceRange<Pos>,
96        token_range: SourceRange<Pos>,
97    },
98    Module {
99        uri: ModuleURI,
100        rules: ModuleRules<Pos>,
101        name_range: SourceRange<Pos>,
102        opts: Vec<SModuleArg<Pos, Self>>,
103        sig: Option<Language>,
104        meta_theory: Option<ModuleReference>,
105        full_range: SourceRange<Pos>,
106        children: Vec<STeXToken<Pos>>,
107        smodule_range: SourceRange<Pos>,
108    },
109    MathStructure {
110        uri: SymbolReference<Pos>,
111        extends: Vec<(SymbolReference<Pos>, SourceRange<Pos>)>,
112        name_range: SourceRange<Pos>,
113        opts: Vec<MathStructureArg<Pos, Self>>,
114        full_range: SourceRange<Pos>,
115        children: Vec<STeXToken<Pos>>,
116        mathstructure_range: SourceRange<Pos>,
117    },
118    ConservativeExt {
119        uri: SymbolReference<Pos>,
120        ext_range: SourceRange<Pos>,
121        full_range: SourceRange<Pos>,
122        children: Vec<STeXToken<Pos>>,
123        extstructure_range: SourceRange<Pos>,
124    },
125    MorphismEnv {
126        full_range: SourceRange<Pos>,
127        env_range: SourceRange<Pos>,
128        name_range: SourceRange<Pos>,
129        uri: SymbolURI,
130        star: bool,
131        domain: ModuleOrStruct<Pos>,
132        domain_range: SourceRange<Pos>,
133        kind: MorphismKind,
134        children: Vec<STeXToken<Pos>>,
135    },
136    InlineMorphism {
137        full_range: SourceRange<Pos>,
138        token_range: SourceRange<Pos>,
139        name_range: SourceRange<Pos>,
140        uri: SymbolURI,
141        star: bool,
142        domain: ModuleOrStruct<Pos>,
143        domain_range: SourceRange<Pos>,
144        kind: MorphismKind,
145        assignments: Vec<InlineMorphAssign<Pos, Self>>,
146    },
147    Paragraph {
148        kind: ParagraphKind,
149        full_range: SourceRange<Pos>,
150        name_range: SourceRange<Pos>,
151        symbol: Option<SymbolReference<Pos>>,
152        parsed_args: Vec<ParagraphArg<Pos, STeXToken<Pos>>>,
153        children: Vec<STeXToken<Pos>>,
154    },
155    Problem {
156        sub: bool,
157        full_range: SourceRange<Pos>,
158        name_range: SourceRange<Pos>,
159        parsed_args: Vec<ProblemArg<Pos, STeXToken<Pos>>>,
160        children: Vec<STeXToken<Pos>>,
161    },
162    InlineParagraph {
163        kind: ParagraphKind,
164        full_range: SourceRange<Pos>,
165        token_range: SourceRange<Pos>,
166        symbol: Option<SymbolReference<Pos>>,
167        parsed_args: Vec<ParagraphArg<Pos, STeXToken<Pos>>>,
168        children: Vec<STeXToken<Pos>>,
169        children_range: SourceRange<Pos>,
170    },
171    #[allow(clippy::type_complexity)]
172    Symdecl {
173        uri: SymbolReference<Pos>,
174        main_name_range: SourceRange<Pos>,
175        full_range: SourceRange<Pos>,
176        parsed_args: Vec<SymdeclArg<Pos, Self>>,
177        token_range: SourceRange<Pos>,
178    },
179    #[allow(clippy::type_complexity)]
180    TextSymdecl {
181        uri: SymbolReference<Pos>,
182        main_name_range: SourceRange<Pos>,
183        full_range: SourceRange<Pos>,
184        parsed_args: Vec<TextSymdeclArg<Pos, Self>>,
185        token_range: SourceRange<Pos>,
186    },
187    Notation {
188        uri: SmallVec<SymbolReference<Pos>, 1>,
189        token_range: SourceRange<Pos>,
190        name_range: SourceRange<Pos>,
191        notation_args: Vec<NotationArg<Pos, Self>>,
192        full_range: SourceRange<Pos>,
193    },
194    RenameDecl {
195        uri: SymbolReference<Pos>,
196        token_range: SourceRange<Pos>,
197        orig_range: SourceRange<Pos>,
198        name_range: Option<SourceRange<Pos>>,
199        macroname_range: SourceRange<Pos>,
200        full_range: SourceRange<Pos>,
201    },
202    Assign {
203        uri: SymbolReference<Pos>,
204        token_range: SourceRange<Pos>,
205        orig_range: SourceRange<Pos>,
206        full_range: SourceRange<Pos>,
207    },
208    #[allow(clippy::type_complexity)]
209    Symdef {
210        uri: SymbolReference<Pos>,
211        main_name_range: SourceRange<Pos>,
212        full_range: SourceRange<Pos>,
213        parsed_args: Vec<SymdefArg<Pos, Self>>,
214        token_range: SourceRange<Pos>,
215    },
216    #[allow(clippy::type_complexity)]
217    Vardef {
218        name: Name,
219        main_name_range: SourceRange<Pos>,
220        full_range: SourceRange<Pos>,
221        parsed_args: Vec<VardefArg<Pos, Self>>,
222        token_range: SourceRange<Pos>,
223    },
224    #[allow(clippy::type_complexity)]
225    Varseq {
226        name: Name,
227        main_name_range: SourceRange<Pos>,
228        full_range: SourceRange<Pos>,
229        parsed_args: Vec<VardefArg<Pos, Self>>,
230        token_range: SourceRange<Pos>,
231    },
232    SemanticMacro {
233        uri: SymbolReference<Pos>,
234        argnum: u8,
235        full_range: SourceRange<Pos>,
236        token_range: SourceRange<Pos>,
237    },
238    VariableMacro {
239        name: Name,
240        orig: SourceRange<Pos>,
241        argnum: u8,
242        sequence: bool,
243        full_range: SourceRange<Pos>,
244        token_range: SourceRange<Pos>,
245    },
246    SymName {
247        uri: SmallVec<SymbolReference<Pos>, 1>,
248        full_range: SourceRange<Pos>,
249        token_range: SourceRange<Pos>,
250        name_range: SourceRange<Pos>,
251        mode: SymnameMode<Pos>,
252    },
253    Symuse {
254        uri: SmallVec<SymbolReference<Pos>, 1>,
255        full_range: SourceRange<Pos>,
256        token_range: SourceRange<Pos>,
257        name_range: SourceRange<Pos>,
258    },
259    Definiens {
260        uri: SmallVec<SymbolReference<Pos>, 1>,
261        full_range: SourceRange<Pos>,
262        token_range: SourceRange<Pos>,
263        name_range: Option<SourceRange<Pos>>,
264    },
265    Defnotation {
266        full_range: SourceRange<Pos>,
267    },
268    Svar {
269        name: Name,
270        full_range: SourceRange<Pos>,
271        token_range: SourceRange<Pos>,
272        name_range: Option<SourceRange<Pos>>,
273        arg_range: SourceRange<Pos>,
274    },
275    Symref {
276        uri: SmallVec<SymbolReference<Pos>, 1>,
277        full_range: SourceRange<Pos>,
278        token_range: SourceRange<Pos>,
279        name_range: SourceRange<Pos>,
280        text: (SourceRange<Pos>, Vec<STeXToken<Pos>>),
281    },
282    Precondition {
283        uri: SmallVec<SymbolReference<Pos>, 1>,
284        full_range: SourceRange<Pos>,
285        token_range: SourceRange<Pos>,
286        dim_range: SourceRange<Pos>,
287        symbol_range: SourceRange<Pos>,
288        dim: CognitiveDimension,
289    },
290    Objective {
291        uri: SmallVec<SymbolReference<Pos>, 1>,
292        full_range: SourceRange<Pos>,
293        token_range: SourceRange<Pos>,
294        dim_range: SourceRange<Pos>,
295        symbol_range: SourceRange<Pos>,
296        dim: CognitiveDimension,
297    },
298    Vec(Vec<STeXToken<Pos>>),
299}
300
301impl<'a, P: SourcePos> FromLaTeXToken<'a, P, &'a str> for STeXToken<P> {
302    fn from_comment(_: SourceRange<P>) -> Option<Self> {
303        None
304    }
305    fn from_group(_: SourceRange<P>, v: Vec<Self>) -> Option<Self> {
306        Some(Self::Vec(v))
307    }
308    fn from_math(_: bool, _: SourceRange<P>, v: Vec<Self>) -> Option<Self> {
309        Some(Self::Vec(v))
310    }
311    fn from_control_sequence(_: P, _: &'a str) -> Option<Self> {
312        None
313    }
314    fn from_text(_: SourceRange<P>, _: &'a str) -> Option<Self> {
315        None
316    }
317    fn from_macro_application(_: Macro<'a, P, &'a str>) -> Option<Self> {
318        None
319    }
320    fn from_environment(e: Environment<'a, P, &'a str, Self>) -> Option<Self> {
321        Some(Self::Vec(e.children))
322    }
323}
324
325#[derive(Copy, Clone, Debug, serde::Serialize)]
326pub enum MorphismKind {
327    CopyModule,
328    InterpretModule,
329}
330
331#[derive(Debug, Clone, serde::Serialize)]
332pub enum SymnameMode<Pos: SourcePos> {
333    Cap {
334        post: Option<(SourceRange<Pos>, SourceRange<Pos>, String)>,
335    },
336    PostS {
337        pre: Option<(SourceRange<Pos>, SourceRange<Pos>, String)>,
338    },
339    CapAndPostS,
340    PrePost {
341        pre: Option<(SourceRange<Pos>, SourceRange<Pos>, String)>,
342        post: Option<(SourceRange<Pos>, SourceRange<Pos>, String)>,
343    },
344}
345
346#[derive(Debug, Clone, serde::Serialize)]
347pub struct InlineMorphAssign<Pos: SourcePos, T> {
348    pub symbol: SymbolReference<Pos>,
349    pub symbol_range: SourceRange<Pos>,
350    pub first: Option<(Pos, InlineMorphAssKind<Pos, T>)>,
351    pub second: Option<(Pos, InlineMorphAssKind<Pos, T>)>,
352}
353
354impl<Pos: SourcePos, T1> InlineMorphAssign<Pos, T1> {
355    pub fn into_other<T2>(
356        self,
357        mut cont: impl FnMut(Vec<T1>) -> Vec<T2>,
358    ) -> InlineMorphAssign<Pos, T2> {
359        let InlineMorphAssign {
360            symbol,
361            symbol_range,
362            first,
363            second,
364        } = self;
365        InlineMorphAssign {
366            symbol,
367            symbol_range,
368            first: first.map(|(p, k)| {
369                (
370                    p,
371                    match k {
372                        InlineMorphAssKind::Rename(a, b, c) => InlineMorphAssKind::Rename(a, b, c),
373                        InlineMorphAssKind::Df(v) => InlineMorphAssKind::Df(cont(v)),
374                    },
375                )
376            }),
377            second: second.map(|(p, k)| {
378                (
379                    p,
380                    match k {
381                        InlineMorphAssKind::Rename(a, b, c) => InlineMorphAssKind::Rename(a, b, c),
382                        InlineMorphAssKind::Df(v) => InlineMorphAssKind::Df(cont(v)),
383                    },
384                )
385            }),
386        }
387    }
388}
389
390pub struct InlineMorphAssIter<'a, Pos: SourcePos, T>(
391    std::slice::Iter<'a, InlineMorphAssign<Pos, T>>,
392    Option<std::slice::Iter<'a, T>>,
393);
394impl<'a, Pos: SourcePos, T> InlineMorphAssIter<'a, Pos, T> {
395    pub fn new(v: &'a [InlineMorphAssign<Pos, T>]) -> Self {
396        Self(v.iter(), None)
397    }
398}
399impl<'a, Pos: SourcePos, T> Iterator for InlineMorphAssIter<'a, Pos, T> {
400    type Item = &'a T;
401    fn next(&mut self) -> Option<Self::Item> {
402        loop {
403            if let Some(n) = &mut self.1 {
404                if let Some(n) = n.next() {
405                    return Some(n);
406                }
407            }
408            if let Some(a) = self.0.next() {
409                if let Some((_, InlineMorphAssKind::Df(v))) = &a.first {
410                    self.1 = Some(v.iter());
411                    continue;
412                }
413                if let Some((_, InlineMorphAssKind::Df(v))) = &a.second {
414                    self.1 = Some(v.iter());
415                }
416            } else {
417                return None;
418            }
419        }
420    }
421}
422
423#[derive(Debug, Clone, serde::Serialize)]
424pub enum InlineMorphAssKind<Pos: SourcePos, T> {
425    Df(Vec<T>),
426    Rename(Option<(Name, SourceRange<Pos>)>, Box<str>, SourceRange<Pos>),
427}
428
429#[derive(Debug, Clone, serde::Serialize)]
430pub struct SymbolReference<Pos: SourcePos> {
431    pub uri: SymbolURI,
432    pub filepath: Option<std::sync::Arc<Path>>,
433    pub range: SourceRange<Pos>,
434}
435
436#[derive(Debug, Clone, serde::Serialize)]
437pub struct ModuleReference {
438    pub uri: ModuleURI,
439    pub in_doc: DocumentURI,
440    pub rel_path: Option<std::sync::Arc<str>>,
441    pub full_path: Option<std::sync::Arc<Path>>,
442}
443impl ModuleReference {
444    /*
445    #[must_use]
446    pub fn doc_uri(&self) -> Option<DocumentURI> {
447      let rel_path = &**self.rel_path.as_ref()?;
448      let (path,name) = rel_path.rsplit_once('/').map_or_else(
449        || (None,rel_path),
450        |(path,name)| (Some(path),name)
451      );
452      let path = path.map_or_else(
453        || Ok(self.uri.archive_uri().owned().into()),
454        |path| self.uri.archive_uri().owned() % path
455      ).ok()?;
456      let (name,language) = name.rsplit_once('.')
457        .map_or((name,Language::default()), |(name,l)| (name,l.parse().unwrap_or_default()));
458      let name = if name.ends_with(Into::<&str>::into(language)) && name.len() > 3 {
459        &name[..name.len() - 3]
460      } else {name};
461      (path & (name,language)).ok()
462    }
463     */
464}
465
466pub enum GetModuleError {
467    NotFound(ModuleURI),
468    Cycle(Vec<DocumentURI>),
469}
470impl std::fmt::Display for GetModuleError {
471    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
472        match self {
473            GetModuleError::NotFound(uri) => write!(f, "module not found: {}", uri),
474            GetModuleError::Cycle(cycle) => write!(
475                f,
476                "cycle in module dependencies: {}",
477                cycle
478                    .iter()
479                    .map(|uri| uri.to_string())
480                    .collect::<Vec<_>>()
481                    .join(" -> ")
482            ),
483        }
484    }
485}
486
487pub trait STeXModuleStore {
488    const FULL: bool;
489    fn get_module(
490        &mut self,
491        module: &ModuleReference,
492        in_path: Option<&std::sync::Arc<Path>>,
493    ) -> Result<STeXParseData, GetModuleError>;
494}
495impl STeXModuleStore for () {
496    const FULL: bool = false;
497    #[inline]
498    fn get_module(
499        &mut self,
500        r: &ModuleReference,
501        _: Option<&std::sync::Arc<Path>>,
502    ) -> Result<STeXParseData, GetModuleError> {
503        Err(GetModuleError::NotFound(r.uri.clone()))
504    }
505}
506
507#[derive(Debug, serde::Serialize)]
508pub enum ModuleRule<Pos: SourcePos> {
509    Import(ModuleReference),
510    Symbol(SymbolRule<Pos>),
511    Structure {
512        symbol: SymbolRule<Pos>,
513        //reference:ModuleReference,
514        rules: ModuleRules<Pos>,
515    },
516    ConservativeExt(SymbolReference<Pos>, ModuleRules<Pos>),
517    StructureImport(SymbolReference<Pos>),
518}
519
520#[derive(Debug, Clone, serde::Serialize)]
521pub struct SymbolRule<Pos: SourcePos> {
522    pub uri: SymbolReference<Pos>,
523    pub macroname: Option<std::sync::Arc<str>>,
524    pub has_tp: bool,
525    pub has_df: bool,
526    pub argnum: u8,
527}
528impl<Pos: SourcePos> SymbolRule<Pos> {
529    fn as_rule<'a, MS: STeXModuleStore, Err: FnMut(String, SourceRange<Pos>, DiagnosticLevel)>(
530        &self,
531    ) -> Option<(
532        Cow<'a, str>,
533        AnyMacro<'a, ParseStr<'a, Pos>, STeXToken<Pos>, Err, STeXParseState<'a, Pos, MS>>,
534    )> {
535        self.macroname.as_ref().map(|m| {
536            (
537                m.to_string().into(),
538                AnyMacro::Ext(DynMacro {
539                    ptr: super::rules::semantic_macro as _,
540                    arg: MacroArg::Symbol(self.uri.clone(), self.argnum),
541                }),
542            )
543        })
544    }
545}
546impl<Pos: SourcePos> Eq for SymbolReference<Pos> {}
547impl<Pos: SourcePos> PartialEq for SymbolReference<Pos> {
548    #[inline]
549    fn eq(&self, other: &Self) -> bool {
550        self.uri == other.uri
551    }
552}
553
554#[derive(Debug, Clone, serde::Serialize)]
555pub struct ModuleRules<Pos: SourcePos> {
556    pub rules: std::sync::Arc<[ModuleRule<Pos>]>,
557}
558impl<Pos: SourcePos> Default for ModuleRules<Pos> {
559    #[inline]
560    fn default() -> Self {
561        Self {
562            rules: std::sync::Arc::new([]),
563        }
564    }
565}
566
567pub struct STeXParseState<'a, Pos: SourcePos, MS: STeXModuleStore> {
568    pub(super) archive: Option<ArchiveURIRef<'a>>,
569    pub(super) in_path: Option<std::sync::Arc<Path>>,
570    pub(super) doc_uri: &'a DocumentURI,
571    pub(super) backend: &'a AnyBackend,
572    pub(super) language: Language,
573    pub(super) dependencies: Vec<std::sync::Arc<Path>>,
574    pub(super) modules: SmallVec<(ModuleURI, ModuleRules<Pos>), 1>,
575    module_store: MS,
576    name_counter: IdCounter,
577}
578impl<'a, MS: STeXModuleStore> STeXParseState<'a, LSPLineCol, MS> {
579    fn load_module(
580        &mut self,
581        module: &ModuleReference,
582    ) -> Result<ModuleRules<LSPLineCol>, GetModuleError> {
583        for (uri, m) in &self.modules {
584            if *uri == module.uri {
585                return Ok(m.clone());
586            }
587        }
588        /*if let Some(fp) = &module.full_path {
589          self.dependencies.push(fp.clone());
590        }*/
591        match self.module_store.get_module(module, self.in_path.as_ref()) {
592            Ok(d) => {
593                for (uri, m) in d.lock().modules.iter() {
594                    if *uri == module.uri {
595                        return Ok(m.clone());
596                    }
597                }
598                Err(GetModuleError::NotFound(module.uri.clone()))
599            }
600            Err(e) => Err(e),
601        }
602    }
603
604    fn load_rules<'b, Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel)>(
605        mod_ref: ModuleReference,
606        irules: ModuleRules<LSPLineCol>,
607        prev: &[STeXGroup<'a, MS, LSPLineCol, Err>],
608        current: &mut HMap<
609            Cow<'a, str>,
610            AnyMacro<'a, ParseStr<'a, LSPLineCol>, STeXToken<LSPLineCol>, Err, Self>,
611        >,
612        changes: &mut HMap<
613            Cow<'a, str>,
614            Option<AnyMacro<'a, ParseStr<'a, LSPLineCol>, STeXToken<LSPLineCol>, Err, Self>>,
615        >,
616        semantic_rules: &mut Vec<SemanticRule<LSPLineCol>>,
617        f: &mut impl FnMut(&ModuleReference) -> Option<ModuleRules<LSPLineCol>>,
618        cycles_count: u16,
619    ) -> Result<(), ()> {
620        if cycles_count >= 500 {
621            return Err(());
622        }
623        if Self::has_module(prev, semantic_rules, &mod_ref) {
624            return Ok(());
625        }
626        for rule in irules.rules.iter() {
627            match rule {
628                ModuleRule::Import(m) => {
629                    if let Some(rls) = f(m) {
630                        Self::load_rules(
631                            m.clone(),
632                            rls.clone(),
633                            prev,
634                            current,
635                            changes,
636                            semantic_rules,
637                            f,
638                            cycles_count + 1,
639                        )?;
640                    }
641                }
642                ModuleRule::Symbol(rule) if MS::FULL => {
643                    //symbols.push(rule.clone());
644                    if let Some((name, rule)) = rule.as_rule() {
645                        let old = current.insert(name.clone(), rule);
646                        if let Entry::Vacant(e) = changes.entry(name) {
647                            e.insert(old);
648                        }
649                    }
650                }
651                ModuleRule::Structure { symbol, rules } => {
652                    semantic_rules.push(SemanticRule::Structure {
653                        symbol: symbol.clone(),
654                        rules: rules.clone(),
655                    });
656                    if MS::FULL {
657                        if let Some((name, rule)) = symbol.as_rule() {
658                            let old = current.insert(name.clone(), rule);
659                            if let Entry::Vacant(e) = changes.entry(name) {
660                                e.insert(old);
661                            }
662                        }
663                    }
664                }
665                ModuleRule::ConservativeExt(s, rls) => {
666                    semantic_rules.push(SemanticRule::ConservativeExt(s.clone(), rls.clone()))
667                }
668                _ => (),
669            }
670        }
671        semantic_rules.push(SemanticRule::Module(mod_ref, irules));
672        Ok(())
673    }
674
675    fn has_module<Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel)>(
676        prev: &[STeXGroup<'a, MS, LSPLineCol, Err>],
677        current: &Vec<SemanticRule<LSPLineCol>>,
678        mod_ref: &ModuleReference,
679    ) -> bool {
680        if current
681            .iter()
682            .any(|e| matches!(e,SemanticRule::Module(r,_) if r.uri == mod_ref.uri))
683        {
684            return true;
685        }
686        for p in prev.iter().rev() {
687            if matches!(&p.kind,GroupKind::Module { uri, .. } if *uri == mod_ref.uri) {
688                return true;
689            }
690            if p.semantic_rules
691                .iter()
692                .any(|e| matches!(e,SemanticRule::Module(r,_) if r.uri == mod_ref.uri))
693            {
694                return true;
695            }
696        }
697        false
698    }
699
700    pub fn add_use<Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel)>(
701        &mut self,
702        module: &ModuleReference,
703        groups: Groups<'a, '_, ParseStr<'a, LSPLineCol>, STeXToken<LSPLineCol>, Err, Self>,
704        range: SourceRange<LSPLineCol>,
705    ) {
706        let groups_ls = &mut **groups.groups;
707        assert!(!groups_ls.is_empty());
708        let i = groups_ls.len() - 1;
709        let (prev, after) = groups_ls.split_at_mut(i);
710        let prev = &*prev;
711        let g = &mut after[0];
712        match self.load_module(module) {
713            Ok(irules) => {
714                if Self::load_rules(
715                    module.clone(),
716                    irules,
717                    prev,
718                    groups.rules,
719                    &mut g.inner.macro_rule_changes,
720                    &mut g.semantic_rules,
721                    &mut |m| match self.load_module(m) {
722                        Ok(r) => Some(r),
723                        Err(e) => {
724                            groups
725                                .tokenizer
726                                .problem(range.start, e, DiagnosticLevel::Error);
727                            None
728                        }
729                    },
730                    0,
731                )
732                .is_err()
733                {
734                    groups
735                        .tokenizer
736                        .problem(range.start, "Import cycle", DiagnosticLevel::Error)
737                }
738            }
739            Err(e) => groups
740                .tokenizer
741                .problem(range.start, e, DiagnosticLevel::Error),
742        }
743    }
744
745    fn has_structure<Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel)>(
746        prev: &[STeXGroup<'a, MS, LSPLineCol, Err>],
747        current: &Vec<SemanticRule<LSPLineCol>>,
748        sym_ref: &SymbolReference<LSPLineCol>,
749    ) -> bool {
750        if current
751            .iter()
752            .any(|e| matches!(e,SemanticRule::StructureImport(r,_) if r.uri == sym_ref.uri))
753        {
754            return true;
755        }
756        for p in prev.iter().rev() {
757            if p.semantic_rules
758                .iter()
759                .any(|e| matches!(e,SemanticRule::StructureImport(r,_) if r.uri == sym_ref.uri))
760            {
761                return true;
762            }
763        }
764        false
765    }
766    fn load_structure<Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel)>(
767        symbol: &SymbolReference<LSPLineCol>,
768        prev: &[STeXGroup<'a, MS, LSPLineCol, Err>],
769        semantic_rules: &Vec<SemanticRule<LSPLineCol>>,
770    ) -> Option<ModuleRules<LSPLineCol>> {
771        for r in semantic_rules.iter().rev() {
772            match r {
773                SemanticRule::Structure {
774                    symbol: isymbol,
775                    rules,
776                    ..
777                } if isymbol.uri.uri == symbol.uri => return Some(rules.clone()),
778                _ => (),
779            }
780        }
781        for g in prev.iter().rev() {
782            for r in g.semantic_rules.iter().rev() {
783                match r {
784                    SemanticRule::Structure {
785                        symbol: isymbol,
786                        rules,
787                        ..
788                    } if isymbol.uri.uri == symbol.uri => return Some(rules.clone()),
789                    _ => (),
790                }
791            }
792        }
793        None
794    }
795
796    fn load_structure_rules<Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel)>(
797        symbol: SymbolReference<LSPLineCol>,
798        irules: ModuleRules<LSPLineCol>,
799        prev: &[STeXGroup<'a, MS, LSPLineCol, Err>],
800        current: &mut HMap<
801            Cow<'a, str>,
802            AnyMacro<'a, ParseStr<'a, LSPLineCol>, STeXToken<LSPLineCol>, Err, Self>,
803        >,
804        changes: &mut HMap<
805            Cow<'a, str>,
806            Option<AnyMacro<'a, ParseStr<'a, LSPLineCol>, STeXToken<LSPLineCol>, Err, Self>>,
807        >,
808        semantic_rules: &mut Vec<SemanticRule<LSPLineCol>>,
809    ) {
810        macro_rules! do_rule {
811            ($rule:ident) => {
812                match $rule {
813                    ModuleRule::StructureImport(m)
814                        if !Self::has_structure(prev, semantic_rules, &symbol) =>
815                    {
816                        if let Some(rls) = Self::load_structure(m, prev, semantic_rules) {
817                            Self::load_structure_rules(
818                                m.clone(),
819                                rls,
820                                prev,
821                                current,
822                                changes,
823                                semantic_rules,
824                            );
825                        }
826                    }
827                    ModuleRule::Symbol(rule) if MS::FULL => {
828                        //symbols.push(rule.clone());
829                        if let Some((name, rule)) = rule.as_rule() {
830                            let old = current.insert(name.clone(), rule);
831                            if let Entry::Vacant(e) = changes.entry(name) {
832                                e.insert(old);
833                            }
834                        }
835                    }
836                    ModuleRule::Structure { symbol, rules } => {
837                        semantic_rules.push(SemanticRule::Structure {
838                            symbol: symbol.clone(),
839                            rules: rules.clone(),
840                        });
841                        if MS::FULL {
842                            if let Some((name, rule)) = symbol.as_rule() {
843                                let old = current.insert(name.clone(), rule);
844                                if let Entry::Vacant(e) = changes.entry(name) {
845                                    e.insert(old);
846                                }
847                            }
848                        }
849                    }
850                    _ => (),
851                }
852            };
853        }
854        for rule in irules.rules.iter() {
855            do_rule!(rule)
856        }
857        for g in prev.iter().rev() {
858            for rule in g.semantic_rules.iter().rev() {
859                if let SemanticRule::ConservativeExt(s, rls) = rule {
860                    //tracing::info!("Checking {} vs {}",s.uri,symbol.uri);
861                    if s.uri == symbol.uri {
862                        for rule in rls.rules.iter() {
863                            do_rule!(rule)
864                        }
865                    }
866                }
867            }
868        }
869        semantic_rules.push(SemanticRule::StructureImport(symbol, irules))
870    }
871
872    pub fn import_structure<Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel)>(
873        &mut self,
874        symbol: &SymbolReference<LSPLineCol>,
875        srules: &ModuleRules<LSPLineCol>,
876        groups: &mut Groups<'a, '_, ParseStr<'a, LSPLineCol>, STeXToken<LSPLineCol>, Err, Self>,
877        range: SourceRange<LSPLineCol>,
878    ) {
879        let groups_ls = &mut **groups.groups;
880        let Some(i) = groups_ls.iter().enumerate().rev().find_map(|(i, g)| {
881            if matches!(
882                &g.kind,
883                GroupKind::Module { .. } | GroupKind::MathStructure { .. }
884            ) {
885                Some(i)
886            } else {
887                None
888            }
889        }) else {
890            groups.tokenizer.problem(
891                range.start,
892                "\\importmodule is only allowed in a module".to_string(),
893                DiagnosticLevel::Error,
894            );
895            return;
896        };
897        let (prev, after) = groups_ls.split_at_mut(i);
898        let prev = &*prev;
899        let g = &mut after[0];
900        let rules = match &mut g.kind {
901            GroupKind::Module { rules, .. } | GroupKind::MathStructure { rules, .. } => rules,
902            _ => impossible!(),
903        };
904        if rules
905            .iter()
906            .any(|r| matches!(r,ModuleRule::StructureImport(s) if s.uri == symbol.uri))
907        {
908            return;
909        }
910        rules.push(ModuleRule::StructureImport(symbol.clone()));
911        if !Self::has_structure(prev, &g.semantic_rules, &symbol) {
912            // if MS::FULL {
913            Self::load_structure_rules(
914                symbol.clone(),
915                srules.clone(),
916                prev,
917                groups.rules,
918                &mut g.inner.macro_rule_changes,
919                &mut g.semantic_rules,
920            );
921            // }
922        }
923    }
924
925    pub fn use_structure<Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel)>(
926        &mut self,
927        symbol: &SymbolReference<LSPLineCol>,
928        srules: &ModuleRules<LSPLineCol>,
929        groups: &mut Groups<'a, '_, ParseStr<'a, LSPLineCol>, STeXToken<LSPLineCol>, Err, Self>,
930        _range: SourceRange<LSPLineCol>,
931    ) {
932        let groups_ls = &mut **groups.groups;
933        let i = groups_ls.len() - 1;
934        let (prev, after) = groups_ls.split_at_mut(i);
935        let prev = &*prev;
936        let g = &mut after[0];
937        if !Self::has_structure(prev, &g.semantic_rules, &symbol) {
938            // if MS::FULL {
939            Self::load_structure_rules(
940                symbol.clone(),
941                srules.clone(),
942                prev,
943                groups.rules,
944                &mut g.inner.macro_rule_changes,
945                &mut g.semantic_rules,
946            );
947            // }
948        }
949    }
950
951    pub fn add_import<Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel)>(
952        &mut self,
953        module: &ModuleReference,
954        groups: Groups<'a, '_, ParseStr<'a, LSPLineCol>, STeXToken<LSPLineCol>, Err, Self>,
955        range: SourceRange<LSPLineCol>,
956    ) {
957        let groups_ls = &mut **groups.groups;
958        let Some(i) = groups_ls.iter().enumerate().rev().find_map(|(i, g)| {
959            if matches!(
960                &g.kind,
961                GroupKind::Module { .. } | GroupKind::MathStructure { .. }
962            ) {
963                Some(i)
964            } else {
965                None
966            }
967        }) else {
968            groups.tokenizer.problem(
969                range.start,
970                "\\importmodule is only allowed in a module".to_string(),
971                DiagnosticLevel::Error,
972            );
973            return;
974        };
975        let (prev, after) = groups_ls.split_at_mut(i);
976        let prev = &*prev;
977        let g = &mut after[0];
978        let rules = match &mut g.kind {
979            GroupKind::Module { rules, .. } | GroupKind::MathStructure { rules, .. } => rules,
980            _ => unreachable!(),
981        };
982        if rules
983            .iter()
984            .any(|r| matches!(r,ModuleRule::Import(m) if m.uri == module.uri))
985        {
986            return;
987        }
988        rules.push(ModuleRule::Import(module.clone()));
989        match self.load_module(module) {
990            Ok(irules) => {
991                if Self::load_rules(
992                    module.clone(),
993                    irules,
994                    prev,
995                    groups.rules,
996                    &mut g.inner.macro_rule_changes,
997                    &mut g.semantic_rules,
998                    &mut |m| match self.load_module(m) {
999                        Ok(r) => Some(r),
1000                        Err(e) => {
1001                            groups
1002                                .tokenizer
1003                                .problem(range.start, e, DiagnosticLevel::Error);
1004                            None
1005                        }
1006                    },
1007                    0,
1008                )
1009                .is_err()
1010                {
1011                    groups
1012                        .tokenizer
1013                        .problem(range.start, "Import cycle", DiagnosticLevel::Error)
1014                }
1015            }
1016            Err(e) => groups
1017                .tokenizer
1018                .problem(range.start, e, DiagnosticLevel::Error),
1019        }
1020    }
1021
1022    fn get_symbol_macro_or_name<Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel)>(
1023        &self,
1024        groups: &Groups<'a, '_, ParseStr<'a, LSPLineCol>, STeXToken<LSPLineCol>, Err, Self>,
1025        namestr: &str,
1026    ) -> Option<SmallVec<SymbolReference<LSPLineCol>, 1>> {
1027        let mut ret = SmallVec::new();
1028        for g in groups.groups.iter().rev() {
1029            for r in g.semantic_rules.iter().rev() {
1030                match r {
1031                    SemanticRule::Symbol(r) | SemanticRule::Structure { symbol: r, .. } => {
1032                        if r.macroname.as_ref().is_some_and(|n| &**n == namestr) {
1033                            if !ret.contains(&r.uri) {
1034                                ret.push(r.uri.clone());
1035                            }
1036                            continue;
1037                        }
1038                        if r.uri.uri.name().last_name().as_ref() == namestr {
1039                            if !ret.contains(&r.uri) {
1040                                ret.push(r.uri.clone());
1041                            }
1042                        }
1043                    }
1044                    SemanticRule::Module(_, r) | SemanticRule::StructureImport(_, r) => {
1045                        for r in r.rules.iter().rev() {
1046                            match r {
1047                                ModuleRule::Symbol(r) | ModuleRule::Structure { symbol: r, .. } => {
1048                                    if r.macroname.as_ref().is_some_and(|n| &**n == namestr) {
1049                                        if !ret.contains(&r.uri) {
1050                                            ret.push(r.uri.clone());
1051                                        }
1052                                        continue;
1053                                    }
1054                                    if r.uri.uri.name().last_name().as_ref() == namestr {
1055                                        if !ret.contains(&r.uri) {
1056                                            ret.push(r.uri.clone());
1057                                        }
1058                                    }
1059                                }
1060                                _ => (),
1061                            }
1062                        }
1063                    }
1064                    SemanticRule::ConservativeExt(s, rls)
1065                        if Self::has_structure(&groups.groups, &Vec::new(), s) =>
1066                    {
1067                        for r in rls.rules.iter().rev() {
1068                            match r {
1069                                ModuleRule::Symbol(r) | ModuleRule::Structure { symbol: r, .. } => {
1070                                    if r.macroname.as_ref().is_some_and(|n| &**n == namestr) {
1071                                        if !ret.contains(&r.uri) {
1072                                            ret.push(r.uri.clone());
1073                                        }
1074                                        continue;
1075                                    }
1076                                    if r.uri.uri.name().last_name().as_ref() == namestr {
1077                                        if !ret.contains(&r.uri) {
1078                                            ret.push(r.uri.clone());
1079                                        }
1080                                    }
1081                                }
1082                                _ => (),
1083                            }
1084                        }
1085                    }
1086                    _ => (),
1087                }
1088            }
1089        }
1090        if ret.is_empty() {
1091            None
1092        } else {
1093            Some(ret)
1094        }
1095    }
1096
1097    fn get_structure_macro_or_name<Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel)>(
1098        &self,
1099        groups: &Groups<'a, '_, ParseStr<'a, LSPLineCol>, STeXToken<LSPLineCol>, Err, Self>,
1100        namestr: &str,
1101    ) -> Option<(SymbolReference<LSPLineCol>, ModuleRules<LSPLineCol>)> {
1102        for g in groups.groups.iter().rev() {
1103            for r in g.semantic_rules.iter().rev() {
1104                match r {
1105                    SemanticRule::Structure { symbol, rules, .. } => {
1106                        if symbol.macroname.as_ref().is_some_and(|n| &**n == namestr) {
1107                            return Some((symbol.uri.clone(), rules.clone()));
1108                        }
1109                        if symbol.uri.uri.name().last_name().as_ref() == namestr {
1110                            return Some((symbol.uri.clone(), rules.clone()));
1111                        }
1112                    }
1113                    SemanticRule::Module(_, r) => {
1114                        for r in r.rules.iter().rev() {
1115                            match r {
1116                                ModuleRule::Structure { symbol, rules, .. } => {
1117                                    if symbol.macroname.as_ref().is_some_and(|n| &**n == namestr) {
1118                                        return Some((symbol.uri.clone(), rules.clone()));
1119                                    }
1120                                    if symbol.uri.uri.name().last_name().as_ref() == namestr {
1121                                        return Some((symbol.uri.clone(), rules.clone()));
1122                                    }
1123                                }
1124                                _ => (),
1125                            }
1126                        }
1127                    }
1128                    _ => (),
1129                }
1130            }
1131        }
1132        None
1133    }
1134
1135    fn compare(symbol: &str, module: &str, path: Option<&str>, uri: &SymbolURI) -> bool {
1136        fn compare_names(n1: &str, n2: &Name) -> Option<bool> {
1137            let mut symbol_steps = n1.split('/').rev();
1138            let mut uri_steps = n2.steps().iter().rev().map(|s| s.as_ref());
1139            loop {
1140                let Some(sym) = symbol_steps.next() else {
1141                    if uri_steps.next().is_some() {
1142                        return None;
1143                    } else {
1144                        return Some(true);
1145                    }
1146                };
1147                let Some(uristep) = uri_steps.next() else {
1148                    return Some(false);
1149                };
1150                if sym != uristep {
1151                    if symbol_steps.next().is_none() && uristep.ends_with(sym) {
1152                        return None;
1153                    }
1154                    return Some(false);
1155                }
1156            }
1157        }
1158        if compare_names(symbol, uri.name()) != Some(true) {
1159            return false;
1160        }
1161        match compare_names(module, uri.module().name()) {
1162            None | Some(true) if path.is_none() => return true,
1163            Some(false) | None => return false,
1164            Some(true) => (),
1165        }
1166        let Some(mut path) = path else { unreachable!() };
1167        if let Some(uri_path) = uri.path() {
1168            for step in uri_path.steps().iter().rev() {
1169                if path.is_empty() {
1170                    return true;
1171                }
1172                if let Some(p) = path.strip_suffix(step.as_ref()) {
1173                    if let Some(p) = p.strip_suffix('/') {
1174                        path = p
1175                    } else {
1176                        if p.is_empty() {
1177                            return true;
1178                        }
1179                    }
1180                } else {
1181                    return false;
1182                }
1183            }
1184        }
1185        let id = uri.archive_id().as_ref();
1186        return id.ends_with(path);
1187    }
1188
1189    fn get_symbol_complex<Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel)>(
1190        &self,
1191        groups: &Groups<'a, '_, ParseStr<'a, LSPLineCol>, STeXToken<LSPLineCol>, Err, Self>,
1192        symbol: &str,
1193        module: &str,
1194        path: Option<&str>,
1195    ) -> Option<SmallVec<SymbolReference<LSPLineCol>, 1>> {
1196        let mut ret = SmallVec::new();
1197        for g in groups.groups.iter().rev() {
1198            for r in g.semantic_rules.iter().rev() {
1199                match r {
1200                    SemanticRule::Symbol(r) | SemanticRule::Structure { symbol: r, .. }
1201                        if Self::compare(symbol, module, path, &r.uri.uri) =>
1202                    {
1203                        if !ret.contains(&r.uri) {
1204                            ret.push(r.uri.clone());
1205                        }
1206                    }
1207                    SemanticRule::Module(_, r) | SemanticRule::StructureImport(_, r) => {
1208                        for r in r.rules.iter().rev() {
1209                            match r {
1210                                ModuleRule::Symbol(r) | ModuleRule::Structure { symbol: r, .. }
1211                                    if Self::compare(symbol, module, path, &r.uri.uri) =>
1212                                {
1213                                    if !ret.contains(&r.uri) {
1214                                        ret.push(r.uri.clone());
1215                                    }
1216                                }
1217                                _ => (),
1218                            }
1219                        }
1220                    }
1221                    SemanticRule::ConservativeExt(s, rls)
1222                        if Self::has_structure(&groups.groups, &Vec::new(), s) =>
1223                    {
1224                        for r in rls.rules.iter().rev() {
1225                            match r {
1226                                ModuleRule::Symbol(r) | ModuleRule::Structure { symbol: r, .. }
1227                                    if Self::compare(symbol, module, path, &r.uri.uri) =>
1228                                {
1229                                    if !ret.contains(&r.uri) {
1230                                        ret.push(r.uri.clone());
1231                                    }
1232                                }
1233                                _ => (),
1234                            }
1235                        }
1236                    }
1237                    _ => (),
1238                }
1239            }
1240        }
1241        if ret.is_empty() {
1242            None
1243        } else {
1244            Some(ret)
1245        }
1246    }
1247
1248    fn get_structure_uri<Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel)>(
1249        &self,
1250        groups: &Groups<'a, '_, ParseStr<'a, LSPLineCol>, STeXToken<LSPLineCol>, Err, Self>,
1251        uri: &SymbolReference<LSPLineCol>,
1252    ) -> Option<ModuleRules<LSPLineCol>> {
1253        for g in groups.groups.iter().rev() {
1254            for r in g.semantic_rules.iter().rev() {
1255                match r {
1256                    SemanticRule::Structure { symbol, rules, .. } if symbol.uri.uri == uri.uri => {
1257                        return Some(rules.clone())
1258                    }
1259                    SemanticRule::Module(_, r) => {
1260                        for r in r.rules.iter().rev() {
1261                            match r {
1262                                ModuleRule::Structure { symbol, rules, .. }
1263                                    if symbol.uri.uri == uri.uri =>
1264                                {
1265                                    return Some(rules.clone())
1266                                }
1267                                _ => (),
1268                            }
1269                        }
1270                    }
1271                    _ => (),
1272                }
1273            }
1274        }
1275        None
1276    }
1277
1278    fn get_structure_complex<Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel)>(
1279        &self,
1280        groups: &Groups<'a, '_, ParseStr<'a, LSPLineCol>, STeXToken<LSPLineCol>, Err, Self>,
1281        namestr: &str,
1282        module: &str,
1283        path: Option<&str>,
1284    ) -> Option<(SymbolReference<LSPLineCol>, ModuleRules<LSPLineCol>)> {
1285        for g in groups.groups.iter().rev() {
1286            for r in g.semantic_rules.iter().rev() {
1287                match r {
1288                    SemanticRule::Structure { symbol, rules, .. }
1289                        if Self::compare(namestr, module, path, &symbol.uri.uri) =>
1290                    {
1291                        return Some((symbol.uri.clone(), rules.clone()))
1292                    }
1293                    SemanticRule::Module(_, r) => {
1294                        for r in r.rules.iter().rev() {
1295                            match r {
1296                                ModuleRule::Structure { symbol, rules, .. }
1297                                    if Self::compare(namestr, module, path, &symbol.uri.uri) =>
1298                                {
1299                                    return Some((symbol.uri.clone(), rules.clone()))
1300                                }
1301                                _ => (),
1302                            }
1303                        }
1304                    }
1305                    _ => (),
1306                }
1307            }
1308        }
1309        None
1310    }
1311
1312    pub fn get_symbol<Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel)>(
1313        &self,
1314        start: LSPLineCol,
1315        groups: &mut Groups<'a, '_, ParseStr<'a, LSPLineCol>, STeXToken<LSPLineCol>, Err, Self>,
1316        namestr: &str,
1317    ) -> Option<SmallVec<SymbolReference<LSPLineCol>, 1>> {
1318        //let realname = namestr.trim().split_ascii_whitespace().collect::<Vec<_>>().join(" ");
1319        let mut steps = namestr.split('?').rev(); //realname.split('?').rev();
1320        let name = steps.next()?;
1321
1322        let module = if let Some(module) = steps.next() {
1323            module
1324        } else {
1325            if !name.contains('/') {
1326                //return self.get_symbol_macro_or_name(groups,name);
1327                let r = self.get_symbol_macro_or_name(groups, name)?;
1328                if r.len() > 1 {
1329                    groups.tokenizer.problem(
1330                        start,
1331                        format!("Ambiguous symbol reference: {namestr}"),
1332                        DiagnosticLevel::Warning,
1333                    );
1334                }
1335                return Some(r);
1336            } else {
1337                ""
1338            }
1339        };
1340        let path = if steps.next().is_none() {
1341            None
1342        } else {
1343            let i = namestr.len() - (name.len() + 1 + module.len() + 1);
1344            Some(&namestr[..i])
1345        };
1346        let r = self.get_symbol_complex(groups, name, module, path)?;
1347        if r.len() > 1 {
1348            groups.tokenizer.problem(
1349                start,
1350                format!("Ambiguous symbol reference: {namestr}"),
1351                DiagnosticLevel::Warning,
1352            );
1353        }
1354        Some(r)
1355    }
1356
1357    pub fn get_structure<Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel)>(
1358        &self,
1359        groups: &Groups<'a, '_, ParseStr<'a, LSPLineCol>, STeXToken<LSPLineCol>, Err, Self>,
1360        namestr: &str,
1361    ) -> Option<(SymbolReference<LSPLineCol>, ModuleRules<LSPLineCol>)> {
1362        //let realname = namestr.trim().split_ascii_whitespace().collect::<Vec<_>>().join(" ");
1363        let mut steps = namestr.split('?').rev(); //realname.split('?').rev();
1364        let name = steps.next()?;
1365
1366        let Some(module) = steps.next() else {
1367            return self.get_structure_macro_or_name(groups, name);
1368        };
1369        let path = if steps.next().is_none() {
1370            None
1371        } else {
1372            let i = namestr.len() - (name.len() + 1 + module.len() + 1);
1373            Some(&namestr[..i])
1374        };
1375        self.get_structure_complex(groups, name, module, path)
1376    }
1377
1378    pub(super) fn resolve_module_or_struct<
1379        Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
1380    >(
1381        &mut self,
1382        groups: &Groups<'a, '_, ParseStr<'a, LSPLineCol>, STeXToken<LSPLineCol>, Err, Self>,
1383        module_or_struct: &str,
1384        archive: Option<ArchiveId>,
1385    ) -> Option<(ModuleOrStruct<LSPLineCol>, Vec<ModuleRules<LSPLineCol>>)> {
1386        fn mmatch<
1387            'a,
1388            MS: STeXModuleStore,
1389            Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
1390        >(
1391            slf: &mut STeXParseState<'a, LSPLineCol, MS>,
1392            groups: &Groups<
1393                'a,
1394                '_,
1395                ParseStr<'a, LSPLineCol>,
1396                STeXToken<LSPLineCol>,
1397                Err,
1398                STeXParseState<'a, LSPLineCol, MS>,
1399            >,
1400            rules: &ModuleRules<LSPLineCol>,
1401            dones: &mut Vec<ContentURI>,
1402            target: &mut Vec<ModuleRules<LSPLineCol>>,
1403        ) -> Option<()> {
1404            for r in rules.rules.iter() {
1405                match r {
1406                    ModuleRule::Import(m)
1407                        if !dones
1408                            .iter()
1409                            .any(|u| matches!(u,ContentURI::Module(u) if *u == m.uri)) =>
1410                    {
1411                        load_module(slf, groups, m, dones, target)?
1412                    }
1413                    ModuleRule::StructureImport(s)
1414                        if !dones
1415                            .iter()
1416                            .any(|u| matches!(u,ContentURI::Symbol(u) if *u == s.uri)) =>
1417                    {
1418                        load_structure(slf, groups, s, dones, target)?
1419                    }
1420                    _ => (),
1421                }
1422            }
1423            Some(())
1424        }
1425        fn load_module<
1426            'a,
1427            MS: STeXModuleStore,
1428            Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
1429        >(
1430            slf: &mut STeXParseState<'a, LSPLineCol, MS>,
1431            groups: &Groups<
1432                'a,
1433                '_,
1434                ParseStr<'a, LSPLineCol>,
1435                STeXToken<LSPLineCol>,
1436                Err,
1437                STeXParseState<'a, LSPLineCol, MS>,
1438            >,
1439            module: &ModuleReference,
1440            dones: &mut Vec<ContentURI>,
1441            target: &mut Vec<ModuleRules<LSPLineCol>>,
1442        ) -> Option<()> {
1443            dones.push(module.uri.clone().into());
1444            let rls = slf.load_module(module).ok()?;
1445            mmatch(slf, groups, &rls, dones, target)?;
1446            target.push(rls);
1447            Some(())
1448        }
1449        fn load_structure<
1450            'a,
1451            MS: STeXModuleStore,
1452            Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
1453        >(
1454            slf: &mut STeXParseState<'a, LSPLineCol, MS>,
1455            groups: &Groups<
1456                'a,
1457                '_,
1458                ParseStr<'a, LSPLineCol>,
1459                STeXToken<LSPLineCol>,
1460                Err,
1461                STeXParseState<'a, LSPLineCol, MS>,
1462            >,
1463            structure: &SymbolReference<LSPLineCol>,
1464            dones: &mut Vec<ContentURI>,
1465            target: &mut Vec<ModuleRules<LSPLineCol>>,
1466        ) -> Option<()> {
1467            dones.push(structure.uri.clone().into());
1468            let rls = slf.get_structure_uri(groups, structure)?;
1469            mmatch(slf, groups, &rls, dones, target)?;
1470            target.push(rls);
1471            Some(())
1472        }
1473        let mut dones = Vec::new();
1474        if archive.is_none() {
1475            if let Some((m, rls)) = self.find_module(module_or_struct) {
1476                let mut ret = Vec::new();
1477                let rls = rls.clone();
1478                let rf = ModuleOrStruct::Module(ModuleReference {
1479                    uri: m.clone(),
1480                    in_doc: self.doc_uri.clone(),
1481                    rel_path: None,
1482                    full_path: self.in_path.clone(),
1483                });
1484                mmatch(self, groups, &rls, &mut dones, &mut ret)?;
1485                ret.push(rls);
1486                return Some((rf, ret));
1487            }
1488            if let Some((s, r)) = self.get_structure(groups, module_or_struct) {
1489                let mut ret = Vec::new();
1490                mmatch(self, groups, &r, &mut dones, &mut ret)?;
1491                ret.push(r);
1492                return Some((ModuleOrStruct::Struct(s), ret));
1493            }
1494        }
1495        if let Some(m) = self.resolve_module(module_or_struct, archive) {
1496            let mut ret = Vec::new();
1497            load_module(self, groups, &m, &mut dones, &mut ret)?;
1498            Some((ModuleOrStruct::Module(m), ret))
1499        } else {
1500            None
1501        }
1502    }
1503}
1504
1505impl<'a, Pos: SourcePos, MS: STeXModuleStore> STeXParseState<'a, Pos, MS> {
1506    #[inline]
1507    #[must_use]
1508    pub fn new(
1509        archive: Option<ArchiveURIRef<'a>>,
1510        in_path: Option<&'a Path>,
1511        uri: &'a DocumentURI,
1512        backend: &'a AnyBackend,
1513        on_module: MS,
1514    ) -> Self {
1515        let language = in_path.map(Language::from_file).unwrap_or_default();
1516        Self {
1517            archive,
1518            in_path: in_path.map(Into::into),
1519            doc_uri: uri,
1520            language,
1521            backend,
1522            modules: SmallVec::new(),
1523            module_store: on_module,
1524            name_counter: IdCounter::default(),
1525            dependencies: Vec::new(),
1526        }
1527    }
1528
1529    pub fn set_structure<Err: FnMut(String, SourceRange<Pos>, DiagnosticLevel)>(
1530        &mut self,
1531        groups: &mut Groups<'a, '_, ParseStr<'a, Pos>, STeXToken<Pos>, Err, Self>,
1532        rules: ModuleRules<Pos>,
1533        range: SourceRange<Pos>,
1534    ) {
1535        for g in groups.groups.iter_mut().rev() {
1536            match &mut g.kind {
1537                GroupKind::Module { rules: rls, .. } => match rls.last_mut() {
1538                    Some(ModuleRule::Structure {
1539                        symbol,
1540                        rules: rls1,
1541                        ..
1542                    }) => {
1543                        for sr in g.semantic_rules.iter_mut().rev() {
1544                            match sr {
1545                                SemanticRule::Structure {
1546                                    symbol: symbol2,
1547                                    rules: rls2,
1548                                    ..
1549                                } if symbol.uri.uri == symbol2.uri.uri => {
1550                                    *rls2 = rules.clone();
1551                                    break;
1552                                }
1553                                _ => (),
1554                            }
1555                        }
1556                        *rls1 = rules;
1557                        return;
1558                    }
1559                    Some(ModuleRule::ConservativeExt(_, rls1)) => {
1560                        for sr in g.semantic_rules.iter_mut().rev() {
1561                            match sr {
1562                                SemanticRule::ConservativeExt(_, rls2) => {
1563                                    *rls2 = rules.clone();
1564                                    break;
1565                                }
1566                                _ => (),
1567                            }
1568                        }
1569                        *rls1 = rules;
1570                        return;
1571                    }
1572                    _ => {
1573                        groups.tokenizer.problem(
1574                            range.start,
1575                            "mathstructure ended unexpectedly".to_string(),
1576                            DiagnosticLevel::Error,
1577                        );
1578                        return;
1579                    }
1580                },
1581                _ => (),
1582            }
1583        }
1584        groups.tokenizer.problem(
1585            range.start,
1586            "mathstructure is only allowed in a module".to_string(),
1587            DiagnosticLevel::Error,
1588        );
1589    }
1590
1591    pub fn add_structure<Err: FnMut(String, SourceRange<Pos>, DiagnosticLevel)>(
1592        &mut self,
1593        groups: &mut Groups<'a, '_, ParseStr<'a, Pos>, STeXToken<Pos>, Err, Self>,
1594        name: Name,
1595        macroname: Option<std::sync::Arc<str>>,
1596        range: SourceRange<Pos>,
1597    ) -> Option<SymbolReference<Pos>> {
1598        for g in groups.groups.iter_mut().rev() {
1599            match &mut g.kind {
1600                GroupKind::Module { uri, rules, .. } => {
1601                    let suri = uri.clone() | name;
1602                    let uri = SymbolReference {
1603                        uri: suri,
1604                        filepath: self.in_path.clone(),
1605                        range,
1606                    };
1607                    for r in &*rules {
1608                        match r {
1609                            ModuleRule::Symbol(s) | ModuleRule::Structure { symbol: s, .. }
1610                                if s.uri.uri == uri.uri =>
1611                            {
1612                                groups.tokenizer.problem(
1613                                    range.start,
1614                                    format!("symbol with name {} already exists", s.uri.uri),
1615                                    DiagnosticLevel::Warning,
1616                                );
1617                            }
1618                            _ => (),
1619                        }
1620                    }
1621                    let rule = SymbolRule {
1622                        uri,
1623                        macroname,
1624                        has_tp: false,
1625                        has_df: false,
1626                        argnum: 0,
1627                    };
1628                    if MS::FULL {
1629                        if let Some((name, rule)) = rule.as_rule() {
1630                            let old = groups.rules.insert(name.clone(), rule);
1631                            if let Entry::Vacant(e) = g.inner.macro_rule_changes.entry(name) {
1632                                e.insert(old);
1633                            }
1634                        }
1635                    }
1636                    g.semantic_rules.push(SemanticRule::Structure {
1637                        //module_uri: rule.uri.uri.clone().into_module(),
1638                        symbol: rule.clone(),
1639                        rules: ModuleRules::default(),
1640                    });
1641                    let uri = rule.uri.clone();
1642                    rules.push(ModuleRule::Structure {
1643                        symbol: rule,
1644                        rules: ModuleRules::default(),
1645                    });
1646                    return Some(uri);
1647                }
1648                _ => (),
1649            }
1650        }
1651        groups.tokenizer.problem(
1652            range.start,
1653            "mathstructure is only allowed in a module".to_string(),
1654            DiagnosticLevel::Error,
1655        );
1656        None
1657    }
1658
1659    #[inline]
1660    fn new_id(&mut self, prefix: Cow<'static, str>) -> Box<str> {
1661        self.name_counter.new_id(prefix)
1662    }
1663
1664    pub fn add_conservative_ext<Err: FnMut(String, SourceRange<Pos>, DiagnosticLevel)>(
1665        &mut self,
1666        groups: &mut Groups<'a, '_, ParseStr<'a, Pos>, STeXToken<Pos>, Err, Self>,
1667        orig: &SymbolReference<Pos>,
1668        range: SourceRange<Pos>,
1669    ) -> Option<ModuleURI> {
1670        for g in groups.groups.iter_mut().rev() {
1671            match &mut g.kind {
1672                GroupKind::Module { uri, rules, .. } => {
1673                    let name = self.new_id(Cow::Borrowed("EXTSTRUCT"));
1674                    let euri = (uri.clone() / &*name).ok()?;
1675                    g.semantic_rules.push(SemanticRule::ConservativeExt(
1676                        orig.clone(),
1677                        ModuleRules::default(),
1678                    ));
1679                    rules.push(ModuleRule::ConservativeExt(
1680                        orig.clone(),
1681                        ModuleRules::default(),
1682                    ));
1683                    return Some(euri);
1684                }
1685                _ => (),
1686            }
1687        }
1688        groups.tokenizer.problem(
1689            range.start,
1690            "mathstructure is only allowed in a module".to_string(),
1691            DiagnosticLevel::Error,
1692        );
1693        None
1694    }
1695
1696    pub fn add_symbol<Err: FnMut(String, SourceRange<Pos>, DiagnosticLevel)>(
1697        &mut self,
1698        groups: &mut Groups<'a, '_, ParseStr<'a, Pos>, STeXToken<Pos>, Err, Self>,
1699        name: Name,
1700        macroname: Option<std::sync::Arc<str>>,
1701        range: SourceRange<Pos>,
1702        has_tp: bool,
1703        has_df: bool,
1704        argnum: u8,
1705    ) -> Option<SymbolReference<Pos>> {
1706        for g in groups.groups.iter_mut().rev() {
1707            match &mut g.kind {
1708                GroupKind::Module { uri, rules, .. }
1709                | GroupKind::MathStructure { uri, rules }
1710                | GroupKind::ConservativeExt(uri, rules) => {
1711                    let suri = uri.clone() | name;
1712                    let uri = SymbolReference {
1713                        uri: suri,
1714                        filepath: self.in_path.clone(),
1715                        range,
1716                    };
1717                    for r in &*rules {
1718                        match r {
1719                            ModuleRule::Symbol(s) | ModuleRule::Structure { symbol: s, .. }
1720                                if s.uri.uri == uri.uri =>
1721                            {
1722                                groups.tokenizer.problem(
1723                                    range.start,
1724                                    format!("symbol with name {} already exists", s.uri.uri),
1725                                    DiagnosticLevel::Warning,
1726                                );
1727                            }
1728                            _ => (),
1729                        }
1730                    }
1731                    let rule = SymbolRule {
1732                        uri,
1733                        macroname,
1734                        has_tp,
1735                        has_df,
1736                        argnum,
1737                    };
1738                    if MS::FULL {
1739                        if let Some((name, rule)) = rule.as_rule() {
1740                            let old = groups.rules.insert(name.clone(), rule);
1741                            if let Entry::Vacant(e) = g.inner.macro_rule_changes.entry(name) {
1742                                e.insert(old);
1743                            }
1744                        }
1745                    }
1746                    g.semantic_rules.push(SemanticRule::Symbol(rule.clone()));
1747                    let uri = rule.uri.clone();
1748                    rules.push(ModuleRule::Symbol(rule));
1749                    //g.symbols.push(rule);
1750                    return Some(uri);
1751                }
1752                _ => (),
1753            }
1754        }
1755        groups.tokenizer.problem(
1756            range.start,
1757            "\\symdecl is only allowed in a module".to_string(),
1758            DiagnosticLevel::Error,
1759        );
1760        None
1761    }
1762
1763    #[allow(clippy::case_sensitive_file_extension_comparisons)]
1764    #[allow(clippy::needless_pass_by_value)]
1765    pub(super) fn resolve_module(
1766        &self,
1767        module: &'a str,
1768        archive: Option<ArchiveId>,
1769    ) -> Option<ModuleReference> {
1770        if let Some((m, _)) = self.find_module(module) {
1771            return Some(ModuleReference {
1772                uri: m.clone(),
1773                in_doc: self.doc_uri.clone(),
1774                rel_path: None,
1775                full_path: self.in_path.clone(),
1776            });
1777        }
1778        let (mut basepath, archive) = archive.as_ref().map_or_else(
1779            || {
1780                self.archive.and_then(|a| {
1781                    self.in_path
1782                        .as_ref()
1783                        .and_then(|p| p.to_str())
1784                        .and_then(|s| {
1785                            s.find("source")
1786                                .map(|i| (PathBuf::from(&s[..i - 1]).join("source"), a.owned()))
1787                        })
1788                })
1789            },
1790            |a| {
1791                self.backend
1792                    .with_local_archive(a, |a| a.map(|a| (a.source_dir(), a.uri().owned())))
1793            },
1794        )?;
1795
1796        let (path, module) = if let Some((a, b)) = module.split_once('?') {
1797            (a, b)
1798        } else {
1799            ("", module)
1800        };
1801
1802        let top_module = if let Some((t, _)) = module.split_once('/') {
1803            t
1804        } else {
1805            module
1806        };
1807
1808        let last = if let Some((p, last)) = path.rsplit_once('/') {
1809            basepath = p.split('/').fold(basepath, |p, s| p.join(s));
1810            last
1811        } else {
1812            path
1813        };
1814
1815        let uri = ((PathURI::from(archive) / path).ok()? | module).ok()?;
1816
1817        let p = basepath
1818            .join(last)
1819            .join(format!("{top_module}.{}.tex", self.language));
1820        if p.exists() {
1821            return Some(ModuleReference {
1822                rel_path: Some(format!("{path}/{top_module}.{}.tex", self.language).into()),
1823                in_doc: (uri.as_path().owned() & (top_module, self.language)).ok()?,
1824                full_path: Some(p.into()),
1825                uri,
1826            });
1827        }
1828
1829        let p = basepath.join(last).join(format!("{top_module}.en.tex"));
1830        if p.exists() {
1831            return Some(ModuleReference {
1832                rel_path: Some(format!("{path}/{top_module}.en.tex").into()),
1833                in_doc: (uri.as_path().owned() & (top_module, Language::English)).ok()?,
1834                full_path: Some(p.into()),
1835                uri,
1836            });
1837        }
1838
1839        let p = basepath.join(last).join(format!("{top_module}.tex"));
1840        if p.exists() {
1841            return Some(ModuleReference {
1842                rel_path: Some(format!("{path}/{top_module}.tex").into()),
1843                in_doc: (uri.as_path().owned() & (top_module, Language::English)).ok()?,
1844                full_path: Some(p.into()),
1845                uri,
1846            });
1847        }
1848
1849        let path_uri = uri.as_path().owned().up();
1850
1851        let p = basepath.join(format!("{last}.{}.tex", self.language));
1852        if p.exists() {
1853            return Some(ModuleReference {
1854                uri,
1855                in_doc: (path_uri & (last, self.language)).ok()?,
1856                rel_path: Some(format!("{path}.{}.tex", self.language).into()),
1857                full_path: Some(p.into()),
1858            });
1859        }
1860
1861        let p = basepath.join(format!("{last}.en.tex"));
1862        if p.exists() {
1863            return Some(ModuleReference {
1864                uri,
1865                in_doc: (path_uri & (last, Language::English)).ok()?,
1866                rel_path: Some(format!("{path}.en.tex").into()),
1867                full_path: Some(p.into()),
1868            });
1869        }
1870
1871        let p = basepath.join(format!("{last}.tex"));
1872        if p.exists() {
1873            return Some(ModuleReference {
1874                uri,
1875                in_doc: (path_uri & (last, Language::English)).ok()?,
1876                rel_path: Some(format!("{path}.tex").into()),
1877                full_path: Some(p.into()),
1878            });
1879        }
1880        None
1881    }
1882
1883    fn find_module(&self, m: &str) -> Option<(&ModuleURI, &ModuleRules<Pos>)> {
1884        'top: for (muri, rls) in &self.modules {
1885            let mut f_steps = m.split('/');
1886            let mut m_steps = muri.name().steps().iter();
1887            loop {
1888                let Some(f) = f_steps.next() else {
1889                    if m_steps.next().is_none() {
1890                        return Some((muri, rls));
1891                    }
1892                    continue 'top;
1893                };
1894                let Some(m) = m_steps.next() else {
1895                    continue 'top;
1896                };
1897                if f != m.as_ref() {
1898                    continue 'top;
1899                }
1900            }
1901        }
1902        None
1903    }
1904}
1905
1906#[derive(Default)]
1907#[allow(clippy::large_enum_variant)]
1908pub enum GroupKind<Pos: SourcePos> {
1909    #[default]
1910    None,
1911    Problem,
1912    Module {
1913        uri: ModuleURI,
1914        rules: Vec<ModuleRule<Pos>>,
1915    },
1916    MathStructure {
1917        uri: ModuleURI,
1918        rules: Vec<ModuleRule<Pos>>,
1919    },
1920    ConservativeExt(ModuleURI, Vec<ModuleRule<Pos>>),
1921    DefPara(Vec<SymbolReference<Pos>>),
1922    Morphism {
1923        domain: ModuleOrStruct<Pos>,
1924        rules: Vec<ModuleRules<Pos>>,
1925        specs: VecMap<SymbolReference<Pos>, MorphismSpec<Pos>>,
1926    },
1927}
1928
1929#[derive(Clone, Debug, Default)]
1930pub struct MorphismSpec<Pos: SourcePos> {
1931    pub macroname: Option<Box<str>>,
1932    pub new_name: Option<Name>,
1933    pub is_assigned_at: Option<SourceRange<Pos>>,
1934    pub decl_range: SourceRange<Pos>,
1935}
1936
1937#[derive(Debug, Clone, serde::Serialize)]
1938pub enum ModuleOrStruct<Pos: SourcePos> {
1939    Module(ModuleReference),
1940    Struct(SymbolReference<Pos>),
1941}
1942
1943#[non_exhaustive]
1944pub struct STeXGroup<
1945    'a,
1946    MS: STeXModuleStore,
1947    Pos: SourcePos + 'a,
1948    Err: FnMut(String, SourceRange<Pos>, DiagnosticLevel),
1949> {
1950    pub inner: Group<'a, ParseStr<'a, Pos>, STeXToken<Pos>, Err, STeXParseState<'a, Pos, MS>>,
1951    pub kind: GroupKind<Pos>,
1952    pub semantic_rules: Vec<SemanticRule<Pos>>,
1953    pub uses: VecSet<ModuleURI>,
1954}
1955
1956pub enum SemanticRule<Pos: SourcePos> {
1957    Symbol(SymbolRule<Pos>),
1958    Module(ModuleReference, ModuleRules<Pos>),
1959    Structure {
1960        symbol: SymbolRule<Pos>,
1961        //module_uri:ModuleURI,
1962        rules: ModuleRules<Pos>,
1963    },
1964    ConservativeExt(SymbolReference<Pos>, ModuleRules<Pos>),
1965    StructureImport(SymbolReference<Pos>, ModuleRules<Pos>),
1966}
1967
1968impl<
1969        'a,
1970        MS: STeXModuleStore,
1971        Pos: SourcePos + 'a,
1972        Err: FnMut(String, SourceRange<Pos>, DiagnosticLevel),
1973    > GroupState<'a, ParseStr<'a, Pos>, STeXToken<Pos>, Err, STeXParseState<'a, Pos, MS>>
1974    for STeXGroup<'a, MS, Pos, Err>
1975{
1976    #[inline]
1977    fn new(parent: Option<&mut Self>) -> Self {
1978        Self {
1979            inner: Group::new(parent.map(|p| &mut p.inner)),
1980            kind: GroupKind::None,
1981            semantic_rules: Vec::new(),
1982            uses: VecSet::default(),
1983        }
1984    }
1985
1986    #[inline]
1987    fn inner(
1988        &self,
1989    ) -> &Group<'a, ParseStr<'a, Pos>, STeXToken<Pos>, Err, STeXParseState<'a, Pos, MS>> {
1990        &self.inner
1991    }
1992    #[inline]
1993    fn inner_mut(
1994        &mut self,
1995    ) -> &mut Group<'a, ParseStr<'a, Pos>, STeXToken<Pos>, Err, STeXParseState<'a, Pos, MS>> {
1996        &mut self.inner
1997    }
1998    #[inline]
1999    fn close(
2000        self,
2001        parser: &mut LaTeXParser<
2002            'a,
2003            ParseStr<'a, Pos>,
2004            STeXToken<Pos>,
2005            Err,
2006            STeXParseState<'a, Pos, MS>,
2007        >,
2008    ) {
2009        self.inner.close(parser);
2010    }
2011    #[inline]
2012    fn add_macro_rule(
2013        &mut self,
2014        name: Cow<'a, str>,
2015        old: Option<
2016            AnyMacro<'a, ParseStr<'a, Pos>, STeXToken<Pos>, Err, STeXParseState<'a, Pos, MS>>,
2017        >,
2018    ) {
2019        self.inner.add_macro_rule(name, old);
2020    }
2021    #[inline]
2022    fn add_environment_rule(
2023        &mut self,
2024        name: Cow<'a, str>,
2025        old: Option<
2026            AnyEnv<'a, ParseStr<'a, Pos>, STeXToken<Pos>, Err, STeXParseState<'a, Pos, MS>>,
2027        >,
2028    ) {
2029        self.inner.add_environment_rule(name, old);
2030    }
2031    #[inline]
2032    fn letter_change(&mut self, old: &str) {
2033        self.inner.letter_change(old);
2034    }
2035}
2036
2037#[derive(Clone, Debug)]
2038pub enum MacroArg<Pos: SourcePos> {
2039    Symbol(SymbolReference<Pos>, u8),
2040    Variable(Name, SourceRange<Pos>, bool, u8),
2041}
2042
2043impl<
2044        'a,
2045        MS: STeXModuleStore,
2046        Pos: SourcePos + 'a,
2047        Err: FnMut(String, SourceRange<Pos>, DiagnosticLevel),
2048    > ParserState<'a, ParseStr<'a, Pos>, STeXToken<Pos>, Err> for STeXParseState<'a, Pos, MS>
2049{
2050    type Group = STeXGroup<'a, MS, Pos, Err>;
2051    type MacroArg = MacroArg<Pos>;
2052}