1use crate::{Literal, Term, Universe};
38use super::command::Command;
39use super::error::ParseError;
40use std::collections::HashSet;
41
42pub fn parse_inductive(input: &str) -> Result<Command, ParseError> {
53 let mut parser = LiterateParser::new(input);
54 parser.parse_literate_inductive()
55}
56
57pub fn parse_definition(input: &str) -> Result<Command, ParseError> {
62 let mut parser = LiterateParser::new(input);
63 parser.parse_literate_definition()
64}
65
66pub fn parse_let_definition(input: &str) -> Result<Command, ParseError> {
72 let mut parser = LiterateParser::new(input);
73 parser.parse_literate_let()
74}
75
76pub fn parse_theorem(input: &str) -> Result<Command, ParseError> {
81 let mut parser = LiterateParser::new(input);
82 parser.parse_literate_theorem()
83}
84
85struct LiterateParser<'a> {
90 input: &'a str,
91 pos: usize,
92 bound_vars: HashSet<String>,
93 current_function: Option<String>,
94 return_type: Option<Term>,
96}
97
98impl<'a> LiterateParser<'a> {
99 fn new(input: &'a str) -> Self {
100 Self {
101 input,
102 pos: 0,
103 bound_vars: HashSet::new(),
104 current_function: None,
105 return_type: None,
106 }
107 }
108
109 fn parse_literate_inductive(&mut self) -> Result<Command, ParseError> {
115 self.skip_whitespace();
116
117 if self.try_consume_keyword("An") || self.try_consume_keyword("A") {
119 } else {
121 return Err(ParseError::Expected {
122 expected: "'A' or 'An'".to_string(),
123 found: self.peek_word().unwrap_or("EOF".to_string()),
124 });
125 }
126
127 self.skip_whitespace();
128
129 let name = self.parse_ident()?;
131
132 self.skip_whitespace();
133
134 let params = if self.try_consume_keyword("of") {
136 self.skip_whitespace();
137 self.parse_param_list()?
138 } else {
139 vec![]
140 };
141
142 self.skip_whitespace();
143
144 if !self.try_consume_keyword("is") {
146 return Err(ParseError::Expected {
147 expected: "'is'".to_string(),
148 found: self.peek_word().unwrap_or("EOF".to_string()),
149 });
150 }
151 self.skip_whitespace();
152 if !self.try_consume_keyword("either") {
153 return Err(ParseError::Expected {
154 expected: "'either'".to_string(),
155 found: self.peek_word().unwrap_or("EOF".to_string()),
156 });
157 }
158
159 self.skip_whitespace();
160
161 let constructors = if self.peek_char(':') {
163 self.advance(); self.parse_indented_variants(&name, ¶ms)?
166 } else {
167 self.parse_inline_variants(&name, ¶ms)?
169 };
170
171 if constructors.is_empty() {
172 return Err(ParseError::Missing("constructors".to_string()));
173 }
174
175 Ok(Command::Inductive {
176 name,
177 params,
178 sort: Term::Sort(Universe::Type(0)),
179 constructors,
180 })
181 }
182
183 fn parse_inline_variants(
185 &mut self,
186 inductive_name: &str,
187 params: &[(String, Term)],
188 ) -> Result<Vec<(String, Term)>, ParseError> {
189 let mut constructors = Vec::new();
190
191 loop {
192 self.skip_whitespace();
193
194 if self.at_end() || self.peek_char('.') {
195 break;
196 }
197
198 let (ctor_name, ctor_type) = self.parse_variant(inductive_name, params)?;
200 constructors.push((ctor_name, ctor_type));
201
202 self.skip_whitespace();
203
204 if !self.try_consume_keyword("or") {
206 break;
207 }
208 }
209
210 self.skip_whitespace();
212 let _ = self.try_consume(".");
213
214 Ok(constructors)
215 }
216
217 fn parse_indented_variants(
219 &mut self,
220 inductive_name: &str,
221 params: &[(String, Term)],
222 ) -> Result<Vec<(String, Term)>, ParseError> {
223 let mut constructors = Vec::new();
224
225 loop {
226 self.skip_whitespace_and_newlines();
227
228 if self.at_end() {
229 break;
230 }
231
232 if !self.peek_char(' ') && !self.peek_char('\t') && !self.peek_char('a') && !self.peek_char('A') {
234 if let Some(c) = self.peek() {
236 if !c.is_uppercase() && c != 'a' && c != 'A' {
237 break;
238 }
239 }
240 }
241
242 self.skip_whitespace();
244
245 if self.at_end() {
247 break;
248 }
249
250 let (ctor_name, ctor_type) = self.parse_variant(inductive_name, params)?;
252 constructors.push((ctor_name, ctor_type));
253
254 self.skip_whitespace();
256 let _ = self.try_consume(".");
257 }
258
259 Ok(constructors)
260 }
261
262 fn parse_variant(
264 &mut self,
265 inductive_name: &str,
266 params: &[(String, Term)],
267 ) -> Result<(String, Term), ParseError> {
268 self.skip_whitespace();
269
270 let _ = self.try_consume_keyword("an") || self.try_consume_keyword("a");
272 self.skip_whitespace();
273
274 let ctor_name = self.parse_ident()?;
276
277 self.skip_whitespace();
278
279 let result_type = self.build_applied_type(inductive_name, params);
281
282 if self.try_consume_keyword("with") {
284 let fields = self.parse_field_list()?;
286
287 let mut ctor_type = result_type;
289 for (_field_name, field_type) in fields.into_iter().rev() {
290 ctor_type = Term::Pi {
291 param: "_".to_string(),
292 param_type: Box::new(field_type),
293 body_type: Box::new(ctor_type),
294 };
295 }
296
297 Ok((ctor_name, ctor_type))
298 } else {
299 Ok((ctor_name, result_type))
301 }
302 }
303
304 fn parse_field_list(&mut self) -> Result<Vec<(String, Term)>, ParseError> {
306 let mut fields = Vec::new();
307
308 loop {
309 self.skip_whitespace();
310
311 let field_name = self.parse_ident()?;
313
314 self.skip_whitespace();
315
316 if !self.try_consume(":") {
318 return Err(ParseError::Expected {
319 expected: "':'".to_string(),
320 found: self.peek_word().unwrap_or("EOF".to_string()),
321 });
322 }
323
324 self.skip_whitespace();
325
326 let field_type = self.parse_type()?;
328
329 fields.push((field_name, field_type));
330
331 self.skip_whitespace();
332
333 if !self.try_consume_keyword("and") {
335 break;
336 }
337 }
338
339 Ok(fields)
340 }
341
342 fn build_applied_type(&self, name: &str, params: &[(String, Term)]) -> Term {
344 let mut result = Term::Global(name.to_string());
345 for (param_name, _) in params {
346 result = Term::App(Box::new(result), Box::new(Term::Var(param_name.clone())));
347 }
348 result
349 }
350
351 fn parse_literate_definition(&mut self) -> Result<Command, ParseError> {
357 self.skip_whitespace();
358
359 if !self.try_consume("## To ") && !self.try_consume("##To ") {
361 return Err(ParseError::Expected {
362 expected: "'## To'".to_string(),
363 found: self.peek_word().unwrap_or("EOF".to_string()),
364 });
365 }
366
367 self.skip_whitespace();
368
369 let mut name = self.parse_ident()?;
371
372 if name == "be" {
375 self.skip_whitespace();
376 name = self.parse_ident()?;
377 }
378
379 self.current_function = Some(name.clone());
380
381 self.skip_whitespace();
382
383 let all_params = self.parse_function_params()?;
386
387 self.skip_whitespace();
388
389 let return_type = if self.try_consume("->") {
391 self.skip_whitespace();
392 let ret = self.parse_type()?;
393 self.return_type = Some(ret.clone());
395 Some(ret)
396 } else {
397 None
398 };
399
400 self.skip_whitespace();
401
402 if !self.try_consume(":") {
404 return Err(ParseError::Expected {
405 expected: "':'".to_string(),
406 found: self.peek_word().unwrap_or("EOF".to_string()),
407 });
408 }
409
410 for (param_name, _) in &all_params {
412 self.bound_vars.insert(param_name.clone());
413 }
414
415 self.skip_whitespace_and_newlines();
417 let body = self.parse_body()?;
418
419 let needs_fix = self.contains_self_reference(&name, &body);
421
422 let mut func_body = body;
424 for (param_name, param_type) in all_params.iter().rev() {
425 func_body = Term::Lambda {
426 param: param_name.clone(),
427 param_type: Box::new(param_type.clone()),
428 body: Box::new(func_body),
429 };
430 }
431
432 if needs_fix {
434 func_body = Term::Fix {
435 name: name.clone(),
436 body: Box::new(func_body),
437 };
438 }
439
440 let ty = if let Some(ret) = return_type {
442 let mut full_type = ret;
443 for (_, param_type) in all_params.iter().rev() {
444 full_type = Term::Pi {
445 param: "_".to_string(),
446 param_type: Box::new(param_type.clone()),
447 body_type: Box::new(full_type),
448 };
449 }
450 Some(full_type)
451 } else {
452 None
453 };
454
455 self.current_function = None;
456
457 Ok(Command::Definition {
458 name,
459 ty,
460 body: func_body,
461 is_hint: false,
462 implicit_count: 0,
463 })
464 }
465
466 fn parse_literate_let(&mut self) -> Result<Command, ParseError> {
472 self.skip_whitespace();
473
474 if !self.try_consume_keyword("Let") {
476 return Err(ParseError::Expected {
477 expected: "'Let'".to_string(),
478 found: self.peek_word().unwrap_or("EOF".to_string()),
479 });
480 }
481
482 self.skip_whitespace();
483
484 let name = self.parse_ident()?;
486
487 self.skip_whitespace();
488
489 if !self.try_consume_keyword("be") {
491 return Err(ParseError::Expected {
492 expected: "'be'".to_string(),
493 found: self.peek_word().unwrap_or("EOF".to_string()),
494 });
495 }
496
497 self.skip_whitespace();
498
499 let body = self.parse_term()?;
501
502 self.skip_whitespace();
504 let _ = self.try_consume(".");
505
506 Ok(Command::Definition {
507 name,
508 ty: None,
509 body,
510 is_hint: false,
511 implicit_count: 0,
512 })
513 }
514
515 fn parse_literate_theorem(&mut self) -> Result<Command, ParseError> {
520 self.skip_whitespace();
521
522 if !self.try_consume("## Theorem:") {
524 return Err(ParseError::Expected {
525 expected: "'## Theorem:'".to_string(),
526 found: self.peek_word().unwrap_or("EOF".to_string()),
527 });
528 }
529
530 self.skip_whitespace();
531
532 let name = self.parse_ident()?;
534
535 self.skip_whitespace_and_newlines();
536
537 if !self.try_consume_keyword("Statement") {
539 return Err(ParseError::Expected {
540 expected: "'Statement'".to_string(),
541 found: self.peek_word().unwrap_or("EOF".to_string()),
542 });
543 }
544 self.skip_whitespace();
545 if !self.try_consume(":") {
546 return Err(ParseError::Expected {
547 expected: "':'".to_string(),
548 found: self.peek_word().unwrap_or("EOF".to_string()),
549 });
550 }
551
552 self.skip_whitespace();
553
554 let statement = self.parse_term()?;
556
557 self.skip_whitespace();
559 let _ = self.try_consume(".");
560
561 self.skip_whitespace_and_newlines();
562
563 let (body, ty) = if self.try_consume_keyword("Proof") {
565 self.skip_whitespace();
566 if !self.try_consume(":") {
567 return Err(ParseError::Expected {
568 expected: "':'".to_string(),
569 found: self.peek_word().unwrap_or("EOF".to_string()),
570 });
571 }
572 self.skip_whitespace();
573
574 let proof = self.parse_proof_tactic(&statement)?;
576
577 self.skip_whitespace();
579 let _ = self.try_consume(".");
580
581 (proof, Some(Term::Global("Derivation".to_string())))
582 } else {
583 (statement, Some(Term::Sort(Universe::Prop)))
585 };
586
587 self.skip_whitespace_and_newlines();
589 let is_hint = if self.try_consume_keyword("Attribute") {
590 self.skip_whitespace();
591 if !self.try_consume(":") {
592 return Err(ParseError::Expected {
593 expected: "':'".to_string(),
594 found: self.peek_word().unwrap_or("EOF".to_string()),
595 });
596 }
597 self.skip_whitespace();
598
599 let hint = self.try_consume_keyword("hint");
600
601 self.skip_whitespace();
603 let _ = self.try_consume(".");
604
605 hint
606 } else {
607 false
608 };
609
610 Ok(Command::Definition {
611 name,
612 ty,
613 body,
614 is_hint,
615 implicit_count: 0,
616 })
617 }
618
619 fn parse_proof_tactic(&mut self, statement: &Term) -> Result<Term, ParseError> {
626 if self.try_consume_keyword("ring") {
627 self.skip_whitespace();
629 let _ = self.try_consume(".");
630
631 let goal_syntax = self.term_to_syntax(statement, &[]);
633 Ok(Term::App(
634 Box::new(Term::Global("try_ring".to_string())),
635 Box::new(goal_syntax),
636 ))
637 } else if self.try_consume_keyword("refl") {
638 self.skip_whitespace();
640 let _ = self.try_consume(".");
641
642 let goal_syntax = self.term_to_syntax(statement, &[]);
643 Ok(Term::App(
644 Box::new(Term::Global("try_refl".to_string())),
645 Box::new(goal_syntax),
646 ))
647 } else if self.try_consume_keyword("lia") {
648 self.skip_whitespace();
650 let _ = self.try_consume(".");
651
652 let goal_syntax = self.term_to_syntax(statement, &[]);
653 Ok(Term::App(
654 Box::new(Term::Global("try_lia".to_string())),
655 Box::new(goal_syntax),
656 ))
657 } else if self.try_consume_keyword("cc") {
658 self.skip_whitespace();
660 let _ = self.try_consume(".");
661
662 let goal_syntax = self.term_to_syntax(statement, &[]);
663 Ok(Term::App(
664 Box::new(Term::Global("try_cc".to_string())),
665 Box::new(goal_syntax),
666 ))
667 } else if self.try_consume_keyword("simp") {
668 self.skip_whitespace();
670 let _ = self.try_consume(".");
671
672 let goal_syntax = self.term_to_syntax(statement, &[]);
673 Ok(Term::App(
674 Box::new(Term::Global("try_simp".to_string())),
675 Box::new(goal_syntax),
676 ))
677 } else if self.try_consume_keyword("omega") {
678 self.skip_whitespace();
680 let _ = self.try_consume(".");
681
682 let goal_syntax = self.term_to_syntax(statement, &[]);
683 Ok(Term::App(
684 Box::new(Term::Global("try_omega".to_string())),
685 Box::new(goal_syntax),
686 ))
687 } else if self.try_consume_keyword("auto") {
688 self.skip_whitespace();
690 let _ = self.try_consume(".");
691
692 let goal_syntax = self.term_to_syntax(statement, &[]);
693 Ok(Term::App(
694 Box::new(Term::Global("try_auto".to_string())),
695 Box::new(goal_syntax),
696 ))
697 } else if self.try_consume_keyword("induction") {
698 self.skip_whitespace();
700 let var_name = self.parse_ident()?;
701 self.skip_whitespace();
702 let _ = self.try_consume(".");
703
704 let cases = self.parse_bullet_cases(statement)?;
706
707 self.build_induction_derivation(&var_name, statement, cases)
709 } else {
710 Err(ParseError::Expected {
711 expected: "proof tactic (ring, refl, lia, cc, simp, omega, auto, induction)".to_string(),
712 found: self.peek_word().unwrap_or("EOF".to_string()),
713 })
714 }
715 }
716
717 fn peek_bullet(&mut self) -> bool {
719 let saved_pos = self.pos;
721 self.skip_whitespace_and_newlines();
722 let result = matches!(self.peek(), Some('-') | Some('*') | Some('+'));
723 self.pos = saved_pos;
724 result
725 }
726
727 fn consume_bullet(&mut self) {
729 self.skip_whitespace_and_newlines();
730 if matches!(self.peek(), Some('-') | Some('*') | Some('+')) {
731 self.advance();
732 }
733 }
734
735 fn parse_bullet_cases(&mut self, statement: &Term) -> Result<Vec<Term>, ParseError> {
737 let mut cases = Vec::new();
738
739 while self.peek_bullet() {
740 self.consume_bullet();
741 self.skip_whitespace();
742
743 let case_proof = self.parse_tactic_sequence(statement)?;
745 cases.push(case_proof);
746 }
747
748 Ok(cases)
749 }
750
751 fn parse_tactic_sequence(&mut self, statement: &Term) -> Result<Term, ParseError> {
753 let mut tactics = Vec::new();
754
755 loop {
756 self.skip_whitespace();
757
758 if self.peek_bullet() || self.at_end() || self.peek_keyword("Attribute") {
760 break;
761 }
762
763 match self.parse_single_tactic(statement) {
765 Ok(tactic) => tactics.push(tactic),
766 Err(_) => break,
767 }
768 }
769
770 if tactics.is_empty() {
771 return Err(ParseError::Missing("tactic in bullet case".to_string()));
772 }
773
774 let mut result = tactics.pop().unwrap();
776 while let Some(prev) = tactics.pop() {
777 result = Term::App(
778 Box::new(Term::App(
779 Box::new(Term::Global("tact_seq".to_string())),
780 Box::new(prev),
781 )),
782 Box::new(result),
783 );
784 }
785
786 Ok(result)
787 }
788
789 fn parse_single_tactic(&mut self, statement: &Term) -> Result<Term, ParseError> {
791 let goal_syntax = self.term_to_syntax(statement, &[]);
792
793 if self.try_consume_keyword("ring") {
794 self.skip_whitespace();
795 let _ = self.try_consume(".");
796 Ok(Term::App(
797 Box::new(Term::Global("try_ring".to_string())),
798 Box::new(goal_syntax),
799 ))
800 } else if self.try_consume_keyword("refl") {
801 self.skip_whitespace();
802 let _ = self.try_consume(".");
803 Ok(Term::App(
804 Box::new(Term::Global("try_refl".to_string())),
805 Box::new(goal_syntax),
806 ))
807 } else if self.try_consume_keyword("lia") {
808 self.skip_whitespace();
809 let _ = self.try_consume(".");
810 Ok(Term::App(
811 Box::new(Term::Global("try_lia".to_string())),
812 Box::new(goal_syntax),
813 ))
814 } else if self.try_consume_keyword("cc") {
815 self.skip_whitespace();
816 let _ = self.try_consume(".");
817 Ok(Term::App(
818 Box::new(Term::Global("try_cc".to_string())),
819 Box::new(goal_syntax),
820 ))
821 } else if self.try_consume_keyword("simp") {
822 self.skip_whitespace();
823 let _ = self.try_consume(".");
824 Ok(Term::App(
825 Box::new(Term::Global("try_simp".to_string())),
826 Box::new(goal_syntax),
827 ))
828 } else if self.try_consume_keyword("omega") {
829 self.skip_whitespace();
830 let _ = self.try_consume(".");
831 Ok(Term::App(
832 Box::new(Term::Global("try_omega".to_string())),
833 Box::new(goal_syntax),
834 ))
835 } else if self.try_consume_keyword("auto") {
836 self.skip_whitespace();
837 let _ = self.try_consume(".");
838 Ok(Term::App(
839 Box::new(Term::Global("try_auto".to_string())),
840 Box::new(goal_syntax),
841 ))
842 } else if self.try_consume_keyword("intro") {
843 self.skip_whitespace();
844 let _var = if !self.peek_char('.') && !self.at_end() {
846 self.parse_ident().ok()
847 } else {
848 None
849 };
850 self.skip_whitespace();
851 let _ = self.try_consume(".");
852 Ok(Term::App(
853 Box::new(Term::Global("try_intro".to_string())),
854 Box::new(goal_syntax),
855 ))
856 } else {
857 Err(ParseError::Expected {
858 expected: "tactic".to_string(),
859 found: self.peek_word().unwrap_or("EOF".to_string()),
860 })
861 }
862 }
863
864 fn build_induction_derivation(
866 &self,
867 _var_name: &str,
868 statement: &Term,
869 cases: Vec<Term>,
870 ) -> Result<Term, ParseError> {
871 let ind_type = Term::App(
873 Box::new(Term::Global("SName".to_string())),
874 Box::new(Term::Lit(Literal::Text("Nat".to_string()))),
875 );
876
877 let motive = self.term_to_syntax(statement, &[]);
879
880 let mut case_chain = Term::Global("DCaseEnd".to_string());
882 for case_proof in cases.into_iter().rev() {
883 case_chain = Term::App(
884 Box::new(Term::App(
885 Box::new(Term::Global("DCase".to_string())),
886 Box::new(case_proof),
887 )),
888 Box::new(case_chain),
889 );
890 }
891
892 Ok(Term::App(
894 Box::new(Term::App(
895 Box::new(Term::App(
896 Box::new(Term::Global("try_induction".to_string())),
897 Box::new(ind_type),
898 )),
899 Box::new(motive),
900 )),
901 Box::new(case_chain),
902 ))
903 }
904
905 fn parse_function_params(&mut self) -> Result<Vec<(String, Term)>, ParseError> {
907 let mut params = Vec::new();
908
909 loop {
910 self.skip_whitespace();
911
912 if !self.peek_char('(') {
914 break;
915 }
916
917 self.advance(); self.skip_whitespace();
920
921 let param_name = self.parse_ident()?;
922 self.skip_whitespace();
923
924 if !self.try_consume(":") {
925 return Err(ParseError::Expected {
926 expected: "':'".to_string(),
927 found: self.peek_word().unwrap_or("EOF".to_string()),
928 });
929 }
930 self.skip_whitespace();
931
932 let param_type = self.parse_type()?;
933 self.skip_whitespace();
934
935 if !self.try_consume(")") {
936 return Err(ParseError::Expected {
937 expected: "')'".to_string(),
938 found: self.peek_word().unwrap_or("EOF".to_string()),
939 });
940 }
941
942 params.push((param_name, param_type));
943
944 self.skip_whitespace();
945
946 let _ = self.try_consume_keyword("and");
948 }
949
950 Ok(params)
951 }
952
953 fn parse_param_list(&mut self) -> Result<Vec<(String, Term)>, ParseError> {
955 let mut params = Vec::new();
956
957 if !self.peek_char('(') {
958 return Ok(params);
959 }
960
961 self.advance(); self.skip_whitespace();
963
964 loop {
965 let param_name = self.parse_ident()?;
966 self.skip_whitespace();
967
968 if !self.try_consume(":") {
969 return Err(ParseError::Expected {
970 expected: "':'".to_string(),
971 found: self.peek_word().unwrap_or("EOF".to_string()),
972 });
973 }
974 self.skip_whitespace();
975
976 let param_type = self.parse_type()?;
977 params.push((param_name, param_type));
978
979 self.skip_whitespace();
980
981 if self.try_consume(")") {
982 break;
983 }
984
985 if !self.try_consume(",") && !self.try_consume_keyword("and") {
986 return Err(ParseError::Expected {
987 expected: "')' or ','".to_string(),
988 found: self.peek_word().unwrap_or("EOF".to_string()),
989 });
990 }
991 self.skip_whitespace();
992 }
993
994 Ok(params)
995 }
996
997 fn parse_body(&mut self) -> Result<Term, ParseError> {
1003 self.skip_whitespace();
1004
1005 if self.peek_keyword("Consider") {
1007 return self.parse_consider();
1008 }
1009
1010 if self.peek_keyword("Yield") {
1012 return self.parse_yield();
1013 }
1014
1015 if self.peek_keyword("given") {
1017 return self.parse_given_lambda();
1018 }
1019
1020 if self.peek_char('|') {
1022 return self.parse_pipe_lambda();
1023 }
1024
1025 self.parse_term()
1027 }
1028
1029 fn parse_consider(&mut self) -> Result<Term, ParseError> {
1031 self.consume_keyword("Consider")?;
1032 self.skip_whitespace();
1033
1034 let discriminant = self.parse_term()?;
1036
1037 self.skip_whitespace();
1038
1039 if !self.try_consume(":") {
1041 return Err(ParseError::Expected {
1042 expected: "':'".to_string(),
1043 found: self.peek_word().unwrap_or("EOF".to_string()),
1044 });
1045 }
1046
1047 let mut cases = Vec::new();
1049 let motive = self.return_type.clone().unwrap_or_else(|| Term::Sort(Universe::Type(0)));
1052
1053 loop {
1054 self.skip_whitespace_and_newlines();
1055
1056 if !self.peek_keyword("When") {
1057 break;
1058 }
1059
1060 self.consume_keyword("When")?;
1061 self.skip_whitespace();
1062
1063 let ctor_name = self.parse_ident()?;
1065 self.skip_whitespace();
1066
1067 let mut binders = Vec::new();
1069 while !self.peek_char(':') && !self.at_end() {
1070 let binder = self.parse_ident()?;
1071 binders.push(binder);
1072 self.skip_whitespace();
1073 }
1074
1075 if !self.try_consume(":") {
1077 return Err(ParseError::Expected {
1078 expected: "':'".to_string(),
1079 found: self.peek_word().unwrap_or("EOF".to_string()),
1080 });
1081 }
1082
1083 self.skip_whitespace();
1084
1085 for binder in &binders {
1087 self.bound_vars.insert(binder.clone());
1088 }
1089
1090 let case_body = self.parse_body()?;
1092
1093 for binder in &binders {
1095 self.bound_vars.remove(binder);
1096 }
1097
1098 let mut wrapped_body = case_body;
1100 for binder in binders.into_iter().rev() {
1101 wrapped_body = Term::Lambda {
1102 param: binder,
1103 param_type: Box::new(Term::Global("_".to_string())), body: Box::new(wrapped_body),
1105 };
1106 }
1107
1108 cases.push(wrapped_body);
1109
1110 self.skip_whitespace();
1112 let _ = self.try_consume(".");
1113 }
1114
1115 if cases.is_empty() {
1116 return Err(ParseError::Missing("When clauses".to_string()));
1117 }
1118
1119 if let Term::Var(ref _v) = discriminant {
1121 }
1123
1124 Ok(Term::Match {
1125 discriminant: Box::new(discriminant),
1126 motive: Box::new(motive),
1127 cases,
1128 })
1129 }
1130
1131 fn parse_yield(&mut self) -> Result<Term, ParseError> {
1133 self.consume_keyword("Yield")?;
1134 self.skip_whitespace();
1135 self.parse_term()
1136 }
1137
1138 fn parse_given_lambda(&mut self) -> Result<Term, ParseError> {
1140 self.consume_keyword("given")?;
1141 self.skip_whitespace();
1142
1143 let param = self.parse_ident()?;
1144 self.skip_whitespace();
1145
1146 if !self.try_consume(":") {
1147 return Err(ParseError::Expected {
1148 expected: "':'".to_string(),
1149 found: self.peek_word().unwrap_or("EOF".to_string()),
1150 });
1151 }
1152 self.skip_whitespace();
1153
1154 let param_type = self.parse_type()?;
1155 self.skip_whitespace();
1156
1157 self.consume_keyword("yields")?;
1158 self.skip_whitespace();
1159
1160 self.bound_vars.insert(param.clone());
1161 let body = self.parse_term()?;
1162 self.bound_vars.remove(¶m);
1163
1164 Ok(Term::Lambda {
1165 param,
1166 param_type: Box::new(param_type),
1167 body: Box::new(body),
1168 })
1169 }
1170
1171 fn parse_pipe_lambda(&mut self) -> Result<Term, ParseError> {
1173 self.advance(); self.skip_whitespace();
1175
1176 let param = self.parse_ident()?;
1177 self.skip_whitespace();
1178
1179 if !self.try_consume(":") {
1180 return Err(ParseError::Expected {
1181 expected: "':'".to_string(),
1182 found: self.peek_word().unwrap_or("EOF".to_string()),
1183 });
1184 }
1185 self.skip_whitespace();
1186
1187 let param_type = self.parse_type()?;
1188 self.skip_whitespace();
1189
1190 if !self.try_consume("|") {
1191 return Err(ParseError::Expected {
1192 expected: "'|'".to_string(),
1193 found: self.peek_word().unwrap_or("EOF".to_string()),
1194 });
1195 }
1196 self.skip_whitespace();
1197
1198 if !self.try_consume("->") {
1199 return Err(ParseError::Expected {
1200 expected: "'->'".to_string(),
1201 found: self.peek_word().unwrap_or("EOF".to_string()),
1202 });
1203 }
1204 self.skip_whitespace();
1205
1206 self.bound_vars.insert(param.clone());
1207 let body = self.parse_term()?;
1208 self.bound_vars.remove(¶m);
1209
1210 Ok(Term::Lambda {
1211 param,
1212 param_type: Box::new(param_type),
1213 body: Box::new(body),
1214 })
1215 }
1216
1217 fn parse_term(&mut self) -> Result<Term, ParseError> {
1219 let lhs = self.parse_comparison()?;
1220
1221 self.skip_whitespace();
1222
1223 if self.peek_keyword("equals") {
1225 self.consume_keyword("equals")?;
1226 self.skip_whitespace();
1227 let rhs = self.parse_comparison()?; return Ok(Term::App(
1229 Box::new(Term::App(
1230 Box::new(Term::App(
1231 Box::new(Term::Global("Eq".to_string())),
1232 Box::new(Term::Hole), )),
1234 Box::new(lhs),
1235 )),
1236 Box::new(rhs),
1237 ));
1238 }
1239
1240 if self.peek_keyword("implies") {
1242 self.consume_keyword("implies")?;
1243 self.skip_whitespace();
1244 let rhs = self.parse_term()?; return Ok(Term::Pi {
1246 param: "_".to_string(),
1247 param_type: Box::new(lhs),
1248 body_type: Box::new(rhs),
1249 });
1250 }
1251
1252 Ok(lhs)
1253 }
1254
1255 fn parse_comparison(&mut self) -> Result<Term, ParseError> {
1263 let lhs = self.parse_additive()?;
1264 self.skip_whitespace();
1265
1266 let op_name = if self.try_consume("<=") || self.try_consume("≤") {
1268 Some("le")
1269 } else if self.try_consume(">=") || self.try_consume("≥") {
1270 Some("ge")
1271 } else if self.try_consume("<") {
1272 Some("lt")
1273 } else if self.try_consume(">") {
1274 Some("gt")
1275 } else {
1276 None
1277 };
1278
1279 if let Some(op) = op_name {
1280 self.skip_whitespace();
1281 let rhs = self.parse_additive()?; return Ok(Term::App(
1283 Box::new(Term::App(
1284 Box::new(Term::Global(op.to_string())),
1285 Box::new(lhs),
1286 )),
1287 Box::new(rhs),
1288 ));
1289 }
1290
1291 Ok(lhs)
1292 }
1293
1294 fn parse_additive(&mut self) -> Result<Term, ParseError> {
1297 let mut result = self.parse_multiplicative()?;
1298
1299 loop {
1300 self.skip_whitespace();
1301
1302 let op_name = if self.try_consume("+") {
1303 Some("add")
1304 } else if self.peek_char('-') && !self.peek_arrow() && !self.peek_negative_number() {
1305 self.advance(); Some("sub")
1307 } else {
1308 None
1309 };
1310
1311 if let Some(op) = op_name {
1312 self.skip_whitespace();
1313 let rhs = self.parse_multiplicative()?;
1314 result = Term::App(
1315 Box::new(Term::App(
1316 Box::new(Term::Global(op.to_string())),
1317 Box::new(result),
1318 )),
1319 Box::new(rhs),
1320 );
1321 } else {
1322 break;
1323 }
1324 }
1325
1326 Ok(result)
1327 }
1328
1329 fn parse_multiplicative(&mut self) -> Result<Term, ParseError> {
1332 let mut result = self.parse_app()?;
1333
1334 loop {
1335 self.skip_whitespace();
1336
1337 if self.try_consume("*") {
1338 self.skip_whitespace();
1339 let rhs = self.parse_app()?;
1340 result = Term::App(
1341 Box::new(Term::App(
1342 Box::new(Term::Global("mul".to_string())),
1343 Box::new(result),
1344 )),
1345 Box::new(rhs),
1346 );
1347 } else {
1348 break;
1349 }
1350 }
1351
1352 Ok(result)
1353 }
1354
1355 fn parse_app(&mut self) -> Result<Term, ParseError> {
1357 let mut func = self.parse_atom()?;
1358
1359 loop {
1360 self.skip_whitespace();
1361
1362 if self.peek_char('(') {
1364 self.advance(); self.skip_whitespace();
1366
1367 if !self.peek_char(')') {
1368 loop {
1369 let arg = self.parse_term()?;
1370 func = Term::App(Box::new(func), Box::new(arg));
1371 self.skip_whitespace();
1372
1373 if self.try_consume(",") {
1374 self.skip_whitespace();
1375 } else {
1376 break;
1377 }
1378 }
1379 }
1380
1381 if !self.try_consume(")") {
1382 return Err(ParseError::Expected {
1383 expected: "')'".to_string(),
1384 found: self.peek_word().unwrap_or("EOF".to_string()),
1385 });
1386 }
1387 continue;
1388 }
1389
1390 if self.at_end()
1393 || self.peek_char(')')
1394 || self.peek_char('.')
1395 || self.peek_char(',')
1396 || self.peek_char(':')
1397 || self.peek_char('|')
1398 || self.peek_keyword("When")
1399 || self.peek_keyword("Yield")
1400 || self.peek_keyword("and")
1401 || self.peek_keyword("or")
1402 || self.peek_keyword("equals")
1403 || self.peek_keyword("implies")
1404 || self.peek_char('+')
1406 || self.peek_char('*')
1407 || self.peek_comparison_operator()
1408 || (self.peek_char('-') && !self.peek_arrow() && !self.peek_negative_number())
1409 {
1410 break;
1411 }
1412
1413 if let Ok(arg) = self.parse_atom() {
1415 func = Term::App(Box::new(func), Box::new(arg));
1416 } else {
1417 break;
1418 }
1419 }
1420
1421 Ok(func)
1422 }
1423
1424 fn parse_atom(&mut self) -> Result<Term, ParseError> {
1426 self.skip_whitespace();
1427
1428 if let Some(c) = self.peek() {
1430 if c.is_ascii_digit() {
1431 return self.parse_number();
1432 }
1433 if c == '-' {
1434 let saved_pos = self.pos;
1436 self.advance();
1437 if let Some(next) = self.peek() {
1438 if next.is_ascii_digit() {
1439 self.pos = saved_pos;
1440 return self.parse_number();
1441 }
1442 }
1443 self.pos = saved_pos;
1444 }
1445 }
1446
1447 if self.peek_char('"') {
1449 return self.parse_string();
1450 }
1451
1452 if self.peek_char('(') {
1454 self.advance();
1455 let term = self.parse_term()?;
1456 self.skip_whitespace();
1457 if !self.try_consume(")") {
1458 return Err(ParseError::Expected {
1459 expected: "')'".to_string(),
1460 found: self.peek_word().unwrap_or("EOF".to_string()),
1461 });
1462 }
1463 return Ok(term);
1464 }
1465
1466 if self.try_consume_keyword("the") {
1468 self.skip_whitespace();
1469 if self.try_consume_keyword("diagonalization") {
1471 self.skip_whitespace();
1472 if !self.try_consume_keyword("of") {
1473 return Err(ParseError::Expected {
1474 expected: "'of'".to_string(),
1475 found: self.peek_word().unwrap_or("EOF".to_string()),
1476 });
1477 }
1478 self.skip_whitespace();
1479 let arg = self.parse_atom()?;
1480 return Ok(Term::App(
1481 Box::new(Term::Global("syn_diag".to_string())),
1482 Box::new(arg),
1483 ));
1484 }
1485 if self.peek_keyword("Name") {
1487 self.consume_keyword("Name")?;
1488 self.skip_whitespace();
1489 let arg = self.parse_atom()?;
1490 return Ok(Term::App(
1491 Box::new(Term::Global("SName".to_string())),
1492 Box::new(arg),
1493 ));
1494 }
1495 }
1497
1498 if self.peek_keyword("Name") {
1500 self.consume_keyword("Name")?;
1501 self.skip_whitespace();
1502 let arg = self.parse_atom()?;
1503 return Ok(Term::App(
1504 Box::new(Term::Global("SName".to_string())),
1505 Box::new(arg),
1506 ));
1507 }
1508
1509 if self.peek_keyword("Variable") {
1511 self.consume_keyword("Variable")?;
1512 self.skip_whitespace();
1513 let arg = self.parse_atom()?;
1514 return Ok(Term::App(
1515 Box::new(Term::Global("SVar".to_string())),
1516 Box::new(arg),
1517 ));
1518 }
1519
1520 if self.peek_keyword("Apply") {
1522 self.consume_keyword("Apply")?;
1523 self.skip_whitespace();
1524 if !self.try_consume("(") {
1525 return Err(ParseError::Expected {
1526 expected: "'('".to_string(),
1527 found: self.peek_word().unwrap_or("EOF".to_string()),
1528 });
1529 }
1530 self.skip_whitespace();
1531 let func_arg = self.parse_term()?;
1532 self.skip_whitespace();
1533 if !self.try_consume(",") {
1534 return Err(ParseError::Expected {
1535 expected: "','".to_string(),
1536 found: self.peek_word().unwrap_or("EOF".to_string()),
1537 });
1538 }
1539 self.skip_whitespace();
1540 let arg_arg = self.parse_term()?;
1541 self.skip_whitespace();
1542 if !self.try_consume(")") {
1543 return Err(ParseError::Expected {
1544 expected: "')'".to_string(),
1545 found: self.peek_word().unwrap_or("EOF".to_string()),
1546 });
1547 }
1548 return Ok(Term::App(
1549 Box::new(Term::App(
1550 Box::new(Term::Global("SApp".to_string())),
1551 Box::new(func_arg),
1552 )),
1553 Box::new(arg_arg),
1554 ));
1555 }
1556
1557 if self.peek_keyword("there") {
1559 return self.parse_existential();
1560 }
1561
1562 let ident = self.parse_ident()?;
1564
1565 self.skip_whitespace();
1567 if self.try_consume_keyword("of") {
1568 self.skip_whitespace();
1569 let arg = self.parse_atom()?;
1570 let func = if self.bound_vars.contains(&ident) {
1571 Term::Var(ident)
1572 } else {
1573 Term::Global(ident)
1574 };
1575 return Ok(Term::App(Box::new(func), Box::new(arg)));
1576 }
1577
1578 if self.bound_vars.contains(&ident) || self.current_function.as_ref() == Some(&ident) {
1580 Ok(Term::Var(ident))
1581 } else {
1582 match ident.as_str() {
1584 "Prop" => Ok(Term::Sort(Universe::Prop)),
1585 "Type" => Ok(Term::Sort(Universe::Type(0))),
1586 _ => Ok(Term::Global(ident)),
1587 }
1588 }
1589 }
1590
1591 fn parse_existential(&mut self) -> Result<Term, ParseError> {
1594 self.consume_keyword("there")?;
1595 self.skip_whitespace();
1596 self.consume_keyword("exists")?;
1597 self.skip_whitespace();
1598
1599 let _ = self.try_consume_keyword("an") || self.try_consume_keyword("a");
1601 self.skip_whitespace();
1602
1603 let var_name = self.parse_ident()?;
1605 self.skip_whitespace();
1606
1607 if !self.try_consume(":") {
1609 return Err(ParseError::Expected {
1610 expected: "':'".to_string(),
1611 found: self.peek_word().unwrap_or("EOF".to_string()),
1612 });
1613 }
1614 self.skip_whitespace();
1615
1616 let var_type = self.parse_type()?;
1618 self.skip_whitespace();
1619
1620 if !self.try_consume_keyword("such") {
1622 return Err(ParseError::Expected {
1623 expected: "'such'".to_string(),
1624 found: self.peek_word().unwrap_or("EOF".to_string()),
1625 });
1626 }
1627 self.skip_whitespace();
1628 if !self.try_consume_keyword("that") {
1629 return Err(ParseError::Expected {
1630 expected: "'that'".to_string(),
1631 found: self.peek_word().unwrap_or("EOF".to_string()),
1632 });
1633 }
1634 self.skip_whitespace();
1635
1636 self.bound_vars.insert(var_name.clone());
1638 let body = self.parse_term()?;
1639 self.bound_vars.remove(&var_name);
1640
1641 Ok(Term::App(
1643 Box::new(Term::App(
1644 Box::new(Term::Global("Ex".to_string())),
1645 Box::new(var_type),
1646 )),
1647 Box::new(Term::Lambda {
1648 param: var_name,
1649 param_type: Box::new(Term::Global("_".to_string())), body: Box::new(body),
1651 }),
1652 ))
1653 }
1654
1655 fn parse_type(&mut self) -> Result<Term, ParseError> {
1657 self.skip_whitespace();
1658
1659 let base = self.parse_ident()?;
1661
1662 self.skip_whitespace();
1663
1664 if self.try_consume_keyword("of") {
1666 self.skip_whitespace();
1667 let arg = self.parse_type()?;
1668 return Ok(Term::App(
1669 Box::new(Term::Global(base)),
1670 Box::new(arg),
1671 ));
1672 }
1673
1674 match base.as_str() {
1676 "Prop" => Ok(Term::Sort(Universe::Prop)),
1677 "Type" => Ok(Term::Sort(Universe::Type(0))),
1678 _ => Ok(Term::Global(base)),
1679 }
1680 }
1681
1682 fn parse_number(&mut self) -> Result<Term, ParseError> {
1684 let mut num_str = String::new();
1685
1686 if self.peek_char('-') {
1688 num_str.push('-');
1689 self.advance();
1690 }
1691
1692 while let Some(c) = self.peek() {
1694 if c.is_ascii_digit() {
1695 num_str.push(c);
1696 self.advance();
1697 } else {
1698 break;
1699 }
1700 }
1701
1702 let value: i64 = num_str
1703 .parse()
1704 .map_err(|_| ParseError::InvalidNumber(num_str))?;
1705
1706 Ok(Term::Lit(Literal::Int(value)))
1707 }
1708
1709 fn parse_string(&mut self) -> Result<Term, ParseError> {
1711 self.advance(); let mut content = String::new();
1714 loop {
1715 match self.peek() {
1716 Some('"') => {
1717 self.advance();
1718 break;
1719 }
1720 Some('\\') => {
1721 self.advance();
1722 match self.peek() {
1723 Some('n') => {
1724 content.push('\n');
1725 self.advance();
1726 }
1727 Some('t') => {
1728 content.push('\t');
1729 self.advance();
1730 }
1731 Some(c) => {
1732 content.push(c);
1733 self.advance();
1734 }
1735 None => return Err(ParseError::UnexpectedEof),
1736 }
1737 }
1738 Some(c) => {
1739 content.push(c);
1740 self.advance();
1741 }
1742 None => return Err(ParseError::UnexpectedEof),
1743 }
1744 }
1745
1746 Ok(Term::Lit(Literal::Text(content)))
1747 }
1748
1749 fn term_to_syntax(&self, term: &Term, bound_vars: &[String]) -> Term {
1756 match term {
1757 Term::Var(name) => {
1758 if let Some(idx) = bound_vars.iter().rev().position(|n| n == name) {
1760 Term::App(
1761 Box::new(Term::Global("SVar".to_string())),
1762 Box::new(Term::Lit(Literal::Int(idx as i64))),
1763 )
1764 } else {
1765 Term::App(
1767 Box::new(Term::Global("SName".to_string())),
1768 Box::new(Term::Lit(Literal::Text(name.clone()))),
1769 )
1770 }
1771 }
1772 Term::Global(name) => {
1773 Term::App(
1775 Box::new(Term::Global("SName".to_string())),
1776 Box::new(Term::Lit(Literal::Text(name.clone()))),
1777 )
1778 }
1779 Term::Const { name, .. } => {
1780 Term::App(
1783 Box::new(Term::Global("SName".to_string())),
1784 Box::new(Term::Lit(Literal::Text(name.clone()))),
1785 )
1786 }
1787 Term::Lit(Literal::Int(n)) => {
1788 Term::App(
1790 Box::new(Term::Global("SLit".to_string())),
1791 Box::new(Term::Lit(Literal::Int(*n))),
1792 )
1793 }
1794 Term::Lit(Literal::Float(_f)) => {
1795 Term::App(
1797 Box::new(Term::Global("SName".to_string())),
1798 Box::new(Term::Lit(Literal::Text("Error_Float".to_string()))),
1799 )
1800 }
1801 Term::Lit(Literal::BigInt(_)) => {
1802 Term::App(
1804 Box::new(Term::Global("SName".to_string())),
1805 Box::new(Term::Lit(Literal::Text("Error_BigInt".to_string()))),
1806 )
1807 }
1808 Term::Lit(Literal::Nat(_)) => {
1809 Term::App(
1811 Box::new(Term::Global("SName".to_string())),
1812 Box::new(Term::Lit(Literal::Text("Error_Nat".to_string()))),
1813 )
1814 }
1815 Term::Lit(Literal::Duration(_d)) => {
1816 Term::App(
1818 Box::new(Term::Global("SName".to_string())),
1819 Box::new(Term::Lit(Literal::Text("Error_Duration".to_string()))),
1820 )
1821 }
1822 Term::Lit(Literal::Date(_d)) => {
1823 Term::App(
1825 Box::new(Term::Global("SName".to_string())),
1826 Box::new(Term::Lit(Literal::Text("Error_Date".to_string()))),
1827 )
1828 }
1829 Term::Lit(Literal::Moment(_m)) => {
1830 Term::App(
1832 Box::new(Term::Global("SName".to_string())),
1833 Box::new(Term::Lit(Literal::Text("Error_Moment".to_string()))),
1834 )
1835 }
1836 Term::Lit(Literal::Text(s)) => {
1837 Term::App(
1839 Box::new(Term::Global("SName".to_string())),
1840 Box::new(Term::Lit(Literal::Text(s.clone()))),
1841 )
1842 }
1843 Term::App(f, x) => {
1844 let f_syn = self.term_to_syntax(f, bound_vars);
1846 let x_syn = self.term_to_syntax(x, bound_vars);
1847 Term::App(
1848 Box::new(Term::App(
1849 Box::new(Term::Global("SApp".to_string())),
1850 Box::new(f_syn),
1851 )),
1852 Box::new(x_syn),
1853 )
1854 }
1855 Term::Lambda { param, param_type, body } => {
1856 let ty_syn = self.term_to_syntax(param_type, bound_vars);
1858 let mut new_bound = bound_vars.to_vec();
1859 new_bound.push(param.clone());
1860 let body_syn = self.term_to_syntax(body, &new_bound);
1861 Term::App(
1862 Box::new(Term::App(
1863 Box::new(Term::Global("SLam".to_string())),
1864 Box::new(ty_syn),
1865 )),
1866 Box::new(body_syn),
1867 )
1868 }
1869 Term::Pi { param, param_type, body_type } => {
1870 let ty_syn = self.term_to_syntax(param_type, bound_vars);
1872 let mut new_bound = bound_vars.to_vec();
1873 new_bound.push(param.clone());
1874 let body_syn = self.term_to_syntax(body_type, &new_bound);
1875 Term::App(
1876 Box::new(Term::App(
1877 Box::new(Term::Global("SPi".to_string())),
1878 Box::new(ty_syn),
1879 )),
1880 Box::new(body_syn),
1881 )
1882 }
1883 Term::Sort(Universe::Prop) => {
1884 Term::App(
1886 Box::new(Term::Global("SSort".to_string())),
1887 Box::new(Term::Global("UProp".to_string())),
1888 )
1889 }
1890 Term::Sort(Universe::Type(n)) => {
1891 Term::App(
1893 Box::new(Term::Global("SSort".to_string())),
1894 Box::new(Term::App(
1895 Box::new(Term::Global("UType".to_string())),
1896 Box::new(Term::Lit(Literal::Int(*n as i64))),
1897 )),
1898 )
1899 }
1900 Term::Sort(_) => {
1901 Term::App(
1904 Box::new(Term::Global("SSort".to_string())),
1905 Box::new(Term::Global("UPoly".to_string())),
1906 )
1907 }
1908 Term::Hole => {
1909 Term::App(
1911 Box::new(Term::Global("SName".to_string())),
1912 Box::new(Term::Lit(Literal::Text("Int".to_string()))),
1913 )
1914 }
1915 Term::Match { .. } | Term::Fix { .. } | Term::MutualFix { .. } | Term::Let { .. } => {
1916 Term::App(
1918 Box::new(Term::Global("SName".to_string())),
1919 Box::new(Term::Lit(Literal::Text("Error".to_string()))),
1920 )
1921 }
1922 }
1923 }
1924
1925 fn contains_self_reference(&self, name: &str, term: &Term) -> bool {
1931 match term {
1932 Term::Var(v) => v == name,
1933 Term::Global(_) => false,
1934 Term::Const { .. } => false,
1935 Term::Sort(_) => false,
1936 Term::Lit(_) => false,
1937 Term::Pi { param_type, body_type, .. } => {
1938 self.contains_self_reference(name, param_type)
1939 || self.contains_self_reference(name, body_type)
1940 }
1941 Term::Lambda { param_type, body, .. } => {
1942 self.contains_self_reference(name, param_type)
1943 || self.contains_self_reference(name, body)
1944 }
1945 Term::App(f, a) => {
1946 self.contains_self_reference(name, f) || self.contains_self_reference(name, a)
1947 }
1948 Term::Match { discriminant, motive, cases } => {
1949 self.contains_self_reference(name, discriminant)
1950 || self.contains_self_reference(name, motive)
1951 || cases.iter().any(|c| self.contains_self_reference(name, c))
1952 }
1953 Term::Fix { body, .. } => self.contains_self_reference(name, body),
1954 Term::MutualFix { defs, .. } => {
1955 defs.iter().any(|(_, b)| self.contains_self_reference(name, b))
1956 }
1957 Term::Let { ty, value, body, .. } => {
1958 self.contains_self_reference(name, ty)
1959 || self.contains_self_reference(name, value)
1960 || self.contains_self_reference(name, body)
1961 }
1962 Term::Hole => false, }
1964 }
1965
1966 fn skip_whitespace(&mut self) {
1971 while let Some(c) = self.peek() {
1972 if c == ' ' || c == '\t' {
1973 self.advance();
1974 } else {
1975 break;
1976 }
1977 }
1978 }
1979
1980 fn skip_whitespace_and_newlines(&mut self) {
1981 while let Some(c) = self.peek() {
1982 if c.is_whitespace() {
1983 self.advance();
1984 } else {
1985 break;
1986 }
1987 }
1988 }
1989
1990 fn peek(&self) -> Option<char> {
1991 self.input[self.pos..].chars().next()
1992 }
1993
1994 fn peek_char(&self, c: char) -> bool {
1995 self.peek() == Some(c)
1996 }
1997
1998 fn peek_keyword(&self, keyword: &str) -> bool {
1999 if !self.input[self.pos..].starts_with(keyword) {
2000 return false;
2001 }
2002 let after = self.pos + keyword.len();
2003 if after >= self.input.len() {
2004 return true;
2005 }
2006 let next_char = self.input[after..].chars().next();
2007 !next_char.map(|c| c.is_alphanumeric() || c == '_').unwrap_or(false)
2008 }
2009
2010 fn peek_word(&self) -> Option<String> {
2011 let start = self.pos;
2012 let mut end = start;
2013 for c in self.input[start..].chars() {
2014 if c.is_alphanumeric() || c == '_' {
2015 end += c.len_utf8();
2016 } else {
2017 break;
2018 }
2019 }
2020 if end > start {
2021 Some(self.input[start..end].to_string())
2022 } else {
2023 self.peek().map(|c| c.to_string())
2024 }
2025 }
2026
2027 fn advance(&mut self) {
2028 if let Some(c) = self.peek() {
2029 self.pos += c.len_utf8();
2030 }
2031 }
2032
2033 fn at_end(&self) -> bool {
2034 self.pos >= self.input.len()
2035 }
2036
2037 fn try_consume(&mut self, s: &str) -> bool {
2038 if self.input[self.pos..].starts_with(s) {
2039 self.pos += s.len();
2040 true
2041 } else {
2042 false
2043 }
2044 }
2045
2046 fn try_consume_keyword(&mut self, keyword: &str) -> bool {
2047 if self.peek_keyword(keyword) {
2048 self.pos += keyword.len();
2049 true
2050 } else {
2051 false
2052 }
2053 }
2054
2055 fn consume_keyword(&mut self, keyword: &str) -> Result<(), ParseError> {
2056 if self.try_consume_keyword(keyword) {
2057 Ok(())
2058 } else {
2059 Err(ParseError::Expected {
2060 expected: format!("'{}'", keyword),
2061 found: self.peek_word().unwrap_or("EOF".to_string()),
2062 })
2063 }
2064 }
2065
2066 fn parse_ident(&mut self) -> Result<String, ParseError> {
2067 self.skip_whitespace();
2068 let start = self.pos;
2069
2070 if let Some(c) = self.peek() {
2072 if !c.is_alphabetic() && c != '_' {
2073 return Err(ParseError::Expected {
2074 expected: "identifier".to_string(),
2075 found: c.to_string(),
2076 });
2077 }
2078 } else {
2079 return Err(ParseError::UnexpectedEof);
2080 }
2081
2082 while let Some(c) = self.peek() {
2084 if c.is_alphanumeric() || c == '_' {
2085 self.advance();
2086 } else {
2087 break;
2088 }
2089 }
2090
2091 let ident = self.input[start..self.pos].to_string();
2092 if ident.is_empty() {
2093 Err(ParseError::InvalidIdent("empty".to_string()))
2094 } else {
2095 Ok(ident)
2096 }
2097 }
2098
2099 fn peek_negative_number(&self) -> bool {
2105 if !self.peek_char('-') {
2106 return false;
2107 }
2108 self.input.get(self.pos + 1..)
2109 .and_then(|s| s.chars().next())
2110 .map(|c| c.is_ascii_digit())
2111 .unwrap_or(false)
2112 }
2113
2114 fn peek_arrow(&self) -> bool {
2116 self.input[self.pos..].starts_with("->")
2117 }
2118
2119 fn peek_comparison_operator(&self) -> bool {
2121 let rest = &self.input[self.pos..];
2122 rest.starts_with("<=") || rest.starts_with(">=")
2123 || rest.starts_with("≤") || rest.starts_with("≥")
2124 || rest.starts_with('<') || rest.starts_with('>')
2125 }
2126}
2127
2128#[cfg(test)]
2133mod tests {
2134 use super::*;
2135
2136 #[test]
2137 fn test_parse_simple_inductive() {
2138 let cmd = parse_inductive("A Bool is either Yes or No").unwrap();
2139 if let Command::Inductive { name, constructors, .. } = cmd {
2140 assert_eq!(name, "Bool");
2141 assert_eq!(constructors.len(), 2);
2142 assert_eq!(constructors[0].0, "Yes");
2143 assert_eq!(constructors[1].0, "No");
2144 } else {
2145 panic!("Expected Inductive command");
2146 }
2147 }
2148
2149 #[test]
2150 fn test_parse_inductive_with_article() {
2151 let cmd = parse_inductive("A Decision is either a Yes or a No").unwrap();
2152 if let Command::Inductive { name, constructors, .. } = cmd {
2153 assert_eq!(name, "Decision");
2154 assert_eq!(constructors.len(), 2);
2155 } else {
2156 panic!("Expected Inductive command");
2157 }
2158 }
2159
2160 #[test]
2161 fn test_parse_recursive_inductive() {
2162 let cmd = parse_inductive("A Nat is either Zero or a Succ with pred: Nat").unwrap();
2163 if let Command::Inductive { name, constructors, .. } = cmd {
2164 assert_eq!(name, "Nat");
2165 assert_eq!(constructors.len(), 2);
2166 assert_eq!(constructors[0].0, "Zero");
2167 assert_eq!(constructors[1].0, "Succ");
2168 if let Term::Pi { .. } = &constructors[1].1 {
2170 } else {
2172 panic!("Expected Succ to have Pi type");
2173 }
2174 } else {
2175 panic!("Expected Inductive command");
2176 }
2177 }
2178
2179 #[test]
2180 fn test_parse_simple_definition() {
2181 let cmd = parse_definition("## To id (x: Nat) -> Nat: Yield x").unwrap();
2182 if let Command::Definition { name, body, .. } = cmd {
2183 assert_eq!(name, "id");
2184 if let Term::Lambda { param, .. } = body {
2186 assert_eq!(param, "x");
2187 } else {
2188 panic!("Expected Lambda body");
2189 }
2190 } else {
2191 panic!("Expected Definition command");
2192 }
2193 }
2194
2195 #[test]
2196 fn test_implicit_fixpoint_detection() {
2197 let cmd = parse_definition(
2199 "## To add (n: Nat) and (m: Nat) -> Nat: Consider n: When Zero: Yield m. When Succ k: Yield Succ (add k m)."
2200 ).unwrap();
2201
2202 if let Command::Definition { name, body, .. } = cmd {
2203 assert_eq!(name, "add");
2204 if let Term::Fix { name: fix_name, .. } = body {
2206 assert_eq!(fix_name, "add");
2207 } else {
2208 panic!("Expected Fix wrapper for recursive function");
2209 }
2210 } else {
2211 panic!("Expected Definition command");
2212 }
2213 }
2214
2215 #[test]
2216 fn test_parse_given_lambda() {
2217 let mut parser = LiterateParser::new("given x: Nat yields Succ x");
2218 let term = parser.parse_given_lambda().unwrap();
2219
2220 if let Term::Lambda { param, .. } = term {
2221 assert_eq!(param, "x");
2222 } else {
2223 panic!("Expected Lambda");
2224 }
2225 }
2226
2227 #[test]
2228 fn test_parse_pipe_lambda() {
2229 let mut parser = LiterateParser::new("|x: Nat| -> Succ x");
2230 let term = parser.parse_pipe_lambda().unwrap();
2231
2232 if let Term::Lambda { param, .. } = term {
2233 assert_eq!(param, "x");
2234 } else {
2235 panic!("Expected Lambda");
2236 }
2237 }
2238
2239 #[test]
2244 fn test_parse_let_definition() {
2245 let cmd = parse_let_definition("Let T be Zero").unwrap();
2246 if let Command::Definition { name, ty, body, .. } = cmd {
2247 assert_eq!(name, "T");
2248 assert!(ty.is_none());
2249 if let Term::Global(g) = body {
2250 assert_eq!(g, "Zero");
2251 } else {
2252 panic!("Expected Global term");
2253 }
2254 } else {
2255 panic!("Expected Definition command");
2256 }
2257 }
2258
2259 #[test]
2260 fn test_parse_name_syntax() {
2261 let mut parser = LiterateParser::new("Name \"Not\"");
2262 let term = parser.parse_term().unwrap();
2263
2264 if let Term::App(f, arg) = term {
2266 if let Term::Global(g) = *f {
2267 assert_eq!(g, "SName");
2268 } else {
2269 panic!("Expected Global SName");
2270 }
2271 if let Term::Lit(Literal::Text(s)) = *arg {
2272 assert_eq!(s, "Not");
2273 } else {
2274 panic!("Expected Text literal");
2275 }
2276 } else {
2277 panic!("Expected App");
2278 }
2279 }
2280
2281 #[test]
2282 fn test_parse_variable_syntax() {
2283 let mut parser = LiterateParser::new("Variable 0");
2284 let term = parser.parse_term().unwrap();
2285
2286 if let Term::App(f, arg) = term {
2288 if let Term::Global(g) = *f {
2289 assert_eq!(g, "SVar");
2290 } else {
2291 panic!("Expected Global SVar");
2292 }
2293 if let Term::Lit(Literal::Int(n)) = *arg {
2294 assert_eq!(n, 0);
2295 } else {
2296 panic!("Expected Int literal");
2297 }
2298 } else {
2299 panic!("Expected App");
2300 }
2301 }
2302
2303 #[test]
2304 fn test_parse_apply_syntax() {
2305 let mut parser = LiterateParser::new("Apply(Name \"Not\", Variable 0)");
2306 let term = parser.parse_term().unwrap();
2307
2308 if let Term::App(outer_f, _outer_arg) = term {
2310 if let Term::App(inner_f, _inner_arg) = *outer_f {
2311 if let Term::Global(g) = *inner_f {
2312 assert_eq!(g, "SApp");
2313 } else {
2314 panic!("Expected Global SApp");
2315 }
2316 } else {
2317 panic!("Expected inner App");
2318 }
2319 } else {
2320 panic!("Expected outer App");
2321 }
2322 }
2323
2324 #[test]
2325 fn test_parse_diagonalization() {
2326 let mut parser = LiterateParser::new("the diagonalization of T");
2327 let term = parser.parse_term().unwrap();
2328
2329 if let Term::App(f, arg) = term {
2331 if let Term::Global(g) = *f {
2332 assert_eq!(g, "syn_diag");
2333 } else {
2334 panic!("Expected Global syn_diag");
2335 }
2336 if let Term::Global(a) = *arg {
2337 assert_eq!(a, "T");
2338 } else {
2339 panic!("Expected Global T");
2340 }
2341 } else {
2342 panic!("Expected App");
2343 }
2344 }
2345
2346 #[test]
2347 fn test_parse_implies() {
2348 let mut parser = LiterateParser::new("A implies B");
2349 let term = parser.parse_term().unwrap();
2350
2351 if let Term::Pi { param, param_type, body_type } = term {
2353 assert_eq!(param, "_");
2354 if let Term::Global(a) = *param_type {
2355 assert_eq!(a, "A");
2356 } else {
2357 panic!("Expected Global A");
2358 }
2359 if let Term::Global(b) = *body_type {
2360 assert_eq!(b, "B");
2361 } else {
2362 panic!("Expected Global B");
2363 }
2364 } else {
2365 panic!("Expected Pi");
2366 }
2367 }
2368
2369 #[test]
2370 fn test_parse_existential() {
2371 let mut parser = LiterateParser::new("there exists a d: Derivation such that P");
2372 let term = parser.parse_term().unwrap();
2373
2374 if let Term::App(outer_f, lambda) = term {
2376 if let Term::App(ex, typ) = *outer_f {
2377 if let Term::Global(g) = *ex {
2378 assert_eq!(g, "Ex");
2379 } else {
2380 panic!("Expected Global Ex");
2381 }
2382 if let Term::Global(t) = *typ {
2383 assert_eq!(t, "Derivation");
2384 } else {
2385 panic!("Expected Global Derivation");
2386 }
2387 } else {
2388 panic!("Expected inner App for Ex");
2389 }
2390 if let Term::Lambda { param, body, .. } = *lambda {
2391 assert_eq!(param, "d");
2392 if let Term::Global(p) = *body {
2393 assert_eq!(p, "P");
2394 } else {
2395 panic!("Expected Global P in lambda body");
2396 }
2397 } else {
2398 panic!("Expected Lambda");
2399 }
2400 } else {
2401 panic!("Expected App");
2402 }
2403 }
2404
2405 #[test]
2406 fn test_parse_complex_let_with_apply() {
2407 let cmd = parse_let_definition("Let T be Apply(Name \"Not\", Apply(Name \"Provable\", Variable 0)).").unwrap();
2408 if let Command::Definition { name, ty, body, .. } = cmd {
2409 assert_eq!(name, "T");
2410 assert!(ty.is_none());
2411 if let Term::App(_, _) = body {
2413 } else {
2415 panic!("Expected App body");
2416 }
2417 } else {
2418 panic!("Expected Definition command");
2419 }
2420 }
2421
2422 #[test]
2427 fn test_parse_predicate_definition() {
2428 let cmd = parse_definition("## To be Provable (s: Syntax) -> Prop: Yield s").unwrap();
2430 if let Command::Definition { name, .. } = cmd {
2431 assert_eq!(name, "Provable"); } else {
2433 panic!("Expected Definition command");
2434 }
2435 }
2436
2437 #[test]
2438 fn test_parse_nullary_predicate() {
2439 let cmd = parse_definition("## To be Consistent -> Prop: Yield True").unwrap();
2441 if let Command::Definition { name, body, .. } = cmd {
2442 assert_eq!(name, "Consistent");
2443 if let Term::Global(g) = body {
2445 assert_eq!(g, "True");
2446 } else {
2447 panic!("Expected Global True");
2448 }
2449 } else {
2450 panic!("Expected Definition command");
2451 }
2452 }
2453
2454 #[test]
2455 fn test_parse_the_name_syntax() {
2456 let mut parser = LiterateParser::new("the Name \"Not\"");
2458 let term = parser.parse_term().unwrap();
2459
2460 if let Term::App(f, arg) = term {
2461 if let Term::Global(g) = *f {
2462 assert_eq!(g, "SName");
2463 } else {
2464 panic!("Expected Global SName");
2465 }
2466 if let Term::Lit(Literal::Text(s)) = *arg {
2467 assert_eq!(s, "Not");
2468 } else {
2469 panic!("Expected Text literal");
2470 }
2471 } else {
2472 panic!("Expected App");
2473 }
2474 }
2475
2476 #[test]
2477 fn test_parse_theorem() {
2478 let cmd = parse_theorem("## Theorem: MyTheorem\n Statement: A implies B.").unwrap();
2480 if let Command::Definition { name, ty, body, .. } = cmd {
2481 assert_eq!(name, "MyTheorem");
2482 assert!(ty.is_some());
2484 if let Some(Term::Sort(Universe::Prop)) = ty {
2485 } else {
2487 panic!("Expected Prop type");
2488 }
2489 if let Term::Pi { .. } = body {
2491 } else {
2493 panic!("Expected Pi body (implication)");
2494 }
2495 } else {
2496 panic!("Expected Definition command");
2497 }
2498 }
2499
2500 #[test]
2501 fn test_parse_theorem_with_complex_statement() {
2502 let cmd = parse_theorem("## Theorem: Godel\n Statement: Consistent implies Not(Provable(G)).").unwrap();
2504 if let Command::Definition { name, ty, .. } = cmd {
2505 assert_eq!(name, "Godel");
2506 assert!(ty.is_some());
2507 if let Some(Term::Sort(Universe::Prop)) = ty {
2508 } else {
2510 panic!("Expected Prop type");
2511 }
2512 } else {
2513 panic!("Expected Definition command");
2514 }
2515 }
2516
2517 #[test]
2518 fn test_parse_equals_infix() {
2519 let mut parser = LiterateParser::new("A equals B");
2521 let term = parser.parse_term().unwrap();
2522
2523 if let Term::App(outer, rhs) = term {
2525 if let Term::Global(b) = *rhs {
2526 assert_eq!(b, "B");
2527 } else {
2528 panic!("Expected Global B");
2529 }
2530 if let Term::App(mid, lhs) = *outer {
2531 if let Term::Global(a) = *lhs {
2532 assert_eq!(a, "A");
2533 } else {
2534 panic!("Expected Global A");
2535 }
2536 if let Term::App(inner, placeholder) = *mid {
2537 if let Term::Global(eq) = *inner {
2538 assert_eq!(eq, "Eq");
2539 } else {
2540 panic!("Expected Global Eq");
2541 }
2542 if !matches!(*placeholder, Term::Hole) {
2543 panic!("Expected Hole placeholder");
2544 }
2545 } else {
2546 panic!("Expected inner App");
2547 }
2548 } else {
2549 panic!("Expected mid App");
2550 }
2551 } else {
2552 panic!("Expected outer App");
2553 }
2554 }
2555
2556 #[test]
2557 fn test_parse_equals_with_application() {
2558 let mut parser = LiterateParser::new("f(x) equals y");
2560 let term = parser.parse_term().unwrap();
2561
2562 if let Term::App(outer, rhs) = term {
2564 if let Term::Global(y) = *rhs {
2565 assert_eq!(y, "y");
2566 } else {
2567 panic!("Expected Global y");
2568 }
2569 if let Term::App(mid, lhs) = *outer {
2570 if let Term::App(f_box, x_box) = *lhs {
2572 if let Term::Global(f) = *f_box {
2573 assert_eq!(f, "f");
2574 }
2575 if let Term::Global(x) = *x_box {
2576 assert_eq!(x, "x");
2577 }
2578 } else {
2579 panic!("Expected lhs to be App(f, x)");
2580 }
2581 } else {
2582 panic!("Expected mid App");
2583 }
2584 } else {
2585 panic!("Expected outer App");
2586 }
2587 }
2588
2589 #[test]
2594 fn test_parse_infix_le() {
2595 let mut parser = LiterateParser::new("x <= y");
2596 let term = parser.parse_term().unwrap();
2597 if let Term::App(outer, rhs) = term {
2599 if let Term::App(inner, lhs) = *outer {
2600 if let Term::Global(op) = *inner {
2601 assert_eq!(op, "le");
2602 } else {
2603 panic!("Expected Global le");
2604 }
2605 if let Term::Global(l) = *lhs {
2606 assert_eq!(l, "x");
2607 } else {
2608 panic!("Expected Global x");
2609 }
2610 } else {
2611 panic!("Expected inner App");
2612 }
2613 if let Term::Global(r) = *rhs {
2614 assert_eq!(r, "y");
2615 } else {
2616 panic!("Expected Global y");
2617 }
2618 } else {
2619 panic!("Expected outer App");
2620 }
2621 }
2622
2623 #[test]
2624 fn test_parse_infix_lt() {
2625 let mut parser = LiterateParser::new("a < b");
2626 let term = parser.parse_term().unwrap();
2627 if let Term::App(outer, _) = term {
2628 if let Term::App(inner, _) = *outer {
2629 if let Term::Global(op) = *inner {
2630 assert_eq!(op, "lt");
2631 } else {
2632 panic!("Expected Global lt");
2633 }
2634 } else {
2635 panic!("Expected inner App");
2636 }
2637 } else {
2638 panic!("Expected outer App");
2639 }
2640 }
2641
2642 #[test]
2643 fn test_parse_infix_ge() {
2644 let mut parser = LiterateParser::new("x >= y");
2645 let term = parser.parse_term().unwrap();
2646 if let Term::App(outer, _) = term {
2647 if let Term::App(inner, _) = *outer {
2648 if let Term::Global(op) = *inner {
2649 assert_eq!(op, "ge");
2650 } else {
2651 panic!("Expected Global ge");
2652 }
2653 } else {
2654 panic!("Expected inner App");
2655 }
2656 } else {
2657 panic!("Expected outer App");
2658 }
2659 }
2660
2661 #[test]
2662 fn test_parse_infix_gt() {
2663 let mut parser = LiterateParser::new("x > y");
2664 let term = parser.parse_term().unwrap();
2665 if let Term::App(outer, _) = term {
2666 if let Term::App(inner, _) = *outer {
2667 if let Term::Global(op) = *inner {
2668 assert_eq!(op, "gt");
2669 } else {
2670 panic!("Expected Global gt");
2671 }
2672 } else {
2673 panic!("Expected inner App");
2674 }
2675 } else {
2676 panic!("Expected outer App");
2677 }
2678 }
2679
2680 #[test]
2681 fn test_parse_infix_add() {
2682 let mut parser = LiterateParser::new("x + y");
2683 let term = parser.parse_term().unwrap();
2684 if let Term::App(outer, _) = term {
2685 if let Term::App(inner, _) = *outer {
2686 if let Term::Global(op) = *inner {
2687 assert_eq!(op, "add");
2688 } else {
2689 panic!("Expected Global add");
2690 }
2691 } else {
2692 panic!("Expected inner App");
2693 }
2694 } else {
2695 panic!("Expected outer App");
2696 }
2697 }
2698
2699 #[test]
2700 fn test_parse_infix_sub() {
2701 let mut parser = LiterateParser::new("x - y");
2702 let term = parser.parse_term().unwrap();
2703 if let Term::App(outer, _) = term {
2704 if let Term::App(inner, _) = *outer {
2705 if let Term::Global(op) = *inner {
2706 assert_eq!(op, "sub");
2707 } else {
2708 panic!("Expected Global sub");
2709 }
2710 } else {
2711 panic!("Expected inner App");
2712 }
2713 } else {
2714 panic!("Expected outer App");
2715 }
2716 }
2717
2718 #[test]
2719 fn test_parse_infix_mul() {
2720 let mut parser = LiterateParser::new("x * y");
2721 let term = parser.parse_term().unwrap();
2722 if let Term::App(outer, _) = term {
2723 if let Term::App(inner, _) = *outer {
2724 if let Term::Global(op) = *inner {
2725 assert_eq!(op, "mul");
2726 } else {
2727 panic!("Expected Global mul");
2728 }
2729 } else {
2730 panic!("Expected inner App");
2731 }
2732 } else {
2733 panic!("Expected outer App");
2734 }
2735 }
2736
2737 #[test]
2738 fn test_parse_precedence_mul_over_add() {
2739 let mut parser = LiterateParser::new("x + y * z");
2741 let term = parser.parse_term().unwrap();
2742 if let Term::App(outer, rhs) = term {
2744 if let Term::App(inner, _) = *outer {
2745 if let Term::Global(op) = *inner {
2746 assert_eq!(op, "add");
2747 } else {
2748 panic!("Expected add");
2749 }
2750 } else {
2751 panic!("Expected inner App");
2752 }
2753 if let Term::App(mul_outer, _) = *rhs {
2755 if let Term::App(mul_inner, _) = *mul_outer {
2756 if let Term::Global(op) = *mul_inner {
2757 assert_eq!(op, "mul");
2758 } else {
2759 panic!("Expected mul");
2760 }
2761 } else {
2762 panic!("Expected mul inner App");
2763 }
2764 } else {
2765 panic!("Expected mul App");
2766 }
2767 } else {
2768 panic!("Expected outer App");
2769 }
2770 }
2771
2772 #[test]
2773 fn test_parse_left_associative_add() {
2774 let mut parser = LiterateParser::new("x + y + z");
2776 let term = parser.parse_term().unwrap();
2777 if let Term::App(outer, rhs) = term {
2779 if let Term::Global(z) = *rhs {
2780 assert_eq!(z, "z");
2781 } else {
2782 panic!("Expected z");
2783 }
2784 if let Term::App(mid, lhs_add) = *outer {
2785 if let Term::Global(op) = *mid {
2786 assert_eq!(op, "add");
2787 }
2788 if let Term::App(inner_outer, _) = *lhs_add {
2790 if let Term::App(inner_inner, _) = *inner_outer {
2791 if let Term::Global(op2) = *inner_inner {
2792 assert_eq!(op2, "add");
2793 }
2794 }
2795 }
2796 }
2797 } else {
2798 panic!("Expected App");
2799 }
2800 }
2801
2802 #[test]
2803 fn test_parse_comparison_with_arithmetic() {
2804 let mut parser = LiterateParser::new("x + 1 <= y * 2");
2806 let term = parser.parse_term().unwrap();
2807 if let Term::App(outer, _) = term {
2808 if let Term::App(inner, _) = *outer {
2809 if let Term::Global(op) = *inner {
2810 assert_eq!(op, "le");
2811 } else {
2812 panic!("Expected le");
2813 }
2814 } else {
2815 panic!("Expected inner App");
2816 }
2817 } else {
2818 panic!("Expected outer App");
2819 }
2820 }
2821
2822 #[test]
2823 fn test_parse_unicode_le() {
2824 let mut parser = LiterateParser::new("x ≤ y");
2825 let term = parser.parse_term().unwrap();
2826 if let Term::App(outer, _) = term {
2827 if let Term::App(inner, _) = *outer {
2828 if let Term::Global(op) = *inner {
2829 assert_eq!(op, "le");
2830 } else {
2831 panic!("Expected le for ≤");
2832 }
2833 }
2834 } else {
2835 panic!("Expected App");
2836 }
2837 }
2838
2839 #[test]
2840 fn test_parse_unicode_ge() {
2841 let mut parser = LiterateParser::new("x ≥ y");
2842 let term = parser.parse_term().unwrap();
2843 if let Term::App(outer, _) = term {
2844 if let Term::App(inner, _) = *outer {
2845 if let Term::Global(op) = *inner {
2846 assert_eq!(op, "ge");
2847 } else {
2848 panic!("Expected ge for ≥");
2849 }
2850 }
2851 } else {
2852 panic!("Expected App");
2853 }
2854 }
2855
2856 #[test]
2857 fn test_parse_negative_number_preserved() {
2858 let mut parser = LiterateParser::new("-5 + x");
2860 let term = parser.parse_term().unwrap();
2861 if let Term::App(outer, _) = term {
2863 if let Term::App(inner, lhs) = *outer {
2864 if let Term::Global(op) = *inner {
2865 assert_eq!(op, "add");
2866 }
2867 if let Term::Lit(Literal::Int(n)) = *lhs {
2868 assert_eq!(n, -5);
2869 } else {
2870 panic!("Expected -5 literal");
2871 }
2872 }
2873 } else {
2874 panic!("Expected App");
2875 }
2876 }
2877
2878 #[test]
2879 fn test_parse_subtraction_not_negative() {
2880 let mut parser = LiterateParser::new("x - 5");
2882 let term = parser.parse_term().unwrap();
2883 if let Term::App(outer, rhs) = term {
2884 if let Term::App(inner, _) = *outer {
2885 if let Term::Global(op) = *inner {
2886 assert_eq!(op, "sub");
2887 }
2888 }
2889 if let Term::Lit(Literal::Int(n)) = *rhs {
2890 assert_eq!(n, 5); } else {
2892 panic!("Expected 5 literal");
2893 }
2894 } else {
2895 panic!("Expected App");
2896 }
2897 }
2898
2899 #[test]
2900 fn test_parse_infix_with_sexp_mix() {
2901 let mut parser = LiterateParser::new("(add x y) <= z");
2903 let term = parser.parse_term().unwrap();
2904 if let Term::App(outer, _) = term {
2905 if let Term::App(inner, lhs) = *outer {
2906 if let Term::Global(op) = *inner {
2907 assert_eq!(op, "le");
2908 }
2909 if let Term::App(add_outer, _) = *lhs {
2911 if let Term::App(add_inner, _) = *add_outer {
2912 if let Term::Global(add_op) = *add_inner {
2913 assert_eq!(add_op, "add");
2914 }
2915 }
2916 }
2917 }
2918 } else {
2919 panic!("Expected App");
2920 }
2921 }
2922}