1#![allow(clippy::ref_option)]
2#![allow(clippy::case_sensitive_file_extension_comparisons)]
3#![allow(clippy::cast_possible_truncation)]
4#![allow(unused_variables)]
5
6use std::{borrow::Cow, path::Path, str::FromStr};
7
8use flams_ontology::{
9 languages::Language,
10 narration::paragraphs::ParagraphKind,
11 uris::{ArchiveId, ArchiveURITrait, ModuleURI, Name, PathURITrait, SymbolURI, URIRefTrait},
12};
13use flams_system::backend::{Backend, GlobalBackend};
14use flams_utils::{
15 impossible,
16 parsing::ParseStr,
17 sourcerefs::{LSPLineCol, SourcePos, SourceRange},
18 vecmap::VecMap,
19 CondSerialize,
20};
21use smallvec::SmallVec;
22
23use crate::{
24 quickparse::{
25 latex::{
26 rules::{
27 AnyMacro, DynMacro, EnvironmentResult, EnvironmentRule, MacroResult, MacroRule,
28 },
29 Environment, KeyValKind, LaTeXParser, Macro, ParsedKeyValue,
30 },
31 stex::structs::MorphismKind,
32 },
33 tex,
34};
35use flams_utils::parsing::ParseSource;
36
37use super::{
38 structs::{
39 GroupKind, InlineMorphAssKind, InlineMorphAssign, MacroArg, ModuleOrStruct,
40 ModuleReference, ModuleRule, ModuleRules, MorphismSpec, STeXGroup, STeXModuleStore,
41 STeXParseState, STeXToken, SymbolReference, SymbolRule,
42 },
43 DiagnosticLevel,
44};
45
46#[must_use]
47#[allow(clippy::type_complexity)]
48pub fn all_rules<
49 'a,
50 MS: STeXModuleStore,
51 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
52>() -> [(
53 &'static str,
54 MacroRule<
55 'a,
56 ParseStr<'a, LSPLineCol>,
57 STeXToken<LSPLineCol>,
58 Err,
59 STeXParseState<'a, LSPLineCol, MS>,
60 >,
61); 43] {
62 [
63 ("importmodule", importmodule as _),
64 ("setmetatheory", setmetatheory as _),
65 ("usemodule", usemodule as _),
66 ("usestructure", usestructure as _),
67 ("inputref", inputref as _),
68 ("includeproblem", includeproblem as _),
69 ("mhinput", mhinput as _),
70 ("mhgraphics", mhgraphics as _),
71 ("cmhgraphics", mhgraphics as _),
72 ("stexstyleassertion", stexstyleassertion as _),
73 ("stexstyledefinition", stexstyledefinition as _),
74 ("stexstyleparagraph", stexstyleparagraph as _),
75 ("symdecl", symdecl as _),
76 ("textsymdecl", textsymdecl as _),
77 ("symdef", symdef as _),
78 ("vardef", vardef as _),
79 ("varseq", varseq as _),
80 ("symref", symref as _),
81 ("sr", symref as _),
82 ("symname", symname as _),
83 ("sn", symname as _),
84 ("Symname", Symname as _),
85 ("Sn", Symname as _),
86 ("sns", symnames as _),
87 ("Sns", Symnames as _),
88 ("symuse", symuse as _),
89 ("svar", svar as _),
90 ("notation", notation as _),
91 ("definame", defi_only as _),
92 ("Definame", defi_only as _),
93 ("definames", defi_only as _),
94 ("Definames", defi_only as _),
95 ("definiendum", defi_only as _),
96 ("definiens", defi_only as _),
97 ("defnotation", defi_only as _),
98 ("inlinedef", inlinedef as _),
99 ("inlineass", inlineass as _),
100 ("inlinepara", inlinepara as _),
101 ("inlineex", inlineex as _),
102 ("copymod", copymod as _),
103 ("interpretmod", interpretmod as _),
104 ("precondition", precondition as _),
105 ("objective", objective as _),
106 ]
107}
108
109#[must_use]
110#[allow(clippy::type_complexity)]
111pub fn declarative_rules<
112 'a,
113 MS: STeXModuleStore,
114 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
115>() -> [(
116 &'static str,
117 MacroRule<
118 'a,
119 ParseStr<'a, LSPLineCol>,
120 STeXToken<LSPLineCol>,
121 Err,
122 STeXParseState<'a, LSPLineCol, MS>,
123 >,
124); 14] {
125 [
126 ("importmodule", importmodule as _),
127 ("setmetatheory", setmetatheory as _),
128 ("stexstyleassertion", stexstyleassertion as _),
129 ("stexstyledefinition", stexstyledefinition as _),
130 ("stexstyleparagraph", stexstyleparagraph as _),
131 ("symdecl", symdecl as _),
132 ("textsymdecl", textsymdecl as _),
133 ("symdef", symdef as _),
134 ("inlinedef", inlinedef as _),
135 ("inlineass", inlineass as _),
136 ("inlinepara", inlinepara as _),
137 ("inlineex", inlineex as _),
138 ("copymod", copymod as _),
139 ("interpretmod", interpretmod as _),
140 ]
141}
142
143#[must_use]
144#[allow(clippy::type_complexity)]
145pub fn all_env_rules<
146 'a,
147 MS: STeXModuleStore,
148 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
149>() -> [(
150 &'static str,
151 EnvironmentRule<
152 'a,
153 ParseStr<'a, LSPLineCol>,
154 STeXToken<LSPLineCol>,
155 Err,
156 STeXParseState<'a, LSPLineCol, MS>,
157 >,
158); 16] {
159 [
160 ("smodule", (smodule_open as _, smodule_close as _)),
161 (
162 "mathstructure",
163 (mathstructure_open as _, mathstructure_close as _),
164 ),
165 (
166 "extstructure",
167 (extstructure_open as _, extstructure_close as _),
168 ),
169 (
170 "extstructure*",
171 (extstructure_ast_open as _, extstructure_ast_close as _),
172 ),
173 ("sassertion", (sassertion_open as _, sassertion_close as _)),
174 (
175 "sdefinition",
176 (sdefinition_open as _, sdefinition_close as _),
177 ),
178 ("sparagraph", (sparagraph_open as _, sparagraph_close as _)),
179 ("sexample", (sexample_open as _, sexample_close as _)),
180 (
181 "ndefinition",
182 (sdefinition_open as _, sdefinition_close as _),
183 ),
184 ("nparagraph", (sparagraph_open as _, sparagraph_close as _)),
185 ("copymodule", (copymodule_open as _, copymodule_close as _)),
186 (
187 "copymodule*",
188 (copymodule_ast_open as _, copymodule_ast_close as _),
189 ),
190 (
191 "interpretmodule",
192 (interpretmodule_open as _, interpretmodule_close as _),
193 ),
194 (
195 "interpretmodule*",
196 (
197 interpretmodule_ast_open as _,
198 interpretmodule_ast_close as _,
199 ),
200 ),
201 ("sproblem", (sproblem_open as _, sproblem_close as _)),
202 ("subproblem", (subproblem_open as _, subproblem_close as _)),
203 ]
204}
205
206#[must_use]
207#[allow(clippy::type_complexity)]
208pub fn declarative_env_rules<
209 'a,
210 MS: STeXModuleStore,
211 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
212>() -> [(
213 &'static str,
214 EnvironmentRule<
215 'a,
216 ParseStr<'a, LSPLineCol>,
217 STeXToken<LSPLineCol>,
218 Err,
219 STeXParseState<'a, LSPLineCol, MS>,
220 >,
221); 12] {
222 [
223 ("smodule", (smodule_open as _, smodule_close as _)),
224 (
225 "mathstructure",
226 (mathstructure_open as _, mathstructure_close as _),
227 ),
228 (
229 "extstructure",
230 (extstructure_open as _, extstructure_close as _),
231 ),
232 (
233 "extstructure*",
234 (extstructure_ast_open as _, extstructure_ast_close as _),
235 ),
236 ("sassertion", (sassertion_open as _, sassertion_close as _)),
237 (
238 "sdefinition",
239 (sdefinition_open as _, sdefinition_close as _),
240 ),
241 ("sparagraph", (sparagraph_open as _, sparagraph_close as _)),
242 ("sexample", (sexample_open as _, sexample_close as _)),
243 ("copymodule", (copymodule_open as _, copymodule_close as _)),
244 (
245 "copymodule*",
246 (copymodule_ast_open as _, copymodule_ast_close as _),
247 ),
248 (
249 "interpretmodule",
250 (interpretmodule_open as _, interpretmodule_close as _),
251 ),
252 (
253 "interpretmodule*",
254 (
255 interpretmodule_ast_open as _,
256 interpretmodule_ast_close as _,
257 ),
258 ),
259 ]
260}
261
262macro_rules! stex {
263 ($p:ident => @begin $($stuff:tt)+) => {
264 tex!(<{'a,Pos:SourcePos,MS:STeXModuleStore,Err:FnMut(String,SourceRange<Pos>,DiagnosticLevel)} E{'a,Pos,&'a str,STeXToken<Pos>} P{'a,ParseStr<'a,Pos>,STeXToken<Pos>,Err,STeXParseState<'a,Pos,MS>} R{'a,Pos,&'a str,STeXToken<Pos>}>
265 $p => @begin $($stuff)*
266 );
267 };
268 ($p:ident => $($stuff:tt)+) => {
269 tex!(<{'a,Pos:SourcePos,MS:STeXModuleStore,Err:FnMut(String,SourceRange<Pos>,DiagnosticLevel)} M{'a,Pos,&'a str} P{'a,ParseStr<'a,Pos>,STeXToken<Pos>,Err,STeXParseState<'a,Pos,MS>} R{'a,Pos,&'a str,STeXToken<Pos>}>
270 $p => $($stuff)*
271 );
272 };
273 (LSP: $p:ident => @begin $($stuff:tt)+) => {
274 tex!(<{'a,MS:STeXModuleStore,Err:FnMut(String,SourceRange<LSPLineCol>,DiagnosticLevel)} E{'a,LSPLineCol,&'a str,STeXToken<LSPLineCol>} P{'a,ParseStr<'a,LSPLineCol>,STeXToken<LSPLineCol>,Err,STeXParseState<'a,LSPLineCol,MS>} R{'a,LSPLineCol,&'a str,STeXToken<LSPLineCol>}>
275 $p => @begin $($stuff)*
276 );
277 };
278 (LSP: $p:ident => $($stuff:tt)+) => {
279 tex!(<{'a,MS:STeXModuleStore,Err:FnMut(String,SourceRange<LSPLineCol>,DiagnosticLevel)} M{'a,LSPLineCol,&'a str} P{'a,ParseStr<'a,LSPLineCol>,STeXToken<LSPLineCol>,Err,STeXParseState<'a,LSPLineCol,MS>} R{'a,LSPLineCol,&'a str,STeXToken<LSPLineCol>}>
280 $p => $($stuff)*
281 );
282 };
283}
284
285stex!(LSP: p => importmodule[archive:str]{module:name} => {
286 let (archive,archive_range) = archive.map_or((None,None),|(a,r)| (Some(ArchiveId::new(a)),Some(r)));
287 if let Some(r) = p.state.resolve_module(module.0, archive) {
288 let path = p.state.in_path.as_ref().unwrap();
289 let (state,groups) = p.split();
290 state.add_import(&r, groups,importmodule.range);
291 MacroResult::Success(STeXToken::ImportModule {
292 archive_range, path_range:module.1,module:r,
293 full_range:importmodule.range, token_range:importmodule.token_range
294 })
295 } else {
296 p.tokenizer.problem(importmodule.range.start, format!("Module {} not found",module.0),DiagnosticLevel::Error);
297 MacroResult::Simple(importmodule)
298 }
299});
300
301stex!(p => importmodule_deps[archive:str]{module:name} => {
302 let (archive,archive_range) = archive.map_or((None,None),|(a,r)| (Some(ArchiveId::new(a)),Some(r)));
303 if let Some(r) = p.state.resolve_module(module.0, archive) {
304 MacroResult::Success(STeXToken::ImportModule {
305 archive_range, path_range:module.1,module:r,
306 full_range:importmodule_deps.range, token_range:importmodule_deps.token_range
307 })
308 } else {
309 p.tokenizer.problem(importmodule_deps.range.start, format!("Module {} not found",module.0),DiagnosticLevel::Error);
310 MacroResult::Simple(importmodule_deps)
311 }
312});
313
314stex!(LSP:p => usemodule[archive:str]{module:name} => {
315 let (archive,archive_range) = archive.map_or((None,None),|(a,r)| (Some(ArchiveId::new(a)),Some(r)));
316 if let Some(r) = p.state.resolve_module(module.0, archive) {
317 let (state,groups) = p.split();
318 state.add_use(&r, groups,usemodule.range);
319 MacroResult::Success(STeXToken::UseModule {
320 archive_range, path_range:module.1,module:r,
321 full_range:usemodule.range, token_range:usemodule.token_range
322 })
323 } else {
324 p.tokenizer.problem(usemodule.range.start, format!("Module {} not found",module.0),DiagnosticLevel::Error);
325 MacroResult::Simple(usemodule)
326 }
327 }
328);
329
330stex!(LSP:p => usestructure{exts:!name} => {
331 let (state,mut groups) = p.split();
332 let Some((sym,rules)) = state.get_structure(&groups,&exts.0) else {
333 groups.tokenizer.problem(exts.1.start, format!("Unknown structure {}",exts.0),DiagnosticLevel::Error);
334 return MacroResult::Simple(usestructure)
335 };
336 state.use_structure(&sym,&rules,&mut groups,usestructure.range);
337 MacroResult::Success(STeXToken::UseStructure {
338 structure:sym,structure_range:exts.1,
339 full_range:usestructure.range, token_range:usestructure.token_range
340 })
341}
342);
343
344stex!(p => usemodule_deps[archive:str]{module:name} => {
345 let (archive,archive_range) = archive.map_or((None,None),|(a,r)| (Some(ArchiveId::new(a)),Some(r)));
346 if let Some(r) = p.state.resolve_module(module.0, archive) {
347 MacroResult::Success(STeXToken::UseModule {
348 archive_range, path_range:module.1,module:r,
349 full_range:usemodule_deps.range,token_range:usemodule_deps.token_range
350 })
351 } else {
352 p.tokenizer.problem(usemodule_deps.range.start, format!("Module {} not found",module.0),DiagnosticLevel::Error);
353 MacroResult::Simple(usemodule_deps)
354 }
355 }
356);
357
358stex!(p => setmetatheory[archive:str]{module:name} => {
359 let (archive,archive_range) = archive.map_or((None,None),|(a,r)| (Some(ArchiveId::new(a)),Some(r)));
360 if let Some(r) = p.state.resolve_module(module.0, archive) {
361 MacroResult::Success(STeXToken::SetMetatheory {
362 archive_range, path_range:module.1,module:r,
363 full_range:setmetatheory.range, token_range:setmetatheory.token_range
364 })
365 } else {
366 p.tokenizer.problem(setmetatheory.range.start, format!("Module {} not found",module.0),DiagnosticLevel::Error);
367 MacroResult::Simple(setmetatheory)
368 }
369 }
370);
371
372stex!(p => stexstyleassertion[_]{_}{_}!);
373stex!(p => stexstyledefinition[_]{_}{_}!);
374stex!(p => stexstyleparagraph[_]{_}{_}!);
375
376stex!(p => inputref('*'?_s)[archive:str]{filepath:name} => {
377 let archive = archive.map(|(s,p)| (ArchiveId::new(s),p));
378 let rel_path: std::sync::Arc<str> = if filepath.0.ends_with(".tex") {
379 filepath.0.into()
380 } else {
381 format!("{}.tex",filepath.0).into()
382 };
383 {
384 if let Some(id) = archive.as_ref().map_or_else(||
385 p.state.archive.as_ref().map(|a| a.id()),
386 |(a,_)| Some(a)
387 ) {
388 p.state.backend.with_local_archive(id,|a|
389 if let Some(a) = a {
390 let path = a.source_dir();
391 let path = rel_path.as_ref().split('/').fold(path,|p,s| p.join(s));
392 if !path.exists() {
393 p.tokenizer.problem(filepath.1.start,format!("File {} not found",path.display()),DiagnosticLevel::Error);
394 }
395 } else {}
396 );
397 }
398 }
399 let filepath = (rel_path,filepath.1);
400 MacroResult::Success(STeXToken::Inputref {
401 archive, filepath,full_range:inputref.range,
402 token_range:inputref.token_range
403 })
404 }
405);
406
407stex!(p => mhinput[archive:str]{filepath:name} => {
408 let archive = archive.map(|(s,p)| (ArchiveId::new(s),p));
409 let rel_path: std::sync::Arc<str> = if filepath.0.ends_with(".tex") {
410 filepath.0.into()
411 } else {
412 format!("{}.tex",filepath.0).into()
413 };
414 {
415 if let Some(id) = archive.as_ref().map_or_else(||
416 p.state.archive.as_ref().map(|a| a.id()),
417 |(a,_)| Some(a)
418 ) {
419 p.state.backend.with_local_archive(id,|a|
420 if let Some(a) = a {
421 let path = a.source_dir();
422 let path = rel_path.as_ref().split('/').fold(path,|p,s| p.join(s));
423 if !path.exists() {
424 p.tokenizer.problem(filepath.1.start,format!("File {} not found",path.display()),DiagnosticLevel::Error);
425 }
426 } else {}
427 );
428 }
429 }
430 let filepath = (rel_path,filepath.1);
431 MacroResult::Success(STeXToken::MHInput {
432 archive, filepath,full_range:mhinput.range,
433 token_range:mhinput.token_range
434 })
435 }
436);
437
438fn strip_comments(s: &str) -> Cow<'_, str> {
439 if let Some(i) = s.find('%') {
440 let rest = &s[i..];
441 let j = rest
442 .find("\r\n")
443 .or_else(|| rest.find('\n'))
444 .or_else(|| rest.find('\r'));
445 if let Some(j) = j {
446 let r = strip_comments(&rest[j..]);
447 if r.is_empty() {
448 Cow::Borrowed(&s[..i])
449 } else {
450 Cow::Owned(format!("{}{}", &s[..i], r))
451 }
452 } else {
453 Cow::Borrowed(&s[..i])
454 }
455 } else {
456 Cow::Borrowed(s)
457 }
458}
459
460macro_rules! optargtype {
461 ($parser:ident => $name:ident { $( {$fieldname:ident = $id:literal : $($tp:tt)+} )* $(_ = $default:ident)? }) => {
462 #[derive(serde::Serialize)]
463 pub enum $name<Pos:SourcePos> {
464 $(
465 $fieldname(ParsedKeyValue<Pos,optargtype!(@TYPE $($tp)*)>)
466 ),*
467 $(, $default(SourceRange<Pos>,Box<str>))?
468 }
469 impl<Pos:SourcePos> std::fmt::Debug for $name<Pos> {
470 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
471 f.write_str(stringify!($name))
472 }
473 }
474 impl<Pos:SourcePos> Clone for $name<Pos> {
475 fn clone(&self) -> Self {
476 match self {
477 $(
478 Self::$fieldname(v) => Self::$fieldname(v.clone())
479 ),*
480 }
481 }
482 }
483 impl<'a,Pos:SourcePos,Err:FnMut(String,SourceRange<Pos>,DiagnosticLevel),MS:STeXModuleStore>
484 KeyValKind<'a,Pos,STeXToken<Pos>,Err,STeXParseState<'a,Pos,MS>> for $name<Pos> {
485 fn next_val(
486 $parser:&mut crate::quickparse::latex::KeyValParser<'a, '_,Pos,STeXToken<Pos>,Err,STeXParseState<'a,Pos,MS>>,
487 key:&str
488 ) -> Option<Self> {
489 #[allow(unused_imports)]
490 use super::super::latex::KeyValParsable;
491 match key {
492 $(
493 $id => optargtype!(@PARSE $parser $fieldname $($tp)*),
494 )*
495 _ => optargtype!(@DEFAULT $($parser $default)?)
496 }
497 }
498 }
499 };
500 ($parser:ident => $name:ident <T> { $( {$fieldname:ident = $id:literal : $($tp:tt)+} )* $(_ = $default:ident)? } @ $iter:ident) => {
501 #[derive(serde::Serialize)]
502 pub enum $name<Pos:SourcePos,T:CondSerialize> {
503 $(
504 $fieldname(ParsedKeyValue<Pos,optargtype!(@TYPE T $($tp)*)>)
505 ),*
506 $(, $default(SourceRange<Pos>,Box<str>))?
507 }
508 impl<Pos:SourcePos,T:CondSerialize> std::fmt::Debug for $name<Pos,T> {
509 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
510 f.write_str(stringify!($name))
511 }
512 }
513 impl<Pos:SourcePos,T:Clone+CondSerialize> Clone for $name<Pos,T> {
514 fn clone(&self) -> Self {
515 match self {
516 $(
517 Self::$fieldname(v) => Self::$fieldname(v.clone())
518 ),*
519 $(,
520 Self::$default(r,s) => Self::$default(*r,s.clone())
521 )?
522 }
523 }
524 }
525
526 impl<'a,Pos:SourcePos,Err:FnMut(String,SourceRange<Pos>,DiagnosticLevel),MS:STeXModuleStore>
527 KeyValKind<'a,Pos,STeXToken<Pos>,Err,STeXParseState<'a,Pos,MS>> for $name<Pos,STeXToken<Pos>> {
528 fn next_val(
529 $parser:&mut crate::quickparse::latex::KeyValParser<'a, '_,Pos,STeXToken<Pos>,Err,STeXParseState<'a,Pos,MS>>,
530 key:&str
531 ) -> Option<Self> {
532 #[allow(unused_imports)]
533 use super::super::latex::KeyValParsable;
534 match key {
535 $(
536 $id => optargtype!(@PARSE+ $parser $fieldname $($tp)*),
537 )*
538 _ => optargtype!(@DEFAULT $($parser $default)?)
539 }
540 }
541 }
542
543 impl<Pos:SourcePos,T1:CondSerialize> $name<Pos,T1> {
544 pub fn into_other<T2:CondSerialize>(self,mut cont:impl FnMut(Vec<T1>) -> Vec<T2>) -> $name<Pos,T2> {
545 match self {
546 $(
547 $name::$fieldname(val) => optargtype!(@TRANSLATE val cont $name $fieldname $($tp)*)
548 ),*
549 $(, $name::$default(range,name) => $name::$default(range,name))?
550 }
551 }
552 }
553
554 pub struct $iter<'a,Pos:SourcePos,T:CondSerialize>{
555 current:Option<std::slice::Iter<'a,T>>,
556 nexts:std::slice::Iter<'a,$name<Pos,T>>
557 }
558 impl<'a,Pos:SourcePos,T:CondSerialize> $iter<'a,Pos,T> {
559 pub fn new(sn:&'a[$name<Pos,T>]) -> Self {
560 Self { current:None,nexts:sn.iter()}
561 }
562 }
563 impl<'a,Pos:SourcePos,T:CondSerialize> Iterator for $iter<'a,Pos,T> {
564 type Item = &'a T;
565 fn next(&mut self) -> Option<Self::Item> {
566 if let Some(c) = &mut self.current {
567 if let Some(n) = c.next() { return Some(n)}
568 }
569 loop {
570 let Some(n) = self.nexts.next() else {return None};
571 match n {
572 optargtype!(@DOITER e $name {} {$($fieldname $($tp)*; )*}) => {
573 let mut next = e.val.iter();
574 if let Some(n) = next.next() {
575 self.current = Some(next);
576 return Some(n)
577 }
578 }
579 _ => ()
580 }
581 }
582 }
583 }
584 };
585 (LSP $parser:ident => $name:ident <T> { $( {$fieldname:ident = $id:literal : $($tp:tt)+} )* $(_ = $default:ident)? } @ $iter:ident) => {
586
587 #[derive(serde::Serialize)]
588 pub enum $name<Pos:SourcePos,T:CondSerialize> {
589 $(
590 $fieldname(ParsedKeyValue<Pos,optargtype!(@TYPE T $($tp)*)>)
591 ),*
592 $(, $default(SourceRange<Pos>,Box<str>))?
593 }
594 impl<Pos:SourcePos,T:CondSerialize> std::fmt::Debug for $name<Pos,T> {
595 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
596 f.write_str(stringify!($name))
597 }
598 }
599 impl<Pos:SourcePos,T:Clone+CondSerialize> Clone for $name<Pos,T> {
600 fn clone(&self) -> Self {
601 match self {
602 $(
603 Self::$fieldname(v) => Self::$fieldname(v.clone())
604 ),*
605 $(,
606 Self::$default(r,s) => Self::$default(*r,s.clone())
607 )?
608 }
609 }
610 }
611
612 impl<'a,Err:FnMut(String,SourceRange<LSPLineCol>,DiagnosticLevel),MS:STeXModuleStore>
613 KeyValKind<'a,LSPLineCol,STeXToken<LSPLineCol>,Err,STeXParseState<'a,LSPLineCol,MS>> for $name<LSPLineCol,STeXToken<LSPLineCol>> {
614 fn next_val(
615 $parser:&mut crate::quickparse::latex::KeyValParser<'a, '_,LSPLineCol,STeXToken<LSPLineCol>,Err,STeXParseState<'a,LSPLineCol,MS>>,
616 key:&str
617 ) -> Option<Self> {
618 #[allow(unused_imports)]
619 use super::super::latex::KeyValParsable;
620 match key {
621 $(
622 $id => optargtype!(@PARSE+ $parser $fieldname $($tp)*),
623 )*
624 _ => optargtype!(@DEFAULT $($parser $default)?)
625 }
626 }
627 }
628
629 impl<T1:CondSerialize> $name<LSPLineCol,T1> {
630 pub fn into_other<T2:CondSerialize>(self,mut cont:impl FnMut(Vec<T1>) -> Vec<T2>) -> $name<LSPLineCol,T2> {
631 match self {
632 $(
633 $name::$fieldname(val) => optargtype!(@TRANSLATE val cont $name $fieldname $($tp)*)
634 ),*
635 $(, $name::$default(range,name) => $name::$default(range,name))?
636 }
637 }
638 }
639
640 pub struct $iter<'a,T:CondSerialize>{
641 current:Option<std::slice::Iter<'a,T>>,
642 nexts:std::slice::Iter<'a,$name<LSPLineCol,T>>
643 }
644 impl<'a,T:CondSerialize> $iter<'a,T> {
645 pub fn new(sn:&'a[$name<LSPLineCol,T>]) -> Self {
646 Self { current:None,nexts:sn.iter()}
647 }
648 }
649 impl<'a,T:CondSerialize> Iterator for $iter<'a,T> {
650 type Item = &'a T;
651 fn next(&mut self) -> Option<Self::Item> {
652 if let Some(c) = &mut self.current {
653 if let Some(n) = c.next() { return Some(n)}
654 }
655 loop {
656 let Some(n) = self.nexts.next() else {return None};
657 match n {
658 optargtype!(@DOITER e $name {} {$($fieldname $($tp)*; )*}) => {
659 let mut next = e.val.iter();
660 if let Some(n) = next.next() {
661 self.current = Some(next);
662 return Some(n)
663 }
664 }
665 _ => ()
666 }
667 }
668 }
669 }
670 };
671 (@DEFAULT ) => { None };
672 (@DEFAULT $parser:ident $default:ident) => {
673 if $parser.has_value {
674 $parser.skip_value();
675 $parser.problem("Invalid value",DiagnosticLevel::Error);
676 None
677 } else {
678 Some(Self::$default($parser.key_range,$parser.key.to_string().into()))
679 }
680 };
681
682 (@DOITER $e:ident $name:ident {$($tks:tt)*} {} ) => {$($tks)*};
683
684 (@TYPE $(T)? str) => {Box<str>};
685 (@PARSE $(+)? $parser:ident $fieldname:ident str ) => {$parser.parse().map(Self::$fieldname)};
686 (@TRANSLATE $val:ident $cont:ident $name:ident $fieldname:ident str) => {
687 $name::$fieldname($val)
688 };
689 (@DOITER $e:ident $name:ident {$($tks:tt)*} {$fieldname:ident str; $($rest:tt)* }) => {
690 optargtype!(@DOITER $e $name {$($tks)*} { $($rest)* })
691 };
692
693 (@TYPE $(T)? ()) => {()};
694 (@PARSE $(+)? $parser:ident $fieldname:ident () ) => {$parser.parse().map(Self::$fieldname)};
695 (@TRANSLATE $val:ident $cont:ident $name:ident $fieldname:ident ()) => {
696 $name::$fieldname($val)
697 };
698 (@DOITER $e:ident $name:ident {$($tks:tt)*} {$fieldname:ident (); $($rest:tt)* }) => {
699 optargtype!(@DOITER $e $name {$($tks)*} { $($rest)* })
700 };
701
702 (@TYPE $(T)? Language) => {Language};
703 (@PARSE $(+)? $parser:ident $fieldname:ident Language ) => {$parser.parse().map(Self::$fieldname)};
704 (@TRANSLATE $val:ident $cont:ident $name:ident $fieldname:ident Language) => {
705 $name::$fieldname($val)
706 };
707 (@DOITER $e:ident $name:ident {$($tks:tt)*} {$fieldname:ident Language; $($rest:tt)* }) => {
708 optargtype!(@DOITER $e $name {$($tks)*} { $($rest)* })
709 };
710
711 (@TYPE $(T)? f32) => {f32};
712 (@PARSE $(+)? $parser:ident $fieldname:ident f32 ) => {$parser.parse().map(Self::$fieldname)};
713 (@TRANSLATE $val:ident $cont:ident $name:ident $fieldname:ident f32) => {
714 $name::$fieldname($val)
715 };
716 (@DOITER $e:ident $name:ident {$($tks:tt)*} {$fieldname:ident f32; $($rest:tt)* }) => {
717 optargtype!(@DOITER $e $name {$($tks)*} { $($rest)* })
718 };
719
720 (@TYPE $(T)? bool?) => {bool};
721 (@PARSE $(+)? $parser:ident $fieldname:ident bool? ) => {
722 if $parser.has_value {$parser.parse().map(Self::$fieldname)} else { Some(Self::$fieldname(
723 ParsedKeyValue{key_range:$parser.key_range,val_range:SourceRange{start:$parser.start,end:$parser.start},val:true}
724 )) }
725 };
726 (@TRANSLATE $val:ident $cont:ident $name:ident $fieldname:ident bool?) => {
727 $name::$fieldname($val)
728 };
729 (@DOITER $e:ident $name:ident {$($tks:tt)*} {$fieldname:ident bool?; $($rest:tt)* }) => {
730 optargtype!(@DOITER $e $name {$($tks)*} { $($rest)* })
731 };
732
733 (@TYPE $(T)? !) => {()};
734 (@PARSE $(+)? $parser:ident $fieldname:ident ! ) => {{
735 if $parser.has_value {
736 $parser.problem("Invalid value",DiagnosticLevel::Error);
737 }
738 $parser.parse().map(Self::$fieldname)
739 }};
740 (@TRANSLATE $val:ident $cont:ident $name:ident $fieldname:ident !) => {
741 $name::$fieldname($val)
742 };
743 (@DOITER $e:ident $name:ident {$($tks:tt)*} {$fieldname:ident !; $($rest:tt)* }) => {
744 optargtype!(@DOITER $e $name {$($tks)*} { $($rest)* })
745 };
746
747 (@TYPE T T*) => {Vec<T>};
748 (@PARSE+ $parser:ident $fieldname:ident T* ) => {$parser.parse().map(Self::$fieldname)};
749 (@TRANSLATE $val:ident $cont:ident $name:ident $fieldname:ident T*) => {
750 $name::$fieldname(ParsedKeyValue{key_range:$val.key_range,val_range:$val.val_range,val:$cont($val.val)})
751 };
752 (@DOITER $e:ident $name:ident {} {$fieldname:ident T*; $($rest:tt)* }) => {
753 optargtype!(@DOITER $e $name {$name::$fieldname($e)} { $($rest)* })
754 };
755 (@DOITER $e:ident $name:ident {$($tks:tt)+} {$fieldname:ident T*; $($rest:tt)* }) => {
756 optargtype!(@DOITER $e $name {$($tks)* | $name::$fieldname($e)} { $($rest)* })
757 };
758
759 (@TYPE $(T)? Args) => {u8};
760 (@PARSE $(+)? $parser:ident $fieldname:ident Args) => {{
761 let Some(s) = $parser.read_value_str_normalized() else {
762 $parser.problem("Missing value for args",DiagnosticLevel::Error);
763 return None
764 };
765 if s.bytes().all(|b| b.is_ascii_digit()) && s.len() == 1 {
766 let arg:u8 = s.parse().unwrap_or_else(|_| unreachable!());
767 Some(Self::Args($parser.to_key_value(arg)))
768 } else if s.bytes().all(|b| b == b'i' || b == b'a' || b == b'b' || b == b'B') {
769 if s.len() > 9 {
770 $parser.problem("Too many arguments",DiagnosticLevel::Error);
771 None
772 } else {
773 Some(Self::Args($parser.to_key_value(s.len() as u8)))
774 }
775 } else {
776 $parser.problem(format!("Invalid args value: >{s}<"),DiagnosticLevel::Error);
777 None
778 }
779 }};
780 (@TRANSLATE $val:ident $cont:ident $name:ident $fieldname:ident Args) => {
781 $name::$fieldname($val)
782 };
783 (@DOITER $e:ident $name:ident {$($tks:tt)*} {$fieldname:ident Args; $($rest:tt)* }) => {
784 optargtype!(@DOITER $e $name {$($tks)*} { $($rest)* })
785 };
786
787 (@TYPE $(T)? { $tp:ty => $($r:tt)*}) => {$tp};
788 (@PARSE $(+)? $parser:ident $fieldname:ident { $tp:ty => $($r:tt)*}) => {{$($r)*}};
789 (@TRANSLATE $val:ident $cont:ident $name:ident $fieldname:ident { $tp:ty => $($r:tt)*}) => {
790 $name::$fieldname($val)
791 };
792 (@DOITER $e:ident $name:ident {$($tks:tt)*} {$fieldname:ident { $tp:ty => $($r:tt)*}; $($rest:tt)* }) => {
793 optargtype!(@DOITER $e $name {$($tks)*} { $($rest)* })
794 };
795}
796
797optargtype! {parser =>
798 IncludeProblemArg {
799 {Pts = "pts" : f32}
800 {Min = "min": f32}
801 {Archive = "archive": str}
802 }
803}
804
805stex!(p => includeproblem[args:type IncludeProblemArg<Pos>]{filepath:name} => {
806 let args = args.unwrap_or_default();
807 let archive = args.iter().find_map(|p| if let IncludeProblemArg::Archive(a) = p {Some(a)} else {None})
808 .map(|p| (ArchiveId::new(&p.val),p.val_range));
809 let rel_path: std::sync::Arc<str> = if filepath.0.ends_with(".tex") {
810 filepath.0.into()
811 } else {
812 format!("{}.tex",filepath.0).into()
813 };
814 {
815 if let Some(id) = archive.as_ref().map_or_else(||
816 p.state.archive.as_ref().map(|a| a.id()),
817 |(a,_)| Some(a)
818 ) {
819 p.state.backend.with_local_archive(id,|a|
820 if let Some(a) = a {
821 let path = a.source_dir();
822 let path = rel_path.as_ref().split('/').fold(path,|p,s| p.join(s));
823 if !path.exists() {
824 p.tokenizer.problem(filepath.1.start,format!("File {} not found",path.display()),DiagnosticLevel::Error);
825 }
826 } else {}
827 );
828 }
829 }
830 let filepath = (rel_path,filepath.1);
831 MacroResult::Success(STeXToken::IncludeProblem {
832 filepath,full_range:includeproblem.range,archive,
833 token_range:includeproblem.token_range,args
834 })
835 }
836);
837
838optargtype! {parser =>
839 MHGraphicsArg {
840 {Width = "width" : str}
841 {Height = "height": str}
842 {Archive = "archive": str}
843 {Viewport = "viewport": str}
844 {Trim = "trim": str}
845 {Scale = "scale": f32}
846 {Angle = "angle": f32}
847 {Clip = "clip":()}
848 {KeepAspectRatio = "keepaspectratio":()}
849 }
850}
851
852stex!(p => mhgraphics[args:type MHGraphicsArg<Pos>]{filepath:name} => {
853 fn img_exists(path:&Path,rel_path:&mut String,warn:impl FnOnce(&str)) -> bool {
854 const IMG_EXTS: [&str;10] = ["png","PNG","jpg","JPG","jpeg","JPEG","bmp","BMP","pdf","PDF"];
855 if let Some(e) = path.extension().and_then(|s| s.to_str().and_then(|s| IMG_EXTS.iter().find(|e| **e == s))) {
856 if ["pdf","PDF"].contains(e) {
857 warn(".pdf extension not suitable for HTML\n\nrustex will substitute with a png instead.\nYou may want to directly use the .png here");
858 }
859 return path.exists();
860 }
861 for e in &IMG_EXTS {
862 if path.with_extension(e).exists() {
863 if ["pdf","PDF"].contains(e) {
864 warn(".pdf extension not suitable for HTML\n\nrustex will substitute with a png instead.\nYou may want to directly use the .png here");
865 }
866 if let Some(ex) = path.extension().and_then(|s| s.to_str()) {
867 let len = rel_path.len() - ex.len();
868 rel_path.truncate(len);
869 rel_path.push_str(*e);
870 } else {
871 rel_path.push('.');
872 rel_path.push_str(*e);
873 }
874 return true
875 }
876 }
877 false
878 }
879 let args = args.unwrap_or_default();
880 for a in &args {
881 match a {
882 MHGraphicsArg::Scale(x) => p.tokenizer.problem(x.key_range.start,"`scale` results in an image size relative to the original image file. Absolute values (`width` or `height`) are strongly encouraged",DiagnosticLevel::Warning),
883 _ => ()
884 }
885 }
886 if !args.iter().any(|e| matches!(e,MHGraphicsArg::Width(_)|MHGraphicsArg::Height(_))) {
887 p.tokenizer.problem(mhgraphics.token_range.start,"No `width` or `height` attribute in image. It is strongly encouraged to provide one of them.",DiagnosticLevel::Warning)
888 }
889 let archive = args.iter().find_map(|p| if let MHGraphicsArg::Archive(a) = p {Some(a)} else {None})
890 .map(|p| (ArchiveId::new(&p.val),p.val_range));
891 let mut rel_path = filepath.0.to_string();
892 {
893 if let Some(id) = archive.as_ref().map_or_else(||
894 p.state.archive.as_ref().map(|a| a.id()),
895 |(a,_)| Some(a)
896 ) {
897 p.state.backend.with_local_archive(id,|a|
898 if let Some(a) = a {
899 let path = a.source_dir();
900 let path = rel_path.as_str().split('/').fold(path,|p,s| p.join(s));
901 if !img_exists(&path,&mut rel_path,|s| p.tokenizer.problem(filepath.1.start,s,DiagnosticLevel::Info)) {
902 p.tokenizer.problem(filepath.1.start,format!("Image file {} not found",path.display()),DiagnosticLevel::Error);
903 }
904 } else {}
905 );
906 }
907 }
908 let filepath = (rel_path.into(),filepath.1);
909 MacroResult::Success(STeXToken::MHGraphics {
910 filepath,full_range:mhgraphics.range,archive,
911 token_range:mhgraphics.token_range,args
912 })
913 }
914);
915
916optargtype! {parser =>
917 SymdeclArg<T> {
918 {Name = "name" : str}
919 {Tp = "type": T*}
920 {Df = "def": T*}
921 {Return = "return": T*}
922 {Style = "style": ()}
923 {Assoc = "assoc": ()}
924 {Role = "role": ()}
925 {Argtypes = "argtypes": T*}
926 {Reorder = "reorder": ()}
927 {Args = "args": Args}
928 } @ SymdeclArgIter
929}
930
931stex!(p => symdecl('*'?star){name:!name}[args:type SymdeclArg<Pos,STeXToken<Pos>>] => {
932 let macroname = if star {None} else {Some(&name.0)};
933 let args = args.unwrap_or_default();
934 let main_name_range = name.1;
935 let mut name:(&str,_) = (&name.0,name.1);
936 let mut has_df = false;
937 let mut has_tp = false;
938 let mut argnum = 0;
939 for e in &args { match e {
940 SymdeclArg::Name(ParsedKeyValue { val_range, val,.. }) => {
941 name = (val,*val_range);
942 }
943 SymdeclArg::Tp(_) | SymdeclArg::Return(_) => has_tp = true,
944 SymdeclArg::Df(_) => has_df = true,
945 SymdeclArg::Args(v) => argnum = v.val,
946 _ => ()
947 }}
948
949 let (state,mut groups) = p.split();
950 let Ok(fname) : Result<Name,_> = name.0.parse() else {
951 p.tokenizer.problem(name.1.start, format!("Invalid uri segment {}",name.0),DiagnosticLevel::Error);
952 return MacroResult::Simple(symdecl)
953 };
954 let mn = macroname.as_ref();
955 if let Some(uri) = state.add_symbol(&mut groups,fname,
956 mn.map(|s| s.to_string().into()),
957 symdecl.range,has_tp,has_df,argnum
958 ) {
959 MacroResult::Success(STeXToken::Symdecl {
960 uri, main_name_range,
961 full_range:symdecl.range,parsed_args:args,
962 token_range:symdecl.token_range
963 })
964 } else {
965 MacroResult::Simple(symdecl)
966 }
967 }
968);
969
970optargtype! {parser =>
971 TextSymdeclArg<T> {
972 {Name = "name" : str}
973 {Style = "style": ()}
974 {Tp = "type": T*}
975 {Df = "def": T*}
976 } @ TextSymdeclArgIter
977}
978
979stex!(p => textsymdecl{name:name}[args:type TextSymdeclArg<Pos,STeXToken<Pos>>] => {
980 let macroname = Some(name.0);
981 let main_name_range = name.1;
982 let args = args.unwrap_or_default();
983 let mut name:(&str,_) = (&name.0,name.1);
984 for e in &args { match e {
987 TextSymdeclArg::Name(ParsedKeyValue { val_range, val,.. }) => {
988 name = (val,*val_range);
989 }
990 _ => ()
993 }}
994
995 let (state,mut groups) = p.split();
996 let Ok(fname) : Result<Name,_> = name.0.parse() else {
997 p.tokenizer.problem(name.1.start, format!("Invalid uri segment {}",name.0),DiagnosticLevel::Error);
998 return MacroResult::Simple(textsymdecl)
999 };
1000 let mn = macroname.as_ref();
1001 if let Some(uri) = state.add_symbol(&mut groups,fname,
1002 mn.map(|s| s.to_string().into()),
1003 textsymdecl.range,false,false,0
1004 ) {
1005 MacroResult::Success(STeXToken::TextSymdecl {
1006 uri, main_name_range,
1007 full_range:textsymdecl.range,parsed_args:args,
1008 token_range:textsymdecl.token_range
1009 })
1010 } else {
1011 MacroResult::Simple(textsymdecl)
1012 }
1013}
1014);
1015
1016optargtype! {parser =>
1017 NotationArg<T> {
1018 {Prec = "prec": T*}
1019 {Op = "op": T*}
1020 _ = Id
1021 } @ NotationArgIter
1022}
1023
1024stex!(LSP: p => notation('*'?star){name:!name}[args:type NotationArg<LSPLineCol,STeXToken<LSPLineCol>>] => {
1025 let args = args.unwrap_or_default();
1026 let (state,mut groups) = p.split();
1027 let Some(s) = state.get_symbol(name.1.start,&mut groups,&name.0) else {
1028 p.tokenizer.problem(name.1.start, format!("Unknown symbol {}",name.0),DiagnosticLevel::Error);
1029 return MacroResult::Simple(notation);
1030 };
1031 MacroResult::Success(STeXToken::Notation {
1032 uri:s,
1033 token_range:notation.token_range,
1034 name_range:name.1,
1035 notation_args:args,
1036 full_range:notation.range
1037 })
1038});
1039
1040optargtype! {parser =>
1041 SymdefArg<T> {
1042 {Name = "name" : str}
1043 {Tp = "type": T*}
1044 {Df = "def": T*}
1045 {Return = "return": T*}
1046 {Style = "style": ()}
1047 {Assoc = "assoc": ()}
1048 {Role = "role": ()}
1049 {Argtypes = "argtypes": T*}
1050 {Reorder = "reorder": ()}
1051 {Args = "args": Args}
1052 {Prec = "prec": T*}
1053 {Op = "op": T*}
1054 _ = Id
1055 } @ SymdefArgIter
1056}
1057
1058stex!(p => symdef{name:!name}[args:type SymdefArg<Pos,STeXToken<Pos>>] => {
1059 let macroname = Some(&name.0);
1060 let main_name_range = name.1;
1061 let args = args.unwrap_or_default();
1062 let mut name:(&str,_) = (&name.0,name.1);
1063 let mut has_df = false;
1064 let mut has_tp = false;
1065 let mut argnum = 0;
1066 for e in &args { match e {
1067 SymdefArg::Name(ParsedKeyValue { key_range, val_range, val }) => {
1068 name = (val,*val_range);
1069 }
1070 SymdefArg::Tp(_) | SymdefArg::Return(_) => has_tp = true,
1071 SymdefArg::Df(_) => has_df = true,
1072 SymdefArg::Args(v) => argnum = v.val,
1073 _ => ()
1074 }}
1075
1076 let (state,mut groups) = p.split();
1077 let Ok(fname) : Result<Name,_> = name.0.parse() else {
1078 p.tokenizer.problem(name.1.start, format!("Invalid uri segment {}",name.0),DiagnosticLevel::Error);
1079 return MacroResult::Simple(symdef)
1080 };
1081 let mn = macroname.as_ref();
1082 if let Some(uri) = state.add_symbol(&mut groups,fname,
1083 mn.map(|s| s.to_string().into()),
1084 symdef.range,has_tp,has_df,argnum
1085 ) {
1086 MacroResult::Success(STeXToken::Symdef {
1087 uri, main_name_range,
1088 full_range:symdef.range,parsed_args:args,
1089 token_range:symdef.token_range
1090 })
1091 } else {
1092 MacroResult::Simple(symdef)
1093 }
1094}
1095);
1096
1097stex!(LSP: p => precondition{dim:!name}{symbol:!name} => {
1098 let Ok(cogdim) = dim.0.parse() else {
1099 p.tokenizer.problem(dim.1.start,format!("Invalid cognitive dimension {}",dim.0),DiagnosticLevel::Error);
1100 return MacroResult::Simple(precondition);
1101 };
1102 let (state,mut groups) = p.split();
1103 if !groups.groups.iter().rev().any(|g| matches!(g.kind,GroupKind::Problem)) {
1104 groups.tokenizer.problem(symbol.1.start, "\\precondition is only allowed in a problem",DiagnosticLevel::Error);
1105 }
1106 let Some(s) = state.get_symbol(symbol.1.start,&mut groups,&symbol.0) else {
1107 groups.tokenizer.problem(symbol.1.start, format!("Unknown symbol {}",symbol.0),DiagnosticLevel::Error);
1108 return MacroResult::Simple(precondition);
1109 };
1110 MacroResult::Success(STeXToken::Precondition {
1111 uri:s, full_range: precondition.range, token_range: precondition.token_range, dim_range:dim.1,
1112 symbol_range:symbol.1,dim:cogdim
1113 })
1114});
1115
1116stex!(LSP: p => objective{dim:!name}{symbol:!name} => {
1117 let Ok(cogdim) = dim.0.parse() else {
1118 p.tokenizer.problem(dim.1.start,format!("Invalid cognitive dimension {}",dim.0),DiagnosticLevel::Error);
1119 return MacroResult::Simple(objective);
1120 };
1121 let (state,mut groups) = p.split();
1122 if !groups.groups.iter().rev().any(|g| matches!(g.kind,GroupKind::Problem)) {
1123 groups.tokenizer.problem(symbol.1.start, "\\objective is only allowed in a problem",DiagnosticLevel::Error);
1124 }
1125 let Some(s) = state.get_symbol(symbol.1.start,&mut groups,&symbol.0) else {
1126 groups.tokenizer.problem(symbol.1.start, format!("Unknown symbol {}",symbol.0),DiagnosticLevel::Error);
1127 return MacroResult::Simple(objective);
1128 };
1129 MacroResult::Success(STeXToken::Objective {
1130 uri:s, full_range: objective.range, token_range: objective.token_range, dim_range:dim.1,
1131 symbol_range:symbol.1,dim:cogdim
1132 })
1133});
1134
1135stex!(LSP: p => symref[mut args:Map]{name:!name}{text:T} => {
1136 let (state,mut groups) = p.split();
1137 let Some(s) = state.get_symbol(name.1.start,&mut groups,&name.0) else {
1138 p.tokenizer.problem(name.1.start, format!("Unknown symbol {}",name.0),DiagnosticLevel::Error);
1139 return MacroResult::Simple(symref);
1140 };
1141 args.inner.remove(&"root");
1142 for (k,v) in args.inner.iter() {
1143 p.tokenizer.problem(v.key_range.start, format!("Unknown argument {}",k),DiagnosticLevel::Error);
1144 }
1145 MacroResult::Success(STeXToken::Symref {
1146 uri:s, full_range: symref.range, token_range: symref.token_range,
1147 name_range: name.1, text
1148 })
1149});
1150
1151stex!(LSP: p => symname[mut args:Map]{name:!name} => {
1152 let (state,mut groups) = p.split();
1153 let Some(s) = state.get_symbol(name.1.start,&mut groups,&name.0) else {
1154 p.tokenizer.problem(name.1.start, format!("Unknown symbol {}",name.0),DiagnosticLevel::Error);
1155 return MacroResult::Simple(symname);
1156 };
1157 let pre = if let Some(val) = args.inner.remove(&"pre") {
1158 Some((val.key_range,val.val_range,strip_comments(val.str).trim().to_string()))
1159 } else { None };
1160 let post = if let Some(val) = args.inner.remove(&"post") {
1161 Some((val.key_range,val.val_range,strip_comments(val.str).trim().to_string()))
1162 } else { None };
1163 for (k,v) in args.inner.iter() {
1164 p.tokenizer.problem(v.key_range.start, format!("Unknown argument {}",k),DiagnosticLevel::Error);
1165 }
1166 MacroResult::Success(STeXToken::SymName {
1167 uri:s, full_range: symname.range, token_range: symname.token_range,
1168 name_range: name.1,
1169 mode: super::structs::SymnameMode::PrePost{ pre, post }
1170 })
1171});
1172
1173stex!(LSP: p => Symname[mut args:Map]{name:!name} => {
1174 let (state,mut groups) = p.split();
1175 let Some(s) = state.get_symbol(name.1.start,&mut groups,&name.0) else {
1176 p.tokenizer.problem(name.1.start, format!("Unknown symbol {}",name.0),DiagnosticLevel::Error);
1177 return MacroResult::Simple(Symname);
1178 };
1179 let post = if let Some(val) = args.inner.remove(&"post") {
1180 Some((val.key_range,val.val_range,strip_comments(val.str).trim().to_string()))
1181 } else { None };
1182 for (k,v) in args.inner.iter() {
1183 p.tokenizer.problem(v.key_range.start, format!("Unknown argument {}",k),DiagnosticLevel::Error);
1184 }
1185 MacroResult::Success(STeXToken::SymName {
1186 uri:s, full_range: Symname.range, token_range: Symname.token_range,
1187 name_range: name.1,
1188 mode: super::structs::SymnameMode::Cap{ post }
1189 })
1190});
1191
1192stex!(LSP: p => symnames[mut args:Map]{name:!name} => {
1193 let (state,mut groups) = p.split();
1194 let Some(s) = state.get_symbol(name.1.start,&mut groups,&name.0) else {
1195 p.tokenizer.problem(name.1.start, format!("Unknown symbol {}",name.0),DiagnosticLevel::Error);
1196 return MacroResult::Simple(symnames);
1197 };
1198 let pre = if let Some(val) = args.inner.remove(&"pre") {
1199 Some((val.key_range,val.val_range,strip_comments(val.str).trim().to_string()))
1200 } else { None };
1201 for (k,v) in args.inner.iter() {
1202 p.tokenizer.problem(v.key_range.start, format!("Unknown argument {}",k),DiagnosticLevel::Error);
1203 }
1204 MacroResult::Success(STeXToken::SymName {
1205 uri:s, full_range: symnames.range, token_range: symnames.token_range,
1206 name_range: name.1,
1207 mode: super::structs::SymnameMode::PostS{ pre }
1208 })
1209});
1210
1211stex!(LSP: p => Symnames{name:!name} => {
1212 let (state,mut groups) = p.split();
1213 let Some(s) = state.get_symbol(name.1.start,&mut groups,&name.0) else {
1214 p.tokenizer.problem(name.1.start, format!("Unknown symbol {}",name.0),DiagnosticLevel::Error);
1215 return MacroResult::Simple(Symnames);
1216 };
1217 MacroResult::Success(STeXToken::SymName {
1218 uri:s, full_range: Symnames.range, token_range: Symnames.token_range,
1219 name_range: name.1,
1220 mode: super::structs::SymnameMode::CapAndPostS
1221 })
1222});
1223
1224stex!(LSP: p => definame[mut args:Map]{name:!name} => {
1225 let (state,mut groups) = p.split();
1226 let Some(s) = state.get_symbol(name.1.start,&mut groups,&name.0) else {
1227 p.tokenizer.problem(name.1.start, format!("Unknown symbol {}",name.0),DiagnosticLevel::Error);
1228 return MacroResult::Simple(definame);
1229 };
1230 let pre = if let Some(val) = args.inner.remove(&"pre") {
1231 Some((val.key_range,val.val_range,strip_comments(val.str).trim().to_string()))
1232 } else { None };
1233 let post = if let Some(val) = args.inner.remove(&"post") {
1234 Some((val.key_range,val.val_range,strip_comments(val.str).trim().to_string()))
1235 } else { None };
1236 args.inner.remove(&"root");
1237 for (k,v) in args.inner.iter() {
1238 p.tokenizer.problem(v.key_range.start, format!("Unknown argument {}",k),DiagnosticLevel::Error);
1239 }
1240 MacroResult::Success(STeXToken::SymName {
1241 uri:s, full_range: definame.range, token_range: definame.token_range,
1242 name_range: name.1,
1243 mode: super::structs::SymnameMode::PrePost{ pre, post }
1244 })
1245});
1246
1247stex!(LSP: p => Definame[mut args:Map]{name:!name} => {
1248 let (state,mut groups) = p.split();
1249 let Some(s) = state.get_symbol(name.1.start,&mut groups,&name.0) else {
1250 p.tokenizer.problem(name.1.start, format!("Unknown symbol {}",name.0),DiagnosticLevel::Error);
1251 return MacroResult::Simple(Definame);
1252 };
1253 let post = if let Some(val) = args.inner.remove(&"post") {
1254 Some((val.key_range,val.val_range,strip_comments(val.str).trim().to_string()))
1255 } else { None };
1256 for (k,v) in args.inner.iter() {
1257 p.tokenizer.problem(v.key_range.start, format!("Unknown argument {}",k),DiagnosticLevel::Error);
1258 }
1259 MacroResult::Success(STeXToken::SymName {
1260 uri:s, full_range: Definame.range, token_range: Definame.token_range,
1261 name_range: name.1,
1262 mode: super::structs::SymnameMode::Cap{ post }
1263 })
1264});
1265
1266stex!(LSP: p => definames[mut args:Map]{name:!name} => {
1267 let (state,mut groups) = p.split();
1268 let Some(s) = state.get_symbol(name.1.start,&mut groups,&name.0) else {
1269 p.tokenizer.problem(name.1.start, format!("Unknown symbol {}",name.0),DiagnosticLevel::Error);
1270 return MacroResult::Simple(definames);
1271 };
1272 let pre = if let Some(val) = args.inner.remove(&"pre") {
1273 Some((val.key_range,val.val_range,strip_comments(val.str).trim().to_string()))
1274 } else { None };
1275 for (k,v) in args.inner.iter() {
1276 p.tokenizer.problem(v.key_range.start, format!("Unknown argument {}",k),DiagnosticLevel::Error);
1277 }
1278 MacroResult::Success(STeXToken::SymName {
1279 uri:s, full_range: definames.range, token_range: definames.token_range,
1280 name_range: name.1,
1281 mode: super::structs::SymnameMode::PostS{ pre }
1282 })
1283});
1284
1285stex!(LSP: p => Definames{name:!name} => {
1286 let (state,mut groups) = p.split();
1287 let Some(s) = state.get_symbol(name.1.start,&mut groups,&name.0) else {
1288 p.tokenizer.problem(name.1.start, format!("Unknown symbol {}",name.0),DiagnosticLevel::Error);
1289 return MacroResult::Simple(Definames);
1290 };
1291 MacroResult::Success(STeXToken::SymName {
1292 uri:s, full_range: Definames.range, token_range: Definames.token_range,
1293 name_range: name.1,
1294 mode: super::structs::SymnameMode::CapAndPostS
1295 })
1296});
1297
1298stex!(LSP: p => symuse{name:!name} => {
1299 let (state,mut groups) = p.split();
1300 let Some(s) = state.get_symbol(name.1.start,&mut groups,&name.0) else {
1301 p.tokenizer.problem(name.1.start, format!("Unknown symbol {}",name.0),DiagnosticLevel::Error);
1302 return MacroResult::Simple(symuse);
1303 };
1304 MacroResult::Success(STeXToken::Symuse {
1305 uri:s, full_range: symuse.range, token_range: symuse.token_range,
1306 name_range: name.1
1307 })
1308});
1309
1310stex!(LSP: p => defnotation => {
1311 MacroResult::Success(STeXToken::Defnotation{full_range:defnotation.token_range})
1312});
1313
1314stex!(LSP: p => definiens[name_opt:!name] => {
1315 let (state,mut groups) = p.split();
1316 let (s,rng) = if let Some(name) = name_opt {
1317 if let Some((s,_)) = get_in_morphism(&mut groups.groups, &name.0) {
1318 (smallvec::smallvec![s.uri.clone()],Some(name.1))
1319 } else {
1320 let Some(s) = state.get_symbol(name.1.start,&mut groups,&name.0) else {
1321 p.tokenizer.problem(name.1.start, format!("Unknown symbol {}",name.0),DiagnosticLevel::Error);
1322 return MacroResult::Simple(definiens);
1323 };
1324 (s,Some(name.1))
1325 }
1326 } else {
1327 let Some(s) = groups.groups.iter().rev().find_map(|g|
1328 if let GroupKind::DefPara(defs) = &g.kind {
1329 defs.first().cloned()
1330 } else {None}
1331 ) else {
1332 p.tokenizer.problem(definiens.range.start, "No definition found".to_string(),DiagnosticLevel::Error);
1333 return MacroResult::Simple(definiens);
1334 };
1335 (smallvec::smallvec![s],None)
1336 };
1337 set_defined(s.first().unwrap_or_else(|| unreachable!()), definiens.range, &mut groups.groups);
1338 MacroResult::Success(STeXToken::Definiens {
1339 uri:s, full_range: definiens.range, token_range: definiens.token_range,
1340 name_range: rng
1341 })
1342});
1343
1344stex!(LSP: p => defi_only => {
1345 p.tokenizer.problem(p.curr_pos(), "only allowed in definitions".to_string(),DiagnosticLevel::Error);
1346 MacroResult::Simple(defi_only)
1347});
1348
1349optargtype! {parser =>
1350 VardefArg<T> {
1351 {Name = "name" : str}
1352 {Args = "args": Args}
1353 {Tp = "type": T*}
1354 {Df = "def": T*}
1355 {Return = "return": T*}
1356 {Style = "style": ()}
1357 {Assoc = "assoc": ()}
1358 {Role = "role": ()}
1359 {Argtypes = "argtypes": T*}
1360 {Reorder = "reorder": ()}
1361 {Bind = "bind": !}
1362 {Prec = "prec": T*}
1363 {Op = "op": T*}
1364 _ = Id
1365 } @ VardefArgIter
1366}
1367
1368stex!(p => vardef{name:!name}[args:type VardefArg<Pos,STeXToken<Pos>>] => {
1369 let macroname = name.0.to_string();
1370 let args = args.unwrap_or_default();
1371 let main_name_range = name.1;
1372 let mut name: (&str,_) = (&name.0,name.1);
1373 let mut argnum = 0;
1376
1377 for e in &args { match e {
1378 VardefArg::Name(ParsedKeyValue { key_range, val_range, val }) => {
1379 name = (val,*val_range);
1380 }
1381 VardefArg::Args(v) => argnum = v.val,
1384 _ => ()
1385 }}
1386
1387 let (state,mut groups) = p.split();
1388 let Ok(fname) : Result<Name,_> = name.0.parse() else {
1389 p.tokenizer.problem(name.1.start, format!("Invalid uri segment {}",name.0),DiagnosticLevel::Error);
1390 return MacroResult::Simple(vardef)
1391 };
1392 let rule = AnyMacro::Ext(DynMacro {
1393 ptr: variable_macro as _,
1394 arg:MacroArg::Variable(fname.clone(), vardef.range, false,argnum)
1395 });
1396 p.add_macro_rule(macroname.clone().into(), Some(rule));
1397 MacroResult::Success(STeXToken::Vardef {
1398 name:fname, main_name_range,
1399 full_range:vardef.range,parsed_args:args,
1400 token_range:vardef.token_range
1401 })
1402});
1403
1404stex!(p => varseq{name:!name}[args:type VardefArg<Pos,STeXToken<Pos>>] => {
1405 let macroname = name.0.to_string();
1406 let args = args.unwrap_or_default();
1407 let main_name_range = name.1;
1408 let mut name : (&str,_) = (&name.0,name.1);
1409 let mut argnum = 0;
1412
1413 for e in &args { match e {
1414 VardefArg::Name(ParsedKeyValue { key_range, val_range, val }) => {
1415 name = (val,*val_range);
1416 }
1417 VardefArg::Args(v) => argnum = v.val,
1420 _ => ()
1421 }}
1422
1423 let (state,mut groups) = p.split();
1424 let Ok(fname) : Result<Name,_> = name.0.parse() else {
1425 p.tokenizer.problem(name.1.start, format!("Invalid uri segment {}",name.0),DiagnosticLevel::Error);
1426 return MacroResult::Simple(varseq)
1427 };
1428 let rule = AnyMacro::Ext(DynMacro {
1429 ptr: variable_macro as _,
1430 arg:MacroArg::Variable(fname.clone(), varseq.range, true,argnum)
1431 });
1432 p.add_macro_rule(macroname.clone().into(), Some(rule));
1433 MacroResult::Success(STeXToken::Varseq {
1434 name:fname, main_name_range,
1435 full_range:varseq.range,parsed_args:args,
1436 token_range:varseq.token_range
1437 })
1438});
1439
1440stex!(p => svar[optname:!name]{arg:!name} => {
1441 let (name,name_range) = if let Some(optname) = optname {
1442 (optname.0,Some(optname.1))
1443 } else {
1444 (arg.0,None)
1445 };
1446 let Ok(name) = Name::from_str(name.as_ref()) else {
1447 p.tokenizer.problem(name_range.unwrap().start, format!("Invalid uri segment {}",name),DiagnosticLevel::Error);
1448 return MacroResult::Simple(svar)
1449 };
1450 MacroResult::Success(STeXToken::Svar {
1451 name, full_range:svar.range,name_range,arg_range:arg.1,
1452 token_range:svar.token_range
1453 })
1454});
1455
1456lazy_static::lazy_static! {
1457 static ref META_REL_PATH:std::sync::Arc<str> = "Metatheory.en.tex".into();
1458 static ref META_FULL_PATH:Option<std::sync::Arc<Path>> =
1459 GlobalBackend::get().with_local_archive(flams_ontology::metatheory::URI.archive_id(), |a|
1460 a.map(|a| a.source_dir().join("Metatheory.en.tex").into())
1461 );
1462}
1463
1464fn get_module<
1465 'a,
1466 'b,
1467 Pos: SourcePos + 'a,
1468 MS: STeXModuleStore,
1469 Err: FnMut(String, SourceRange<Pos>, DiagnosticLevel),
1470>(
1471 p: &'b mut LaTeXParser<'a, ParseStr<'a, Pos>, STeXToken<Pos>, Err, STeXParseState<'a, Pos, MS>>,
1472) -> Option<(&'b ModuleURI, &'b mut Vec<ModuleRule<Pos>>)> {
1473 p.groups.iter_mut().rev().find_map(|g| match &mut g.kind {
1474 GroupKind::Module { uri, rules } | GroupKind::MathStructure { uri, rules } => {
1475 Some((&*uri, rules))
1476 }
1477 _ => None,
1478 })
1479}
1480
1481optargtype!(parser =>
1482 SModuleArg<T> {
1483 {Sig = "sig": Language}
1484 {Meta = "meta": str}
1485 {Title = "title": T*}
1488 } @ SModuleArgIter
1489);
1490
1491stex!(LSP: p => @begin{smodule}([opt:type SModuleArg<LSPLineCol,STeXToken<LSPLineCol>>]{name:name}){
1492 let opt = opt.unwrap_or_default();
1493 let mut sig = None;
1494 let mut has_meta_theory = Some(false);
1495 for e in &opt { match e {
1496 SModuleArg::Sig(s) => sig = Some(s.val),
1497 SModuleArg::Meta(s) => {
1498 if s.val.is_empty() || &*s.val == "{}" {
1499 has_meta_theory = None;
1500 } else {
1501 p.tokenizer.problem(smodule.begin.range.start,"TODO: metatheory",DiagnosticLevel::Error);
1502 has_meta_theory = Some(true);
1503 }
1504 }
1505 _ => ()
1506 }}
1507 let meta_theory = if has_meta_theory == Some(false) {
1508 Some(ModuleReference {
1509 uri:flams_ontology::metatheory::URI.clone(),
1510 in_doc:flams_ontology::metatheory::DOC_URI.clone(),
1511 rel_path:Some(META_REL_PATH.clone()),
1512 full_path:META_FULL_PATH.clone()
1513 })
1514 } else { None };
1515
1516 let uri = if let Some((m,_)) = get_module(p) {
1517 m.clone() / name.0
1518 } else {
1519 p.state.doc_uri.module_uri_from(name.0)
1520 };
1521 let Ok(uri) = uri else {
1522 p.tokenizer.problem(name.1.start, format!("Invalid uri segment {}",name.1),DiagnosticLevel::Error);
1523 return ()
1524 };
1525 p.groups.last_mut().unwrap_or_else(|| unreachable!()).kind = GroupKind::Module{
1526 uri:uri.clone(),rules:Vec::new()
1527 };
1528 if let Some(l) = sig {
1529 if let Some(path) = &p.state.in_path {
1530 let curr_lang = p.state.language;
1531 let Some(filename) = path.file_name().and_then(|s| s.to_str()) else {
1532 p.tokenizer.problem(smodule.begin.range.start, "file path error", DiagnosticLevel::Error);
1533 return
1534 };
1535 let filename = {
1536 let Some(filename) = filename.strip_suffix(".tex") else {
1537 p.tokenizer.problem(smodule.begin.range.start, "file path error", DiagnosticLevel::Error);
1538 return
1539 };
1540 let init = if filename.ends_with(<&'static str>::from(curr_lang)) {
1541 &filename[..filename.len()-3]
1542 } else {filename};
1543 format!("{init}.{l}.tex")
1544 };
1545 let full_path = path.with_file_name(&filename);
1546 let rel_path = p.state.archive.as_ref().and_then(|a| {
1547 p.state.backend.with_local_archive(a.id(), |a|
1548 a.and_then(|a| path.strip_prefix(a.path()).ok().and_then(|p|
1549 p.strip_prefix("source").ok().map(|p| p.with_file_name(filename).display().to_string().into())
1550 ))
1551 )
1552 });
1553
1554 let uri = uri.clone();
1555 let in_doc = p.state.doc_uri.as_path().owned() & (p.state.doc_uri.name().clone(),l);
1556 let mrf = ModuleReference {
1557 uri,in_doc,rel_path,full_path:Some(full_path.into())
1558 };
1559 let (state,groups) = p.split();
1560 state.add_import(&mrf, groups, smodule.begin.range);
1561 }
1562 }
1563 if let Some(rf) = meta_theory.as_ref() {
1564 let (state,groups) = p.split();
1565 state.add_import(rf, groups, smodule.begin.range);
1567 }
1568 smodule.children.push(STeXToken::Module{
1569 uri,full_range:smodule.begin.range,sig,meta_theory,
1570 children:Vec::new(),name_range:name.1,
1571 smodule_range:smodule.name_range,opts:opt,
1572 rules:ModuleRules::default()
1573 });
1574 }{
1575 let Some(g) = p.groups.last_mut() else {
1576 p.tokenizer.problem(smodule.begin.range.start,"Module ended unexpectedly",DiagnosticLevel::Error);
1577 return EnvironmentResult::Simple(smodule)
1578 };
1579 let GroupKind::Module { uri, rules } = std::mem::take(&mut g.kind) else {
1580 return EnvironmentResult::Simple(smodule);
1581 };
1582 let rules = ModuleRules{ rules:rules.into()};
1583 p.state.modules.push((uri,rules.clone()));
1584 match smodule.children.first() {
1585 Some(STeXToken::Module { .. }) => {
1586 let mut ch = smodule.children.drain(..);
1587 let Some(STeXToken::Module { uri,mut full_range,sig,meta_theory,mut children,name_range,smodule_range,opts,.. }) = ch.next() else {
1588 unreachable!()
1589 };
1590 children.extend(ch);
1591 if let Some(end) = smodule.end {
1592 full_range.end = end.range.end;
1593 }
1594 EnvironmentResult::Success(STeXToken::Module { uri,rules,full_range,sig,meta_theory,children,name_range,smodule_range,opts })
1595 }
1596 _ => EnvironmentResult::Simple(smodule)
1597 }
1598 }
1599);
1600
1601optargtype!(parser =>
1602 MathStructureArg<T> {
1603 {This = "this": T*}
1604 _ = Name
1605 } @ MathStructureArgIter
1606);
1607
1608stex!(LSP: p => @begin{mathstructure}({name:!name}[args:type MathStructureArg<LSPLineCol,STeXToken<LSPLineCol>>]){
1609 let args = args.unwrap_or_default();
1610 let name_range = name.1;
1611 let macroname = &name.0;
1612 let mut name : &str = &name.0;
1613 for a in &args{ match a {
1614 MathStructureArg::Name(_,n) => name = n,
1615 _ => ()
1616 }}
1617
1618 let Ok(fname) : Result<Name,_> = name.parse() else {
1619 p.tokenizer.problem(name_range.start, format!("Invalid uri segment {}",name),DiagnosticLevel::Error);
1620 return
1621 };
1622 let (state,mut groups) = p.split();
1623 let Some(uri) = state.add_structure(
1624 &mut groups,fname,Some(macroname.to_string().into()),mathstructure.begin.range
1625 ) else {
1626 return
1627 };
1628
1629 groups.groups.last_mut().unwrap_or_else(|| unreachable!()).kind = GroupKind::MathStructure{
1630 uri:uri.uri.clone().into_module(),rules:Vec::new()
1631 };
1632
1633 mathstructure.children.push(STeXToken::MathStructure {
1634 uri, name_range,
1635 opts:args,
1636 mathstructure_range: mathstructure.name_range,
1637 full_range: mathstructure.begin.range,
1638 extends: Vec::new(),
1639 children: Vec::new()
1640 })
1641}{
1642 match mathstructure.children.first() {
1643 Some(STeXToken::MathStructure { .. }) => {
1644 let mut ch = mathstructure.children.drain(..);
1645 let Some(STeXToken::MathStructure { uri, opts, extends, name_range, mut full_range, mut children, mathstructure_range }) = ch.next() else{
1646 unreachable!()
1647 };
1648 children.extend(ch);
1649 if let Some(end) = mathstructure.end.as_ref() {
1650 full_range.end = end.range.end;
1651 }
1652
1653 let Some(g) = p.groups.last_mut() else {
1654 p.tokenizer.problem(mathstructure.begin.range.start,"Mathstructure ended unexpectedly",DiagnosticLevel::Error);
1655 return EnvironmentResult::Simple(mathstructure)
1656 };
1657 let GroupKind::MathStructure { uri:_, rules } = std::mem::take(&mut g.kind) else {
1658 return EnvironmentResult::Simple(mathstructure);
1659 };
1660 let rules = ModuleRules{ rules:rules.into()};
1661 let (state,mut groups) = p.split();
1662 state.set_structure(&mut groups, rules, full_range);
1663
1664 EnvironmentResult::Success(STeXToken::MathStructure {
1665 uri,extends,name_range,full_range,opts,children,mathstructure_range
1666 })
1667 }
1668 _ => {
1669 EnvironmentResult::Simple(mathstructure)
1670 }
1671 }
1672});
1673
1674stex!(LSP: p => @begin{extstructure}({name:!name}[args:type MathStructureArg<LSPLineCol,STeXToken<LSPLineCol>>]{exts:!name+}){
1675 let args = args.unwrap_or_default();
1676 let name_range = name.1;
1677 let macroname = &name.0;
1678 let mut name: &str = &name.0;
1679 for a in &args{ match a {
1680 MathStructureArg::Name(_,n) => name = n,
1681 _ => ()
1682 }}
1683
1684 let Ok(fname) : Result<Name,_> = name.parse() else {
1685 p.tokenizer.problem(name_range.start, format!("Invalid uri segment {}",name),DiagnosticLevel::Error);
1686 return
1687 };
1688 let (state,mut groups) = p.split();
1689 let mut extends = Vec::new();
1690 for (n,r) in exts {
1691 let Some(s) = state.get_structure(&groups,&n) else {
1692 groups.tokenizer.problem(r.start, format!("Unknown structure {n}"),DiagnosticLevel::Error);
1693 return
1694 };
1695 extends.push((s.0,s.1,r));
1696 }
1697 let Some(uri) = state.add_structure(
1698 &mut groups,fname,Some(macroname.clone().into()),extstructure.begin.range
1699 ) else { return };
1700
1701 groups.groups.last_mut().unwrap_or_else(|| unreachable!()).kind = GroupKind::MathStructure{
1702 uri:uri.uri.clone().into_module(),rules:Vec::new()
1703 };
1704
1705 for (s,r,_) in &extends {
1706 state.import_structure(s,r,&mut groups,extstructure.begin.range);
1707 }
1708
1709 extstructure.children.push(STeXToken::MathStructure {
1710 uri, name_range,
1711 opts:args,
1712 mathstructure_range: extstructure.name_range,
1713 full_range: extstructure.begin.range,
1714 extends:extends.into_iter().map(|(a,_,b)| (a,b)).collect(),
1715 children: Vec::new()
1716 })
1717}{
1718 match extstructure.children.first() {
1719 Some(STeXToken::MathStructure { .. }) => {
1720 let mut ch = extstructure.children.drain(..);
1721 let Some(STeXToken::MathStructure { uri,opts , extends, name_range, mut full_range, mut children, mathstructure_range }) = ch.next() else{
1722 unreachable!()
1723 };
1724 children.extend(ch);
1725 if let Some(end) = extstructure.end.as_ref() {
1726 full_range.end = end.range.end;
1727 }
1728
1729 let Some(g) = p.groups.last_mut() else {
1730 p.tokenizer.problem(extstructure.begin.range.start,"extstructure ended unexpectedly",DiagnosticLevel::Error);
1731 return EnvironmentResult::Simple(extstructure)
1732 };
1733 let GroupKind::MathStructure { uri:_, rules } = std::mem::take(&mut g.kind) else {
1734 return EnvironmentResult::Simple(extstructure);
1735 };
1736 let rules = ModuleRules{ rules:rules.into()};
1737 let (state,mut groups) = p.split();
1738 state.set_structure(&mut groups, rules, full_range);
1739
1740 EnvironmentResult::Success(STeXToken::MathStructure {
1741 uri,extends,name_range,full_range,opts,children,mathstructure_range
1742 })
1743 }
1744 _ => {
1745 EnvironmentResult::Simple(extstructure)
1746 }
1747 }
1748});
1749
1750stex!(LSP: p => @begin{extstructure_ast}({exts:!name}){
1751 let (state,mut groups) = p.split();
1752 let Some((sym,rules)) = state.get_structure(&groups,&exts.0) else {
1753 groups.tokenizer.problem(exts.1.start, format!("Unknown structure {}",exts.0),DiagnosticLevel::Error);
1754 return
1755 };
1756 let Some(uri) = state.add_conservative_ext(&mut groups, &sym, extstructure_ast.begin.range) else {
1757 groups.tokenizer.problem(exts.1.start, "Not in a module".to_string(),DiagnosticLevel::Error);
1758 return
1759 };
1760 groups.groups.last_mut().unwrap_or_else(|| unreachable!()).kind = GroupKind::ConservativeExt(uri,Vec::new());
1761 state.use_structure(&sym,&rules,&mut groups,extstructure_ast.begin.range);
1762
1763 extstructure_ast.children.push(STeXToken::ConservativeExt {
1764 uri:sym, ext_range:exts.1,
1765 extstructure_range: extstructure_ast.name_range,
1766 full_range: extstructure_ast.begin.range,
1767 children: Vec::new()
1768 });
1769}{
1770 match extstructure_ast.children.first() {
1771 Some(STeXToken::ConservativeExt { .. }) => {
1772 let mut ch = extstructure_ast.children.drain(..);
1773 let Some(STeXToken::ConservativeExt { uri,ext_range, extstructure_range, mut full_range, mut children }) = ch.next() else{
1774 unreachable!()
1775 };
1776 children.extend(ch);
1777 if let Some(end) = extstructure_ast.end.as_ref() {
1778 full_range.end = end.range.end;
1779 }
1780
1781 let Some(g) = p.groups.last_mut() else {
1782 p.tokenizer.problem(extstructure_ast.begin.range.start,"extstructure* ended unexpectedly",DiagnosticLevel::Error);
1783 return EnvironmentResult::Simple(extstructure_ast)
1784 };
1785 let GroupKind::ConservativeExt(_,rules) = std::mem::take(&mut g.kind) else {
1786 return EnvironmentResult::Simple(extstructure_ast);
1787 };
1788 let rules = ModuleRules{ rules:rules.into()};
1789 let (state,mut groups) = p.split();
1790 state.set_structure(&mut groups, rules, full_range);
1791
1792 EnvironmentResult::Success(STeXToken::ConservativeExt {
1793 uri,ext_range,extstructure_range,full_range,children
1794 })
1795 }
1796 _ => {
1797 EnvironmentResult::Simple(extstructure_ast)
1798 }
1799 }
1800});
1801
1802stex!(p => @begin{smodule_deps}([opt]{name:name}){
1803 let opt = opt.as_keyvals();
1804 let sig = opt.get(&"sig").and_then(|v| v.val.parse().ok());
1805 let uri = if let Some((m,_)) = get_module(p) {
1806 m.clone() / name.0
1807 } else {
1808 p.state.doc_uri.module_uri_from(name.0)
1809 };
1810 let Ok(uri) = uri else {
1811 p.tokenizer.problem(name.1.start, format!("Invalid uri segment {}",name.1),DiagnosticLevel::Error);
1812 return ()
1813 };
1814 let meta_theory = match opt.get(&"meta").map(|v| v.val) {
1815 None => Some(ModuleReference{
1816 uri:flams_ontology::metatheory::URI.clone(),
1817 in_doc:flams_ontology::metatheory::DOC_URI.clone(),
1818 rel_path:Some(META_REL_PATH.clone()),
1819 full_path:META_FULL_PATH.clone()
1820 }),
1821 Some(""|"{}") => None,
1822 Some(o) => None};
1824 smodule_deps.children.push(STeXToken::Module{
1826 uri,full_range:smodule_deps.begin.range,sig,meta_theory,
1827 children:Vec::new(),name_range:name.1,rules:ModuleRules::default(),
1828 smodule_range:smodule_deps.name_range,opts:Vec::new()
1829 });
1830 }{
1831 match smodule_deps.children.first() {
1833 Some(STeXToken::Module { .. }) => {
1834 let mut ch = smodule_deps.children.drain(..);
1835 let Some(STeXToken::Module { uri,mut full_range,sig,meta_theory,mut children,name_range,rules,smodule_range,opts }) = ch.next() else {
1836 unreachable!()
1837 };
1838 children.extend(ch);
1839 if let Some(end) = smodule_deps.end {
1840 full_range.end = end.range.end;
1841 }
1842 EnvironmentResult::Success(STeXToken::Module { uri,rules,full_range,sig,meta_theory,children,name_range,smodule_range,opts })
1843 }
1844 _ => EnvironmentResult::Simple(smodule_deps)
1845 }
1846 }
1847);
1848
1849optargtype! {LSP parser =>
1850 ParagraphArg<T> {
1851 {Id = "id": ()}
1852 {Name = "name": str}
1853 {MacroName = "macro": str}
1854 {Title = "title": T*}
1855 {Args = "args": Args}
1856 {Tp = "type": T*}
1857 {Df = "def": T*}
1858 {Return = "return": T*}
1859 {Style = "style": str}
1860 {Assoc = "assoc": ()}
1861 {Role = "role": ()}
1862 {From = "from": ()}
1863 {To = "to": ()}
1864 {Argtypes = "argtypes": T*}
1865 {Reorder = "reorder": ()}
1866 {Judgment = "judgment": ()}
1867 {Fors = "for": {Vec<(SmallVec<SymbolReference<Pos>,1>,SourceRange<LSPLineCol>)> =>
1868 let strs = parser.read_value_strs_normalized();
1869 let (state,mut groups) = parser.parser.split();
1870 let ret = strs.into_iter().filter_map(|(name,range)|
1871 if let Some((symbol,_)) = get_in_morphism(&mut groups.groups, &name) {
1872 Some((smallvec::smallvec![symbol.uri.clone()],range))
1873 } else if let Some(symbol) = state.get_symbol(range.start,&mut groups, &name) {
1874 Some((symbol,range))
1875 } else {
1876 groups.tokenizer.problem(range.start,format!("Unknown symbol: {name}"),DiagnosticLevel::Error);
1877 None
1878 }
1879 ).collect();
1880 Some(Self::Fors(parser.to_key_value(ret)))
1881 }}
1882 } @ ParagraphArgIter
1883}
1884
1885fn do_def_macros<
1886 'a,
1887 MS: STeXModuleStore,
1888 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
1889>(
1890 p: &mut LaTeXParser<
1891 'a,
1892 ParseStr<'a, LSPLineCol>,
1893 STeXToken<LSPLineCol>,
1894 Err,
1895 STeXParseState<'a, LSPLineCol, MS>,
1896 >,
1897) {
1898 p.add_macro_rule(
1899 Cow::Borrowed("definame"),
1900 Some(AnyMacro::Ptr(definame as _)),
1901 );
1902 p.add_macro_rule(
1903 Cow::Borrowed("Definame"),
1904 Some(AnyMacro::Ptr(Definame as _)),
1905 );
1906 p.add_macro_rule(
1907 Cow::Borrowed("definames"),
1908 Some(AnyMacro::Ptr(definames as _)),
1909 );
1910 p.add_macro_rule(
1911 Cow::Borrowed("Definames"),
1912 Some(AnyMacro::Ptr(Definames as _)),
1913 );
1914 p.add_macro_rule(
1915 Cow::Borrowed("definiendum"),
1916 Some(AnyMacro::Ptr(symref as _)),
1917 );
1918 p.add_macro_rule(
1919 Cow::Borrowed("defnotation"),
1920 Some(AnyMacro::Ptr(defnotation as _)),
1921 );
1922}
1923
1924fn do_paragraph<
1925 'a,
1926 MS: STeXModuleStore,
1927 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
1928>(
1929 kind: ParagraphKind,
1930 p: &mut LaTeXParser<
1931 'a,
1932 ParseStr<'a, LSPLineCol>,
1933 STeXToken<LSPLineCol>,
1934 Err,
1935 STeXParseState<'a, LSPLineCol, MS>,
1936 >,
1937 range: SourceRange<LSPLineCol>,
1938 open_group: bool,
1939) -> (
1940 Option<SymbolReference<LSPLineCol>>,
1941 Vec<ParagraphArg<LSPLineCol, STeXToken<LSPLineCol>>>,
1942) {
1943 let is_def_first = matches!(kind, ParagraphKind::Definition | ParagraphKind::Assertion);
1944 if open_group {
1945 p.open_group();
1946 }
1947 if is_def_first {
1948 p.add_macro_rule(
1949 Cow::Borrowed("definiens"),
1950 Some(AnyMacro::Ptr(definiens as _)),
1951 );
1952 if MS::FULL {
1953 do_def_macros(p);
1954 }
1955 }
1956
1957 let args =
1958 <Vec<ParagraphArg<_, _>> as crate::quickparse::latex::KeyValValues<_, _, _, _>>::parse_opt(
1959 p,
1960 )
1961 .unwrap_or_default();
1962
1963 let mut name = None;
1964 let mut macroname = None;
1965 let mut argnum = 0;
1966 let mut has_tp = false;
1967 let mut has_def = false;
1968 let mut needs_name = false;
1969 let mut is_symdoc = false;
1970 let mut fors: &[_] = &[];
1971 for e in &args {
1972 match e {
1973 ParagraphArg::Name(n) => name = Some(&n.val),
1974 ParagraphArg::MacroName(n) => macroname = Some(&n.val),
1975 ParagraphArg::Args(n) => argnum = n.val,
1976 ParagraphArg::Tp(_) | ParagraphArg::Return(_) => has_tp = true,
1977 ParagraphArg::Df(_) => has_def = true,
1978 ParagraphArg::Argtypes(_)
1979 | ParagraphArg::Assoc(_)
1980 | ParagraphArg::Reorder(_)
1981 | ParagraphArg::Role(_) => needs_name = true,
1982 ParagraphArg::Style(s) if s.val.contains("symdoc") => is_symdoc = true,
1983 ParagraphArg::Fors(f) => fors = &f.val,
1984 _ => (),
1985 }
1986 }
1987
1988 let sym = if name.is_some() || macroname.is_some() {
1989 let fname = name.unwrap_or_else(|| macroname.unwrap_or_else(|| unreachable!()));
1990 let Ok(fname): Result<Name, _> = fname.parse() else {
1991 p.tokenizer.problem(
1992 range.start,
1993 format!("Invalid uri segment {fname}"),
1994 DiagnosticLevel::Error,
1995 );
1996 return (None, args);
1997 };
1998 let (state, mut groups) = p.split();
1999 state.add_symbol(
2000 &mut groups,
2001 fname,
2002 macroname.map(|r| r.clone().into()),
2003 range,
2004 has_tp,
2005 has_def,
2006 argnum,
2007 )
2008 } else if argnum > 0 || has_tp || has_def || needs_name {
2009 p.tokenizer.problem(
2010 range.start,
2011 format!("Missing name or macroname"),
2012 DiagnosticLevel::Error,
2013 );
2014 None
2015 } else {
2016 None
2017 };
2018
2019 if !is_def_first && (sym.is_some() || matches!(kind,ParagraphKind::Paragraph if is_symdoc)) {
2020 p.add_macro_rule(
2021 Cow::Borrowed("definiens"),
2022 Some(AnyMacro::Ptr(definiens as _)),
2023 );
2024 if MS::FULL {
2025 do_def_macros(p);
2026 }
2027 }
2028
2029 let mut v: Vec<_> = fors
2030 .iter()
2031 .map(|(v, _)| v.first().unwrap_or_else(|| unreachable!()).clone())
2032 .collect();
2033 if let Some(s) = &sym {
2034 v.push(s.clone());
2035 }
2036 p.groups.last_mut().unwrap_or_else(|| unreachable!()).kind = GroupKind::DefPara(v);
2037 (sym, args)
2038}
2039
2040fn inline_paragraph<
2041 'a,
2042 MS: STeXModuleStore,
2043 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
2044>(
2045 kind: ParagraphKind,
2046 p: &mut LaTeXParser<
2047 'a,
2048 ParseStr<'a, LSPLineCol>,
2049 STeXToken<LSPLineCol>,
2050 Err,
2051 STeXParseState<'a, LSPLineCol, MS>,
2052 >,
2053 mut m: Macro<'a, LSPLineCol, &'a str>,
2054 ) -> MacroResult<'a, LSPLineCol, &'a str, STeXToken<LSPLineCol>> {
2056 let (sym, args) = do_paragraph(kind, p, m.range, true);
2057 let children = p.get_argument(&mut m);
2058 p.close_group();
2059 MacroResult::Success(STeXToken::InlineParagraph {
2060 kind,
2061 full_range: m.range,
2062 token_range: m.token_range,
2063 symbol: sym,
2064 parsed_args: args,
2065 children_range: children.0,
2066 children: children.1,
2067 })
2068}
2069
2070fn open_paragraph<
2071 'a,
2072 MS: STeXModuleStore,
2073 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
2074>(
2075 kind: ParagraphKind,
2076 p: &mut LaTeXParser<
2077 'a,
2078 ParseStr<'a, LSPLineCol>,
2079 STeXToken<LSPLineCol>,
2080 Err,
2081 STeXParseState<'a, LSPLineCol, MS>,
2082 >,
2083 env: &mut Environment<'a, LSPLineCol, &'a str, STeXToken<LSPLineCol>>,
2084) {
2085 let (sym, args) = do_paragraph(kind, p, env.begin.range, false);
2086 env.children.push(STeXToken::Paragraph {
2087 kind,
2088 full_range: env.begin.range,
2089 name_range: env.name_range,
2090 symbol: sym,
2091 parsed_args: args,
2092 children: Vec::new(),
2093 });
2094}
2095
2096fn close_paragraph<
2097 'a,
2098 MS: STeXModuleStore,
2099 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
2100>(
2101 p: &mut LaTeXParser<
2102 'a,
2103 ParseStr<'a, LSPLineCol>,
2104 STeXToken<LSPLineCol>,
2105 Err,
2106 STeXParseState<'a, LSPLineCol, MS>,
2107 >,
2108 mut env: Environment<'a, LSPLineCol, &'a str, STeXToken<LSPLineCol>>,
2109) -> EnvironmentResult<'a, LSPLineCol, &'a str, STeXToken<LSPLineCol>> {
2110 match env.children.first() {
2111 Some(STeXToken::Paragraph { .. }) => {
2112 let mut ch = env.children.drain(..);
2113 let Some(STeXToken::Paragraph {
2114 kind,
2115 mut full_range,
2116 name_range,
2117 symbol,
2118 parsed_args,
2119 mut children,
2120 }) = ch.next()
2121 else {
2122 impossible!()
2123 };
2124 children.extend(ch);
2125 if let Some(end) = env.end.as_ref() {
2126 full_range.end = end.range.end;
2127 }
2128 EnvironmentResult::Success(STeXToken::Paragraph {
2129 kind,
2130 full_range,
2131 name_range,
2132 symbol,
2133 parsed_args,
2134 children,
2135 })
2136 }
2137 _ => EnvironmentResult::Simple(env),
2138 }
2139}
2140
2141stex!(LSP: p => @begin{sassertion}(){
2142 open_paragraph(ParagraphKind::Assertion, p, sassertion);
2143}{
2144 close_paragraph(p, sassertion)
2145});
2146
2147stex!(LSP: p => @begin{sdefinition}(){
2148 open_paragraph(ParagraphKind::Definition, p, sdefinition);
2149}{
2150 close_paragraph(p, sdefinition)
2151});
2152
2153stex!(LSP: p => @begin{sparagraph}(){
2154 open_paragraph(ParagraphKind::Paragraph, p, sparagraph);
2155}{
2156 close_paragraph(p, sparagraph)
2157});
2158
2159stex!(LSP: p => @begin{sexample}(){
2160 open_paragraph(ParagraphKind::Example, p, sexample);
2161}{
2162 close_paragraph(p, sexample)
2163});
2164
2165stex!(LSP: p => inlinedef => {
2166 inline_paragraph(ParagraphKind::Definition, p, inlinedef)
2167});
2168
2169stex!(LSP: p => inlineass => {
2170 inline_paragraph(ParagraphKind::Assertion, p, inlineass)
2171});
2172
2173stex!(LSP: p => inlinepara => {
2174 inline_paragraph(ParagraphKind::Paragraph, p, inlinepara)
2175});
2176
2177stex!(LSP: p => inlineex => {
2178 inline_paragraph(ParagraphKind::Example, p, inlineex)
2179});
2180
2181optargtype! {LSP parser =>
2182 ProblemArg<T> {
2183 {Id = "id": ()}
2184 {Title = "title": T*}
2185 {Style = "style": str}
2186 {Pts = "pts": f32}
2187 {Min = "min": f32}
2188 {Autogradable = "autogradable": bool?}
2190
2191 } @ ProblemArgIter
2192}
2193
2194fn open_problem<
2195 'a,
2196 MS: STeXModuleStore,
2197 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
2198>(
2199 sub: bool,
2200 p: &mut LaTeXParser<
2201 'a,
2202 ParseStr<'a, LSPLineCol>,
2203 STeXToken<LSPLineCol>,
2204 Err,
2205 STeXParseState<'a, LSPLineCol, MS>,
2206 >,
2207 env: &mut Environment<'a, LSPLineCol, &'a str, STeXToken<LSPLineCol>>,
2208) {
2209 let args =
2210 <Vec<ProblemArg<_, _>> as crate::quickparse::latex::KeyValValues<_, _, _, _>>::parse_opt(p)
2211 .unwrap_or_default();
2212 p.groups.last_mut().unwrap_or_else(|| unreachable!()).kind = GroupKind::Problem;
2213 env.children.push(STeXToken::Problem {
2214 sub,
2215 full_range: env.begin.range,
2216 name_range: env.name_range,
2217 parsed_args: args,
2218 children: Vec::new(),
2219 });
2220}
2221fn close_problem<
2222 'a,
2223 MS: STeXModuleStore,
2224 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
2225>(
2226 p: &mut LaTeXParser<
2227 'a,
2228 ParseStr<'a, LSPLineCol>,
2229 STeXToken<LSPLineCol>,
2230 Err,
2231 STeXParseState<'a, LSPLineCol, MS>,
2232 >,
2233 mut env: Environment<'a, LSPLineCol, &'a str, STeXToken<LSPLineCol>>,
2234) -> EnvironmentResult<'a, LSPLineCol, &'a str, STeXToken<LSPLineCol>> {
2235 if let Some(STeXToken::Problem { .. }) = env.children.first() {
2236 let mut ch = env.children.drain(..);
2237 let Some(STeXToken::Problem {
2238 sub,
2239 mut full_range,
2240 parsed_args,
2241 name_range,
2242 mut children,
2243 }) = ch.next()
2244 else {
2245 impossible!()
2246 };
2247 children.extend(ch);
2248 if let Some(end) = env.end.as_ref() {
2249 full_range.end = end.range.end;
2250 }
2251 EnvironmentResult::Success(STeXToken::Problem {
2252 sub,
2253 full_range,
2254 name_range,
2255 parsed_args,
2256 children,
2257 })
2258 } else {
2259 EnvironmentResult::Simple(env)
2260 }
2261}
2262
2263stex!(LSP: p => @begin{sproblem}(){
2264 open_problem(false,p,sproblem)
2265}{
2266 close_problem(p,sproblem)
2267});
2268stex!(LSP: p => @begin{subproblem}(){
2269 open_problem(true,p,subproblem)
2270}{
2271 close_problem(p,subproblem)
2272});
2273
2274fn get_in_morphism<
2275 'a,
2276 'b,
2277 MS: STeXModuleStore,
2278 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
2279>(
2280 groups: &'b mut Vec<STeXGroup<'a, MS, LSPLineCol, Err>>,
2281 name: &str,
2282) -> Option<(
2283 &'b SymbolRule<LSPLineCol>,
2284 &'b mut VecMap<SymbolReference<LSPLineCol>, MorphismSpec<LSPLineCol>>,
2285)> {
2286 for g in groups.iter_mut().rev() {
2287 match &mut g.kind {
2288 GroupKind::Morphism {
2289 domain,
2290 rules,
2291 specs,
2292 } => {
2293 let mut name = name;
2294 for (s, r) in &specs.0 {
2295 if r.macroname.as_ref().is_some_and(|n| &**n == name)
2296 || r.new_name
2297 .as_ref()
2298 .is_some_and(|n| n.last_name().as_ref() == name)
2299 {
2300 name = s.uri.name().last_name().as_ref();
2301 break;
2302 }
2303 }
2304 for r in rules.iter().rev().map(|r| r.rules.iter().rev()).flatten() {
2305 match r {
2306 ModuleRule::Symbol(s) | ModuleRule::Structure { symbol: s, .. }
2307 if s.macroname.as_ref().is_some_and(|n| &**n == name)
2308 || s.uri.uri.name().last_name().as_ref() == name =>
2309 {
2310 return Some((s, specs))
2311 }
2312 _ => (),
2313 }
2314 }
2315 break;
2316 }
2317 _ => (),
2318 }
2319 }
2320 None
2321}
2322
2323fn set_defined<
2324 'a,
2325 MS: STeXModuleStore,
2326 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
2327>(
2328 symbol: &SymbolReference<LSPLineCol>,
2329 range: SourceRange<LSPLineCol>,
2330 groups: &mut Vec<STeXGroup<'a, MS, LSPLineCol, Err>>,
2331) {
2332 for g in groups.iter_mut().rev() {
2333 match &mut g.kind {
2334 GroupKind::Morphism {
2335 domain,
2336 rules,
2337 specs,
2338 } => {
2339 let v = specs.get_or_insert_mut(symbol.clone(), MorphismSpec::default);
2340 v.is_assigned_at = Some(range);
2341 return;
2342 }
2343 GroupKind::Module { rules, .. }
2344 | GroupKind::ConservativeExt(_, rules)
2345 | GroupKind::MathStructure { rules, .. } => {
2346 for r in rules.iter_mut().rev() {
2347 match r {
2348 ModuleRule::Symbol(s) if s.uri.uri == symbol.uri => {
2349 s.has_df = true;
2350 return;
2351 }
2352 _ => (),
2353 }
2354 }
2355 return;
2356 }
2357 _ => (),
2358 }
2359 }
2360}
2361
2362stex!(LSP: p => renamedecl{orig:!name}[name:!name]{macroname:!name} => {
2363 let (_,mut groups) = p.split();
2364 let Some((symbol,specs)) = get_in_morphism(&mut groups.groups, &orig.0) else {
2365 p.tokenizer.problem(renamedecl.range.start, format!("Could not find symbol {} in morphism",orig.0), DiagnosticLevel::Error);
2366 return MacroResult::Simple(renamedecl);
2367 };
2368 let uri = symbol.uri.clone();
2369 let spec = specs.get_or_insert_mut(uri.clone(), MorphismSpec::default);
2370 if spec.macroname.is_some() || spec.new_name.is_some() {
2371 p.tokenizer.problem(renamedecl.range.start, format!("Symbol {} already renamed in morphism",orig.0), DiagnosticLevel::Error);
2372 return MacroResult::Simple(renamedecl);
2373 }
2374 if let Some(name) = name.as_ref() {
2375 let Ok(name) = name.0.parse() else {
2376 p.tokenizer.problem(renamedecl.range.start, format!("Invalid name {}",name.0), DiagnosticLevel::Error);
2377 return MacroResult::Simple(renamedecl);
2378 };
2379 spec.new_name = Some(name);
2380 }
2381 spec.macroname = Some(macroname.0.to_string().into());
2382 if spec.decl_range == SourceRange::default() {
2383 spec.decl_range = renamedecl.range;
2384 }
2385 MacroResult::Success(STeXToken::RenameDecl {
2386 uri, token_range: renamedecl.token_range, orig_range: orig.1,
2387 name_range: name.map(|(_,r)| r),
2388 macroname_range: macroname.1, full_range: renamedecl.range
2389 })
2390});
2391
2392stex!(LSP: p => assign{orig:!name} => {
2393 let (_,mut groups) = p.split();
2394 let Some((symbol,specs)) = get_in_morphism(&mut groups.groups, &orig.0) else {
2395 p.tokenizer.problem(assign.range.start, format!("Could not find symbol {} in morphism",orig.0), DiagnosticLevel::Error);
2396 return MacroResult::Simple(assign);
2397 };
2398 let uri = symbol.uri.clone();
2399 let spec = specs.get_or_insert_mut(uri.clone(), MorphismSpec::default);
2400 if spec.is_assigned_at.is_some() {
2401 p.tokenizer.problem(assign.range.start, format!("Symbol {} already assigned in morphism",orig.0), DiagnosticLevel::Error);
2402 return MacroResult::Simple(assign);
2403 }
2404 if spec.decl_range == SourceRange::default() {
2405 spec.decl_range = assign.range;
2406 }
2407 spec.is_assigned_at = Some(assign.range);
2408 MacroResult::Success(STeXToken::Assign {
2409 uri, token_range: assign.token_range, orig_range: orig.1,
2410 full_range: assign.range
2411 })
2412});
2413
2414fn define_assignment_macros<
2415 'a,
2416 MS: STeXModuleStore,
2417 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
2418>(
2419 p: &mut LaTeXParser<
2420 'a,
2421 ParseStr<'a, LSPLineCol>,
2422 STeXToken<LSPLineCol>,
2423 Err,
2424 STeXParseState<'a, LSPLineCol, MS>,
2425 >,
2426) {
2427 p.add_macro_rule(
2428 Cow::Borrowed("renamedecl"),
2429 Some(AnyMacro::Ptr(renamedecl as _)),
2430 );
2431 p.add_macro_rule(Cow::Borrowed("assign"), Some(AnyMacro::Ptr(assign as _)));
2432}
2433
2434fn setup_morphism<
2435 'a,
2436 MS: STeXModuleStore,
2437 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
2438>(
2439 p: &mut LaTeXParser<
2440 'a,
2441 ParseStr<'a, LSPLineCol>,
2442 STeXToken<LSPLineCol>,
2443 Err,
2444 STeXParseState<'a, LSPLineCol, MS>,
2445 >,
2446 name: &str,
2447 archive: &Option<(&'a str, SourceRange<LSPLineCol>)>,
2448 domain: &str,
2449 pos: LSPLineCol,
2450) -> Option<(
2451 SymbolURI,
2452 ModuleOrStruct<LSPLineCol>,
2453 Vec<ModuleRules<LSPLineCol>>,
2454)> {
2455 let (state, groups) = p.split();
2456 let Some((mors, rules)) = state.resolve_module_or_struct(
2457 &groups,
2458 domain,
2459 archive.as_ref().map(|(r, _)| ArchiveId::new(r)),
2460 ) else {
2461 groups.tokenizer.problem(
2462 pos,
2463 format!("No module or structure {} found", domain),
2464 DiagnosticLevel::Error,
2465 );
2466 return None;
2467 };
2468 let Some((uri, _)) = get_module(p) else {
2469 p.tokenizer
2470 .problem(pos, "Not in a module", DiagnosticLevel::Error);
2471 return None;
2472 };
2473 let Ok(uri) = uri.clone() | name else {
2474 p.tokenizer.problem(
2475 pos,
2476 format!("Invalid module name: {name}"),
2477 DiagnosticLevel::Error,
2478 );
2479 return None;
2480 };
2481 Some((uri, mors, rules))
2482}
2483
2484fn elaborate_morphism<
2485 'a,
2486 MS: STeXModuleStore,
2487 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
2488>(
2489 p: &mut LaTeXParser<
2490 'a,
2491 ParseStr<'a, LSPLineCol>,
2492 STeXToken<LSPLineCol>,
2493 Err,
2494 STeXParseState<'a, LSPLineCol, MS>,
2495 >,
2496 do_macros: bool,
2497 check_defined: bool,
2498 range: SourceRange<LSPLineCol>,
2499 name: &str,
2500 rules: Vec<ModuleRules<LSPLineCol>>,
2501 mut specs: VecMap<SymbolReference<LSPLineCol>, MorphismSpec<LSPLineCol>>,
2502) {
2503 let old_end = std::mem::replace(&mut p.tokenizer.reader.pos, range.end);
2504 let Some(name) = Name::from_str(name).ok() else {
2505 p.tokenizer.problem(
2506 range.start,
2507 format!("Invalid name: {name}"),
2508 DiagnosticLevel::Error,
2509 );
2510 p.tokenizer.reader.pos = old_end;
2511 return;
2512 };
2513 let Some((in_module, _)) = get_module(p) else {
2514 p.tokenizer.problem(
2515 range.start,
2516 format!("Morphism only allowed in module"),
2517 DiagnosticLevel::Error,
2518 );
2519 p.tokenizer.reader.pos = old_end;
2520 return;
2521 };
2522 let (state, mut groups) = p.split();
2523 for rls in rules {
2524 for r in rls.rules.iter() {
2525 if let ModuleRule::Symbol(s) = r {
2526 let (macroname, name, dfed, rng) = if let Some(spec) = specs.remove(&s.uri) {
2527 let m = if let Some(m) = spec.macroname {
2528 Some(m.into())
2529 } else if do_macros {
2530 s.macroname.clone()
2531 } else {
2532 None
2533 };
2534 let n = if let Some(n) = spec.new_name {
2535 n
2536 } else {
2537 name.clone() / s.uri.uri.name().clone()
2538 };
2539 let d = spec.is_assigned_at.is_some() || s.has_df;
2540 (m, n, d, spec.decl_range)
2541 } else {
2542 let m = if do_macros { s.macroname.clone() } else { None };
2543 let n = name.clone() / s.uri.uri.name().clone();
2544 let d = s.has_df;
2545 (m, n, d, range)
2546 };
2547 if check_defined && !dfed {
2548 groups.tokenizer.problem(
2549 range.start,
2550 format!("{} not defined in total morphism", s.uri.uri),
2551 DiagnosticLevel::Error,
2552 );
2553 }
2554 if state
2555 .add_symbol(
2556 &mut groups,
2557 name,
2558 macroname.map(|s| s.into()),
2559 range,
2560 s.has_tp,
2561 dfed,
2562 s.argnum,
2563 )
2564 .is_none()
2565 {
2566 groups.tokenizer.problem(
2567 range.start,
2568 format!("Morphism only allowed in module"),
2569 DiagnosticLevel::Error,
2570 );
2571 }
2572 }
2573 }
2574 }
2575 p.tokenizer.reader.pos = old_end;
2576}
2577
2578stex!(LSP: p => @begin{copymodule}({name:!name}[archive:str]{domain:!name}){
2580 let Some((uri,mors,rules)) = setup_morphism(p, &name.0,&archive,&domain.0,copymodule.begin.range.start) else { return };
2581 p.groups.last_mut().unwrap_or_else(|| unreachable!()).kind = GroupKind::Morphism { domain: mors.clone(), rules, specs: VecMap::default() };
2582 define_assignment_macros(p);
2583 let dom_range_start = archive.map_or(domain.1.start,|(_,r)| r.start);
2584 let domain_range = SourceRange{ start:dom_range_start, end:domain.1.end};
2585 copymodule.children.push(STeXToken::MorphismEnv {
2586 kind:MorphismKind::CopyModule,
2587 domain:mors,uri,
2588 star:false,
2589 full_range:copymodule.begin.range,
2590 env_range:copymodule.name_range,
2591 domain_range,
2592 name_range:name.1,
2593 children:Vec::new()
2594 });
2595}{
2596 match copymodule.children.first() {
2597 Some(STeXToken::MorphismEnv{..}) => {
2598 let mut ch = copymodule.children.drain(..);
2599 let Some(STeXToken::MorphismEnv { mut full_range, star,env_range, name_range, uri, domain, domain_range, kind, mut children }) = ch.next() else {
2600 unreachable!()
2601 };
2602 children.extend(ch);
2603 if let Some(end) =copymodule.end.as_ref() {
2604 full_range.end = end.range.end;
2605 }
2606 let Some(g) = p.groups.last_mut() else {
2607 p.tokenizer.problem(copymodule.begin.range.start,"copymodule ended unexpectedly",DiagnosticLevel::Error);
2608 return EnvironmentResult::Simple(copymodule)
2609 };
2610 let GroupKind::Morphism{domain,rules,specs} = std::mem::take(&mut g.kind) else {
2611 return EnvironmentResult::Simple(copymodule);
2612 };
2613 elaborate_morphism(p,star,false,copymodule.begin.range,uri.name().last_name().as_ref(),rules,specs);
2614 EnvironmentResult::Success(STeXToken::MorphismEnv {
2615 kind, full_range, name_range, star,env_range,uri,domain,domain_range,children
2616 })
2617 }
2618 _ => EnvironmentResult::Simple(copymodule)
2619 }
2620});
2621
2622stex!(LSP: p => @begin{copymodule_ast}({name:!name}[archive:str]{domain:!name}){
2623 let Some((uri,mors,rules)) = setup_morphism(p, &name.0,&archive,&domain.0,copymodule_ast.begin.range.start) else { return };
2624 p.groups.last_mut().unwrap_or_else(|| unreachable!()).kind = GroupKind::Morphism { domain: mors.clone(), rules, specs: VecMap::default() };
2625 define_assignment_macros(p);
2626 let dom_range_start = archive.map_or(domain.1.start,|(_,r)| r.start);
2627 let domain_range = SourceRange{ start:dom_range_start, end:domain.1.end};
2628 copymodule_ast.children.push(STeXToken::MorphismEnv {
2629 kind:MorphismKind::CopyModule,
2630 domain:mors,uri,
2631 star:true,
2632 full_range:copymodule_ast.begin.range,
2633 env_range:copymodule_ast.name_range,
2634 domain_range,
2635 name_range:name.1,
2636 children:Vec::new()
2637 });
2638}{
2639 match copymodule_ast.children.first() {
2640 Some(STeXToken::MorphismEnv{..}) => {
2641 let mut ch = copymodule_ast.children.drain(..);
2642 let Some(STeXToken::MorphismEnv { mut full_range, star,env_range, name_range, uri, domain, domain_range, kind, mut children }) = ch.next() else {
2643 unreachable!()
2644 };
2645 children.extend(ch);
2646 if let Some(end) =copymodule_ast.end.as_ref() {
2647 full_range.end = end.range.end;
2648 }
2649 let Some(g) = p.groups.last_mut() else {
2650 p.tokenizer.problem(copymodule_ast.begin.range.start,"copymodule* ended unexpectedly",DiagnosticLevel::Error);
2651 return EnvironmentResult::Simple(copymodule_ast)
2652 };
2653 let GroupKind::Morphism{domain,rules,specs} = std::mem::take(&mut g.kind) else {
2654 return EnvironmentResult::Simple(copymodule_ast);
2655 };
2656 elaborate_morphism(p,star,false,copymodule_ast.begin.range,uri.name().last_name().as_ref(),rules,specs);
2657 EnvironmentResult::Success(STeXToken::MorphismEnv {
2658 kind, full_range, name_range, star,env_range,uri,domain,domain_range,children
2659 })
2660 }
2661 _ => EnvironmentResult::Simple(copymodule_ast)
2662 }
2663});
2664
2665fn parse_assignments<
2666 'a,
2667 MS: STeXModuleStore,
2668 Err: FnMut(String, SourceRange<LSPLineCol>, DiagnosticLevel),
2669>(
2670 p: &mut LaTeXParser<
2671 'a,
2672 ParseStr<'a, LSPLineCol>,
2673 STeXToken<LSPLineCol>,
2674 Err,
2675 STeXParseState<'a, LSPLineCol, MS>,
2676 >,
2677 m: &mut Macro<'a, LSPLineCol, &'a str>,
2678) -> Option<(
2679 Vec<InlineMorphAssign<LSPLineCol, STeXToken<LSPLineCol>>>,
2680 VecMap<SymbolReference<LSPLineCol>, MorphismSpec<LSPLineCol>>,
2681)> {
2682 let mut specs = Vec::new();
2683 p.skip_comments();
2684 if !p.tokenizer.reader.starts_with('{') {
2685 p.tokenizer
2686 .problem(m.range.start, "Group expected", DiagnosticLevel::Error);
2687 return None;
2688 }
2689 p.tokenizer.reader.pop_head();
2690 p.skip_comments();
2691 loop {
2692 if p.tokenizer.reader.starts_with('}') {
2693 p.tokenizer.reader.pop_head();
2694 break;
2695 }
2696 let start = p.curr_pos();
2697 let symbol_name = p
2698 .tokenizer
2699 .reader
2700 .read_until(|c| c == '}' || c == ',' || c == '=' || c == '%' || c == '@')
2701 .trim();
2702 let symbol_range = SourceRange {
2703 start,
2704 end: p.tokenizer.reader.curr_pos(),
2705 };
2706 let (state, mut groups) = p.split();
2707 let Some(symbol) =
2708 get_in_morphism(&mut groups.groups, symbol_name).map(|(s, _)| s.uri.clone())
2709 else {
2710 groups.tokenizer.problem(
2711 symbol_range.start,
2712 format!("Symbol {symbol_name} not found"),
2713 DiagnosticLevel::Error,
2714 );
2715 return None;
2716 };
2717 p.skip_comments();
2718 let infix = p.curr_pos();
2719 macro_rules! def {
2720 () => {{
2721 p.skip_comments();
2722 let start = p.curr_pos();
2723 let txt = p
2724 .tokenizer
2725 .reader
2726 .read_until_with_brackets::<'{', '}'>(|c| c == ',' || c == '@' || c == '}');
2727 let ret = p.reparse(txt, start);
2728 p.skip_comments();
2729 ret
2730 }};
2731 }
2732 macro_rules! rename {
2733 () => {{
2734 p.skip_comments();
2735 let real_name = if p.tokenizer.reader.starts_with('[') {
2736 p.tokenizer.reader.pop_head();
2737 let start = p.curr_pos();
2738 let namestr = p
2739 .tokenizer
2740 .reader
2741 .read_until(|c| c == ']' || c == '=' || c == ',' || c == '}' || c == '%');
2742 let range = SourceRange {
2743 start,
2744 end: p.curr_pos(),
2745 };
2746 p.skip_comments();
2747 match p.tokenizer.reader.pop_head() {
2748 Some(']') => (),
2749 _ => {
2750 p.tokenizer
2751 .problem(start, "']' expected", DiagnosticLevel::Error);
2752 return None;
2753 }
2754 }
2755 let range = SourceRange {
2756 start,
2757 end: p.curr_pos(),
2758 };
2759 let Ok(name) = Name::from_str(namestr) else {
2760 p.tokenizer.problem(
2761 start,
2762 format!("Invalid name: {namestr}"),
2763 DiagnosticLevel::Error,
2764 );
2765 return None;
2766 };
2767 Some((name, range))
2768 } else {
2769 None
2770 };
2771 let start = p.curr_pos();
2772 let namestr = p
2773 .tokenizer
2774 .reader
2775 .read_until(|c| c == '=' || c == ',' || c == '}' || c == '%');
2776 let range = SourceRange {
2777 start,
2778 end: p.curr_pos(),
2779 };
2780 p.skip_comments();
2781 (real_name, namestr.to_string().into(), range)
2782 }};
2783 }
2784 match p.tokenizer.reader.pop_head() {
2785 Some('=') => {
2786 let ret = def!();
2787 let infix2 = p.curr_pos();
2788 match p.tokenizer.reader.pop_head() {
2789 Some('}') => {
2790 specs.push(InlineMorphAssign {
2791 symbol,
2792 symbol_range,
2793 first: Some((infix, InlineMorphAssKind::Df(ret))),
2794 second: None,
2795 });
2796 break;
2797 }
2798 Some(',') => {
2799 specs.push(InlineMorphAssign {
2800 symbol,
2801 symbol_range,
2802 first: Some((infix, InlineMorphAssKind::Df(ret))),
2803 second: None,
2804 });
2805 p.skip_comments();
2806 }
2807 Some('@') => {
2808 let (real_name, macroname, mrange) = rename!();
2809 match p.tokenizer.reader.pop_head() {
2810 Some('}') => {
2811 specs.push(InlineMorphAssign {
2812 symbol,
2813 symbol_range,
2814 first: Some((infix, InlineMorphAssKind::Df(ret))),
2815 second: Some((
2816 infix2,
2817 InlineMorphAssKind::Rename(real_name, macroname, mrange),
2818 )),
2819 });
2820 break;
2821 }
2822 Some(',') => {
2823 specs.push(InlineMorphAssign {
2824 symbol,
2825 symbol_range,
2826 first: Some((infix, InlineMorphAssKind::Df(ret))),
2827 second: Some((
2828 infix2,
2829 InlineMorphAssKind::Rename(real_name, macroname, mrange),
2830 )),
2831 });
2832 p.skip_comments();
2833 }
2834 _ => {
2835 p.tokenizer.problem(
2836 start,
2837 "'}' or ',' expected",
2838 DiagnosticLevel::Error,
2839 );
2840 return None;
2841 }
2842 }
2843 }
2844 _ => {
2845 p.tokenizer.problem(
2846 symbol_range.end,
2847 "'}', ',' or '@' expected",
2848 DiagnosticLevel::Error,
2849 );
2850 return None;
2851 }
2852 }
2853 }
2854 Some('@') => {
2855 let (real_name, macroname, mrange) = rename!();
2856 let infix2 = p.curr_pos();
2857 match p.tokenizer.reader.pop_head() {
2858 Some('}') => {
2859 specs.push(InlineMorphAssign {
2860 symbol,
2861 symbol_range,
2862 first: Some((
2863 infix,
2864 InlineMorphAssKind::Rename(real_name, macroname, mrange),
2865 )),
2866 second: None,
2867 });
2868 break;
2869 }
2870 Some(',') => {
2871 specs.push(InlineMorphAssign {
2872 symbol,
2873 symbol_range,
2874 first: Some((
2875 infix,
2876 InlineMorphAssKind::Rename(real_name, macroname, mrange),
2877 )),
2878 second: None,
2879 });
2880 p.skip_comments();
2881 }
2882 Some('=') => {
2883 let ret = def!();
2884 match p.tokenizer.reader.pop_head() {
2885 Some('}') => {
2886 specs.push(InlineMorphAssign {
2887 symbol,
2888 symbol_range,
2889 first: Some((
2890 infix,
2891 InlineMorphAssKind::Rename(real_name, macroname, mrange),
2892 )),
2893 second: Some((infix2, InlineMorphAssKind::Df(ret))),
2894 });
2895 break;
2896 }
2897 Some(',') => {
2898 specs.push(InlineMorphAssign {
2899 symbol,
2900 symbol_range,
2901 first: Some((
2902 infix,
2903 InlineMorphAssKind::Rename(real_name, macroname, mrange),
2904 )),
2905 second: Some((infix2, InlineMorphAssKind::Df(ret))),
2906 });
2907 p.skip_comments();
2908 }
2909 _ => {
2910 p.tokenizer.problem(
2911 start,
2912 "'}' or ',' expected",
2913 DiagnosticLevel::Error,
2914 );
2915 return None;
2916 }
2917 }
2918 }
2919 _ => {
2920 p.tokenizer
2921 .problem(start, "']' expected", DiagnosticLevel::Error);
2922 return None;
2923 }
2924 }
2925 }
2926 _ => {
2927 p.tokenizer.problem(
2928 symbol_range.end,
2929 "'@' or '=' expected",
2930 DiagnosticLevel::Error,
2931 );
2932 return None;
2933 }
2934 }
2935 }
2936 m.range.end = p.tokenizer.reader.curr_pos();
2937
2938 let mut nspecs = VecMap::new();
2939 for InlineMorphAssign {
2940 symbol,
2941 first,
2942 second,
2943 ..
2944 } in &specs
2945 {
2946 let mut spec = MorphismSpec::default();
2947 if let Some((_, first)) = first {
2948 match first {
2949 InlineMorphAssKind::Df(_) => spec.is_assigned_at = Some(m.range),
2950 InlineMorphAssKind::Rename(rn, n, _) => {
2951 spec.macroname = Some(n.clone());
2952 if let Some((n, r)) = rn {
2953 spec.new_name = Some(n.clone());
2954 }
2955 }
2956 }
2957 }
2958 if let Some((_, second)) = second {
2959 match second {
2960 InlineMorphAssKind::Df(_) => spec.is_assigned_at = Some(m.range),
2961 InlineMorphAssKind::Rename(rn, n, _) => {
2962 spec.macroname = Some(n.clone());
2963 if let Some((n, r)) = rn {
2964 spec.new_name = Some(n.clone());
2965 }
2966 }
2967 }
2968 }
2969 nspecs.insert(symbol.clone(), spec);
2970 }
2971
2972 Some((specs, nspecs))
2973}
2974
2975stex!(LSP: p => copymod('*'?star){name:!name}[archive:str]{domain:!name} => {
2976 let Some((uri,mors,rules)) = setup_morphism(p, &name.0,&archive,&domain.0,copymod.range.start) else {
2977 return MacroResult::Simple(copymod)
2978 };
2979 p.open_group();
2980 p.groups.last_mut().unwrap_or_else(|| unreachable!()).kind = GroupKind::Morphism { domain: mors, rules, specs: VecMap::default() };
2981 let Some((v,specs)) = parse_assignments(p, &mut copymod) else {
2982 return MacroResult::Simple(copymod)
2983 };
2984 let GroupKind::Morphism { domain: mors, rules, .. } = std::mem::take(&mut p.groups.last_mut().unwrap_or_else(|| unreachable!()).kind) else { unreachable!()};
2985 p.close_group();
2986 elaborate_morphism(p, star, false, copymod.range, &name.0, rules, specs);
2987
2988 MacroResult::Success(STeXToken::InlineMorphism {
2989 full_range: copymod.range, token_range: copymod.token_range,
2990 name_range: name.1, uri, star, domain: mors, domain_range: domain.1,
2991 kind: MorphismKind::CopyModule, assignments: v
2992 })
2993});
2994
2995stex!(LSP: p => interpretmod('*'?star){name:!name}[archive:str]{domain:!name} => {
2996 let Some((uri,mors,rules)) = setup_morphism(p, &name.0,&archive,&domain.0,interpretmod.range.start) else {
2997 return MacroResult::Simple(interpretmod)
2998 };
2999 p.open_group();
3000 p.groups.last_mut().unwrap_or_else(|| unreachable!()).kind = GroupKind::Morphism { domain: mors, rules, specs: VecMap::default() };
3001 let Some((v,specs)) = parse_assignments(p, &mut interpretmod) else {
3002 return MacroResult::Simple(interpretmod)
3003 };
3004 let GroupKind::Morphism { domain: mors, rules, .. } = std::mem::take(&mut p.groups.last_mut().unwrap_or_else(|| unreachable!()).kind) else { unreachable!()};
3005 p.close_group();
3006 elaborate_morphism(p, star, true, interpretmod.range, &name.0, rules, specs);
3007
3008 MacroResult::Success(STeXToken::InlineMorphism {
3009 full_range: interpretmod.range, token_range: interpretmod.token_range,
3010 name_range: name.1, uri, star, domain: mors, domain_range: domain.1,
3011 kind: MorphismKind::CopyModule, assignments: v
3012 })
3013});
3014
3015stex!(LSP: p => @begin{interpretmodule}({name:!name}[archive:str]{domain:!name}){
3017 let Some((uri,mors,rules)) = setup_morphism(p, &name.0,&archive,&domain.0,interpretmodule.begin.range.start) else { return };
3018 p.groups.last_mut().unwrap_or_else(|| unreachable!()).kind = GroupKind::Morphism { domain: mors.clone(), rules, specs: VecMap::default() };
3019 define_assignment_macros(p);
3020 let dom_range_start = archive.map_or(domain.1.start,|(_,r)| r.start);
3021 let domain_range = SourceRange{ start:dom_range_start, end:domain.1.end};
3022 interpretmodule.children.push(STeXToken::MorphismEnv {
3023 kind:MorphismKind::InterpretModule,
3024 domain:mors,uri,
3025 star:false,
3026 full_range:interpretmodule.begin.range,
3027 env_range:interpretmodule.name_range,
3028 domain_range,
3029 name_range:name.1,
3030 children:Vec::new()
3031 });
3032}{
3033 match interpretmodule.children.first() {
3034 Some(STeXToken::MorphismEnv{..}) => {
3035 let mut ch = interpretmodule.children.drain(..);
3036 let Some(STeXToken::MorphismEnv { mut full_range, star,env_range, name_range, uri, domain, domain_range, kind, mut children }) = ch.next() else {
3037 unreachable!()
3038 };
3039 children.extend(ch);
3040 if let Some(end) = interpretmodule.end.as_ref() {
3041 full_range.end = end.range.end;
3042 }
3043 let Some(g) = p.groups.last_mut() else {
3044 p.tokenizer.problem(interpretmodule.begin.range.start,"interpretmodule ended unexpectedly",DiagnosticLevel::Error);
3045 return EnvironmentResult::Simple(interpretmodule)
3046 };
3047 let GroupKind::Morphism{domain,rules,specs} = std::mem::take(&mut g.kind) else {
3048 return EnvironmentResult::Simple(interpretmodule);
3049 };
3050 elaborate_morphism(p,star,true,interpretmodule.begin.range,uri.name().last_name().as_ref(),rules,specs);
3051 EnvironmentResult::Success(STeXToken::MorphismEnv {
3052 kind, full_range, name_range, star,env_range,uri,domain,domain_range,children
3053 })
3054 }
3055 _ => EnvironmentResult::Simple(interpretmodule)
3056 }
3057});
3058
3059stex!(LSP: p => @begin{interpretmodule_ast}({name:!name}[archive:str]{domain:!name}){
3060 let Some((uri,mors,rules)) = setup_morphism(p, &name.0,&archive,&domain.0,interpretmodule_ast.begin.range.start) else { return };
3061 p.groups.last_mut().unwrap_or_else(|| unreachable!()).kind = GroupKind::Morphism { domain: mors.clone(), rules, specs: VecMap::default() };
3062 define_assignment_macros(p);
3063 let dom_range_start = archive.map_or(domain.1.start,|(_,r)| r.start);
3064 let domain_range = SourceRange{ start:dom_range_start, end:domain.1.end};
3065 interpretmodule_ast.children.push(STeXToken::MorphismEnv {
3066 kind:MorphismKind::InterpretModule,
3067 domain:mors,uri,
3068 star:true,
3069 full_range:interpretmodule_ast.begin.range,
3070 env_range:interpretmodule_ast.name_range,
3071 domain_range,
3072 name_range:name.1,
3073 children:Vec::new()
3074 });
3075}{
3076 match interpretmodule_ast.children.first() {
3077 Some(STeXToken::MorphismEnv{..}) => {
3078 let mut ch = interpretmodule_ast.children.drain(..);
3079 let Some(STeXToken::MorphismEnv { mut full_range, star,env_range, name_range, uri, domain, domain_range, kind, mut children }) = ch.next() else {
3080 unreachable!()
3081 };
3082 children.extend(ch);
3083 if let Some(end) = interpretmodule_ast.end.as_ref() {
3084 full_range.end = end.range.end;
3085 }
3086 let Some(g) = p.groups.last_mut() else {
3087 p.tokenizer.problem(interpretmodule_ast.begin.range.start,"interpretmodule ended unexpectedly",DiagnosticLevel::Error);
3088 return EnvironmentResult::Simple(interpretmodule_ast)
3089 };
3090 let GroupKind::Morphism{domain,rules,specs} = std::mem::take(&mut g.kind) else {
3091 return EnvironmentResult::Simple(interpretmodule_ast);
3092 };
3093 elaborate_morphism(p,star,true,interpretmodule_ast.begin.range,uri.name().last_name().as_ref(),rules,specs);
3094 EnvironmentResult::Success(STeXToken::MorphismEnv {
3095 kind, full_range, name_range, star,env_range,uri,domain,domain_range,children
3096 })
3097 }
3098 _ => EnvironmentResult::Simple(interpretmodule_ast)
3099 }
3100});
3101
3102pub(super) fn semantic_macro<
3103 'a,
3104 MS: STeXModuleStore,
3105 Pos: SourcePos + 'a,
3106 Err: FnMut(String, SourceRange<Pos>, DiagnosticLevel),
3107>(
3108 arg: &MacroArg<Pos>, m: Macro<'a, Pos, &'a str>,
3110 _parser: &mut LaTeXParser<
3111 'a,
3112 ParseStr<'a, Pos>,
3113 STeXToken<Pos>,
3114 Err,
3115 STeXParseState<'a, Pos, MS>,
3116 >,
3117) -> MacroResult<'a, Pos, &'a str, STeXToken<Pos>> {
3118 let MacroArg::Symbol(uri, argnum) = arg else {
3119 unreachable!()
3120 };
3121 MacroResult::Success(STeXToken::SemanticMacro {
3122 uri: uri.clone(),
3123 argnum: *argnum,
3124 full_range: m.range,
3125 token_range: m.token_range,
3126 })
3127}
3128
3129pub(super) fn variable_macro<
3130 'a,
3131 MS: STeXModuleStore,
3132 Pos: SourcePos + 'a,
3133 Err: FnMut(String, SourceRange<Pos>, DiagnosticLevel),
3134>(
3135 arg: &MacroArg<Pos>, m: Macro<'a, Pos, &'a str>,
3137 _parser: &mut LaTeXParser<
3138 'a,
3139 ParseStr<'a, Pos>,
3140 STeXToken<Pos>,
3141 Err,
3142 STeXParseState<'a, Pos, MS>,
3143 >,
3144) -> MacroResult<'a, Pos, &'a str, STeXToken<Pos>> {
3145 let MacroArg::Variable(name, range, seq, argnum) = arg else {
3146 unreachable!()
3147 };
3148 MacroResult::Success(STeXToken::VariableMacro {
3149 name: name.clone(),
3150 full_range: m.range,
3151 token_range: m.token_range,
3152 sequence: *seq,
3153 orig: *range,
3154 argnum: *argnum,
3155 })
3156}