1use std::collections::HashMap;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct NotationEntry {
13 pub kind: NotationKind,
15 pub name: String,
17 pub pattern: Vec<NotationPart>,
19 pub expansion: String,
21 pub priority: u32,
23 pub scopes: Vec<String>,
25}
26impl NotationEntry {
27 pub fn new(
29 kind: NotationKind,
30 name: String,
31 pattern: Vec<NotationPart>,
32 expansion: String,
33 priority: u32,
34 ) -> Self {
35 Self {
36 kind,
37 name,
38 pattern,
39 expansion,
40 priority,
41 scopes: Vec::new(),
42 }
43 }
44 pub fn with_scopes(mut self, scopes: Vec<String>) -> Self {
46 self.scopes = scopes;
47 self
48 }
49 pub fn in_scope(&self, scope: &str) -> bool {
51 self.scopes.iter().any(|s| s == scope)
52 }
53 pub fn is_global(&self) -> bool {
55 self.scopes.is_empty()
56 }
57}
58#[allow(dead_code)]
60#[allow(missing_docs)]
61pub struct ScopeGuard<'a> {
62 pub(super) env: &'a mut NotationEnv,
63}
64impl<'a> ScopeGuard<'a> {
65 #[allow(dead_code)]
67 pub fn new(env: &'a mut NotationEnv) -> Self {
68 env.push_scope();
69 ScopeGuard { env }
70 }
71}
72#[allow(dead_code)]
74#[allow(missing_docs)]
75#[derive(Debug, Clone)]
76pub struct OperatorAlias {
77 pub alias: String,
79 pub canonical: String,
81}
82impl OperatorAlias {
83 #[allow(dead_code)]
85 pub fn new(alias: &str, canonical: &str) -> Self {
86 OperatorAlias {
87 alias: alias.to_string(),
88 canonical: canonical.to_string(),
89 }
90 }
91}
92#[allow(dead_code)]
94#[allow(missing_docs)]
95#[derive(Debug, Clone, PartialEq, Eq, Hash)]
96pub enum NotationCategory {
97 Term,
99 Tactic,
101 Command,
103 Custom(String),
105}
106#[derive(Debug, Clone, PartialEq, Eq)]
111pub struct OperatorEntry {
112 pub symbol: String,
114 pub fixity: Fixity,
116 pub precedence: u32,
118 pub expansion: String,
120}
121impl OperatorEntry {
122 pub fn new(symbol: String, fixity: Fixity, precedence: u32, expansion: String) -> Self {
124 Self {
125 symbol,
126 fixity,
127 precedence,
128 expansion,
129 }
130 }
131 pub fn is_prefix(&self) -> bool {
133 self.fixity == Fixity::Prefix
134 }
135 pub fn is_infix(&self) -> bool {
137 matches!(self.fixity, Fixity::Infixl | Fixity::Infixr)
138 }
139 pub fn is_postfix(&self) -> bool {
141 self.fixity == Fixity::Postfix
142 }
143 pub fn is_left_assoc(&self) -> bool {
145 self.fixity == Fixity::Infixl
146 }
147 pub fn is_right_assoc(&self) -> bool {
149 self.fixity == Fixity::Infixr
150 }
151}
152#[allow(dead_code)]
154#[allow(missing_docs)]
155pub struct OverloadRegistry {
156 pub entries: Vec<OverloadEntry>,
158}
159impl OverloadRegistry {
160 #[allow(dead_code)]
162 pub fn new() -> Self {
163 OverloadRegistry {
164 entries: Vec::new(),
165 }
166 }
167 #[allow(dead_code)]
169 pub fn register(&mut self, entry: OverloadEntry) {
170 self.entries.push(entry);
171 }
172 #[allow(dead_code)]
174 pub fn best_overload(&self, symbol: &str) -> Option<&OverloadEntry> {
175 self.entries
176 .iter()
177 .filter(|e| e.symbol == symbol)
178 .max_by_key(|e| e.priority)
179 }
180 #[allow(dead_code)]
182 pub fn all_overloads(&self, symbol: &str) -> Vec<&OverloadEntry> {
183 self.entries.iter().filter(|e| e.symbol == symbol).collect()
184 }
185}
186#[derive(Debug, Clone)]
191pub struct NotationTable {
192 entries: Vec<NotationEntry>,
194 operators: HashMap<String, OperatorEntry>,
196 scoped_entries: HashMap<String, Vec<usize>>,
198 active_scopes: Vec<String>,
200}
201impl NotationTable {
202 pub fn new() -> Self {
204 Self {
205 entries: Vec::new(),
206 operators: HashMap::new(),
207 scoped_entries: HashMap::new(),
208 active_scopes: Vec::new(),
209 }
210 }
211 pub fn register_notation(&mut self, entry: NotationEntry) {
213 let idx = self.entries.len();
214 for scope in &entry.scopes {
215 self.scoped_entries
216 .entry(scope.clone())
217 .or_default()
218 .push(idx);
219 }
220 self.entries.push(entry);
221 }
222 pub fn register_operator(&mut self, entry: OperatorEntry) {
224 self.operators.insert(entry.symbol.clone(), entry);
225 }
226 pub fn lookup_prefix(&self, symbol: &str) -> Option<&OperatorEntry> {
228 self.operators
229 .get(symbol)
230 .filter(|op| op.fixity == Fixity::Prefix)
231 }
232 pub fn lookup_infix(&self, symbol: &str) -> Option<&OperatorEntry> {
234 self.operators
235 .get(symbol)
236 .filter(|op| matches!(op.fixity, Fixity::Infixl | Fixity::Infixr))
237 }
238 pub fn lookup_postfix(&self, symbol: &str) -> Option<&OperatorEntry> {
240 self.operators
241 .get(symbol)
242 .filter(|op| op.fixity == Fixity::Postfix)
243 }
244 pub fn lookup_operator(&self, symbol: &str) -> Option<&OperatorEntry> {
246 self.operators.get(symbol)
247 }
248 pub fn get_precedence(&self, symbol: &str) -> Option<u32> {
250 self.operators.get(symbol).map(|op| op.precedence)
251 }
252 pub fn get_entry(&self, index: usize) -> Option<&NotationEntry> {
254 self.entries.get(index)
255 }
256 pub fn notation_count(&self) -> usize {
258 self.entries.len()
259 }
260 pub fn operator_count(&self) -> usize {
262 self.operators.len()
263 }
264 pub fn open_scope(&mut self, scope: &str) -> Vec<&NotationEntry> {
268 if !self.active_scopes.contains(&scope.to_string()) {
269 self.active_scopes.push(scope.to_string());
270 }
271 self.scoped_entries
272 .get(scope)
273 .map(|indices| {
274 indices
275 .iter()
276 .filter_map(|&idx| self.entries.get(idx))
277 .collect()
278 })
279 .unwrap_or_default()
280 }
281 pub fn close_scope(&mut self, scope: &str) {
283 self.active_scopes.retain(|s| s != scope);
284 }
285 pub fn is_scope_active(&self, scope: &str) -> bool {
287 self.active_scopes.contains(&scope.to_string())
288 }
289 pub fn active_scope_names(&self) -> &[String] {
291 &self.active_scopes
292 }
293 pub fn active_notations(&self) -> Vec<&NotationEntry> {
295 self.entries
296 .iter()
297 .filter(|entry| {
298 entry.is_global() || entry.scopes.iter().any(|s| self.active_scopes.contains(s))
299 })
300 .collect()
301 }
302 pub fn find_by_name(&self, name: &str) -> Vec<&NotationEntry> {
304 self.entries.iter().filter(|e| e.name == name).collect()
305 }
306 pub fn find_by_kind(&self, kind: &NotationKind) -> Vec<&NotationEntry> {
308 self.entries.iter().filter(|e| &e.kind == kind).collect()
309 }
310 pub fn find_operators_by_fixity(&self, fixity: &Fixity) -> Vec<&OperatorEntry> {
312 self.operators
313 .values()
314 .filter(|op| &op.fixity == fixity)
315 .collect()
316 }
317 pub fn all_operator_symbols(&self) -> Vec<&str> {
319 let mut symbols: Vec<&str> = self.operators.keys().map(|s| s.as_str()).collect();
320 symbols.sort();
321 symbols
322 }
323 pub fn compare_precedence(&self, a: &str, b: &str) -> Option<std::cmp::Ordering> {
327 let pa = self.get_precedence(a)?;
328 let pb = self.get_precedence(b)?;
329 Some(pa.cmp(&pb))
330 }
331 pub fn builtin_operators() -> Self {
336 let mut table = Self::new();
337 table.register_operator(OperatorEntry::new(
338 "+".to_string(),
339 Fixity::Infixl,
340 65,
341 "HAdd.hAdd".to_string(),
342 ));
343 table.register_operator(OperatorEntry::new(
344 "-".to_string(),
345 Fixity::Infixl,
346 65,
347 "HSub.hSub".to_string(),
348 ));
349 table.register_operator(OperatorEntry::new(
350 "*".to_string(),
351 Fixity::Infixl,
352 70,
353 "HMul.hMul".to_string(),
354 ));
355 table.register_operator(OperatorEntry::new(
356 "/".to_string(),
357 Fixity::Infixl,
358 70,
359 "HDiv.hDiv".to_string(),
360 ));
361 table.register_operator(OperatorEntry::new(
362 "%".to_string(),
363 Fixity::Infixl,
364 70,
365 "HMod.hMod".to_string(),
366 ));
367 table.register_operator(OperatorEntry::new(
368 "^".to_string(),
369 Fixity::Infixr,
370 75,
371 "HPow.hPow".to_string(),
372 ));
373 table.register_operator(OperatorEntry::new(
374 "=".to_string(),
375 Fixity::Infixl,
376 50,
377 "Eq".to_string(),
378 ));
379 table.register_operator(OperatorEntry::new(
380 "!=".to_string(),
381 Fixity::Infixl,
382 50,
383 "Ne".to_string(),
384 ));
385 table.register_operator(OperatorEntry::new(
386 "<".to_string(),
387 Fixity::Infixl,
388 50,
389 "LT.lt".to_string(),
390 ));
391 table.register_operator(OperatorEntry::new(
392 ">".to_string(),
393 Fixity::Infixl,
394 50,
395 "GT.gt".to_string(),
396 ));
397 table.register_operator(OperatorEntry::new(
398 "<=".to_string(),
399 Fixity::Infixl,
400 50,
401 "LE.le".to_string(),
402 ));
403 table.register_operator(OperatorEntry::new(
404 ">=".to_string(),
405 Fixity::Infixl,
406 50,
407 "GE.ge".to_string(),
408 ));
409 table.register_operator(OperatorEntry::new(
410 "&&".to_string(),
411 Fixity::Infixl,
412 35,
413 "And".to_string(),
414 ));
415 table.register_operator(OperatorEntry::new(
416 "||".to_string(),
417 Fixity::Infixl,
418 30,
419 "Or".to_string(),
420 ));
421 table.register_operator(OperatorEntry::new(
422 "!".to_string(),
423 Fixity::Prefix,
424 100,
425 "Not".to_string(),
426 ));
427 table.register_operator(OperatorEntry::new(
428 "->".to_string(),
429 Fixity::Infixr,
430 25,
431 "Arrow".to_string(),
432 ));
433 table.register_operator(OperatorEntry::new(
434 ":=".to_string(),
435 Fixity::Infixl,
436 1,
437 "Assign".to_string(),
438 ));
439 let ops: Vec<(String, NotationKind, u32, String)> = vec![
440 ("+".into(), NotationKind::Infixl, 65, "HAdd.hAdd".into()),
441 ("-".into(), NotationKind::Infixl, 65, "HSub.hSub".into()),
442 ("*".into(), NotationKind::Infixl, 70, "HMul.hMul".into()),
443 ("/".into(), NotationKind::Infixl, 70, "HDiv.hDiv".into()),
444 ("%".into(), NotationKind::Infixl, 70, "HMod.hMod".into()),
445 ("^".into(), NotationKind::Infixr, 75, "HPow.hPow".into()),
446 ("=".into(), NotationKind::Infixl, 50, "Eq".into()),
447 ("!=".into(), NotationKind::Infixl, 50, "Ne".into()),
448 ("<".into(), NotationKind::Infixl, 50, "LT.lt".into()),
449 (">".into(), NotationKind::Infixl, 50, "GT.gt".into()),
450 ("<=".into(), NotationKind::Infixl, 50, "LE.le".into()),
451 (">=".into(), NotationKind::Infixl, 50, "GE.ge".into()),
452 ("&&".into(), NotationKind::Infixl, 35, "And".into()),
453 ("||".into(), NotationKind::Infixl, 30, "Or".into()),
454 ("!".into(), NotationKind::Prefix, 100, "Not".into()),
455 ("->".into(), NotationKind::Infixr, 25, "Arrow".into()),
456 (":=".into(), NotationKind::Infixl, 1, "Assign".into()),
457 ];
458 for (sym, kind, prec, expansion) in ops {
459 let pattern = match &kind {
460 NotationKind::Prefix => {
461 vec![
462 NotationPart::Literal(sym.clone()),
463 NotationPart::Placeholder("x".into()),
464 ]
465 }
466 NotationKind::Postfix => {
467 vec![
468 NotationPart::Placeholder("x".into()),
469 NotationPart::Literal(sym.clone()),
470 ]
471 }
472 _ => {
473 vec![
474 NotationPart::Placeholder("lhs".into()),
475 NotationPart::Literal(sym.clone()),
476 NotationPart::Placeholder("rhs".into()),
477 ]
478 }
479 };
480 table.register_notation(NotationEntry::new(kind, sym, pattern, expansion, prec));
481 }
482 table
483 }
484}
485#[allow(dead_code)]
487#[allow(missing_docs)]
488pub struct NotationFormatter {
489 pub registry: NotationRegistry,
491}
492impl NotationFormatter {
493 #[allow(dead_code)]
495 pub fn new(reg: NotationRegistry) -> Self {
496 NotationFormatter { registry: reg }
497 }
498 #[allow(dead_code)]
500 pub fn rule_count(&self) -> usize {
501 self.registry.rules.len()
502 }
503}
504#[allow(dead_code)]
506#[allow(missing_docs)]
507#[derive(Debug, Clone)]
508pub struct NotationRule {
509 pub pattern: String,
511 pub expansion: String,
513 pub prec: PrecLevel,
515 pub namespace: Option<String>,
517}
518impl NotationRule {
519 #[allow(dead_code)]
521 pub fn new(pattern: &str, expansion: &str, prec: PrecLevel) -> Self {
522 NotationRule {
523 pattern: pattern.to_string(),
524 expansion: expansion.to_string(),
525 prec,
526 namespace: None,
527 }
528 }
529 #[allow(dead_code)]
531 pub fn in_namespace(mut self, ns: &str) -> Self {
532 self.namespace = Some(ns.to_string());
533 self
534 }
535}
536#[allow(dead_code)]
538#[allow(missing_docs)]
539#[derive(Debug, Clone, PartialEq, Eq)]
540pub enum NotationTokenKind {
541 Literal(String),
543 Hole,
545 NamedHole(String),
547}
548#[allow(dead_code)]
550#[allow(missing_docs)]
551#[derive(Debug, Clone)]
552pub struct OverloadEntry {
553 pub symbol: String,
555 pub typeclass: String,
557 pub priority: u32,
559}
560impl OverloadEntry {
561 #[allow(dead_code)]
563 pub fn new(symbol: &str, typeclass: &str, priority: u32) -> Self {
564 OverloadEntry {
565 symbol: symbol.to_string(),
566 typeclass: typeclass.to_string(),
567 priority,
568 }
569 }
570}
571#[allow(dead_code)]
573#[allow(missing_docs)]
574pub struct NotationRegistry {
575 pub rules: Vec<NotationRule>,
577}
578impl NotationRegistry {
579 #[allow(dead_code)]
581 pub fn new() -> Self {
582 NotationRegistry { rules: Vec::new() }
583 }
584 #[allow(dead_code)]
586 pub fn register(&mut self, rule: NotationRule) {
587 self.rules.push(rule);
588 }
589 #[allow(dead_code)]
591 pub fn find_by_pattern(&self, pattern: &str) -> Vec<&NotationRule> {
592 self.rules.iter().filter(|r| r.pattern == pattern).collect()
593 }
594 #[allow(dead_code)]
596 pub fn find_by_namespace(&self, ns: &str) -> Vec<&NotationRule> {
597 self.rules
598 .iter()
599 .filter(|r| r.namespace.as_deref() == Some(ns))
600 .collect()
601 }
602 #[allow(dead_code)]
604 pub fn len(&self) -> usize {
605 self.rules.len()
606 }
607 #[allow(dead_code)]
609 pub fn is_empty(&self) -> bool {
610 self.rules.is_empty()
611 }
612}
613#[allow(dead_code)]
615#[allow(missing_docs)]
616pub struct BuiltinPrecTable {
617 pub entries: Vec<(String, u32, bool)>,
619}
620impl BuiltinPrecTable {
621 #[allow(dead_code)]
623 pub fn standard() -> Self {
624 BuiltinPrecTable {
625 entries: vec![
626 ("=".to_string(), 50, false),
627 ("<".to_string(), 50, false),
628 (">".to_string(), 50, false),
629 ("<=".to_string(), 50, false),
630 (">=".to_string(), 50, false),
631 ("≠".to_string(), 50, false),
632 ("∧".to_string(), 35, true),
633 ("∨".to_string(), 30, true),
634 ("→".to_string(), 25, false),
635 ("↔".to_string(), 20, false),
636 ("+".to_string(), 65, true),
637 ("-".to_string(), 65, true),
638 ("*".to_string(), 70, true),
639 ("/".to_string(), 70, true),
640 ("%".to_string(), 70, true),
641 ("^".to_string(), 75, false),
642 ],
643 }
644 }
645 #[allow(dead_code)]
647 pub fn lookup(&self, op: &str) -> Option<(u32, bool)> {
648 self.entries
649 .iter()
650 .find(|(o, _, _)| o == op)
651 .map(|(_, p, l)| (*p, *l))
652 }
653}
654#[allow(dead_code)]
656#[allow(missing_docs)]
657pub struct NotationScope {
658 pub name: String,
660 pub rules: Vec<NotationRule>,
662}
663impl NotationScope {
664 #[allow(dead_code)]
666 pub fn new(name: &str) -> Self {
667 NotationScope {
668 name: name.to_string(),
669 rules: Vec::new(),
670 }
671 }
672 #[allow(dead_code)]
674 pub fn add_rule(&mut self, rule: NotationRule) {
675 self.rules.push(rule);
676 }
677}
678#[allow(dead_code)]
680#[allow(missing_docs)]
681#[derive(Debug, Clone)]
682pub struct MacroRule {
683 pub name: String,
685 pub params: Vec<String>,
687 pub body: String,
689}
690impl MacroRule {
691 #[allow(dead_code)]
693 pub fn new(name: &str, params: Vec<&str>, body: &str) -> Self {
694 MacroRule {
695 name: name.to_string(),
696 params: params.into_iter().map(|s| s.to_string()).collect(),
697 body: body.to_string(),
698 }
699 }
700 #[allow(dead_code)]
702 pub fn instantiate(&self, args: &[&str]) -> String {
703 if args.len() != self.params.len() {
704 return format!(
705 "(macro-error: {} expects {} args, got {})",
706 self.name,
707 self.params.len(),
708 args.len()
709 );
710 }
711 let mut result = self.body.clone();
712 for (param, arg) in self.params.iter().zip(args.iter()) {
713 result = result.replace(param.as_str(), arg);
714 }
715 result
716 }
717}
718#[allow(dead_code)]
720#[allow(missing_docs)]
721pub struct SyntaxSugarLibrary {
722 pub sugars: Vec<SyntaxSugar>,
724}
725impl SyntaxSugarLibrary {
726 #[allow(dead_code)]
728 pub fn new() -> Self {
729 SyntaxSugarLibrary { sugars: Vec::new() }
730 }
731 #[allow(dead_code)]
733 pub fn add(&mut self, sugar: SyntaxSugar) {
734 self.sugars.push(sugar);
735 }
736 #[allow(dead_code)]
738 pub fn find(&self, name: &str) -> Option<&SyntaxSugar> {
739 self.sugars.iter().find(|s| s.name == name)
740 }
741 #[allow(dead_code)]
743 pub fn len(&self) -> usize {
744 self.sugars.len()
745 }
746 #[allow(dead_code)]
748 pub fn is_empty(&self) -> bool {
749 self.sugars.is_empty()
750 }
751}
752#[allow(dead_code)]
754#[allow(missing_docs)]
755#[derive(Debug, Clone)]
756pub struct SyntaxExtension {
757 pub name: String,
759 pub is_infix: bool,
761 pub is_prefix: bool,
763 pub is_postfix: bool,
765}
766impl SyntaxExtension {
767 #[allow(dead_code)]
769 pub fn infix(name: &str) -> Self {
770 SyntaxExtension {
771 name: name.to_string(),
772 is_infix: true,
773 is_prefix: false,
774 is_postfix: false,
775 }
776 }
777 #[allow(dead_code)]
779 pub fn prefix(name: &str) -> Self {
780 SyntaxExtension {
781 name: name.to_string(),
782 is_infix: false,
783 is_prefix: true,
784 is_postfix: false,
785 }
786 }
787}
788#[allow(dead_code)]
790#[allow(missing_docs)]
791pub struct OperatorAliasTable {
792 pub entries: Vec<OperatorAlias>,
794}
795impl OperatorAliasTable {
796 #[allow(dead_code)]
798 pub fn new() -> Self {
799 OperatorAliasTable {
800 entries: Vec::new(),
801 }
802 }
803 #[allow(dead_code)]
805 pub fn add(&mut self, alias: OperatorAlias) {
806 self.entries.push(alias);
807 }
808 #[allow(dead_code)]
810 pub fn resolve(&self, op: &str) -> String {
811 self.entries
812 .iter()
813 .find(|e| e.alias == op)
814 .map(|e| e.canonical.clone())
815 .unwrap_or_else(|| op.to_string())
816 }
817 #[allow(dead_code)]
819 pub fn len(&self) -> usize {
820 self.entries.len()
821 }
822 #[allow(dead_code)]
824 pub fn is_empty(&self) -> bool {
825 self.entries.is_empty()
826 }
827}
828#[allow(dead_code)]
830#[allow(missing_docs)]
831pub struct NotationGroup {
832 pub name: String,
834 pub rules: Vec<NotationRule>,
836 pub active: bool,
838}
839impl NotationGroup {
840 #[allow(dead_code)]
842 pub fn new(name: &str) -> Self {
843 NotationGroup {
844 name: name.to_string(),
845 rules: Vec::new(),
846 active: true,
847 }
848 }
849 #[allow(dead_code)]
851 pub fn add(&mut self, rule: NotationRule) {
852 self.rules.push(rule);
853 }
854 #[allow(dead_code)]
856 pub fn deactivate(&mut self) {
857 self.active = false;
858 }
859 #[allow(dead_code)]
861 pub fn active_rules(&self) -> Vec<&NotationRule> {
862 if self.active {
863 self.rules.iter().collect()
864 } else {
865 Vec::new()
866 }
867 }
868}
869#[allow(dead_code)]
871#[allow(missing_docs)]
872pub struct NotationPriorityQueue {
873 pub rules: Vec<NotationRule>,
875}
876impl NotationPriorityQueue {
877 #[allow(dead_code)]
879 pub fn new() -> Self {
880 NotationPriorityQueue { rules: Vec::new() }
881 }
882 #[allow(dead_code)]
884 pub fn insert(&mut self, rule: NotationRule) {
885 let pos = self
886 .rules
887 .partition_point(|r| r.prec.value >= rule.prec.value);
888 self.rules.insert(pos, rule);
889 }
890 #[allow(dead_code)]
892 pub fn rules_at_or_above(&self, prec: u32) -> Vec<&NotationRule> {
893 self.rules.iter().filter(|r| r.prec.value >= prec).collect()
894 }
895 #[allow(dead_code)]
897 pub fn len(&self) -> usize {
898 self.rules.len()
899 }
900 #[allow(dead_code)]
902 pub fn is_empty(&self) -> bool {
903 self.rules.is_empty()
904 }
905}
906#[derive(Debug, Clone, PartialEq, Eq, Hash)]
908pub enum NotationKind {
909 Prefix,
911 Postfix,
913 Infixl,
915 Infixr,
917 Notation,
919}
920#[allow(dead_code)]
922#[allow(missing_docs)]
923#[derive(Debug, Clone)]
924pub struct SyntaxSugar {
925 pub name: String,
927 pub surface: String,
929 pub core: String,
931}
932impl SyntaxSugar {
933 #[allow(dead_code)]
935 pub fn new(name: &str, surface: &str, core: &str) -> Self {
936 SyntaxSugar {
937 name: name.to_string(),
938 surface: surface.to_string(),
939 core: core.to_string(),
940 }
941 }
942}
943#[allow(dead_code)]
945#[allow(missing_docs)]
946#[derive(Debug, Clone)]
947pub struct PatternMatcher {
948 pub pattern: Vec<String>,
950}
951impl PatternMatcher {
952 #[allow(dead_code)]
954 #[allow(clippy::should_implement_trait)]
955 pub fn from_str(s: &str) -> Self {
956 PatternMatcher {
957 pattern: s.split_whitespace().map(|t| t.to_string()).collect(),
958 }
959 }
960 #[allow(dead_code)]
962 pub fn hole_count(&self) -> usize {
963 self.pattern.iter().filter(|t| t.as_str() == "_").count()
964 }
965 #[allow(dead_code)]
967 pub fn all_holes(&self) -> bool {
968 self.pattern.iter().all(|t| t.as_str() == "_")
969 }
970}
971#[derive(Debug, Clone, PartialEq, Eq, Hash)]
973pub enum Fixity {
974 Prefix,
976 Infixl,
978 Infixr,
980 Postfix,
982}
983#[allow(dead_code)]
985#[allow(missing_docs)]
986#[derive(Debug, Clone)]
987pub struct NotationConflict {
988 pub pattern: String,
990 pub expansion_a: String,
992 pub expansion_b: String,
994}
995#[allow(dead_code)]
997#[allow(missing_docs)]
998pub struct NotationEnv {
999 pub scopes: Vec<Vec<NotationRule>>,
1001}
1002impl NotationEnv {
1003 #[allow(dead_code)]
1005 pub fn new() -> Self {
1006 NotationEnv {
1007 scopes: vec![Vec::new()],
1008 }
1009 }
1010 #[allow(dead_code)]
1012 pub fn push_scope(&mut self) {
1013 self.scopes.push(Vec::new());
1014 }
1015 #[allow(dead_code)]
1017 pub fn pop_scope(&mut self) {
1018 if self.scopes.len() > 1 {
1019 self.scopes.pop();
1020 }
1021 }
1022 #[allow(dead_code)]
1024 pub fn add(&mut self, rule: NotationRule) {
1025 if let Some(scope) = self.scopes.last_mut() {
1026 scope.push(rule);
1027 }
1028 }
1029 #[allow(dead_code)]
1031 pub fn lookup(&self, pattern: &str) -> Vec<&NotationRule> {
1032 let mut result = Vec::new();
1033 for scope in self.scopes.iter().rev() {
1034 for rule in scope {
1035 if rule.pattern == pattern {
1036 result.push(rule);
1037 }
1038 }
1039 }
1040 result
1041 }
1042 #[allow(dead_code)]
1044 pub fn total_rules(&self) -> usize {
1045 self.scopes.iter().map(|s| s.len()).sum()
1046 }
1047}
1048#[allow(dead_code)]
1050#[allow(missing_docs)]
1051#[derive(Debug, Clone, PartialEq, Eq)]
1052pub struct PrecLevel {
1053 pub value: u32,
1055 pub left_assoc: bool,
1057 pub right_assoc: bool,
1059}
1060impl PrecLevel {
1061 #[allow(dead_code)]
1063 pub fn left(value: u32) -> Self {
1064 PrecLevel {
1065 value,
1066 left_assoc: true,
1067 right_assoc: false,
1068 }
1069 }
1070 #[allow(dead_code)]
1072 pub fn right(value: u32) -> Self {
1073 PrecLevel {
1074 value,
1075 left_assoc: false,
1076 right_assoc: true,
1077 }
1078 }
1079 #[allow(dead_code)]
1081 pub fn none(value: u32) -> Self {
1082 PrecLevel {
1083 value,
1084 left_assoc: false,
1085 right_assoc: false,
1086 }
1087 }
1088}
1089#[derive(Debug, Clone, PartialEq, Eq)]
1098pub enum NotationPart {
1099 Literal(String),
1101 Placeholder(String),
1103 Prec(u32),
1105}