1use super::syntax::{*, Formula::*};
41use nom::{*, types::CompleteStr};
42use nom_locate::LocatedSpan;
43use std::fmt as fmt;
44use failure::{Fail, Error};
45use std::str::FromStr;
46
47const LOWER: &str = "abcdefghijklmnopqrstuvwxyz_";
48const UPPER: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
49const ALPHA_NUMERIC: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
50const COMMA: &str = ",";
51const APOSTROPHE: &str = "'";
52const L_PAREN: &str = "(";
53const R_PAREN: &str = ")";
54const TRUE: &str = "true";
55const CHAR_TOP: &str = "'|'";
56const TOP: &str = "⊤";
57const FALSE: &str = "false";
58const CHAR_BOTTOM: &str = "_|_";
59const BOTTOM: &str = "⟘";
60const EQUALS: &str = "=";
61const AND: &str = "and";
62const AMPERSAND: &str = "&";
63const WEDGE: &str = "∧";
64const OR: &str = "or";
65const BAR: &str = "|";
66const VEE: &str = "∨";
67const NOT: &str = "not";
68const TILDE: &str = "~";
69const NEG: &str = "¬";
70const IMPLIES: &str = "implies";
71const CHAR_RIGHT_ARROW: &str = "->";
72const RIGHT_ARROW: &str = "→";
73const IFF: &str = "iff";
74const CHAR_DOUBLE_ARROW: &str = "<=>";
75const DOUBLE_ARROW: &str = "⇔";
76const EXISTS: &str = "exists";
77const QUESTION: &str = "?";
78const CHAR_EXISTS: &str = "∃";
79const FORALL: &str = "forall";
80const EXCLAMATION: &str = "!";
81const CHAR_FORALL: &str = "∀";
82const DOT: &str = ".";
83const SEMI_COLON: &str = ";";
84const LINE_COMMENT: &str = "//";
85const L_BLOCK_COMMENT: &str = "/*";
86const R_BLOCK_COMMENT: &str = "*/";
87
88const ERR_DOT: u32 = 1;
90const ERR_SEMI_COLON: u32 = 2;
91const ERR_L_PAREN: u32 = 3;
92const ERR_R_PAREN: u32 = 4;
93
94const ERR_LOWER: u32 = 21;
95
96const ERR_VARS: u32 = 31;
97const ERR_TERM: u32 = 32;
98
99const ERR_EQUALS: u32 = 41;
100const ERR_FORMULA: u32 = 42;
101
102fn error_code_to_string(code: u32) -> &'static str {
103 match code {
104 ERR_DOT => ".",
105 ERR_SEMI_COLON => ";",
106 ERR_L_PAREN => "(",
107 ERR_R_PAREN => ")",
108 ERR_LOWER => "lowercase identifier",
109 ERR_VARS => "variables",
110 ERR_TERM => "term",
111 ERR_EQUALS => "=",
112 ERR_FORMULA => "formula",
113 _ => "unknown",
114 }
115}
116
117#[derive(Debug, Fail)]
118enum ParserError {
119 Missing {
120 line: u32,
121 column: u32,
122 code: u32,
123 },
124 Expecting {
125 line: u32,
126 column: u32,
127 code: u32,
128 found: Option<String>,
129 },
130 Failed {
131 line: u32,
132 column: u32,
133 },
134 Unknown,
135}
136
137impl fmt::Display for ParserError {
138 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
139 match self {
140 ParserError::Missing { line, column, code } => {
141 write!(f, "missing '{}' at line {}, column {}", error_code_to_string(*code), line, column)
142 }
143 ParserError::Expecting { line, column, code, found } => {
144 write!(f, "expecting '{}' on line {}, column {}", error_code_to_string(*code), line, column)
145 .and_then(|result| {
146 if let Some(found) = found {
147 write!(f, "; found \"{}\"", found)
148 } else {
149 Ok(result)
150 }
151 })
152 }
153 ParserError::Failed { line, column } => {
154 write!(f, "failed to parse the input at line {}, column {}", line, column)
155 }
156 ParserError::Unknown => {
157 write!(f, "an error occurred while parsing the input")
158 }
159 }
160 }
161}
162
163type Span<'a> = LocatedSpan<CompleteStr<'a>>;
164
165named!(pub p_line_comment<Span, ()>,
166 map!(
167 many1!(
168 tuple!(
169 nom::space0,
170 preceded!(tag!(LINE_COMMENT), many0!(nom::not_line_ending)),
171 alt!(nom::line_ending | eof!())
172 )
173 ),
174 |_| ()
175 )
176);
177
178named!(pub p_block_comment<Span, ()>,
179 map!(
180 many1!(
181 tuple!(
182 nom::space0,
183 delimited!(
184 tag!(L_BLOCK_COMMENT),
185 many0!(is_not!(R_BLOCK_COMMENT)),
186 tag!(R_BLOCK_COMMENT)
187 )
188 )
189 ),
190 |_| ()
191 )
192);
193
194named!(pub spaces<Span, ()>,
195 map!(many0!(alt!(one_of!(&b" \t\n\r"[..]) => { |_|() } | p_line_comment | p_block_comment)), |_| ())
196);
197
198#[doc(hidden)]
199macro_rules! sp (
200 ($i:expr, $($args:tt)*) => (
201 {
202 use nom::Convert;
203 use nom::Err;
204
205 match sep!($i, spaces, $($args)*) {
206 Err(e) => Err(e),
207 Ok((i1,o)) => {
208 match spaces(i1) {
209 Err(e) => Err(Err::convert(e)),
210 Ok((i2,_)) => Ok((i2, o))
211 }
212 }
213 }
214 }
215 )
216);
217
218named!(p_lower_ident<Span, String>,
219 map!(pair!(one_of!(LOWER), opt!(is_a!(ALPHA_NUMERIC))),
220 |(first, rest): (char, Option<Span>)| {
221 let mut first = first.to_string();
222 if rest.is_some() {
223 first.push_str(rest.unwrap().fragment.0);
224 }
225 first
226 }
227 )
228);
229
230named!(p_upper_ident<Span, String>,
231 map!(pair!(one_of!(UPPER), opt!(is_a!(ALPHA_NUMERIC))),
232 |(first, rest): (char, Option<Span>)| {
233 let mut first = first.to_string();
234 if rest.is_some() {
235 first.push_str(rest.unwrap().fragment.0);
236 }
237 first
238 }
239 )
240);
241
242named!(p_var<Span, V>,
243 map!(p_lower_ident, |v| V::from(&v))
244);
245
246named!(p_vars<Span, Vec<V>>,
247 terminated!(
248 separated_nonempty_list!(
249 tag!(COMMA),
250 sp!(p_var)
251 ),
252 opt!(sp!(tag!(COMMA)))
253 )
254);
255
256named!(p_const<Span, C>,
257 map!(
258 preceded!(
259 tag!(APOSTROPHE),
260 return_error!(ErrorKind::Custom(ERR_LOWER), p_lower_ident)
261 ),
262 |c| C::from(&c)
263 )
264);
265
266named!(p_func<Span, F>,
267 map!(p_lower_ident,
268 |f| F::from(&f)
269 )
270);
271
272named!(p_nonempty_terms<Span, Vec<Term>>,
273 terminated!(
274 separated_nonempty_list!(
275 tag!(COMMA),
276 return_error!(ErrorKind::Custom(ERR_TERM), p_term)
277 ),
278 opt!(sp!(tag!(COMMA)))
279 )
280);
281
282named!(p_term_args<Span, Vec<Term>>,
283 alt!(
284 value!(vec![], delimited!(tag!(L_PAREN), opt!(space),tag!(R_PAREN))) |
285 delimited!(
286 tag!(L_PAREN),
287 p_nonempty_terms,
288 return_error!(ErrorKind::Custom(ERR_R_PAREN), tag!(R_PAREN))
289 )
290 )
291);
292
293named!(p_term<Span, Term>,
294 alt!(
295 map!(
296 terminated!(
297 sp!(p_var),
298 not!(tag!(L_PAREN))
300 ),
301 |v| v.into()
302 ) |
303 map!(sp!(p_const), |c| c.into()) |
304 map!( pair!(sp!(p_func), sp!(p_term_args)),
306 |(f, ts): (F, Vec<Term>)| f.app(ts)
307 )
308 )
309);
310
311named!(p_equals<Span, Formula>,
312 do_parse!(left: p_term >>
313 tag!(EQUALS) >>
314 right: add_return_error!(ErrorKind::Custom(ERR_TERM), p_term) >>
315 (left.equals(right))
316 )
317);
318
319named!(p_pred<Span, Pred>,
320 map!(p_upper_ident,
321 |f| Pred::from(&f)
322 )
323);
324
325named!(p_atom<Span, Formula>,
326 alt!(
327 value!(Top, alt!(tag!(TRUE) | tag!(TOP) | tag!(CHAR_TOP))) |
328 value!(Bottom, alt!(tag!(FALSE) | tag!(BOTTOM) | tag!(CHAR_BOTTOM))) |
329 add_return_error!(ErrorKind::Custom(ERR_EQUALS), p_equals) |
330 map!(
332 pair!(p_pred, sp!(p_term_args)),
333 |(p, ts): (Pred, Vec<Term>)| p.app(ts)
334 ) |
335 delimited!(sp!(tag!(L_PAREN)),
336 return_error!(ErrorKind::Custom(ERR_FORMULA), p_formula),
337 return_error!(ErrorKind::Custom(ERR_R_PAREN), tag!(R_PAREN))
338 )
339 )
340);
341
342named!(p_not<Span, Formula>,
343 alt!(
344 preceded!(
345 sp!(alt!(tag!(NOT) | tag!(TILDE) | tag!(NEG))),
346 map!(alt!(p_not | p_quantified), not)
347 ) |
348 sp!(p_atom)
349 )
350);
351
352named!(p_and<Span, Formula>,
353 map!(
354 pair!(
355 p_not,
356 opt!(
357 preceded!(
358 sp!(alt!(tag!(AND) | tag!(AMPERSAND) | tag!(WEDGE))),
359 alt!(
360 p_and |
361 return_error!(ErrorKind::Custom(ERR_FORMULA), p_quantified)
362 )
363 )
364 )
365 ),
366 |(l, r)| if let Some(r) = r { l.and(r) } else { l }
367 )
368);
369
370named!(p_or<Span, Formula>,
371 map!(
372 pair!(
373 p_and,
374 opt!(
375 preceded!(
376 sp!(alt!(tag!(OR) | tag!(BAR) | tag!(VEE))),
377 return_error!(ErrorKind::Custom(ERR_FORMULA), p_quantified)
378 )
379 )
380 ),
381 |(l, r)| if let Some(r) = r { l.or(r) } else { l }
382 )
383);
384
385named!(p_quantified<Span, Formula>,
386 alt!(
387 do_parse!(
388 q: sp!(
389 alt!(
390 value!(
391 FORALL,
392 alt!(tag!(FORALL) | tag!(EXCLAMATION) | tag!(CHAR_FORALL))
393 ) |
394 value!(
395 EXISTS,
396 alt!(tag!(EXISTS) | tag!(QUESTION) | tag!(CHAR_EXISTS))
397 )
398 )
399 ) >>
400 vs: return_error!(ErrorKind::Custom(ERR_VARS), p_vars) >>
401 return_error!(ErrorKind::Custom(ERR_DOT), sp!(tag!(DOT))) >>
402 f: return_error!(ErrorKind::Custom(ERR_FORMULA), p_quantified) >>
403 ( if q == FORALL { forall(vs, f) } else { exists(vs, f) } )
404 ) |
405 p_or
406 )
407);
408
409named!(p_formula<Span, Formula>,
410 do_parse!(
411 first: p_quantified >>
412 second: fold_many0!(
413 pair!(
414 sp!(
415 alt!(
416 value!(
417 IMPLIES,
418 alt!(tag!(IMPLIES) | tag!(RIGHT_ARROW) | tag!(CHAR_RIGHT_ARROW))
419 ) |
420 value!(
421 IFF,
422 alt!(tag!(IFF) | tag!(DOUBLE_ARROW) | tag!(CHAR_DOUBLE_ARROW))
423 )
424 )
425 ),
426 return_error!(ErrorKind::Custom(ERR_FORMULA), p_quantified)
427 ),
428 first,
429 |acc: Formula, (q, f)| if q == IMPLIES { acc.implies(f) } else { acc.iff(f) }
430 ) >>
431 (second)
432 )
433);
434
435named!(pub theory<Span, Theory>,
436 map!(
437 many_till!(
438 map!(
439 terminated!(
440 sp!(p_formula),
441 return_error!(ErrorKind::Custom(ERR_SEMI_COLON),
442 sp!(tag!(SEMI_COLON))
443 )
444 ),
445 |f| Option::Some(f)
446 ),
447 value!((), sp!(eof!()))
448 ),
449 |(fs, _)| {
450 let formulae: Vec<Formula> = fs.into_iter()
451 .filter_map(|f| f)
452 .collect();
453 Theory::from(formulae)
454 }
455 )
456);
457
458fn make_parser_error(error: &Err<Span, u32>) -> ParserError {
459 match error {
460 Err::Error(Context::Code(pos, ErrorKind::Custom(code))) | Err::Failure(Context::Code(pos, ErrorKind::Custom(code))) => {
461 let found = if pos.fragment.len() != 0 {
462 Some(pos.fragment.0.to_owned())
463 } else {
464 None
465 };
466 let code = *code;
467 match code {
468 ERR_SEMI_COLON | ERR_DOT | ERR_L_PAREN | ERR_R_PAREN
469 => ParserError::Missing { line: pos.line, column: pos.get_column() as u32, code },
470 ERR_FORMULA | ERR_TERM | ERR_VARS | ERR_LOWER
471 => ParserError::Expecting { line: pos.line, column: pos.get_column() as u32, code, found },
472 _ => ParserError::Failed { line: pos.line, column: pos.get_column() as u32 },
473 }
474 }
475 Err::Error(Context::Code(pos, _)) | Err::Failure(Context::Code(pos, _)) => {
476 ParserError::Failed { line: pos.line, column: pos.get_column() as u32 }
477 }
478 _ => ParserError::Unknown,
479 }
480}
481
482impl FromStr for Formula {
483 type Err = Error;
484
485 fn from_str(s: &str) -> Result<Self, Self::Err> {
486 p_formula(Span::new(CompleteStr(s)))
487 .map(|r| r.1)
488 .map_err(|e| make_parser_error(&e).into())
489 }
490}
491
492impl FromStr for Theory {
493 type Err = Error;
494
495 fn from_str(s: &str) -> Result<Self, Self::Err> {
496 theory(Span::new(CompleteStr(s)))
497 .map(|r| r.1)
498 .map_err(|e| make_parser_error(&e).into())
499 }
500}
501
502#[cfg(test)]
503mod test_parser {
504 use super::*;
505 use std::fmt;
506 use crate::test_prelude::*;
507
508 fn success<R: PartialEq + fmt::Debug>(
509 parser: fn(Span) -> nom::IResult<Span, R, u32>,
510 parse_str: &str,
511 expected: R,
512 remaining: &str) {
513 let parsed = parser(Span::new(CompleteStr(parse_str)));
514 assert!(parsed.is_ok());
515 let (rem, res) = parsed.unwrap();
516 assert_eq!(expected, res);
517 assert_eq!(CompleteStr(remaining), rem.fragment);
518 }
519
520 fn success_to_string<R: ToString>(
521 parser: fn(Span) -> nom::IResult<Span, R, u32>,
522 parse_str: &str,
523 expected: &str,
524 remaining: &str) {
525 let parsed = parser(Span::new(CompleteStr(parse_str)));
526 assert!(parsed.is_ok());
527 let (str, result) = parsed.unwrap();
528 assert_eq!(expected, result.to_string());
529 assert_eq!(remaining, str.fragment.0);
530 }
531
532 fn fail<R: PartialEq + fmt::Debug>(
533 parser: fn(Span) -> nom::IResult<Span, R, u32>,
534 parse_str: &str) {
535 let result = parser(Span::new(CompleteStr(parse_str)));
536 assert!(result.is_err());
537 }
538
539 #[test]
540 fn test_lower_identifier() {
541 success(p_lower_ident, "_", "_".to_owned(), "");
542 success(p_lower_ident, "a", "a".to_owned(), "");
543 success(p_lower_ident, "_ab", "_ab".to_owned(), "");
544 success(p_lower_ident, "aB", "aB".to_owned(), "");
545 success(p_lower_ident, "aB!", "aB".to_owned(), "!");
546 success(p_lower_ident, "johnSn0w", "johnSn0w".to_owned(), "");
547
548 fail(p_lower_ident, "B");
549 fail(p_lower_ident, "Blah");
550 fail(p_lower_ident, "!ABC");
551 fail(p_lower_ident, "123");
552 }
553
554 #[test]
555 fn test_upper_identifier() {
556 success(p_upper_ident, "A", "A".to_owned(), "");
557 success(p_upper_ident, "AB", "AB".to_owned(), "");
558 success(p_upper_ident, "AB!", "AB".to_owned(), "!");
559 success(p_upper_ident, "JohnSn0w", "JohnSn0w".to_owned(), "");
560
561 fail(p_upper_ident, "b");
562 fail(p_upper_ident, "blah");
563 fail(p_upper_ident, "!ABC");
564 fail(p_upper_ident, "123");
565 fail(p_upper_ident, "_");
566 fail(p_upper_ident, "_AB");
567 }
568
569 #[test]
570 fn test_var() {
571 success(p_var, "x", _x(), "");
572
573 fail(p_var, " x");
574 fail(p_var, "'a");
575 fail(p_var, "B");
576 }
577
578 #[test]
579 fn test_vars() {
580 success(p_vars, "x", vec![_x()], "");
581 success(p_vars, "x,y", vec![_x(), _y()], "");
582 success(p_vars, " x", vec![_x()], "");
583 success(p_vars, "x, y", vec![_x(), _y()], "");
584 success(p_vars, "x, y\t,\nz", vec![_x(), _y(), _z()], "");
585 success(p_vars, "x,", vec![_x()], "");
586 success(p_vars, "x,y , ", vec![_x(), _y()], "");
587
588 fail(p_vars, ",x");
589 fail(p_vars, "B");
590 }
591
592 #[test]
593 fn test_const() {
594 success(p_const, "'a", _a(), "");
595 fail(p_const, "x");
596 fail(p_const, " 'a");
597 fail(p_const, "' a");
598 fail(p_const, "''a");
599 fail(p_const, "B");
600 }
601
602 #[test]
603 fn test_func() {
604 success(p_func, "f", f(), "");
605 fail(p_func, " f");
606 fail(p_func, "'a");
607 fail(p_func, "'B");
608 fail(p_func, "B");
609 }
610
611 #[test]
612 fn test_term() {
613 success(p_term, "x", x(), "");
614 success(p_term, "'a", a(), "");
615 success(p_term, "f()", f().app0(), "");
616 success(p_term, "f( )", f().app0(), "");
617 success_to_string(p_term, "f(x)", "f(x)", "");
618 success_to_string(p_term, "f(x, y )", "f(x, y)", "");
619 success_to_string(p_term, "f(x, y \n , z)", "f(x, y, z)", "");
620 success_to_string(p_term, "f(f(f(f(f(f(f(x)))))))", "f(f(f(f(f(f(f(x)))))))", "");
621 success_to_string(p_term, "f (x)", "f(x)", "");
622 success_to_string(p_term, "f ( x ) ", "f(x)", "");
623 success_to_string(p_term, "f(w, g ( x, y, z))", "f(w, g(x, y, z))", "");
624 success_to_string(p_term, "f('a, x, g('b, h(x)))", "f('a, x, g('b, h(x)))", "");
625 fail(p_term, "''a");
626 fail(p_term, "P()");
627 fail(p_term, "f(Q())");
628 fail(p_term, "12f(x)");
629 fail(p_term, "f(1, 2)");
630 fail(p_term, "f(x, g(1))");
631 }
632
633 #[test]
634 fn test_equals() {
635 success_to_string(p_equals, "x = y", "x = y", "");
636 success_to_string(p_equals, "'a = 'b", "'a = 'b", "");
637 success_to_string(p_equals, "f(x) = y", "f(x) = y", "");
638 success_to_string(p_equals, " f (x ) = y", "f(x) = y", "");
639
640 fail(p_equals, "A = B");
641 fail(p_equals, "!a = b");
642 fail(p_equals, "a != b");
643 }
644
645 #[test]
646 fn test_pred() {
647 success(p_pred, "P", P(), "");
648 fail(p_pred, " P");
649 fail(p_pred, "'a");
650 fail(p_pred, "x");
651 }
652
653 #[test]
654 fn test_line_comment() {
655 success(p_line_comment, "//\n", (), "");
656 success(p_line_comment, " //\n", (), "");
657 success(p_line_comment, "// comment line \n", (), "");
658 success(p_line_comment, "//comment line \n", (), "");
659 success(p_line_comment, " // comment line \n", (), "");
660 success(p_line_comment, "//", (), "");
661 fail(p_line_comment, "/");
662 }
663
664 #[test]
665 fn test_block_comment() {
666 success(p_block_comment, "/**/", (), "");
667 success(p_block_comment, " /**/", (), "");
668 success(p_block_comment, "/* comment line */", (), "");
669 success(p_block_comment, "/* comment line \n*/", (), "");
670 success(p_block_comment, "/*comment line */", (), "");
671 success(p_block_comment, " /* comment line \n*/", (), "");
672 fail(p_block_comment, "/*");
673 fail(p_block_comment, "/");
674 }
675
676 #[test]
677 fn test_atom() {
678 success(p_atom, TRUE, Top, "");
679 success(p_atom, CHAR_TOP, Top, "");
680 success(p_atom, TOP, Top, "");
681 success(p_atom, FALSE, Bottom, "");
682 success(p_atom, CHAR_BOTTOM, Bottom, "");
683 success(p_atom, BOTTOM, Bottom, "");
684 success_to_string(p_atom, "x = f('a)", "x = f('a)", "");
685 success_to_string(p_atom, "P()", "P()", "");
686 success_to_string(p_atom, "P( )", "P()", "");
687 success_to_string(p_atom, "P(x)", "P(x)", "");
688 success_to_string(p_atom, "P(x, y )", "P(x, y)", "");
689 success_to_string(p_atom, "P(x, y \n , z)", "P(x, y, z)", "");
690 success_to_string(p_atom, "P(f(f(f(f(f(f(x)))))))", "P(f(f(f(f(f(f(x)))))))", "");
691 success_to_string(p_atom, "P (x)", "P(x)", "");
692 success_to_string(p_atom, "P ( x ) ", "P(x)", "");
693 success_to_string(p_atom, "P(w, g ( x, y, z))", "P(w, g(x, y, z))", "");
694 success_to_string(p_atom, "P('a, x, g('b, h(x)))", "P('a, x, g('b, h(x)))", "");
695 fail(p_atom, "''a");
696 fail(p_atom, "f()");
697 fail(p_atom, "P(Q())");
698 fail(p_atom, "12P(x)");
699 fail(p_atom, "P(1, 2)");
700 fail(p_atom, "P(x, g(1))");
701 }
702
703 #[test]
704 fn test_formula() {
705 success_to_string(p_formula, "true", "⊤", "");
706 success_to_string(p_formula, "false", "⟘", "");
707 success_to_string(p_formula, "((((true))))", "⊤", "");
708 success_to_string(p_formula, "( true)", "⊤", "");
709 success_to_string(p_formula, "(true )", "⊤", "");
710 success_to_string(p_formula, "P()", "P()", "");
711 success_to_string(p_formula, " P()", "P()", "");
712 success_to_string(p_formula, " ~P()", "¬P()", "");
713 success_to_string(p_formula, "P(x)", "P(x)", "");
714 success_to_string(p_formula, "P('a)", "P('a)", "");
715 success_to_string(p_formula, "P(x,y)", "P(x, y)", "");
716 success_to_string(p_formula, "P('a,'b)", "P('a, 'b)", "");
717 success_to_string(p_formula, "P('a,x)", "P('a, x)", "");
718 success_to_string(p_formula, "P(x, y)", "P(x, y)", "");
719 success_to_string(p_formula, "P(x, y \n)", "P(x, y)", "");
720 success_to_string(p_formula, "P(f(x))", "P(f(x))", "");
721 success_to_string(
722 p_formula,
723 "P(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(x)))))))))))))))))))))",
724 "P(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(x)))))))))))))))))))))",
725 "",
726 );
727 success_to_string(p_formula, "P(f(x, g(y)), g(f(g(y))))", "P(f(x, g(y)), g(f(g(y))))", "");
728 success_to_string(p_formula, "'a = 'b", "'a = 'b", "");
729 success_to_string(p_formula, "x = x", "x = x", "");
730 success_to_string(p_formula, "f() = x", "f() = x", "");
731 success_to_string(p_formula, "f(x) = x", "f(x) = x", "");
732 success_to_string(p_formula, "f(x) = x", "f(x) = x", "");
733 success_to_string(p_formula, "f(x) = g(h(g(f(x)), y))", "f(x) = g(h(g(f(x)), y))", "");
734 success_to_string(p_formula, "P(x) implies Q(x)", "P(x) → Q(x)", "");
735 success_to_string(p_formula, "P(x) implies Q(x) -> R(x)", "(P(x) → Q(x)) → R(x)", "");
736 success_to_string(p_formula, "P(x) implies (Q(x) -> R(x))", "P(x) → (Q(x) → R(x))", "");
737 success_to_string(p_formula, "P(x) implies (Q(x) -> R(x))", "P(x) → (Q(x) → R(x))", "");
738 success_to_string(p_formula, "P(x) implies (Q(x) -> R(x) -> Q(z))", "P(x) → ((Q(x) → R(x)) → Q(z))", "");
739 success_to_string(p_formula, "P(x) iff Q(x)", "P(x) ⇔ Q(x)", "");
740 success_to_string(p_formula, "P(x) iff Q(x) <=> R(x)", "(P(x) ⇔ Q(x)) ⇔ R(x)", "");
741 success_to_string(p_formula, "P(x) iff (Q(x) <=> R(x))", "P(x) ⇔ (Q(x) ⇔ R(x))", "");
742 success_to_string(p_formula, "P(x) iff (Q(x) <=> R(x) <=> Q(z))", "P(x) ⇔ ((Q(x) ⇔ R(x)) ⇔ Q(z))", "");
743 success_to_string(p_formula, "P(x) iff Q(x) implies R(x)", "(P(x) ⇔ Q(x)) → R(x)", "");
744 success_to_string(p_formula, "P(x) implies Q(x) iff R(x)", "(P(x) → Q(x)) ⇔ R(x)", "");
745 success_to_string(p_formula, "exists x . P(x)", "∃ x. P(x)", "");
746 success_to_string(p_formula, "exists x,y . P(x, y)", "∃ x, y. P(x, y)", "");
747 success_to_string(p_formula, "exists x . exists y, z. P(x, y, z)", "∃ x. (∃ y, z. P(x, y, z))", "");
748 success_to_string(p_formula, "exists x . P(x) implies Q(x)", "(∃ x. P(x)) → Q(x)", "");
749 success_to_string(p_formula, "exists x . (P(x) implies Q(x))", "∃ x. (P(x) → Q(x))", "");
750 success_to_string(p_formula, "forall x . P(x)", "∀ x. P(x)", "");
751 success_to_string(p_formula, "forall x,y . P(x, y)", "∀ x, y. P(x, y)", "");
752 success_to_string(p_formula, "forall x . forall y, z. P(x, y, z)", "∀ x. (∀ y, z. P(x, y, z))", "");
753 success_to_string(p_formula, "forall x . P(x) implies Q(x)", "(∀ x. P(x)) → Q(x)", "");
754 success_to_string(p_formula, "forall x . (P(x) implies Q(x))", "∀ x. (P(x) → Q(x))", "");
755 success_to_string(p_formula, "forall x . exists y . P(x, y)", "∀ x. (∃ y. P(x, y))", "");
756 success_to_string(p_formula, "P(x) or Q(y)", "P(x) ∨ Q(y)", "");
757 success_to_string(p_formula, "P(x) or Q(y) or R(z)", "P(x) ∨ (Q(y) ∨ R(z))", "");
758 success_to_string(p_formula, "(P(x) or Q(y)) or R(z)", "(P(x) ∨ Q(y)) ∨ R(z)", "");
759 success_to_string(p_formula, "P(x) or Q(y) or (R(z) or S(z))", "P(x) ∨ (Q(y) ∨ (R(z) ∨ S(z)))", "");
760 success_to_string(p_formula, "P(x) implies Q(x) or R(x)", "P(x) → (Q(x) ∨ R(x))", "");
761 success_to_string(p_formula, "P(x) or Q(x) implies R(x)", "(P(x) ∨ Q(x)) → R(x)", "");
762 success_to_string(p_formula, "exists x . P(x) or Q(x)", "∃ x. (P(x) ∨ Q(x))", "");
763 success_to_string(p_formula, "P(x) or exists y . Q(y)", "P(x) ∨ (∃ y. Q(y))", "");
764 success_to_string(p_formula, "exists x . P(x) or exists y . Q(y)", "∃ x. (P(x) ∨ (∃ y. Q(y)))", "");
765 success_to_string(p_formula, "P(x) or forall y . Q(y)", "P(x) ∨ (∀ y. Q(y))", "");
766 success_to_string(p_formula, "exists x . P(x) or forall y . Q(y)", "∃ x. (P(x) ∨ (∀ y. Q(y)))", "");
767 success_to_string(p_formula, "P(x) and Q(y) or R(z)", "(P(x) ∧ Q(y)) ∨ R(z)", "");
768 success_to_string(p_formula, "P(x) and (Q(y) or R(z))", "P(x) ∧ (Q(y) ∨ R(z))", "");
769 success_to_string(p_formula, "P(x) or Q(y) and R(z)", "P(x) ∨ (Q(y) ∧ R(z))", "");
770 success_to_string(p_formula, "P(x) and Q(y) and R(z)", "P(x) ∧ (Q(y) ∧ R(z))", "");
771 success_to_string(p_formula, "P(w) and Q(x) and R(y) and S(z)", "P(w) ∧ (Q(x) ∧ (R(y) ∧ S(z)))", "");
772 success_to_string(p_formula, "(P(x) and Q(y)) and R(z)", "(P(x) ∧ Q(y)) ∧ R(z)", "");
773 success_to_string(p_formula, "P(x) and Q(y) implies R(z)", "(P(x) ∧ Q(y)) → R(z)", "");
774 success_to_string(p_formula, "P(x) and exists y . Q(y)", "P(x) ∧ (∃ y. Q(y))", "");
775 success_to_string(p_formula, "exists x . P(x) and exists y . Q(y)", "∃ x. (P(x) ∧ (∃ y. Q(y)))", "");
776 success_to_string(p_formula, "P(x) and forall y . Q(y)", "P(x) ∧ (∀ y. Q(y))", "");
777 success_to_string(p_formula, "exists x . P(x) and forall y . Q(y)", "∃ x. (P(x) ∧ (∀ y. Q(y)))", "");
778 success_to_string(p_formula, "not true", "¬⊤", "");
779 success_to_string(p_formula, "not true -> false", "(¬⊤) → ⟘", "");
780 success_to_string(p_formula, "~x=y", "¬(x = y)", "");
781 success_to_string(p_formula, "true -> not false", "⊤ → (¬⟘)", "");
782 success_to_string(p_formula, "not P(x, y) or Q(z)", "(¬P(x, y)) ∨ Q(z)", "");
783 success_to_string(p_formula, "not P(x, y) and Q(z)", "(¬P(x, y)) ∧ Q(z)", "");
784 success_to_string(p_formula, "not not R(x)", "¬(¬R(x))", "");
785 success_to_string(p_formula, "not not not not not R(x) and S(y)", "(¬(¬(¬(¬(¬R(x)))))) ∧ S(y)", "");
786 success_to_string(p_formula, "not exists y . Q(y)", "¬(∃ y. Q(y))", "");
787 success_to_string(p_formula, "exists x . not exists y . Q(y)", "∃ x. (¬(∃ y. Q(y)))", "");
788 success_to_string(
789 p_formula,
790 "P(x) implies Q(y) and exists z . f(z) = g(f(z)) or (forall y, z . S(y,z) implies false)",
791 "P(x) → (Q(y) ∧ (∃ z. ((f(z) = g(f(z))) ∨ ((∀ y, z. S(y, z)) → ⟘))))",
792 "",
793 );
794 success_to_string(
795 p_formula,
796 "not forall x, y . P(x) and Q(y) implies h(z) = z",
797 "(¬(∀ x, y. (P(x) ∧ Q(y)))) → (h(z) = z)",
798 "",
799 );
800 success_to_string(
801 p_formula,
802 "∀ x. ∃ y. ((x = y) ∧ ¬P(y)) ∨ (Q(x) → R(y))",
803 "∀ x. (∃ y. (((x = y) ∧ (¬P(y))) ∨ (Q(x) → R(y))))",
804 "",
805 );
806 success_to_string(
807 p_formula,
808 "∀ x. (∃ y. (((x = y) ∧ (¬P(y))) ∨ (Q(x) → R(y))))",
809 "∀ x. (∃ y. (((x = y) ∧ (¬P(y))) ∨ (Q(x) → R(y))))",
810 "",
811 );
812 success_to_string(
813 p_formula,
814 "! x. ? y. ((x = y) & ~P(y)) | (Q(x) -> R(y))",
815 "∀ x. (∃ y. (((x = y) ∧ (¬P(y))) ∨ (Q(x) → R(y))))",
816 "",
817 );
818 success_to_string(
819 p_formula,
820 "! x. (? y. (((x = y) & (~P(y))) | (Q(x) -> R(y))))",
821 "∀ x. (∃ y. (((x = y) ∧ (¬P(y))) ∨ (Q(x) → R(y))))",
822 "",
823 );
824 }
825
826 #[test]
827 fn test_theory() {
828 success_to_string(
829 theory,
830 " P(x) ;",
831 "P(x)",
832 "",
833 );
834 success_to_string(
835 theory,
836 "E(x,x);\
837 E(x,y) -> E(y,x) ;\
838 E(x,y) & E(y,z) -> E(x,z);",
839 "E(x, x)\nE(x, y) → E(y, x)\n(E(x, y) ∧ E(y, z)) → E(x, z)",
840 "",
841 );
842 success_to_string(
843 theory,
844 "// comment 0\n\
845 E(x,x)\
846 ;\
847 // another comment\n\
848 E(x,y) -> E(y,x) ;\
849 E(x,y) & E(y,z) -> E(x,z);",
850 "E(x, x)\nE(x, y) → E(y, x)\n(E(x, y) ∧ E(y, z)) → E(x, z)",
851 "",
852 );
853 success_to_string(
854 theory,
855 "// comment 0\n\
856 E /*reflexive*/(//first argument \n\
857 x, \n\
858 /*second argument*/ x)\
859 ;\
860 // another comment\n\
861 /* yet another comment */
862 E(x,y) -> E(y,x) /*symmetric*/ ;\
863 E(x,y) & E(y,z) -> /* transitivity */ E(x,z);",
864 "E(x, x)\nE(x, y) → E(y, x)\n(E(x, y) ∧ E(y, z)) → E(x, z)",
865 "",
866 );
867 success_to_string(
868 theory,
869 "P(x);exists x . Q(x);R(x) -> S(x);",
870 "P(x)\n∃ x. Q(x)\nR(x) → S(x)",
871 "",
872 );
873 }
874
875 #[test]
876 fn parse_failure() {
877 {
878 let parsed: Result<Theory, Error> = "P(X)".parse();
879 assert_eq!("expecting 'term' on line 1, column 3; found \"X)\"", parsed.err().unwrap().to_string());
880 }
881 {
882 let parsed: Result<Theory, Error> = "P('A)".parse();
883 assert_eq!("expecting 'term' on line 1, column 3; found \"'A)\"", parsed.err().unwrap().to_string());
884 }
885 {
886 let parsed: Result<Theory, Error> = "P(x)".parse();
887 assert_eq!("missing ';' at line 1, column 5", parsed.err().unwrap().to_string());
888 }
889 {
890 let parsed: Result<Theory, Error> = "P(x".parse();
891 assert_eq!("missing ')' at line 1, column 4", parsed.err().unwrap().to_string());
892 }
893 {
894 let parsed: Result<Theory, Error> = "~P(x".parse();
895 assert_eq!("missing ')' at line 1, column 5", parsed.err().unwrap().to_string());
896 }
897 {
898 let parsed: Result<Theory, Error> = "P(x) and ".parse();
899 assert_eq!("expecting 'formula' on line 1, column 10", parsed.err().unwrap().to_string());
900 }
901 {
902 let parsed: Result<Theory, Error> = "P(x) and X".parse();
903 assert_eq!("expecting 'formula' on line 1, column 10; found \"X\"", parsed.err().unwrap().to_string());
904 }
905 {
906 let parsed: Result<Theory, Error> = "P(x) or".parse();
907 assert_eq!("expecting 'formula' on line 1, column 8", parsed.err().unwrap().to_string());
908 }
909 {
910 let parsed: Result<Theory, Error> = "P(x) or X".parse();
911 assert_eq!("expecting 'formula' on line 1, column 9; found \"X\"", parsed.err().unwrap().to_string());
912 }
913 {
914 let parsed: Result<Theory, Error> = "P(x) ->".parse();
915 assert_eq!("expecting 'formula' on line 1, column 8", parsed.err().unwrap().to_string());
916 }
917 {
918 let parsed: Result<Theory, Error> = "P(x) -> X".parse();
919 assert_eq!("expecting 'formula' on line 1, column 9; found \"X\"", parsed.err().unwrap().to_string());
920 }
921 {
922 let parsed: Result<Theory, Error> = "P(x) <=>".parse();
923 assert_eq!("expecting 'formula' on line 1, column 9", parsed.err().unwrap().to_string());
924 }
925 {
926 let parsed: Result<Theory, Error> = "P(x) <=> X".parse();
927 assert_eq!("expecting 'formula' on line 1, column 10; found \"X\"", parsed.err().unwrap().to_string());
928 }
929 {
930 let parsed: Result<Theory, Error> = "!x P(x".parse();
931 assert_eq!("missing '.' at line 1, column 4", parsed.err().unwrap().to_string());
932 }
933 {
934 let parsed: Result<Theory, Error> = "! P(x)".parse();
935 assert_eq!("expecting 'variables' on line 1, column 3; found \"P(x)\"", parsed.err().unwrap().to_string());
936 }
937 {
938 let parsed: Result<Theory, Error> = "!x . ".parse();
939 assert_eq!("expecting 'formula' on line 1, column 6", parsed.err().unwrap().to_string());
940 }
941 {
942 let parsed: Result<Theory, Error> = "!x . X".parse();
943 assert_eq!("expecting 'formula' on line 1, column 6; found \"X\"", parsed.err().unwrap().to_string());
944 }
945 {
946 let parsed: Result<Theory, Error> = "?x P(x".parse();
947 assert_eq!("missing '.' at line 1, column 4", parsed.err().unwrap().to_string());
948 }
949 {
950 let parsed: Result<Theory, Error> = "? P(x)".parse();
951 assert_eq!("expecting 'variables' on line 1, column 3; found \"P(x)\"", parsed.err().unwrap().to_string());
952 }
953 {
954 let parsed: Result<Theory, Error> = "?x . ".parse();
955 assert_eq!("expecting 'formula' on line 1, column 6", parsed.err().unwrap().to_string());
956 }
957 {
958 let parsed: Result<Theory, Error> = "?x . X".parse();
959 assert_eq!("expecting 'formula' on line 1, column 6; found \"X\"", parsed.err().unwrap().to_string());
960 }
961 {
962 let parsed: Result<Theory, Error> = "x".parse();
963 assert_eq!("failed to parse the input at line 1, column 1", parsed.err().unwrap().to_string());
964 }
965 {
966 let parsed: Result<Theory, Error> = "(X)".parse();
967 assert_eq!("expecting 'formula' on line 1, column 2; found \"X)\"", parsed.err().unwrap().to_string());
968 }
969 {
970 let parsed: Result<Theory, Error> = "(P(x)".parse();
971 assert_eq!("missing ')' at line 1, column 6", parsed.err().unwrap().to_string());
972 }
973 {
974 let parsed: Result<Theory, Error> = "P(x)\n\
975 Q(x) <=> R(x);".parse();
976 assert_eq!("missing ';' at line 2, column 1", parsed.err().unwrap().to_string());
977 }
978 {
979 let parsed: Result<Theory, Error> = "P(x);\n\
980 Q(x) <=> R(x);\n\
981 S(x) => Q(x);".parse();
982 assert_eq!("missing ';' at line 3, column 6", parsed.err().unwrap().to_string());
983 }
984 {
985 let parsed: Result<Theory, Error> = "P(x);\n\
986 Q(x) <=> R(x);\n\
987 S(x) and ".parse();
988 assert_eq!("expecting 'formula' on line 3, column 10", parsed.err().unwrap().to_string());
989 }
990 }
991}
992
993