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 })
463 }
464
465 fn parse_literate_let(&mut self) -> Result<Command, ParseError> {
471 self.skip_whitespace();
472
473 if !self.try_consume_keyword("Let") {
475 return Err(ParseError::Expected {
476 expected: "'Let'".to_string(),
477 found: self.peek_word().unwrap_or("EOF".to_string()),
478 });
479 }
480
481 self.skip_whitespace();
482
483 let name = self.parse_ident()?;
485
486 self.skip_whitespace();
487
488 if !self.try_consume_keyword("be") {
490 return Err(ParseError::Expected {
491 expected: "'be'".to_string(),
492 found: self.peek_word().unwrap_or("EOF".to_string()),
493 });
494 }
495
496 self.skip_whitespace();
497
498 let body = self.parse_term()?;
500
501 self.skip_whitespace();
503 let _ = self.try_consume(".");
504
505 Ok(Command::Definition {
506 name,
507 ty: None,
508 body,
509 is_hint: false,
510 })
511 }
512
513 fn parse_literate_theorem(&mut self) -> Result<Command, ParseError> {
518 self.skip_whitespace();
519
520 if !self.try_consume("## Theorem:") {
522 return Err(ParseError::Expected {
523 expected: "'## Theorem:'".to_string(),
524 found: self.peek_word().unwrap_or("EOF".to_string()),
525 });
526 }
527
528 self.skip_whitespace();
529
530 let name = self.parse_ident()?;
532
533 self.skip_whitespace_and_newlines();
534
535 if !self.try_consume_keyword("Statement") {
537 return Err(ParseError::Expected {
538 expected: "'Statement'".to_string(),
539 found: self.peek_word().unwrap_or("EOF".to_string()),
540 });
541 }
542 self.skip_whitespace();
543 if !self.try_consume(":") {
544 return Err(ParseError::Expected {
545 expected: "':'".to_string(),
546 found: self.peek_word().unwrap_or("EOF".to_string()),
547 });
548 }
549
550 self.skip_whitespace();
551
552 let statement = self.parse_term()?;
554
555 self.skip_whitespace();
557 let _ = self.try_consume(".");
558
559 self.skip_whitespace_and_newlines();
560
561 let (body, ty) = if self.try_consume_keyword("Proof") {
563 self.skip_whitespace();
564 if !self.try_consume(":") {
565 return Err(ParseError::Expected {
566 expected: "':'".to_string(),
567 found: self.peek_word().unwrap_or("EOF".to_string()),
568 });
569 }
570 self.skip_whitespace();
571
572 let proof = self.parse_proof_tactic(&statement)?;
574
575 self.skip_whitespace();
577 let _ = self.try_consume(".");
578
579 (proof, Some(Term::Global("Derivation".to_string())))
580 } else {
581 (statement, Some(Term::Sort(Universe::Prop)))
583 };
584
585 self.skip_whitespace_and_newlines();
587 let is_hint = if self.try_consume_keyword("Attribute") {
588 self.skip_whitespace();
589 if !self.try_consume(":") {
590 return Err(ParseError::Expected {
591 expected: "':'".to_string(),
592 found: self.peek_word().unwrap_or("EOF".to_string()),
593 });
594 }
595 self.skip_whitespace();
596
597 let hint = self.try_consume_keyword("hint");
598
599 self.skip_whitespace();
601 let _ = self.try_consume(".");
602
603 hint
604 } else {
605 false
606 };
607
608 Ok(Command::Definition {
609 name,
610 ty,
611 body,
612 is_hint,
613 })
614 }
615
616 fn parse_proof_tactic(&mut self, statement: &Term) -> Result<Term, ParseError> {
623 if self.try_consume_keyword("ring") {
624 self.skip_whitespace();
626 let _ = self.try_consume(".");
627
628 let goal_syntax = self.term_to_syntax(statement, &[]);
630 Ok(Term::App(
631 Box::new(Term::Global("try_ring".to_string())),
632 Box::new(goal_syntax),
633 ))
634 } else if self.try_consume_keyword("refl") {
635 self.skip_whitespace();
637 let _ = self.try_consume(".");
638
639 let goal_syntax = self.term_to_syntax(statement, &[]);
640 Ok(Term::App(
641 Box::new(Term::Global("try_refl".to_string())),
642 Box::new(goal_syntax),
643 ))
644 } else if self.try_consume_keyword("lia") {
645 self.skip_whitespace();
647 let _ = self.try_consume(".");
648
649 let goal_syntax = self.term_to_syntax(statement, &[]);
650 Ok(Term::App(
651 Box::new(Term::Global("try_lia".to_string())),
652 Box::new(goal_syntax),
653 ))
654 } else if self.try_consume_keyword("cc") {
655 self.skip_whitespace();
657 let _ = self.try_consume(".");
658
659 let goal_syntax = self.term_to_syntax(statement, &[]);
660 Ok(Term::App(
661 Box::new(Term::Global("try_cc".to_string())),
662 Box::new(goal_syntax),
663 ))
664 } else if self.try_consume_keyword("simp") {
665 self.skip_whitespace();
667 let _ = self.try_consume(".");
668
669 let goal_syntax = self.term_to_syntax(statement, &[]);
670 Ok(Term::App(
671 Box::new(Term::Global("try_simp".to_string())),
672 Box::new(goal_syntax),
673 ))
674 } else if self.try_consume_keyword("omega") {
675 self.skip_whitespace();
677 let _ = self.try_consume(".");
678
679 let goal_syntax = self.term_to_syntax(statement, &[]);
680 Ok(Term::App(
681 Box::new(Term::Global("try_omega".to_string())),
682 Box::new(goal_syntax),
683 ))
684 } else if self.try_consume_keyword("auto") {
685 self.skip_whitespace();
687 let _ = self.try_consume(".");
688
689 let goal_syntax = self.term_to_syntax(statement, &[]);
690 Ok(Term::App(
691 Box::new(Term::Global("try_auto".to_string())),
692 Box::new(goal_syntax),
693 ))
694 } else if self.try_consume_keyword("induction") {
695 self.skip_whitespace();
697 let var_name = self.parse_ident()?;
698 self.skip_whitespace();
699 let _ = self.try_consume(".");
700
701 let cases = self.parse_bullet_cases(statement)?;
703
704 self.build_induction_derivation(&var_name, statement, cases)
706 } else {
707 Err(ParseError::Expected {
708 expected: "proof tactic (ring, refl, lia, cc, simp, omega, auto, induction)".to_string(),
709 found: self.peek_word().unwrap_or("EOF".to_string()),
710 })
711 }
712 }
713
714 fn peek_bullet(&mut self) -> bool {
716 let saved_pos = self.pos;
718 self.skip_whitespace_and_newlines();
719 let result = matches!(self.peek(), Some('-') | Some('*') | Some('+'));
720 self.pos = saved_pos;
721 result
722 }
723
724 fn consume_bullet(&mut self) {
726 self.skip_whitespace_and_newlines();
727 if matches!(self.peek(), Some('-') | Some('*') | Some('+')) {
728 self.advance();
729 }
730 }
731
732 fn parse_bullet_cases(&mut self, statement: &Term) -> Result<Vec<Term>, ParseError> {
734 let mut cases = Vec::new();
735
736 while self.peek_bullet() {
737 self.consume_bullet();
738 self.skip_whitespace();
739
740 let case_proof = self.parse_tactic_sequence(statement)?;
742 cases.push(case_proof);
743 }
744
745 Ok(cases)
746 }
747
748 fn parse_tactic_sequence(&mut self, statement: &Term) -> Result<Term, ParseError> {
750 let mut tactics = Vec::new();
751
752 loop {
753 self.skip_whitespace();
754
755 if self.peek_bullet() || self.at_end() || self.peek_keyword("Attribute") {
757 break;
758 }
759
760 match self.parse_single_tactic(statement) {
762 Ok(tactic) => tactics.push(tactic),
763 Err(_) => break,
764 }
765 }
766
767 if tactics.is_empty() {
768 return Err(ParseError::Missing("tactic in bullet case".to_string()));
769 }
770
771 let mut result = tactics.pop().unwrap();
773 while let Some(prev) = tactics.pop() {
774 result = Term::App(
775 Box::new(Term::App(
776 Box::new(Term::Global("tact_seq".to_string())),
777 Box::new(prev),
778 )),
779 Box::new(result),
780 );
781 }
782
783 Ok(result)
784 }
785
786 fn parse_single_tactic(&mut self, statement: &Term) -> Result<Term, ParseError> {
788 let goal_syntax = self.term_to_syntax(statement, &[]);
789
790 if self.try_consume_keyword("ring") {
791 self.skip_whitespace();
792 let _ = self.try_consume(".");
793 Ok(Term::App(
794 Box::new(Term::Global("try_ring".to_string())),
795 Box::new(goal_syntax),
796 ))
797 } else if self.try_consume_keyword("refl") {
798 self.skip_whitespace();
799 let _ = self.try_consume(".");
800 Ok(Term::App(
801 Box::new(Term::Global("try_refl".to_string())),
802 Box::new(goal_syntax),
803 ))
804 } else if self.try_consume_keyword("lia") {
805 self.skip_whitespace();
806 let _ = self.try_consume(".");
807 Ok(Term::App(
808 Box::new(Term::Global("try_lia".to_string())),
809 Box::new(goal_syntax),
810 ))
811 } else if self.try_consume_keyword("cc") {
812 self.skip_whitespace();
813 let _ = self.try_consume(".");
814 Ok(Term::App(
815 Box::new(Term::Global("try_cc".to_string())),
816 Box::new(goal_syntax),
817 ))
818 } else if self.try_consume_keyword("simp") {
819 self.skip_whitespace();
820 let _ = self.try_consume(".");
821 Ok(Term::App(
822 Box::new(Term::Global("try_simp".to_string())),
823 Box::new(goal_syntax),
824 ))
825 } else if self.try_consume_keyword("omega") {
826 self.skip_whitespace();
827 let _ = self.try_consume(".");
828 Ok(Term::App(
829 Box::new(Term::Global("try_omega".to_string())),
830 Box::new(goal_syntax),
831 ))
832 } else if self.try_consume_keyword("auto") {
833 self.skip_whitespace();
834 let _ = self.try_consume(".");
835 Ok(Term::App(
836 Box::new(Term::Global("try_auto".to_string())),
837 Box::new(goal_syntax),
838 ))
839 } else if self.try_consume_keyword("intro") {
840 self.skip_whitespace();
841 let _var = if !self.peek_char('.') && !self.at_end() {
843 self.parse_ident().ok()
844 } else {
845 None
846 };
847 self.skip_whitespace();
848 let _ = self.try_consume(".");
849 Ok(Term::App(
850 Box::new(Term::Global("try_intro".to_string())),
851 Box::new(goal_syntax),
852 ))
853 } else {
854 Err(ParseError::Expected {
855 expected: "tactic".to_string(),
856 found: self.peek_word().unwrap_or("EOF".to_string()),
857 })
858 }
859 }
860
861 fn build_induction_derivation(
863 &self,
864 _var_name: &str,
865 statement: &Term,
866 cases: Vec<Term>,
867 ) -> Result<Term, ParseError> {
868 let ind_type = Term::App(
870 Box::new(Term::Global("SName".to_string())),
871 Box::new(Term::Lit(Literal::Text("Nat".to_string()))),
872 );
873
874 let motive = self.term_to_syntax(statement, &[]);
876
877 let mut case_chain = Term::Global("DCaseEnd".to_string());
879 for case_proof in cases.into_iter().rev() {
880 case_chain = Term::App(
881 Box::new(Term::App(
882 Box::new(Term::Global("DCase".to_string())),
883 Box::new(case_proof),
884 )),
885 Box::new(case_chain),
886 );
887 }
888
889 Ok(Term::App(
891 Box::new(Term::App(
892 Box::new(Term::App(
893 Box::new(Term::Global("try_induction".to_string())),
894 Box::new(ind_type),
895 )),
896 Box::new(motive),
897 )),
898 Box::new(case_chain),
899 ))
900 }
901
902 fn parse_function_params(&mut self) -> Result<Vec<(String, Term)>, ParseError> {
904 let mut params = Vec::new();
905
906 loop {
907 self.skip_whitespace();
908
909 if !self.peek_char('(') {
911 break;
912 }
913
914 self.advance(); self.skip_whitespace();
917
918 let param_name = self.parse_ident()?;
919 self.skip_whitespace();
920
921 if !self.try_consume(":") {
922 return Err(ParseError::Expected {
923 expected: "':'".to_string(),
924 found: self.peek_word().unwrap_or("EOF".to_string()),
925 });
926 }
927 self.skip_whitespace();
928
929 let param_type = self.parse_type()?;
930 self.skip_whitespace();
931
932 if !self.try_consume(")") {
933 return Err(ParseError::Expected {
934 expected: "')'".to_string(),
935 found: self.peek_word().unwrap_or("EOF".to_string()),
936 });
937 }
938
939 params.push((param_name, param_type));
940
941 self.skip_whitespace();
942
943 let _ = self.try_consume_keyword("and");
945 }
946
947 Ok(params)
948 }
949
950 fn parse_param_list(&mut self) -> Result<Vec<(String, Term)>, ParseError> {
952 let mut params = Vec::new();
953
954 if !self.peek_char('(') {
955 return Ok(params);
956 }
957
958 self.advance(); self.skip_whitespace();
960
961 loop {
962 let param_name = self.parse_ident()?;
963 self.skip_whitespace();
964
965 if !self.try_consume(":") {
966 return Err(ParseError::Expected {
967 expected: "':'".to_string(),
968 found: self.peek_word().unwrap_or("EOF".to_string()),
969 });
970 }
971 self.skip_whitespace();
972
973 let param_type = self.parse_type()?;
974 params.push((param_name, param_type));
975
976 self.skip_whitespace();
977
978 if self.try_consume(")") {
979 break;
980 }
981
982 if !self.try_consume(",") && !self.try_consume_keyword("and") {
983 return Err(ParseError::Expected {
984 expected: "')' or ','".to_string(),
985 found: self.peek_word().unwrap_or("EOF".to_string()),
986 });
987 }
988 self.skip_whitespace();
989 }
990
991 Ok(params)
992 }
993
994 fn parse_body(&mut self) -> Result<Term, ParseError> {
1000 self.skip_whitespace();
1001
1002 if self.peek_keyword("Consider") {
1004 return self.parse_consider();
1005 }
1006
1007 if self.peek_keyword("Yield") {
1009 return self.parse_yield();
1010 }
1011
1012 if self.peek_keyword("given") {
1014 return self.parse_given_lambda();
1015 }
1016
1017 if self.peek_char('|') {
1019 return self.parse_pipe_lambda();
1020 }
1021
1022 self.parse_term()
1024 }
1025
1026 fn parse_consider(&mut self) -> Result<Term, ParseError> {
1028 self.consume_keyword("Consider")?;
1029 self.skip_whitespace();
1030
1031 let discriminant = self.parse_term()?;
1033
1034 self.skip_whitespace();
1035
1036 if !self.try_consume(":") {
1038 return Err(ParseError::Expected {
1039 expected: "':'".to_string(),
1040 found: self.peek_word().unwrap_or("EOF".to_string()),
1041 });
1042 }
1043
1044 let mut cases = Vec::new();
1046 let motive = self.return_type.clone().unwrap_or_else(|| Term::Sort(Universe::Type(0)));
1049
1050 loop {
1051 self.skip_whitespace_and_newlines();
1052
1053 if !self.peek_keyword("When") {
1054 break;
1055 }
1056
1057 self.consume_keyword("When")?;
1058 self.skip_whitespace();
1059
1060 let ctor_name = self.parse_ident()?;
1062 self.skip_whitespace();
1063
1064 let mut binders = Vec::new();
1066 while !self.peek_char(':') && !self.at_end() {
1067 let binder = self.parse_ident()?;
1068 binders.push(binder);
1069 self.skip_whitespace();
1070 }
1071
1072 if !self.try_consume(":") {
1074 return Err(ParseError::Expected {
1075 expected: "':'".to_string(),
1076 found: self.peek_word().unwrap_or("EOF".to_string()),
1077 });
1078 }
1079
1080 self.skip_whitespace();
1081
1082 for binder in &binders {
1084 self.bound_vars.insert(binder.clone());
1085 }
1086
1087 let case_body = self.parse_body()?;
1089
1090 for binder in &binders {
1092 self.bound_vars.remove(binder);
1093 }
1094
1095 let mut wrapped_body = case_body;
1097 for binder in binders.into_iter().rev() {
1098 wrapped_body = Term::Lambda {
1099 param: binder,
1100 param_type: Box::new(Term::Global("_".to_string())), body: Box::new(wrapped_body),
1102 };
1103 }
1104
1105 cases.push(wrapped_body);
1106
1107 self.skip_whitespace();
1109 let _ = self.try_consume(".");
1110 }
1111
1112 if cases.is_empty() {
1113 return Err(ParseError::Missing("When clauses".to_string()));
1114 }
1115
1116 if let Term::Var(ref _v) = discriminant {
1118 }
1120
1121 Ok(Term::Match {
1122 discriminant: Box::new(discriminant),
1123 motive: Box::new(motive),
1124 cases,
1125 })
1126 }
1127
1128 fn parse_yield(&mut self) -> Result<Term, ParseError> {
1130 self.consume_keyword("Yield")?;
1131 self.skip_whitespace();
1132 self.parse_term()
1133 }
1134
1135 fn parse_given_lambda(&mut self) -> Result<Term, ParseError> {
1137 self.consume_keyword("given")?;
1138 self.skip_whitespace();
1139
1140 let param = self.parse_ident()?;
1141 self.skip_whitespace();
1142
1143 if !self.try_consume(":") {
1144 return Err(ParseError::Expected {
1145 expected: "':'".to_string(),
1146 found: self.peek_word().unwrap_or("EOF".to_string()),
1147 });
1148 }
1149 self.skip_whitespace();
1150
1151 let param_type = self.parse_type()?;
1152 self.skip_whitespace();
1153
1154 self.consume_keyword("yields")?;
1155 self.skip_whitespace();
1156
1157 self.bound_vars.insert(param.clone());
1158 let body = self.parse_term()?;
1159 self.bound_vars.remove(¶m);
1160
1161 Ok(Term::Lambda {
1162 param,
1163 param_type: Box::new(param_type),
1164 body: Box::new(body),
1165 })
1166 }
1167
1168 fn parse_pipe_lambda(&mut self) -> Result<Term, ParseError> {
1170 self.advance(); self.skip_whitespace();
1172
1173 let param = self.parse_ident()?;
1174 self.skip_whitespace();
1175
1176 if !self.try_consume(":") {
1177 return Err(ParseError::Expected {
1178 expected: "':'".to_string(),
1179 found: self.peek_word().unwrap_or("EOF".to_string()),
1180 });
1181 }
1182 self.skip_whitespace();
1183
1184 let param_type = self.parse_type()?;
1185 self.skip_whitespace();
1186
1187 if !self.try_consume("|") {
1188 return Err(ParseError::Expected {
1189 expected: "'|'".to_string(),
1190 found: self.peek_word().unwrap_or("EOF".to_string()),
1191 });
1192 }
1193 self.skip_whitespace();
1194
1195 if !self.try_consume("->") {
1196 return Err(ParseError::Expected {
1197 expected: "'->'".to_string(),
1198 found: self.peek_word().unwrap_or("EOF".to_string()),
1199 });
1200 }
1201 self.skip_whitespace();
1202
1203 self.bound_vars.insert(param.clone());
1204 let body = self.parse_term()?;
1205 self.bound_vars.remove(¶m);
1206
1207 Ok(Term::Lambda {
1208 param,
1209 param_type: Box::new(param_type),
1210 body: Box::new(body),
1211 })
1212 }
1213
1214 fn parse_term(&mut self) -> Result<Term, ParseError> {
1216 let lhs = self.parse_comparison()?;
1217
1218 self.skip_whitespace();
1219
1220 if self.peek_keyword("equals") {
1222 self.consume_keyword("equals")?;
1223 self.skip_whitespace();
1224 let rhs = self.parse_comparison()?; return Ok(Term::App(
1226 Box::new(Term::App(
1227 Box::new(Term::App(
1228 Box::new(Term::Global("Eq".to_string())),
1229 Box::new(Term::Hole), )),
1231 Box::new(lhs),
1232 )),
1233 Box::new(rhs),
1234 ));
1235 }
1236
1237 if self.peek_keyword("implies") {
1239 self.consume_keyword("implies")?;
1240 self.skip_whitespace();
1241 let rhs = self.parse_term()?; return Ok(Term::Pi {
1243 param: "_".to_string(),
1244 param_type: Box::new(lhs),
1245 body_type: Box::new(rhs),
1246 });
1247 }
1248
1249 Ok(lhs)
1250 }
1251
1252 fn parse_comparison(&mut self) -> Result<Term, ParseError> {
1260 let lhs = self.parse_additive()?;
1261 self.skip_whitespace();
1262
1263 let op_name = if self.try_consume("<=") || self.try_consume("≤") {
1265 Some("le")
1266 } else if self.try_consume(">=") || self.try_consume("≥") {
1267 Some("ge")
1268 } else if self.try_consume("<") {
1269 Some("lt")
1270 } else if self.try_consume(">") {
1271 Some("gt")
1272 } else {
1273 None
1274 };
1275
1276 if let Some(op) = op_name {
1277 self.skip_whitespace();
1278 let rhs = self.parse_additive()?; return Ok(Term::App(
1280 Box::new(Term::App(
1281 Box::new(Term::Global(op.to_string())),
1282 Box::new(lhs),
1283 )),
1284 Box::new(rhs),
1285 ));
1286 }
1287
1288 Ok(lhs)
1289 }
1290
1291 fn parse_additive(&mut self) -> Result<Term, ParseError> {
1294 let mut result = self.parse_multiplicative()?;
1295
1296 loop {
1297 self.skip_whitespace();
1298
1299 let op_name = if self.try_consume("+") {
1300 Some("add")
1301 } else if self.peek_char('-') && !self.peek_arrow() && !self.peek_negative_number() {
1302 self.advance(); Some("sub")
1304 } else {
1305 None
1306 };
1307
1308 if let Some(op) = op_name {
1309 self.skip_whitespace();
1310 let rhs = self.parse_multiplicative()?;
1311 result = Term::App(
1312 Box::new(Term::App(
1313 Box::new(Term::Global(op.to_string())),
1314 Box::new(result),
1315 )),
1316 Box::new(rhs),
1317 );
1318 } else {
1319 break;
1320 }
1321 }
1322
1323 Ok(result)
1324 }
1325
1326 fn parse_multiplicative(&mut self) -> Result<Term, ParseError> {
1329 let mut result = self.parse_app()?;
1330
1331 loop {
1332 self.skip_whitespace();
1333
1334 if self.try_consume("*") {
1335 self.skip_whitespace();
1336 let rhs = self.parse_app()?;
1337 result = Term::App(
1338 Box::new(Term::App(
1339 Box::new(Term::Global("mul".to_string())),
1340 Box::new(result),
1341 )),
1342 Box::new(rhs),
1343 );
1344 } else {
1345 break;
1346 }
1347 }
1348
1349 Ok(result)
1350 }
1351
1352 fn parse_app(&mut self) -> Result<Term, ParseError> {
1354 let mut func = self.parse_atom()?;
1355
1356 loop {
1357 self.skip_whitespace();
1358
1359 if self.peek_char('(') {
1361 self.advance(); self.skip_whitespace();
1363
1364 if !self.peek_char(')') {
1365 loop {
1366 let arg = self.parse_term()?;
1367 func = Term::App(Box::new(func), Box::new(arg));
1368 self.skip_whitespace();
1369
1370 if self.try_consume(",") {
1371 self.skip_whitespace();
1372 } else {
1373 break;
1374 }
1375 }
1376 }
1377
1378 if !self.try_consume(")") {
1379 return Err(ParseError::Expected {
1380 expected: "')'".to_string(),
1381 found: self.peek_word().unwrap_or("EOF".to_string()),
1382 });
1383 }
1384 continue;
1385 }
1386
1387 if self.at_end()
1390 || self.peek_char(')')
1391 || self.peek_char('.')
1392 || self.peek_char(',')
1393 || self.peek_char(':')
1394 || self.peek_char('|')
1395 || self.peek_keyword("When")
1396 || self.peek_keyword("Yield")
1397 || self.peek_keyword("and")
1398 || self.peek_keyword("or")
1399 || self.peek_keyword("equals")
1400 || self.peek_keyword("implies")
1401 || self.peek_char('+')
1403 || self.peek_char('*')
1404 || self.peek_comparison_operator()
1405 || (self.peek_char('-') && !self.peek_arrow() && !self.peek_negative_number())
1406 {
1407 break;
1408 }
1409
1410 if let Ok(arg) = self.parse_atom() {
1412 func = Term::App(Box::new(func), Box::new(arg));
1413 } else {
1414 break;
1415 }
1416 }
1417
1418 Ok(func)
1419 }
1420
1421 fn parse_atom(&mut self) -> Result<Term, ParseError> {
1423 self.skip_whitespace();
1424
1425 if let Some(c) = self.peek() {
1427 if c.is_ascii_digit() {
1428 return self.parse_number();
1429 }
1430 if c == '-' {
1431 let saved_pos = self.pos;
1433 self.advance();
1434 if let Some(next) = self.peek() {
1435 if next.is_ascii_digit() {
1436 self.pos = saved_pos;
1437 return self.parse_number();
1438 }
1439 }
1440 self.pos = saved_pos;
1441 }
1442 }
1443
1444 if self.peek_char('"') {
1446 return self.parse_string();
1447 }
1448
1449 if self.peek_char('(') {
1451 self.advance();
1452 let term = self.parse_term()?;
1453 self.skip_whitespace();
1454 if !self.try_consume(")") {
1455 return Err(ParseError::Expected {
1456 expected: "')'".to_string(),
1457 found: self.peek_word().unwrap_or("EOF".to_string()),
1458 });
1459 }
1460 return Ok(term);
1461 }
1462
1463 if self.try_consume_keyword("the") {
1465 self.skip_whitespace();
1466 if self.try_consume_keyword("diagonalization") {
1468 self.skip_whitespace();
1469 if !self.try_consume_keyword("of") {
1470 return Err(ParseError::Expected {
1471 expected: "'of'".to_string(),
1472 found: self.peek_word().unwrap_or("EOF".to_string()),
1473 });
1474 }
1475 self.skip_whitespace();
1476 let arg = self.parse_atom()?;
1477 return Ok(Term::App(
1478 Box::new(Term::Global("syn_diag".to_string())),
1479 Box::new(arg),
1480 ));
1481 }
1482 if self.peek_keyword("Name") {
1484 self.consume_keyword("Name")?;
1485 self.skip_whitespace();
1486 let arg = self.parse_atom()?;
1487 return Ok(Term::App(
1488 Box::new(Term::Global("SName".to_string())),
1489 Box::new(arg),
1490 ));
1491 }
1492 }
1494
1495 if self.peek_keyword("Name") {
1497 self.consume_keyword("Name")?;
1498 self.skip_whitespace();
1499 let arg = self.parse_atom()?;
1500 return Ok(Term::App(
1501 Box::new(Term::Global("SName".to_string())),
1502 Box::new(arg),
1503 ));
1504 }
1505
1506 if self.peek_keyword("Variable") {
1508 self.consume_keyword("Variable")?;
1509 self.skip_whitespace();
1510 let arg = self.parse_atom()?;
1511 return Ok(Term::App(
1512 Box::new(Term::Global("SVar".to_string())),
1513 Box::new(arg),
1514 ));
1515 }
1516
1517 if self.peek_keyword("Apply") {
1519 self.consume_keyword("Apply")?;
1520 self.skip_whitespace();
1521 if !self.try_consume("(") {
1522 return Err(ParseError::Expected {
1523 expected: "'('".to_string(),
1524 found: self.peek_word().unwrap_or("EOF".to_string()),
1525 });
1526 }
1527 self.skip_whitespace();
1528 let func_arg = self.parse_term()?;
1529 self.skip_whitespace();
1530 if !self.try_consume(",") {
1531 return Err(ParseError::Expected {
1532 expected: "','".to_string(),
1533 found: self.peek_word().unwrap_or("EOF".to_string()),
1534 });
1535 }
1536 self.skip_whitespace();
1537 let arg_arg = self.parse_term()?;
1538 self.skip_whitespace();
1539 if !self.try_consume(")") {
1540 return Err(ParseError::Expected {
1541 expected: "')'".to_string(),
1542 found: self.peek_word().unwrap_or("EOF".to_string()),
1543 });
1544 }
1545 return Ok(Term::App(
1546 Box::new(Term::App(
1547 Box::new(Term::Global("SApp".to_string())),
1548 Box::new(func_arg),
1549 )),
1550 Box::new(arg_arg),
1551 ));
1552 }
1553
1554 if self.peek_keyword("there") {
1556 return self.parse_existential();
1557 }
1558
1559 let ident = self.parse_ident()?;
1561
1562 self.skip_whitespace();
1564 if self.try_consume_keyword("of") {
1565 self.skip_whitespace();
1566 let arg = self.parse_atom()?;
1567 let func = if self.bound_vars.contains(&ident) {
1568 Term::Var(ident)
1569 } else {
1570 Term::Global(ident)
1571 };
1572 return Ok(Term::App(Box::new(func), Box::new(arg)));
1573 }
1574
1575 if self.bound_vars.contains(&ident) || self.current_function.as_ref() == Some(&ident) {
1577 Ok(Term::Var(ident))
1578 } else {
1579 match ident.as_str() {
1581 "Prop" => Ok(Term::Sort(Universe::Prop)),
1582 "Type" => Ok(Term::Sort(Universe::Type(0))),
1583 _ => Ok(Term::Global(ident)),
1584 }
1585 }
1586 }
1587
1588 fn parse_existential(&mut self) -> Result<Term, ParseError> {
1591 self.consume_keyword("there")?;
1592 self.skip_whitespace();
1593 self.consume_keyword("exists")?;
1594 self.skip_whitespace();
1595
1596 let _ = self.try_consume_keyword("an") || self.try_consume_keyword("a");
1598 self.skip_whitespace();
1599
1600 let var_name = self.parse_ident()?;
1602 self.skip_whitespace();
1603
1604 if !self.try_consume(":") {
1606 return Err(ParseError::Expected {
1607 expected: "':'".to_string(),
1608 found: self.peek_word().unwrap_or("EOF".to_string()),
1609 });
1610 }
1611 self.skip_whitespace();
1612
1613 let var_type = self.parse_type()?;
1615 self.skip_whitespace();
1616
1617 if !self.try_consume_keyword("such") {
1619 return Err(ParseError::Expected {
1620 expected: "'such'".to_string(),
1621 found: self.peek_word().unwrap_or("EOF".to_string()),
1622 });
1623 }
1624 self.skip_whitespace();
1625 if !self.try_consume_keyword("that") {
1626 return Err(ParseError::Expected {
1627 expected: "'that'".to_string(),
1628 found: self.peek_word().unwrap_or("EOF".to_string()),
1629 });
1630 }
1631 self.skip_whitespace();
1632
1633 self.bound_vars.insert(var_name.clone());
1635 let body = self.parse_term()?;
1636 self.bound_vars.remove(&var_name);
1637
1638 Ok(Term::App(
1640 Box::new(Term::App(
1641 Box::new(Term::Global("Ex".to_string())),
1642 Box::new(var_type),
1643 )),
1644 Box::new(Term::Lambda {
1645 param: var_name,
1646 param_type: Box::new(Term::Global("_".to_string())), body: Box::new(body),
1648 }),
1649 ))
1650 }
1651
1652 fn parse_type(&mut self) -> Result<Term, ParseError> {
1654 self.skip_whitespace();
1655
1656 let base = self.parse_ident()?;
1658
1659 self.skip_whitespace();
1660
1661 if self.try_consume_keyword("of") {
1663 self.skip_whitespace();
1664 let arg = self.parse_type()?;
1665 return Ok(Term::App(
1666 Box::new(Term::Global(base)),
1667 Box::new(arg),
1668 ));
1669 }
1670
1671 match base.as_str() {
1673 "Prop" => Ok(Term::Sort(Universe::Prop)),
1674 "Type" => Ok(Term::Sort(Universe::Type(0))),
1675 _ => Ok(Term::Global(base)),
1676 }
1677 }
1678
1679 fn parse_number(&mut self) -> Result<Term, ParseError> {
1681 let mut num_str = String::new();
1682
1683 if self.peek_char('-') {
1685 num_str.push('-');
1686 self.advance();
1687 }
1688
1689 while let Some(c) = self.peek() {
1691 if c.is_ascii_digit() {
1692 num_str.push(c);
1693 self.advance();
1694 } else {
1695 break;
1696 }
1697 }
1698
1699 let value: i64 = num_str
1700 .parse()
1701 .map_err(|_| ParseError::InvalidNumber(num_str))?;
1702
1703 Ok(Term::Lit(Literal::Int(value)))
1704 }
1705
1706 fn parse_string(&mut self) -> Result<Term, ParseError> {
1708 self.advance(); let mut content = String::new();
1711 loop {
1712 match self.peek() {
1713 Some('"') => {
1714 self.advance();
1715 break;
1716 }
1717 Some('\\') => {
1718 self.advance();
1719 match self.peek() {
1720 Some('n') => {
1721 content.push('\n');
1722 self.advance();
1723 }
1724 Some('t') => {
1725 content.push('\t');
1726 self.advance();
1727 }
1728 Some(c) => {
1729 content.push(c);
1730 self.advance();
1731 }
1732 None => return Err(ParseError::UnexpectedEof),
1733 }
1734 }
1735 Some(c) => {
1736 content.push(c);
1737 self.advance();
1738 }
1739 None => return Err(ParseError::UnexpectedEof),
1740 }
1741 }
1742
1743 Ok(Term::Lit(Literal::Text(content)))
1744 }
1745
1746 fn term_to_syntax(&self, term: &Term, bound_vars: &[String]) -> Term {
1753 match term {
1754 Term::Var(name) => {
1755 if let Some(idx) = bound_vars.iter().rev().position(|n| n == name) {
1757 Term::App(
1758 Box::new(Term::Global("SVar".to_string())),
1759 Box::new(Term::Lit(Literal::Int(idx as i64))),
1760 )
1761 } else {
1762 Term::App(
1764 Box::new(Term::Global("SName".to_string())),
1765 Box::new(Term::Lit(Literal::Text(name.clone()))),
1766 )
1767 }
1768 }
1769 Term::Global(name) => {
1770 Term::App(
1772 Box::new(Term::Global("SName".to_string())),
1773 Box::new(Term::Lit(Literal::Text(name.clone()))),
1774 )
1775 }
1776 Term::Lit(Literal::Int(n)) => {
1777 Term::App(
1779 Box::new(Term::Global("SLit".to_string())),
1780 Box::new(Term::Lit(Literal::Int(*n))),
1781 )
1782 }
1783 Term::Lit(Literal::Float(_f)) => {
1784 Term::App(
1786 Box::new(Term::Global("SName".to_string())),
1787 Box::new(Term::Lit(Literal::Text("Error_Float".to_string()))),
1788 )
1789 }
1790 Term::Lit(Literal::Duration(_d)) => {
1791 Term::App(
1793 Box::new(Term::Global("SName".to_string())),
1794 Box::new(Term::Lit(Literal::Text("Error_Duration".to_string()))),
1795 )
1796 }
1797 Term::Lit(Literal::Date(_d)) => {
1798 Term::App(
1800 Box::new(Term::Global("SName".to_string())),
1801 Box::new(Term::Lit(Literal::Text("Error_Date".to_string()))),
1802 )
1803 }
1804 Term::Lit(Literal::Moment(_m)) => {
1805 Term::App(
1807 Box::new(Term::Global("SName".to_string())),
1808 Box::new(Term::Lit(Literal::Text("Error_Moment".to_string()))),
1809 )
1810 }
1811 Term::Lit(Literal::Text(s)) => {
1812 Term::App(
1814 Box::new(Term::Global("SName".to_string())),
1815 Box::new(Term::Lit(Literal::Text(s.clone()))),
1816 )
1817 }
1818 Term::App(f, x) => {
1819 let f_syn = self.term_to_syntax(f, bound_vars);
1821 let x_syn = self.term_to_syntax(x, bound_vars);
1822 Term::App(
1823 Box::new(Term::App(
1824 Box::new(Term::Global("SApp".to_string())),
1825 Box::new(f_syn),
1826 )),
1827 Box::new(x_syn),
1828 )
1829 }
1830 Term::Lambda { param, param_type, body } => {
1831 let ty_syn = self.term_to_syntax(param_type, bound_vars);
1833 let mut new_bound = bound_vars.to_vec();
1834 new_bound.push(param.clone());
1835 let body_syn = self.term_to_syntax(body, &new_bound);
1836 Term::App(
1837 Box::new(Term::App(
1838 Box::new(Term::Global("SLam".to_string())),
1839 Box::new(ty_syn),
1840 )),
1841 Box::new(body_syn),
1842 )
1843 }
1844 Term::Pi { param, param_type, body_type } => {
1845 let ty_syn = self.term_to_syntax(param_type, bound_vars);
1847 let mut new_bound = bound_vars.to_vec();
1848 new_bound.push(param.clone());
1849 let body_syn = self.term_to_syntax(body_type, &new_bound);
1850 Term::App(
1851 Box::new(Term::App(
1852 Box::new(Term::Global("SPi".to_string())),
1853 Box::new(ty_syn),
1854 )),
1855 Box::new(body_syn),
1856 )
1857 }
1858 Term::Sort(Universe::Prop) => {
1859 Term::App(
1861 Box::new(Term::Global("SSort".to_string())),
1862 Box::new(Term::Global("UProp".to_string())),
1863 )
1864 }
1865 Term::Sort(Universe::Type(n)) => {
1866 Term::App(
1868 Box::new(Term::Global("SSort".to_string())),
1869 Box::new(Term::App(
1870 Box::new(Term::Global("UType".to_string())),
1871 Box::new(Term::Lit(Literal::Int(*n as i64))),
1872 )),
1873 )
1874 }
1875 Term::Hole => {
1876 Term::App(
1878 Box::new(Term::Global("SName".to_string())),
1879 Box::new(Term::Lit(Literal::Text("Int".to_string()))),
1880 )
1881 }
1882 Term::Match { .. } | Term::Fix { .. } => {
1883 Term::App(
1885 Box::new(Term::Global("SName".to_string())),
1886 Box::new(Term::Lit(Literal::Text("Error".to_string()))),
1887 )
1888 }
1889 }
1890 }
1891
1892 fn contains_self_reference(&self, name: &str, term: &Term) -> bool {
1898 match term {
1899 Term::Var(v) => v == name,
1900 Term::Global(_) => false,
1901 Term::Sort(_) => false,
1902 Term::Lit(_) => false,
1903 Term::Pi { param_type, body_type, .. } => {
1904 self.contains_self_reference(name, param_type)
1905 || self.contains_self_reference(name, body_type)
1906 }
1907 Term::Lambda { param_type, body, .. } => {
1908 self.contains_self_reference(name, param_type)
1909 || self.contains_self_reference(name, body)
1910 }
1911 Term::App(f, a) => {
1912 self.contains_self_reference(name, f) || self.contains_self_reference(name, a)
1913 }
1914 Term::Match { discriminant, motive, cases } => {
1915 self.contains_self_reference(name, discriminant)
1916 || self.contains_self_reference(name, motive)
1917 || cases.iter().any(|c| self.contains_self_reference(name, c))
1918 }
1919 Term::Fix { body, .. } => self.contains_self_reference(name, body),
1920 Term::Hole => false, }
1922 }
1923
1924 fn skip_whitespace(&mut self) {
1929 while let Some(c) = self.peek() {
1930 if c == ' ' || c == '\t' {
1931 self.advance();
1932 } else {
1933 break;
1934 }
1935 }
1936 }
1937
1938 fn skip_whitespace_and_newlines(&mut self) {
1939 while let Some(c) = self.peek() {
1940 if c.is_whitespace() {
1941 self.advance();
1942 } else {
1943 break;
1944 }
1945 }
1946 }
1947
1948 fn peek(&self) -> Option<char> {
1949 self.input[self.pos..].chars().next()
1950 }
1951
1952 fn peek_char(&self, c: char) -> bool {
1953 self.peek() == Some(c)
1954 }
1955
1956 fn peek_keyword(&self, keyword: &str) -> bool {
1957 if !self.input[self.pos..].starts_with(keyword) {
1958 return false;
1959 }
1960 let after = self.pos + keyword.len();
1961 if after >= self.input.len() {
1962 return true;
1963 }
1964 let next_char = self.input[after..].chars().next();
1965 !next_char.map(|c| c.is_alphanumeric() || c == '_').unwrap_or(false)
1966 }
1967
1968 fn peek_word(&self) -> Option<String> {
1969 let start = self.pos;
1970 let mut end = start;
1971 for c in self.input[start..].chars() {
1972 if c.is_alphanumeric() || c == '_' {
1973 end += c.len_utf8();
1974 } else {
1975 break;
1976 }
1977 }
1978 if end > start {
1979 Some(self.input[start..end].to_string())
1980 } else {
1981 self.peek().map(|c| c.to_string())
1982 }
1983 }
1984
1985 fn advance(&mut self) {
1986 if let Some(c) = self.peek() {
1987 self.pos += c.len_utf8();
1988 }
1989 }
1990
1991 fn at_end(&self) -> bool {
1992 self.pos >= self.input.len()
1993 }
1994
1995 fn try_consume(&mut self, s: &str) -> bool {
1996 if self.input[self.pos..].starts_with(s) {
1997 self.pos += s.len();
1998 true
1999 } else {
2000 false
2001 }
2002 }
2003
2004 fn try_consume_keyword(&mut self, keyword: &str) -> bool {
2005 if self.peek_keyword(keyword) {
2006 self.pos += keyword.len();
2007 true
2008 } else {
2009 false
2010 }
2011 }
2012
2013 fn consume_keyword(&mut self, keyword: &str) -> Result<(), ParseError> {
2014 if self.try_consume_keyword(keyword) {
2015 Ok(())
2016 } else {
2017 Err(ParseError::Expected {
2018 expected: format!("'{}'", keyword),
2019 found: self.peek_word().unwrap_or("EOF".to_string()),
2020 })
2021 }
2022 }
2023
2024 fn parse_ident(&mut self) -> Result<String, ParseError> {
2025 self.skip_whitespace();
2026 let start = self.pos;
2027
2028 if let Some(c) = self.peek() {
2030 if !c.is_alphabetic() && c != '_' {
2031 return Err(ParseError::Expected {
2032 expected: "identifier".to_string(),
2033 found: c.to_string(),
2034 });
2035 }
2036 } else {
2037 return Err(ParseError::UnexpectedEof);
2038 }
2039
2040 while let Some(c) = self.peek() {
2042 if c.is_alphanumeric() || c == '_' {
2043 self.advance();
2044 } else {
2045 break;
2046 }
2047 }
2048
2049 let ident = self.input[start..self.pos].to_string();
2050 if ident.is_empty() {
2051 Err(ParseError::InvalidIdent("empty".to_string()))
2052 } else {
2053 Ok(ident)
2054 }
2055 }
2056
2057 fn peek_negative_number(&self) -> bool {
2063 if !self.peek_char('-') {
2064 return false;
2065 }
2066 self.input.get(self.pos + 1..)
2067 .and_then(|s| s.chars().next())
2068 .map(|c| c.is_ascii_digit())
2069 .unwrap_or(false)
2070 }
2071
2072 fn peek_arrow(&self) -> bool {
2074 self.input[self.pos..].starts_with("->")
2075 }
2076
2077 fn peek_comparison_operator(&self) -> bool {
2079 let rest = &self.input[self.pos..];
2080 rest.starts_with("<=") || rest.starts_with(">=")
2081 || rest.starts_with("≤") || rest.starts_with("≥")
2082 || rest.starts_with('<') || rest.starts_with('>')
2083 }
2084}
2085
2086#[cfg(test)]
2091mod tests {
2092 use super::*;
2093
2094 #[test]
2095 fn test_parse_simple_inductive() {
2096 let cmd = parse_inductive("A Bool is either Yes or No").unwrap();
2097 if let Command::Inductive { name, constructors, .. } = cmd {
2098 assert_eq!(name, "Bool");
2099 assert_eq!(constructors.len(), 2);
2100 assert_eq!(constructors[0].0, "Yes");
2101 assert_eq!(constructors[1].0, "No");
2102 } else {
2103 panic!("Expected Inductive command");
2104 }
2105 }
2106
2107 #[test]
2108 fn test_parse_inductive_with_article() {
2109 let cmd = parse_inductive("A Decision is either a Yes or a No").unwrap();
2110 if let Command::Inductive { name, constructors, .. } = cmd {
2111 assert_eq!(name, "Decision");
2112 assert_eq!(constructors.len(), 2);
2113 } else {
2114 panic!("Expected Inductive command");
2115 }
2116 }
2117
2118 #[test]
2119 fn test_parse_recursive_inductive() {
2120 let cmd = parse_inductive("A Nat is either Zero or a Succ with pred: Nat").unwrap();
2121 if let Command::Inductive { name, constructors, .. } = cmd {
2122 assert_eq!(name, "Nat");
2123 assert_eq!(constructors.len(), 2);
2124 assert_eq!(constructors[0].0, "Zero");
2125 assert_eq!(constructors[1].0, "Succ");
2126 if let Term::Pi { .. } = &constructors[1].1 {
2128 } else {
2130 panic!("Expected Succ to have Pi type");
2131 }
2132 } else {
2133 panic!("Expected Inductive command");
2134 }
2135 }
2136
2137 #[test]
2138 fn test_parse_simple_definition() {
2139 let cmd = parse_definition("## To id (x: Nat) -> Nat: Yield x").unwrap();
2140 if let Command::Definition { name, body, .. } = cmd {
2141 assert_eq!(name, "id");
2142 if let Term::Lambda { param, .. } = body {
2144 assert_eq!(param, "x");
2145 } else {
2146 panic!("Expected Lambda body");
2147 }
2148 } else {
2149 panic!("Expected Definition command");
2150 }
2151 }
2152
2153 #[test]
2154 fn test_implicit_fixpoint_detection() {
2155 let cmd = parse_definition(
2157 "## To add (n: Nat) and (m: Nat) -> Nat: Consider n: When Zero: Yield m. When Succ k: Yield Succ (add k m)."
2158 ).unwrap();
2159
2160 if let Command::Definition { name, body, .. } = cmd {
2161 assert_eq!(name, "add");
2162 if let Term::Fix { name: fix_name, .. } = body {
2164 assert_eq!(fix_name, "add");
2165 } else {
2166 panic!("Expected Fix wrapper for recursive function");
2167 }
2168 } else {
2169 panic!("Expected Definition command");
2170 }
2171 }
2172
2173 #[test]
2174 fn test_parse_given_lambda() {
2175 let mut parser = LiterateParser::new("given x: Nat yields Succ x");
2176 let term = parser.parse_given_lambda().unwrap();
2177
2178 if let Term::Lambda { param, .. } = term {
2179 assert_eq!(param, "x");
2180 } else {
2181 panic!("Expected Lambda");
2182 }
2183 }
2184
2185 #[test]
2186 fn test_parse_pipe_lambda() {
2187 let mut parser = LiterateParser::new("|x: Nat| -> Succ x");
2188 let term = parser.parse_pipe_lambda().unwrap();
2189
2190 if let Term::Lambda { param, .. } = term {
2191 assert_eq!(param, "x");
2192 } else {
2193 panic!("Expected Lambda");
2194 }
2195 }
2196
2197 #[test]
2202 fn test_parse_let_definition() {
2203 let cmd = parse_let_definition("Let T be Zero").unwrap();
2204 if let Command::Definition { name, ty, body, .. } = cmd {
2205 assert_eq!(name, "T");
2206 assert!(ty.is_none());
2207 if let Term::Global(g) = body {
2208 assert_eq!(g, "Zero");
2209 } else {
2210 panic!("Expected Global term");
2211 }
2212 } else {
2213 panic!("Expected Definition command");
2214 }
2215 }
2216
2217 #[test]
2218 fn test_parse_name_syntax() {
2219 let mut parser = LiterateParser::new("Name \"Not\"");
2220 let term = parser.parse_term().unwrap();
2221
2222 if let Term::App(f, arg) = term {
2224 if let Term::Global(g) = *f {
2225 assert_eq!(g, "SName");
2226 } else {
2227 panic!("Expected Global SName");
2228 }
2229 if let Term::Lit(Literal::Text(s)) = *arg {
2230 assert_eq!(s, "Not");
2231 } else {
2232 panic!("Expected Text literal");
2233 }
2234 } else {
2235 panic!("Expected App");
2236 }
2237 }
2238
2239 #[test]
2240 fn test_parse_variable_syntax() {
2241 let mut parser = LiterateParser::new("Variable 0");
2242 let term = parser.parse_term().unwrap();
2243
2244 if let Term::App(f, arg) = term {
2246 if let Term::Global(g) = *f {
2247 assert_eq!(g, "SVar");
2248 } else {
2249 panic!("Expected Global SVar");
2250 }
2251 if let Term::Lit(Literal::Int(n)) = *arg {
2252 assert_eq!(n, 0);
2253 } else {
2254 panic!("Expected Int literal");
2255 }
2256 } else {
2257 panic!("Expected App");
2258 }
2259 }
2260
2261 #[test]
2262 fn test_parse_apply_syntax() {
2263 let mut parser = LiterateParser::new("Apply(Name \"Not\", Variable 0)");
2264 let term = parser.parse_term().unwrap();
2265
2266 if let Term::App(outer_f, _outer_arg) = term {
2268 if let Term::App(inner_f, _inner_arg) = *outer_f {
2269 if let Term::Global(g) = *inner_f {
2270 assert_eq!(g, "SApp");
2271 } else {
2272 panic!("Expected Global SApp");
2273 }
2274 } else {
2275 panic!("Expected inner App");
2276 }
2277 } else {
2278 panic!("Expected outer App");
2279 }
2280 }
2281
2282 #[test]
2283 fn test_parse_diagonalization() {
2284 let mut parser = LiterateParser::new("the diagonalization of T");
2285 let term = parser.parse_term().unwrap();
2286
2287 if let Term::App(f, arg) = term {
2289 if let Term::Global(g) = *f {
2290 assert_eq!(g, "syn_diag");
2291 } else {
2292 panic!("Expected Global syn_diag");
2293 }
2294 if let Term::Global(a) = *arg {
2295 assert_eq!(a, "T");
2296 } else {
2297 panic!("Expected Global T");
2298 }
2299 } else {
2300 panic!("Expected App");
2301 }
2302 }
2303
2304 #[test]
2305 fn test_parse_implies() {
2306 let mut parser = LiterateParser::new("A implies B");
2307 let term = parser.parse_term().unwrap();
2308
2309 if let Term::Pi { param, param_type, body_type } = term {
2311 assert_eq!(param, "_");
2312 if let Term::Global(a) = *param_type {
2313 assert_eq!(a, "A");
2314 } else {
2315 panic!("Expected Global A");
2316 }
2317 if let Term::Global(b) = *body_type {
2318 assert_eq!(b, "B");
2319 } else {
2320 panic!("Expected Global B");
2321 }
2322 } else {
2323 panic!("Expected Pi");
2324 }
2325 }
2326
2327 #[test]
2328 fn test_parse_existential() {
2329 let mut parser = LiterateParser::new("there exists a d: Derivation such that P");
2330 let term = parser.parse_term().unwrap();
2331
2332 if let Term::App(outer_f, lambda) = term {
2334 if let Term::App(ex, typ) = *outer_f {
2335 if let Term::Global(g) = *ex {
2336 assert_eq!(g, "Ex");
2337 } else {
2338 panic!("Expected Global Ex");
2339 }
2340 if let Term::Global(t) = *typ {
2341 assert_eq!(t, "Derivation");
2342 } else {
2343 panic!("Expected Global Derivation");
2344 }
2345 } else {
2346 panic!("Expected inner App for Ex");
2347 }
2348 if let Term::Lambda { param, body, .. } = *lambda {
2349 assert_eq!(param, "d");
2350 if let Term::Global(p) = *body {
2351 assert_eq!(p, "P");
2352 } else {
2353 panic!("Expected Global P in lambda body");
2354 }
2355 } else {
2356 panic!("Expected Lambda");
2357 }
2358 } else {
2359 panic!("Expected App");
2360 }
2361 }
2362
2363 #[test]
2364 fn test_parse_complex_let_with_apply() {
2365 let cmd = parse_let_definition("Let T be Apply(Name \"Not\", Apply(Name \"Provable\", Variable 0)).").unwrap();
2366 if let Command::Definition { name, ty, body, .. } = cmd {
2367 assert_eq!(name, "T");
2368 assert!(ty.is_none());
2369 if let Term::App(_, _) = body {
2371 } else {
2373 panic!("Expected App body");
2374 }
2375 } else {
2376 panic!("Expected Definition command");
2377 }
2378 }
2379
2380 #[test]
2385 fn test_parse_predicate_definition() {
2386 let cmd = parse_definition("## To be Provable (s: Syntax) -> Prop: Yield s").unwrap();
2388 if let Command::Definition { name, .. } = cmd {
2389 assert_eq!(name, "Provable"); } else {
2391 panic!("Expected Definition command");
2392 }
2393 }
2394
2395 #[test]
2396 fn test_parse_nullary_predicate() {
2397 let cmd = parse_definition("## To be Consistent -> Prop: Yield True").unwrap();
2399 if let Command::Definition { name, body, .. } = cmd {
2400 assert_eq!(name, "Consistent");
2401 if let Term::Global(g) = body {
2403 assert_eq!(g, "True");
2404 } else {
2405 panic!("Expected Global True");
2406 }
2407 } else {
2408 panic!("Expected Definition command");
2409 }
2410 }
2411
2412 #[test]
2413 fn test_parse_the_name_syntax() {
2414 let mut parser = LiterateParser::new("the Name \"Not\"");
2416 let term = parser.parse_term().unwrap();
2417
2418 if let Term::App(f, arg) = term {
2419 if let Term::Global(g) = *f {
2420 assert_eq!(g, "SName");
2421 } else {
2422 panic!("Expected Global SName");
2423 }
2424 if let Term::Lit(Literal::Text(s)) = *arg {
2425 assert_eq!(s, "Not");
2426 } else {
2427 panic!("Expected Text literal");
2428 }
2429 } else {
2430 panic!("Expected App");
2431 }
2432 }
2433
2434 #[test]
2435 fn test_parse_theorem() {
2436 let cmd = parse_theorem("## Theorem: MyTheorem\n Statement: A implies B.").unwrap();
2438 if let Command::Definition { name, ty, body, .. } = cmd {
2439 assert_eq!(name, "MyTheorem");
2440 assert!(ty.is_some());
2442 if let Some(Term::Sort(Universe::Prop)) = ty {
2443 } else {
2445 panic!("Expected Prop type");
2446 }
2447 if let Term::Pi { .. } = body {
2449 } else {
2451 panic!("Expected Pi body (implication)");
2452 }
2453 } else {
2454 panic!("Expected Definition command");
2455 }
2456 }
2457
2458 #[test]
2459 fn test_parse_theorem_with_complex_statement() {
2460 let cmd = parse_theorem("## Theorem: Godel\n Statement: Consistent implies Not(Provable(G)).").unwrap();
2462 if let Command::Definition { name, ty, .. } = cmd {
2463 assert_eq!(name, "Godel");
2464 assert!(ty.is_some());
2465 if let Some(Term::Sort(Universe::Prop)) = ty {
2466 } else {
2468 panic!("Expected Prop type");
2469 }
2470 } else {
2471 panic!("Expected Definition command");
2472 }
2473 }
2474
2475 #[test]
2476 fn test_parse_equals_infix() {
2477 let mut parser = LiterateParser::new("A equals B");
2479 let term = parser.parse_term().unwrap();
2480
2481 if let Term::App(outer, rhs) = term {
2483 if let Term::Global(b) = *rhs {
2484 assert_eq!(b, "B");
2485 } else {
2486 panic!("Expected Global B");
2487 }
2488 if let Term::App(mid, lhs) = *outer {
2489 if let Term::Global(a) = *lhs {
2490 assert_eq!(a, "A");
2491 } else {
2492 panic!("Expected Global A");
2493 }
2494 if let Term::App(inner, placeholder) = *mid {
2495 if let Term::Global(eq) = *inner {
2496 assert_eq!(eq, "Eq");
2497 } else {
2498 panic!("Expected Global Eq");
2499 }
2500 if !matches!(*placeholder, Term::Hole) {
2501 panic!("Expected Hole placeholder");
2502 }
2503 } else {
2504 panic!("Expected inner App");
2505 }
2506 } else {
2507 panic!("Expected mid App");
2508 }
2509 } else {
2510 panic!("Expected outer App");
2511 }
2512 }
2513
2514 #[test]
2515 fn test_parse_equals_with_application() {
2516 let mut parser = LiterateParser::new("f(x) equals y");
2518 let term = parser.parse_term().unwrap();
2519
2520 if let Term::App(outer, rhs) = term {
2522 if let Term::Global(y) = *rhs {
2523 assert_eq!(y, "y");
2524 } else {
2525 panic!("Expected Global y");
2526 }
2527 if let Term::App(mid, lhs) = *outer {
2528 if let Term::App(f_box, x_box) = *lhs {
2530 if let Term::Global(f) = *f_box {
2531 assert_eq!(f, "f");
2532 }
2533 if let Term::Global(x) = *x_box {
2534 assert_eq!(x, "x");
2535 }
2536 } else {
2537 panic!("Expected lhs to be App(f, x)");
2538 }
2539 } else {
2540 panic!("Expected mid App");
2541 }
2542 } else {
2543 panic!("Expected outer App");
2544 }
2545 }
2546
2547 #[test]
2552 fn test_parse_infix_le() {
2553 let mut parser = LiterateParser::new("x <= y");
2554 let term = parser.parse_term().unwrap();
2555 if let Term::App(outer, rhs) = term {
2557 if let Term::App(inner, lhs) = *outer {
2558 if let Term::Global(op) = *inner {
2559 assert_eq!(op, "le");
2560 } else {
2561 panic!("Expected Global le");
2562 }
2563 if let Term::Global(l) = *lhs {
2564 assert_eq!(l, "x");
2565 } else {
2566 panic!("Expected Global x");
2567 }
2568 } else {
2569 panic!("Expected inner App");
2570 }
2571 if let Term::Global(r) = *rhs {
2572 assert_eq!(r, "y");
2573 } else {
2574 panic!("Expected Global y");
2575 }
2576 } else {
2577 panic!("Expected outer App");
2578 }
2579 }
2580
2581 #[test]
2582 fn test_parse_infix_lt() {
2583 let mut parser = LiterateParser::new("a < b");
2584 let term = parser.parse_term().unwrap();
2585 if let Term::App(outer, _) = term {
2586 if let Term::App(inner, _) = *outer {
2587 if let Term::Global(op) = *inner {
2588 assert_eq!(op, "lt");
2589 } else {
2590 panic!("Expected Global lt");
2591 }
2592 } else {
2593 panic!("Expected inner App");
2594 }
2595 } else {
2596 panic!("Expected outer App");
2597 }
2598 }
2599
2600 #[test]
2601 fn test_parse_infix_ge() {
2602 let mut parser = LiterateParser::new("x >= y");
2603 let term = parser.parse_term().unwrap();
2604 if let Term::App(outer, _) = term {
2605 if let Term::App(inner, _) = *outer {
2606 if let Term::Global(op) = *inner {
2607 assert_eq!(op, "ge");
2608 } else {
2609 panic!("Expected Global ge");
2610 }
2611 } else {
2612 panic!("Expected inner App");
2613 }
2614 } else {
2615 panic!("Expected outer App");
2616 }
2617 }
2618
2619 #[test]
2620 fn test_parse_infix_gt() {
2621 let mut parser = LiterateParser::new("x > y");
2622 let term = parser.parse_term().unwrap();
2623 if let Term::App(outer, _) = term {
2624 if let Term::App(inner, _) = *outer {
2625 if let Term::Global(op) = *inner {
2626 assert_eq!(op, "gt");
2627 } else {
2628 panic!("Expected Global gt");
2629 }
2630 } else {
2631 panic!("Expected inner App");
2632 }
2633 } else {
2634 panic!("Expected outer App");
2635 }
2636 }
2637
2638 #[test]
2639 fn test_parse_infix_add() {
2640 let mut parser = LiterateParser::new("x + y");
2641 let term = parser.parse_term().unwrap();
2642 if let Term::App(outer, _) = term {
2643 if let Term::App(inner, _) = *outer {
2644 if let Term::Global(op) = *inner {
2645 assert_eq!(op, "add");
2646 } else {
2647 panic!("Expected Global add");
2648 }
2649 } else {
2650 panic!("Expected inner App");
2651 }
2652 } else {
2653 panic!("Expected outer App");
2654 }
2655 }
2656
2657 #[test]
2658 fn test_parse_infix_sub() {
2659 let mut parser = LiterateParser::new("x - y");
2660 let term = parser.parse_term().unwrap();
2661 if let Term::App(outer, _) = term {
2662 if let Term::App(inner, _) = *outer {
2663 if let Term::Global(op) = *inner {
2664 assert_eq!(op, "sub");
2665 } else {
2666 panic!("Expected Global sub");
2667 }
2668 } else {
2669 panic!("Expected inner App");
2670 }
2671 } else {
2672 panic!("Expected outer App");
2673 }
2674 }
2675
2676 #[test]
2677 fn test_parse_infix_mul() {
2678 let mut parser = LiterateParser::new("x * y");
2679 let term = parser.parse_term().unwrap();
2680 if let Term::App(outer, _) = term {
2681 if let Term::App(inner, _) = *outer {
2682 if let Term::Global(op) = *inner {
2683 assert_eq!(op, "mul");
2684 } else {
2685 panic!("Expected Global mul");
2686 }
2687 } else {
2688 panic!("Expected inner App");
2689 }
2690 } else {
2691 panic!("Expected outer App");
2692 }
2693 }
2694
2695 #[test]
2696 fn test_parse_precedence_mul_over_add() {
2697 let mut parser = LiterateParser::new("x + y * z");
2699 let term = parser.parse_term().unwrap();
2700 if let Term::App(outer, rhs) = term {
2702 if let Term::App(inner, _) = *outer {
2703 if let Term::Global(op) = *inner {
2704 assert_eq!(op, "add");
2705 } else {
2706 panic!("Expected add");
2707 }
2708 } else {
2709 panic!("Expected inner App");
2710 }
2711 if let Term::App(mul_outer, _) = *rhs {
2713 if let Term::App(mul_inner, _) = *mul_outer {
2714 if let Term::Global(op) = *mul_inner {
2715 assert_eq!(op, "mul");
2716 } else {
2717 panic!("Expected mul");
2718 }
2719 } else {
2720 panic!("Expected mul inner App");
2721 }
2722 } else {
2723 panic!("Expected mul App");
2724 }
2725 } else {
2726 panic!("Expected outer App");
2727 }
2728 }
2729
2730 #[test]
2731 fn test_parse_left_associative_add() {
2732 let mut parser = LiterateParser::new("x + y + z");
2734 let term = parser.parse_term().unwrap();
2735 if let Term::App(outer, rhs) = term {
2737 if let Term::Global(z) = *rhs {
2738 assert_eq!(z, "z");
2739 } else {
2740 panic!("Expected z");
2741 }
2742 if let Term::App(mid, lhs_add) = *outer {
2743 if let Term::Global(op) = *mid {
2744 assert_eq!(op, "add");
2745 }
2746 if let Term::App(inner_outer, _) = *lhs_add {
2748 if let Term::App(inner_inner, _) = *inner_outer {
2749 if let Term::Global(op2) = *inner_inner {
2750 assert_eq!(op2, "add");
2751 }
2752 }
2753 }
2754 }
2755 } else {
2756 panic!("Expected App");
2757 }
2758 }
2759
2760 #[test]
2761 fn test_parse_comparison_with_arithmetic() {
2762 let mut parser = LiterateParser::new("x + 1 <= y * 2");
2764 let term = parser.parse_term().unwrap();
2765 if let Term::App(outer, _) = term {
2766 if let Term::App(inner, _) = *outer {
2767 if let Term::Global(op) = *inner {
2768 assert_eq!(op, "le");
2769 } else {
2770 panic!("Expected le");
2771 }
2772 } else {
2773 panic!("Expected inner App");
2774 }
2775 } else {
2776 panic!("Expected outer App");
2777 }
2778 }
2779
2780 #[test]
2781 fn test_parse_unicode_le() {
2782 let mut parser = LiterateParser::new("x ≤ y");
2783 let term = parser.parse_term().unwrap();
2784 if let Term::App(outer, _) = term {
2785 if let Term::App(inner, _) = *outer {
2786 if let Term::Global(op) = *inner {
2787 assert_eq!(op, "le");
2788 } else {
2789 panic!("Expected le for ≤");
2790 }
2791 }
2792 } else {
2793 panic!("Expected App");
2794 }
2795 }
2796
2797 #[test]
2798 fn test_parse_unicode_ge() {
2799 let mut parser = LiterateParser::new("x ≥ y");
2800 let term = parser.parse_term().unwrap();
2801 if let Term::App(outer, _) = term {
2802 if let Term::App(inner, _) = *outer {
2803 if let Term::Global(op) = *inner {
2804 assert_eq!(op, "ge");
2805 } else {
2806 panic!("Expected ge for ≥");
2807 }
2808 }
2809 } else {
2810 panic!("Expected App");
2811 }
2812 }
2813
2814 #[test]
2815 fn test_parse_negative_number_preserved() {
2816 let mut parser = LiterateParser::new("-5 + x");
2818 let term = parser.parse_term().unwrap();
2819 if let Term::App(outer, _) = term {
2821 if let Term::App(inner, lhs) = *outer {
2822 if let Term::Global(op) = *inner {
2823 assert_eq!(op, "add");
2824 }
2825 if let Term::Lit(Literal::Int(n)) = *lhs {
2826 assert_eq!(n, -5);
2827 } else {
2828 panic!("Expected -5 literal");
2829 }
2830 }
2831 } else {
2832 panic!("Expected App");
2833 }
2834 }
2835
2836 #[test]
2837 fn test_parse_subtraction_not_negative() {
2838 let mut parser = LiterateParser::new("x - 5");
2840 let term = parser.parse_term().unwrap();
2841 if let Term::App(outer, rhs) = term {
2842 if let Term::App(inner, _) = *outer {
2843 if let Term::Global(op) = *inner {
2844 assert_eq!(op, "sub");
2845 }
2846 }
2847 if let Term::Lit(Literal::Int(n)) = *rhs {
2848 assert_eq!(n, 5); } else {
2850 panic!("Expected 5 literal");
2851 }
2852 } else {
2853 panic!("Expected App");
2854 }
2855 }
2856
2857 #[test]
2858 fn test_parse_infix_with_sexp_mix() {
2859 let mut parser = LiterateParser::new("(add x y) <= z");
2861 let term = parser.parse_term().unwrap();
2862 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, "le");
2866 }
2867 if let Term::App(add_outer, _) = *lhs {
2869 if let Term::App(add_inner, _) = *add_outer {
2870 if let Term::Global(add_op) = *add_inner {
2871 assert_eq!(add_op, "add");
2872 }
2873 }
2874 }
2875 }
2876 } else {
2877 panic!("Expected App");
2878 }
2879 }
2880}