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::Text(s)) => {
1791 Term::App(
1793 Box::new(Term::Global("SName".to_string())),
1794 Box::new(Term::Lit(Literal::Text(s.clone()))),
1795 )
1796 }
1797 Term::App(f, x) => {
1798 let f_syn = self.term_to_syntax(f, bound_vars);
1800 let x_syn = self.term_to_syntax(x, bound_vars);
1801 Term::App(
1802 Box::new(Term::App(
1803 Box::new(Term::Global("SApp".to_string())),
1804 Box::new(f_syn),
1805 )),
1806 Box::new(x_syn),
1807 )
1808 }
1809 Term::Lambda { param, param_type, body } => {
1810 let ty_syn = self.term_to_syntax(param_type, bound_vars);
1812 let mut new_bound = bound_vars.to_vec();
1813 new_bound.push(param.clone());
1814 let body_syn = self.term_to_syntax(body, &new_bound);
1815 Term::App(
1816 Box::new(Term::App(
1817 Box::new(Term::Global("SLam".to_string())),
1818 Box::new(ty_syn),
1819 )),
1820 Box::new(body_syn),
1821 )
1822 }
1823 Term::Pi { param, param_type, body_type } => {
1824 let ty_syn = self.term_to_syntax(param_type, bound_vars);
1826 let mut new_bound = bound_vars.to_vec();
1827 new_bound.push(param.clone());
1828 let body_syn = self.term_to_syntax(body_type, &new_bound);
1829 Term::App(
1830 Box::new(Term::App(
1831 Box::new(Term::Global("SPi".to_string())),
1832 Box::new(ty_syn),
1833 )),
1834 Box::new(body_syn),
1835 )
1836 }
1837 Term::Sort(Universe::Prop) => {
1838 Term::App(
1840 Box::new(Term::Global("SSort".to_string())),
1841 Box::new(Term::Global("UProp".to_string())),
1842 )
1843 }
1844 Term::Sort(Universe::Type(n)) => {
1845 Term::App(
1847 Box::new(Term::Global("SSort".to_string())),
1848 Box::new(Term::App(
1849 Box::new(Term::Global("UType".to_string())),
1850 Box::new(Term::Lit(Literal::Int(*n as i64))),
1851 )),
1852 )
1853 }
1854 Term::Hole => {
1855 Term::App(
1857 Box::new(Term::Global("SName".to_string())),
1858 Box::new(Term::Lit(Literal::Text("Int".to_string()))),
1859 )
1860 }
1861 Term::Match { .. } | Term::Fix { .. } => {
1862 Term::App(
1864 Box::new(Term::Global("SName".to_string())),
1865 Box::new(Term::Lit(Literal::Text("Error".to_string()))),
1866 )
1867 }
1868 }
1869 }
1870
1871 fn contains_self_reference(&self, name: &str, term: &Term) -> bool {
1877 match term {
1878 Term::Var(v) => v == name,
1879 Term::Global(_) => false,
1880 Term::Sort(_) => false,
1881 Term::Lit(_) => false,
1882 Term::Pi { param_type, body_type, .. } => {
1883 self.contains_self_reference(name, param_type)
1884 || self.contains_self_reference(name, body_type)
1885 }
1886 Term::Lambda { param_type, body, .. } => {
1887 self.contains_self_reference(name, param_type)
1888 || self.contains_self_reference(name, body)
1889 }
1890 Term::App(f, a) => {
1891 self.contains_self_reference(name, f) || self.contains_self_reference(name, a)
1892 }
1893 Term::Match { discriminant, motive, cases } => {
1894 self.contains_self_reference(name, discriminant)
1895 || self.contains_self_reference(name, motive)
1896 || cases.iter().any(|c| self.contains_self_reference(name, c))
1897 }
1898 Term::Fix { body, .. } => self.contains_self_reference(name, body),
1899 Term::Hole => false, }
1901 }
1902
1903 fn skip_whitespace(&mut self) {
1908 while let Some(c) = self.peek() {
1909 if c == ' ' || c == '\t' {
1910 self.advance();
1911 } else {
1912 break;
1913 }
1914 }
1915 }
1916
1917 fn skip_whitespace_and_newlines(&mut self) {
1918 while let Some(c) = self.peek() {
1919 if c.is_whitespace() {
1920 self.advance();
1921 } else {
1922 break;
1923 }
1924 }
1925 }
1926
1927 fn peek(&self) -> Option<char> {
1928 self.input[self.pos..].chars().next()
1929 }
1930
1931 fn peek_char(&self, c: char) -> bool {
1932 self.peek() == Some(c)
1933 }
1934
1935 fn peek_keyword(&self, keyword: &str) -> bool {
1936 if !self.input[self.pos..].starts_with(keyword) {
1937 return false;
1938 }
1939 let after = self.pos + keyword.len();
1940 if after >= self.input.len() {
1941 return true;
1942 }
1943 let next_char = self.input[after..].chars().next();
1944 !next_char.map(|c| c.is_alphanumeric() || c == '_').unwrap_or(false)
1945 }
1946
1947 fn peek_word(&self) -> Option<String> {
1948 let start = self.pos;
1949 let mut end = start;
1950 for c in self.input[start..].chars() {
1951 if c.is_alphanumeric() || c == '_' {
1952 end += c.len_utf8();
1953 } else {
1954 break;
1955 }
1956 }
1957 if end > start {
1958 Some(self.input[start..end].to_string())
1959 } else {
1960 self.peek().map(|c| c.to_string())
1961 }
1962 }
1963
1964 fn advance(&mut self) {
1965 if let Some(c) = self.peek() {
1966 self.pos += c.len_utf8();
1967 }
1968 }
1969
1970 fn at_end(&self) -> bool {
1971 self.pos >= self.input.len()
1972 }
1973
1974 fn try_consume(&mut self, s: &str) -> bool {
1975 if self.input[self.pos..].starts_with(s) {
1976 self.pos += s.len();
1977 true
1978 } else {
1979 false
1980 }
1981 }
1982
1983 fn try_consume_keyword(&mut self, keyword: &str) -> bool {
1984 if self.peek_keyword(keyword) {
1985 self.pos += keyword.len();
1986 true
1987 } else {
1988 false
1989 }
1990 }
1991
1992 fn consume_keyword(&mut self, keyword: &str) -> Result<(), ParseError> {
1993 if self.try_consume_keyword(keyword) {
1994 Ok(())
1995 } else {
1996 Err(ParseError::Expected {
1997 expected: format!("'{}'", keyword),
1998 found: self.peek_word().unwrap_or("EOF".to_string()),
1999 })
2000 }
2001 }
2002
2003 fn parse_ident(&mut self) -> Result<String, ParseError> {
2004 self.skip_whitespace();
2005 let start = self.pos;
2006
2007 if let Some(c) = self.peek() {
2009 if !c.is_alphabetic() && c != '_' {
2010 return Err(ParseError::Expected {
2011 expected: "identifier".to_string(),
2012 found: c.to_string(),
2013 });
2014 }
2015 } else {
2016 return Err(ParseError::UnexpectedEof);
2017 }
2018
2019 while let Some(c) = self.peek() {
2021 if c.is_alphanumeric() || c == '_' {
2022 self.advance();
2023 } else {
2024 break;
2025 }
2026 }
2027
2028 let ident = self.input[start..self.pos].to_string();
2029 if ident.is_empty() {
2030 Err(ParseError::InvalidIdent("empty".to_string()))
2031 } else {
2032 Ok(ident)
2033 }
2034 }
2035
2036 fn peek_negative_number(&self) -> bool {
2042 if !self.peek_char('-') {
2043 return false;
2044 }
2045 self.input.get(self.pos + 1..)
2046 .and_then(|s| s.chars().next())
2047 .map(|c| c.is_ascii_digit())
2048 .unwrap_or(false)
2049 }
2050
2051 fn peek_arrow(&self) -> bool {
2053 self.input[self.pos..].starts_with("->")
2054 }
2055
2056 fn peek_comparison_operator(&self) -> bool {
2058 let rest = &self.input[self.pos..];
2059 rest.starts_with("<=") || rest.starts_with(">=")
2060 || rest.starts_with("≤") || rest.starts_with("≥")
2061 || rest.starts_with('<') || rest.starts_with('>')
2062 }
2063}
2064
2065#[cfg(test)]
2070mod tests {
2071 use super::*;
2072
2073 #[test]
2074 fn test_parse_simple_inductive() {
2075 let cmd = parse_inductive("A Bool is either Yes or No").unwrap();
2076 if let Command::Inductive { name, constructors, .. } = cmd {
2077 assert_eq!(name, "Bool");
2078 assert_eq!(constructors.len(), 2);
2079 assert_eq!(constructors[0].0, "Yes");
2080 assert_eq!(constructors[1].0, "No");
2081 } else {
2082 panic!("Expected Inductive command");
2083 }
2084 }
2085
2086 #[test]
2087 fn test_parse_inductive_with_article() {
2088 let cmd = parse_inductive("A Decision is either a Yes or a No").unwrap();
2089 if let Command::Inductive { name, constructors, .. } = cmd {
2090 assert_eq!(name, "Decision");
2091 assert_eq!(constructors.len(), 2);
2092 } else {
2093 panic!("Expected Inductive command");
2094 }
2095 }
2096
2097 #[test]
2098 fn test_parse_recursive_inductive() {
2099 let cmd = parse_inductive("A Nat is either Zero or a Succ with pred: Nat").unwrap();
2100 if let Command::Inductive { name, constructors, .. } = cmd {
2101 assert_eq!(name, "Nat");
2102 assert_eq!(constructors.len(), 2);
2103 assert_eq!(constructors[0].0, "Zero");
2104 assert_eq!(constructors[1].0, "Succ");
2105 if let Term::Pi { .. } = &constructors[1].1 {
2107 } else {
2109 panic!("Expected Succ to have Pi type");
2110 }
2111 } else {
2112 panic!("Expected Inductive command");
2113 }
2114 }
2115
2116 #[test]
2117 fn test_parse_simple_definition() {
2118 let cmd = parse_definition("## To id (x: Nat) -> Nat: Yield x").unwrap();
2119 if let Command::Definition { name, body, .. } = cmd {
2120 assert_eq!(name, "id");
2121 if let Term::Lambda { param, .. } = body {
2123 assert_eq!(param, "x");
2124 } else {
2125 panic!("Expected Lambda body");
2126 }
2127 } else {
2128 panic!("Expected Definition command");
2129 }
2130 }
2131
2132 #[test]
2133 fn test_implicit_fixpoint_detection() {
2134 let cmd = parse_definition(
2136 "## To add (n: Nat) and (m: Nat) -> Nat: Consider n: When Zero: Yield m. When Succ k: Yield Succ (add k m)."
2137 ).unwrap();
2138
2139 if let Command::Definition { name, body, .. } = cmd {
2140 assert_eq!(name, "add");
2141 if let Term::Fix { name: fix_name, .. } = body {
2143 assert_eq!(fix_name, "add");
2144 } else {
2145 panic!("Expected Fix wrapper for recursive function");
2146 }
2147 } else {
2148 panic!("Expected Definition command");
2149 }
2150 }
2151
2152 #[test]
2153 fn test_parse_given_lambda() {
2154 let mut parser = LiterateParser::new("given x: Nat yields Succ x");
2155 let term = parser.parse_given_lambda().unwrap();
2156
2157 if let Term::Lambda { param, .. } = term {
2158 assert_eq!(param, "x");
2159 } else {
2160 panic!("Expected Lambda");
2161 }
2162 }
2163
2164 #[test]
2165 fn test_parse_pipe_lambda() {
2166 let mut parser = LiterateParser::new("|x: Nat| -> Succ x");
2167 let term = parser.parse_pipe_lambda().unwrap();
2168
2169 if let Term::Lambda { param, .. } = term {
2170 assert_eq!(param, "x");
2171 } else {
2172 panic!("Expected Lambda");
2173 }
2174 }
2175
2176 #[test]
2181 fn test_parse_let_definition() {
2182 let cmd = parse_let_definition("Let T be Zero").unwrap();
2183 if let Command::Definition { name, ty, body, .. } = cmd {
2184 assert_eq!(name, "T");
2185 assert!(ty.is_none());
2186 if let Term::Global(g) = body {
2187 assert_eq!(g, "Zero");
2188 } else {
2189 panic!("Expected Global term");
2190 }
2191 } else {
2192 panic!("Expected Definition command");
2193 }
2194 }
2195
2196 #[test]
2197 fn test_parse_name_syntax() {
2198 let mut parser = LiterateParser::new("Name \"Not\"");
2199 let term = parser.parse_term().unwrap();
2200
2201 if let Term::App(f, arg) = term {
2203 if let Term::Global(g) = *f {
2204 assert_eq!(g, "SName");
2205 } else {
2206 panic!("Expected Global SName");
2207 }
2208 if let Term::Lit(Literal::Text(s)) = *arg {
2209 assert_eq!(s, "Not");
2210 } else {
2211 panic!("Expected Text literal");
2212 }
2213 } else {
2214 panic!("Expected App");
2215 }
2216 }
2217
2218 #[test]
2219 fn test_parse_variable_syntax() {
2220 let mut parser = LiterateParser::new("Variable 0");
2221 let term = parser.parse_term().unwrap();
2222
2223 if let Term::App(f, arg) = term {
2225 if let Term::Global(g) = *f {
2226 assert_eq!(g, "SVar");
2227 } else {
2228 panic!("Expected Global SVar");
2229 }
2230 if let Term::Lit(Literal::Int(n)) = *arg {
2231 assert_eq!(n, 0);
2232 } else {
2233 panic!("Expected Int literal");
2234 }
2235 } else {
2236 panic!("Expected App");
2237 }
2238 }
2239
2240 #[test]
2241 fn test_parse_apply_syntax() {
2242 let mut parser = LiterateParser::new("Apply(Name \"Not\", Variable 0)");
2243 let term = parser.parse_term().unwrap();
2244
2245 if let Term::App(outer_f, _outer_arg) = term {
2247 if let Term::App(inner_f, _inner_arg) = *outer_f {
2248 if let Term::Global(g) = *inner_f {
2249 assert_eq!(g, "SApp");
2250 } else {
2251 panic!("Expected Global SApp");
2252 }
2253 } else {
2254 panic!("Expected inner App");
2255 }
2256 } else {
2257 panic!("Expected outer App");
2258 }
2259 }
2260
2261 #[test]
2262 fn test_parse_diagonalization() {
2263 let mut parser = LiterateParser::new("the diagonalization of T");
2264 let term = parser.parse_term().unwrap();
2265
2266 if let Term::App(f, arg) = term {
2268 if let Term::Global(g) = *f {
2269 assert_eq!(g, "syn_diag");
2270 } else {
2271 panic!("Expected Global syn_diag");
2272 }
2273 if let Term::Global(a) = *arg {
2274 assert_eq!(a, "T");
2275 } else {
2276 panic!("Expected Global T");
2277 }
2278 } else {
2279 panic!("Expected App");
2280 }
2281 }
2282
2283 #[test]
2284 fn test_parse_implies() {
2285 let mut parser = LiterateParser::new("A implies B");
2286 let term = parser.parse_term().unwrap();
2287
2288 if let Term::Pi { param, param_type, body_type } = term {
2290 assert_eq!(param, "_");
2291 if let Term::Global(a) = *param_type {
2292 assert_eq!(a, "A");
2293 } else {
2294 panic!("Expected Global A");
2295 }
2296 if let Term::Global(b) = *body_type {
2297 assert_eq!(b, "B");
2298 } else {
2299 panic!("Expected Global B");
2300 }
2301 } else {
2302 panic!("Expected Pi");
2303 }
2304 }
2305
2306 #[test]
2307 fn test_parse_existential() {
2308 let mut parser = LiterateParser::new("there exists a d: Derivation such that P");
2309 let term = parser.parse_term().unwrap();
2310
2311 if let Term::App(outer_f, lambda) = term {
2313 if let Term::App(ex, typ) = *outer_f {
2314 if let Term::Global(g) = *ex {
2315 assert_eq!(g, "Ex");
2316 } else {
2317 panic!("Expected Global Ex");
2318 }
2319 if let Term::Global(t) = *typ {
2320 assert_eq!(t, "Derivation");
2321 } else {
2322 panic!("Expected Global Derivation");
2323 }
2324 } else {
2325 panic!("Expected inner App for Ex");
2326 }
2327 if let Term::Lambda { param, body, .. } = *lambda {
2328 assert_eq!(param, "d");
2329 if let Term::Global(p) = *body {
2330 assert_eq!(p, "P");
2331 } else {
2332 panic!("Expected Global P in lambda body");
2333 }
2334 } else {
2335 panic!("Expected Lambda");
2336 }
2337 } else {
2338 panic!("Expected App");
2339 }
2340 }
2341
2342 #[test]
2343 fn test_parse_complex_let_with_apply() {
2344 let cmd = parse_let_definition("Let T be Apply(Name \"Not\", Apply(Name \"Provable\", Variable 0)).").unwrap();
2345 if let Command::Definition { name, ty, body, .. } = cmd {
2346 assert_eq!(name, "T");
2347 assert!(ty.is_none());
2348 if let Term::App(_, _) = body {
2350 } else {
2352 panic!("Expected App body");
2353 }
2354 } else {
2355 panic!("Expected Definition command");
2356 }
2357 }
2358
2359 #[test]
2364 fn test_parse_predicate_definition() {
2365 let cmd = parse_definition("## To be Provable (s: Syntax) -> Prop: Yield s").unwrap();
2367 if let Command::Definition { name, .. } = cmd {
2368 assert_eq!(name, "Provable"); } else {
2370 panic!("Expected Definition command");
2371 }
2372 }
2373
2374 #[test]
2375 fn test_parse_nullary_predicate() {
2376 let cmd = parse_definition("## To be Consistent -> Prop: Yield True").unwrap();
2378 if let Command::Definition { name, body, .. } = cmd {
2379 assert_eq!(name, "Consistent");
2380 if let Term::Global(g) = body {
2382 assert_eq!(g, "True");
2383 } else {
2384 panic!("Expected Global True");
2385 }
2386 } else {
2387 panic!("Expected Definition command");
2388 }
2389 }
2390
2391 #[test]
2392 fn test_parse_the_name_syntax() {
2393 let mut parser = LiterateParser::new("the Name \"Not\"");
2395 let term = parser.parse_term().unwrap();
2396
2397 if let Term::App(f, arg) = term {
2398 if let Term::Global(g) = *f {
2399 assert_eq!(g, "SName");
2400 } else {
2401 panic!("Expected Global SName");
2402 }
2403 if let Term::Lit(Literal::Text(s)) = *arg {
2404 assert_eq!(s, "Not");
2405 } else {
2406 panic!("Expected Text literal");
2407 }
2408 } else {
2409 panic!("Expected App");
2410 }
2411 }
2412
2413 #[test]
2414 fn test_parse_theorem() {
2415 let cmd = parse_theorem("## Theorem: MyTheorem\n Statement: A implies B.").unwrap();
2417 if let Command::Definition { name, ty, body, .. } = cmd {
2418 assert_eq!(name, "MyTheorem");
2419 assert!(ty.is_some());
2421 if let Some(Term::Sort(Universe::Prop)) = ty {
2422 } else {
2424 panic!("Expected Prop type");
2425 }
2426 if let Term::Pi { .. } = body {
2428 } else {
2430 panic!("Expected Pi body (implication)");
2431 }
2432 } else {
2433 panic!("Expected Definition command");
2434 }
2435 }
2436
2437 #[test]
2438 fn test_parse_theorem_with_complex_statement() {
2439 let cmd = parse_theorem("## Theorem: Godel\n Statement: Consistent implies Not(Provable(G)).").unwrap();
2441 if let Command::Definition { name, ty, .. } = cmd {
2442 assert_eq!(name, "Godel");
2443 assert!(ty.is_some());
2444 if let Some(Term::Sort(Universe::Prop)) = ty {
2445 } else {
2447 panic!("Expected Prop type");
2448 }
2449 } else {
2450 panic!("Expected Definition command");
2451 }
2452 }
2453
2454 #[test]
2455 fn test_parse_equals_infix() {
2456 let mut parser = LiterateParser::new("A equals B");
2458 let term = parser.parse_term().unwrap();
2459
2460 if let Term::App(outer, rhs) = term {
2462 if let Term::Global(b) = *rhs {
2463 assert_eq!(b, "B");
2464 } else {
2465 panic!("Expected Global B");
2466 }
2467 if let Term::App(mid, lhs) = *outer {
2468 if let Term::Global(a) = *lhs {
2469 assert_eq!(a, "A");
2470 } else {
2471 panic!("Expected Global A");
2472 }
2473 if let Term::App(inner, placeholder) = *mid {
2474 if let Term::Global(eq) = *inner {
2475 assert_eq!(eq, "Eq");
2476 } else {
2477 panic!("Expected Global Eq");
2478 }
2479 if !matches!(*placeholder, Term::Hole) {
2480 panic!("Expected Hole placeholder");
2481 }
2482 } else {
2483 panic!("Expected inner App");
2484 }
2485 } else {
2486 panic!("Expected mid App");
2487 }
2488 } else {
2489 panic!("Expected outer App");
2490 }
2491 }
2492
2493 #[test]
2494 fn test_parse_equals_with_application() {
2495 let mut parser = LiterateParser::new("f(x) equals y");
2497 let term = parser.parse_term().unwrap();
2498
2499 if let Term::App(outer, rhs) = term {
2501 if let Term::Global(y) = *rhs {
2502 assert_eq!(y, "y");
2503 } else {
2504 panic!("Expected Global y");
2505 }
2506 if let Term::App(mid, lhs) = *outer {
2507 if let Term::App(f_box, x_box) = *lhs {
2509 if let Term::Global(f) = *f_box {
2510 assert_eq!(f, "f");
2511 }
2512 if let Term::Global(x) = *x_box {
2513 assert_eq!(x, "x");
2514 }
2515 } else {
2516 panic!("Expected lhs to be App(f, x)");
2517 }
2518 } else {
2519 panic!("Expected mid App");
2520 }
2521 } else {
2522 panic!("Expected outer App");
2523 }
2524 }
2525
2526 #[test]
2531 fn test_parse_infix_le() {
2532 let mut parser = LiterateParser::new("x <= y");
2533 let term = parser.parse_term().unwrap();
2534 if let Term::App(outer, rhs) = term {
2536 if let Term::App(inner, lhs) = *outer {
2537 if let Term::Global(op) = *inner {
2538 assert_eq!(op, "le");
2539 } else {
2540 panic!("Expected Global le");
2541 }
2542 if let Term::Global(l) = *lhs {
2543 assert_eq!(l, "x");
2544 } else {
2545 panic!("Expected Global x");
2546 }
2547 } else {
2548 panic!("Expected inner App");
2549 }
2550 if let Term::Global(r) = *rhs {
2551 assert_eq!(r, "y");
2552 } else {
2553 panic!("Expected Global y");
2554 }
2555 } else {
2556 panic!("Expected outer App");
2557 }
2558 }
2559
2560 #[test]
2561 fn test_parse_infix_lt() {
2562 let mut parser = LiterateParser::new("a < b");
2563 let term = parser.parse_term().unwrap();
2564 if let Term::App(outer, _) = term {
2565 if let Term::App(inner, _) = *outer {
2566 if let Term::Global(op) = *inner {
2567 assert_eq!(op, "lt");
2568 } else {
2569 panic!("Expected Global lt");
2570 }
2571 } else {
2572 panic!("Expected inner App");
2573 }
2574 } else {
2575 panic!("Expected outer App");
2576 }
2577 }
2578
2579 #[test]
2580 fn test_parse_infix_ge() {
2581 let mut parser = LiterateParser::new("x >= y");
2582 let term = parser.parse_term().unwrap();
2583 if let Term::App(outer, _) = term {
2584 if let Term::App(inner, _) = *outer {
2585 if let Term::Global(op) = *inner {
2586 assert_eq!(op, "ge");
2587 } else {
2588 panic!("Expected Global ge");
2589 }
2590 } else {
2591 panic!("Expected inner App");
2592 }
2593 } else {
2594 panic!("Expected outer App");
2595 }
2596 }
2597
2598 #[test]
2599 fn test_parse_infix_gt() {
2600 let mut parser = LiterateParser::new("x > y");
2601 let term = parser.parse_term().unwrap();
2602 if let Term::App(outer, _) = term {
2603 if let Term::App(inner, _) = *outer {
2604 if let Term::Global(op) = *inner {
2605 assert_eq!(op, "gt");
2606 } else {
2607 panic!("Expected Global gt");
2608 }
2609 } else {
2610 panic!("Expected inner App");
2611 }
2612 } else {
2613 panic!("Expected outer App");
2614 }
2615 }
2616
2617 #[test]
2618 fn test_parse_infix_add() {
2619 let mut parser = LiterateParser::new("x + y");
2620 let term = parser.parse_term().unwrap();
2621 if let Term::App(outer, _) = term {
2622 if let Term::App(inner, _) = *outer {
2623 if let Term::Global(op) = *inner {
2624 assert_eq!(op, "add");
2625 } else {
2626 panic!("Expected Global add");
2627 }
2628 } else {
2629 panic!("Expected inner App");
2630 }
2631 } else {
2632 panic!("Expected outer App");
2633 }
2634 }
2635
2636 #[test]
2637 fn test_parse_infix_sub() {
2638 let mut parser = LiterateParser::new("x - y");
2639 let term = parser.parse_term().unwrap();
2640 if let Term::App(outer, _) = term {
2641 if let Term::App(inner, _) = *outer {
2642 if let Term::Global(op) = *inner {
2643 assert_eq!(op, "sub");
2644 } else {
2645 panic!("Expected Global sub");
2646 }
2647 } else {
2648 panic!("Expected inner App");
2649 }
2650 } else {
2651 panic!("Expected outer App");
2652 }
2653 }
2654
2655 #[test]
2656 fn test_parse_infix_mul() {
2657 let mut parser = LiterateParser::new("x * y");
2658 let term = parser.parse_term().unwrap();
2659 if let Term::App(outer, _) = term {
2660 if let Term::App(inner, _) = *outer {
2661 if let Term::Global(op) = *inner {
2662 assert_eq!(op, "mul");
2663 } else {
2664 panic!("Expected Global mul");
2665 }
2666 } else {
2667 panic!("Expected inner App");
2668 }
2669 } else {
2670 panic!("Expected outer App");
2671 }
2672 }
2673
2674 #[test]
2675 fn test_parse_precedence_mul_over_add() {
2676 let mut parser = LiterateParser::new("x + y * z");
2678 let term = parser.parse_term().unwrap();
2679 if let Term::App(outer, rhs) = term {
2681 if let Term::App(inner, _) = *outer {
2682 if let Term::Global(op) = *inner {
2683 assert_eq!(op, "add");
2684 } else {
2685 panic!("Expected add");
2686 }
2687 } else {
2688 panic!("Expected inner App");
2689 }
2690 if let Term::App(mul_outer, _) = *rhs {
2692 if let Term::App(mul_inner, _) = *mul_outer {
2693 if let Term::Global(op) = *mul_inner {
2694 assert_eq!(op, "mul");
2695 } else {
2696 panic!("Expected mul");
2697 }
2698 } else {
2699 panic!("Expected mul inner App");
2700 }
2701 } else {
2702 panic!("Expected mul App");
2703 }
2704 } else {
2705 panic!("Expected outer App");
2706 }
2707 }
2708
2709 #[test]
2710 fn test_parse_left_associative_add() {
2711 let mut parser = LiterateParser::new("x + y + z");
2713 let term = parser.parse_term().unwrap();
2714 if let Term::App(outer, rhs) = term {
2716 if let Term::Global(z) = *rhs {
2717 assert_eq!(z, "z");
2718 } else {
2719 panic!("Expected z");
2720 }
2721 if let Term::App(mid, lhs_add) = *outer {
2722 if let Term::Global(op) = *mid {
2723 assert_eq!(op, "add");
2724 }
2725 if let Term::App(inner_outer, _) = *lhs_add {
2727 if let Term::App(inner_inner, _) = *inner_outer {
2728 if let Term::Global(op2) = *inner_inner {
2729 assert_eq!(op2, "add");
2730 }
2731 }
2732 }
2733 }
2734 } else {
2735 panic!("Expected App");
2736 }
2737 }
2738
2739 #[test]
2740 fn test_parse_comparison_with_arithmetic() {
2741 let mut parser = LiterateParser::new("x + 1 <= y * 2");
2743 let term = parser.parse_term().unwrap();
2744 if let Term::App(outer, _) = term {
2745 if let Term::App(inner, _) = *outer {
2746 if let Term::Global(op) = *inner {
2747 assert_eq!(op, "le");
2748 } else {
2749 panic!("Expected le");
2750 }
2751 } else {
2752 panic!("Expected inner App");
2753 }
2754 } else {
2755 panic!("Expected outer App");
2756 }
2757 }
2758
2759 #[test]
2760 fn test_parse_unicode_le() {
2761 let mut parser = LiterateParser::new("x ≤ y");
2762 let term = parser.parse_term().unwrap();
2763 if let Term::App(outer, _) = term {
2764 if let Term::App(inner, _) = *outer {
2765 if let Term::Global(op) = *inner {
2766 assert_eq!(op, "le");
2767 } else {
2768 panic!("Expected le for ≤");
2769 }
2770 }
2771 } else {
2772 panic!("Expected App");
2773 }
2774 }
2775
2776 #[test]
2777 fn test_parse_unicode_ge() {
2778 let mut parser = LiterateParser::new("x ≥ y");
2779 let term = parser.parse_term().unwrap();
2780 if let Term::App(outer, _) = term {
2781 if let Term::App(inner, _) = *outer {
2782 if let Term::Global(op) = *inner {
2783 assert_eq!(op, "ge");
2784 } else {
2785 panic!("Expected ge for ≥");
2786 }
2787 }
2788 } else {
2789 panic!("Expected App");
2790 }
2791 }
2792
2793 #[test]
2794 fn test_parse_negative_number_preserved() {
2795 let mut parser = LiterateParser::new("-5 + x");
2797 let term = parser.parse_term().unwrap();
2798 if let Term::App(outer, _) = term {
2800 if let Term::App(inner, lhs) = *outer {
2801 if let Term::Global(op) = *inner {
2802 assert_eq!(op, "add");
2803 }
2804 if let Term::Lit(Literal::Int(n)) = *lhs {
2805 assert_eq!(n, -5);
2806 } else {
2807 panic!("Expected -5 literal");
2808 }
2809 }
2810 } else {
2811 panic!("Expected App");
2812 }
2813 }
2814
2815 #[test]
2816 fn test_parse_subtraction_not_negative() {
2817 let mut parser = LiterateParser::new("x - 5");
2819 let term = parser.parse_term().unwrap();
2820 if let Term::App(outer, rhs) = term {
2821 if let Term::App(inner, _) = *outer {
2822 if let Term::Global(op) = *inner {
2823 assert_eq!(op, "sub");
2824 }
2825 }
2826 if let Term::Lit(Literal::Int(n)) = *rhs {
2827 assert_eq!(n, 5); } else {
2829 panic!("Expected 5 literal");
2830 }
2831 } else {
2832 panic!("Expected App");
2833 }
2834 }
2835
2836 #[test]
2837 fn test_parse_infix_with_sexp_mix() {
2838 let mut parser = LiterateParser::new("(add x y) <= z");
2840 let term = parser.parse_term().unwrap();
2841 if let Term::App(outer, _) = term {
2842 if let Term::App(inner, lhs) = *outer {
2843 if let Term::Global(op) = *inner {
2844 assert_eq!(op, "le");
2845 }
2846 if let Term::App(add_outer, _) = *lhs {
2848 if let Term::App(add_inner, _) = *add_outer {
2849 if let Term::Global(add_op) = *add_inner {
2850 assert_eq!(add_op, "add");
2851 }
2852 }
2853 }
2854 }
2855 } else {
2856 panic!("Expected App");
2857 }
2858 }
2859}