1use rustc_hash::FxHashSet;
22
23use nom::bytes::complete::tag;
24use nom::character::complete::{char, line_ending, multispace0, space0, space1, u64};
25use nom::combinator::{consumed, cut, eof, value};
26use nom::error::{context, ContextError, ErrorKind, FromExternalError, ParseError};
27use nom::multi::many0_count;
28use nom::sequence::{preceded, terminated};
29use nom::{Err, IResult};
30
31use crate::util::{
32 self, context_loc, eol, fail, fail_with_contexts, line_span, word, word_span, MAX_CAPACITY,
33};
34use crate::{ParseOptions, Problem, Tree, Var, VarSet};
35
36#[allow(clippy::upper_case_acronyms)]
39#[derive(Clone, Copy, PartialEq, Eq, Debug)]
40enum Format {
41 CNF,
42 SAT { xor: bool, eq: bool },
43}
44#[rustfmt::skip]
45const SAT: Format = Format::SAT { xor: false, eq: false };
46#[rustfmt::skip]
47const SATX: Format = Format::SAT { xor: true, eq: false };
48#[rustfmt::skip]
49const SATE: Format = Format::SAT { xor: false, eq: false };
50#[rustfmt::skip]
51const SATEX: Format = Format::SAT { xor: true, eq: true };
52
53fn format<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
54 input: &'a [u8],
55) -> IResult<&'a [u8], Format, E> {
56 let inner = |input: &'a [u8]| match input {
57 [b'c', b'n', b'f', r @ ..] => Ok((r, Format::CNF)),
58 [b's', b'a', b't', b'e', b'x', r @ ..] => Ok((r, SATEX)),
59 [b's', b'a', b't', b'e', r @ ..] => Ok((r, SATE)),
60 [b's', b'a', b't', b'x', r @ ..] => Ok((r, SATX)),
61 [b's', b'a', b't', r @ ..] => Ok((r, SAT)),
62 _ => Err(Err::Error(E::from_error_kind(input, ErrorKind::Alt))),
63 };
64
65 context_loc(
66 || word_span(input),
67 "format must be one of 'cnf', 'sat', 'satx', 'sate', or 'satex'",
68 word(inner),
69 )(input)
70}
71
72fn problem_line<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
78 input: &'a [u8],
79) -> IResult<&'a [u8], ((&'a [u8], Format), (&'a [u8], usize), (&'a [u8], usize)), E> {
80 let inner = |input| {
81 let (input, _) = context(
82 "all lines in the preamble must begin with 'c' or 'p'",
83 cut(char('p')),
84 )(input)?;
85 let (input, _) = space1(input)?;
86 let (input, fmt) = consumed(format)(input)?;
87 let (input, _) = space1(input)?;
88 let (input, num_vars) = consumed(u64)(input)?;
89 if num_vars.1 > MAX_CAPACITY {
90 return fail(num_vars.0, "too many variables");
91 }
92 let num_vars = (num_vars.0, num_vars.1 as usize);
93 if fmt.1 == Format::CNF {
94 let msg = "expected the number of clauses (CNF format)";
95 let (input, _) = context(msg, space1)(input)?;
96 let (input, num_clauses) = context_loc(|| word_span(input), msg, consumed(u64))(input)?;
97 if num_clauses.1 > MAX_CAPACITY {
98 return fail(num_clauses.0, "too many clauses");
99 }
100 let num_clauses = (num_clauses.0, num_clauses.1 as usize);
101 let (input, _) = space0(input)?;
102 value((fmt, num_vars, num_clauses), line_ending)(input)
103 } else {
104 let (input, _) = space0(input)?;
105 context(
106 "expected a line break (SAT formats do not take a number of clauses)",
107 value((fmt, num_vars, ([].as_slice(), 0)), line_ending),
108 )(input)
109 }
110 };
111
112 context_loc(
113 || line_span(input),
114 "problem line must have format 'p <format> <#vars> [<#clauses>]'",
115 cut(inner),
116 )(input)
117}
118
119#[derive(Clone, PartialEq, Eq, Debug)]
120struct Preamble {
121 format: Format,
122 vars: VarSet,
123 num_clauses: usize,
125 clause_tree: Option<Tree<usize>>,
126}
127
128fn preamble<'a, E>(
137 parse_var_order: bool,
138 parse_clause_tree: bool,
139) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Preamble, E>
140where
141 E: ParseError<&'a [u8]> + ContextError<&'a [u8]> + FromExternalError<&'a [u8], String>,
142{
143 move |mut input| {
144 if parse_var_order || parse_clause_tree {
147 let mut vars = VarSet {
148 len: 0,
149 order: Vec::new(),
150 order_tree: None,
151 names: Vec::new(),
152 };
153
154 let mut max_var_span = [].as_slice(); let mut tree_max_var = ([].as_slice(), 0); let mut name_set: FxHashSet<&str> = Default::default();
157
158 let mut clause_tree = None;
160 let mut clause_order_span = [].as_slice();
161 let mut max_clause = ([].as_slice(), 0); loop {
164 let next_input = match preceded(char::<_, E>('c'), space1)(input) {
165 Ok((i, _)) => i,
166 Err(_) => break,
167 };
168 if let Ok((next_input, _)) = preceded(tag("co"), space1::<_, E>)(next_input) {
169 if parse_clause_tree {
170 if clause_tree.is_some() {
171 return fail(line_span(input), "clause order may only be given once");
172 }
173 let t: Tree<usize>;
174 (input, (clause_order_span, (t, max_clause))) =
175 terminated(consumed(util::tree(false, false)), eol)(next_input)?;
176 clause_tree = Some(t);
177 } else {
178 input = match memchr::memchr(b'\n', input) {
179 Some(i) => &input[i + 1..],
180 None => &input[input.len()..],
181 };
182 }
183 } else if let Ok((next_input, _)) = preceded(tag("vo"), space1::<_, E>)(next_input)
184 {
185 if vars.order_tree.is_some() {
187 let msg = "variable order tree may only be given once";
188 return fail(line_span(input), msg);
189 }
190 let t: Tree<Var>;
191 (input, (t, tree_max_var)) =
192 terminated(util::tree(true, true), eol)(next_input)?;
193
194 vars.order.clear();
196 vars.order.reserve(tree_max_var.1 + 1);
197 t.flatten_into(&mut vars.order);
198 vars.order_tree = Some(t);
199 } else if let Ok((next_input, ((var_span, var), name))) =
200 util::var_order_record::<E>(next_input)
201 {
202 input = next_input;
204 if var == 0 {
205 return fail(var_span, "variable number must be greater than 0");
206 }
207 if var > MAX_CAPACITY {
208 return fail(var_span, "variable number too large");
209 }
210
211 let num_vars = var as usize;
212 let var = num_vars - 1;
213
214 if num_vars > vars.names.len() {
215 vars.names.resize(num_vars, None);
216 vars.order.reserve(num_vars - vars.names.len());
217 max_var_span = var_span;
218 } else if vars.names[var].is_some() {
219 return fail(var_span, "second occurrence of variable in order");
220 }
221 vars.names[var] = Some(if let Some(name) = name {
223 let Ok(name) = std::str::from_utf8(name) else {
224 return fail(name, "invalid UTF-8");
225 };
226 if !name_set.insert(name) {
227 return fail(name.as_bytes(), "second occurrence of variable name");
228 }
229 name.to_owned()
230 } else {
231 String::new()
232 });
233 if vars.order_tree.is_none() {
234 vars.order.push(var);
235 }
236 } else {
237 return fail(
238 line_span(input),
239 "expected a variable order record ('c <var> [<name>]'), a variable order tree ('c vo <tree>'), or a clause order tree ('c co <tree>')",
240 );
241 }
242 }
243
244 if vars.order_tree.is_none() && vars.names.len() != vars.order.len() {
245 return fail_with_contexts([
246 (input, "expected another variable order line"),
247 (max_var_span, "note: maximal variable number given here"),
248 ]);
249 }
250
251 let (next_input, (format, num_vars, num_clauses)) = problem_line(input)?;
252 if vars.order_tree.is_none() {
253 if !vars.order.is_empty() && num_vars.1 != vars.order.len() {
254 return fail_with_contexts([
255 (num_vars.0, "number of variables does not match"),
256 (max_var_span, "note: maximal variable number given here"),
257 ]);
258 }
259 } else {
260 if num_vars.1 != tree_max_var.1 + 1 {
261 return fail_with_contexts([
262 (num_vars.0, "number of variables does not match"),
263 (tree_max_var.0, "note: maximal variable number given here"),
264 ]);
265 }
266 if vars.names.len() > num_vars.1 {
267 return fail_with_contexts([
268 (max_var_span, "name assigned to non-existing variable"),
269 (num_vars.0, "note: number of variables given here"),
270 ]);
271 }
272 }
273
274 if clause_tree.is_some() {
275 if format.1 != Format::CNF {
276 let msg0 = "clause tree only supported for 'cnf' format";
277 return fail_with_contexts([
278 (clause_order_span, msg0),
279 (format.0, "note: format given here"),
280 ]);
281 }
282 if max_clause.1 != num_clauses.1 - 1 {
283 return fail_with_contexts([
284 (num_clauses.0, "number of clauses does not match"),
285 (max_clause.0, "note: maximal clause number given here"),
286 ]);
287 }
288 }
289
290 while let Some(name) = vars.names.last() {
292 if !name.as_ref().is_some_and(String::is_empty) {
293 break;
294 }
295 vars.names.pop();
296 }
297 for name in &mut vars.names {
298 if name.as_ref().is_some_and(String::is_empty) {
299 *name = None;
300 }
301 }
302
303 vars.len = num_vars.1;
304 #[cfg(debug_assertions)]
305 vars.check_valid();
306 let preamble = Preamble {
307 format: format.1,
308 vars,
309 num_clauses: num_clauses.1,
310 clause_tree,
311 };
312 Ok((next_input, preamble))
313 } else {
314 let (input, (format, num_vars, num_clauses)) =
315 preceded(many0_count(util::comment), problem_line)(input)?;
316 let preamble = Preamble {
317 format: format.1,
318 vars: VarSet::new(num_vars.1),
319 num_clauses: num_clauses.1,
320 clause_tree: None,
321 };
322 Ok((input, preamble))
323 }
324 }
325}
326
327mod cnf {
328 use nom::branch::alt;
329 use nom::character::complete::{char, multispace0, one_of, u64};
330 use nom::combinator::{consumed, eof, iterator, map, recognize};
331 use nom::error::{context, ContextError, ErrorKind, FromExternalError, ParseError};
332 use nom::sequence::preceded;
333 use nom::{Err, IResult};
334
335 use crate::util::fail;
336 use crate::{Circuit, GateKind, Literal, Problem, Tree};
337
338 use super::Preamble;
339
340 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
341 enum CNFTokenKind {
342 Int(u64),
343 Neg,
344 Xor,
345 }
346
347 #[derive(Clone, PartialEq, Eq, Debug)]
348 struct CNFToken<'a> {
349 span: &'a [u8],
350 kind: CNFTokenKind,
351 }
352
353 fn lex<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
354 input: &'a [u8],
355 ) -> IResult<&'a [u8], CNFToken<'a>, E> {
356 let tok = alt((
357 map(consumed(u64), |(span, n)| CNFToken {
358 span,
359 kind: CNFTokenKind::Int(n),
360 }),
361 map(recognize(char('-')), |span| CNFToken {
362 span,
363 kind: CNFTokenKind::Neg,
364 }),
365 map(recognize(one_of("xX")), |span| CNFToken {
366 span,
367 kind: CNFTokenKind::Xor,
368 }),
369 ));
370
371 preceded(multispace0, tok)(input)
372 }
373
374 fn make_conj_tree(
375 circuit: &mut Circuit,
376 conjuncts: &[Literal],
377 tree: Tree<usize>,
378 stack: &mut Vec<Literal>,
379 ) -> Literal {
380 match tree {
381 Tree::Inner(children) => {
382 let saved_stack_len = stack.len();
383 for child in children {
384 let l = make_conj_tree(circuit, conjuncts, child, stack);
385 stack.push(l);
386 }
387 let root = circuit.push_gate(GateKind::And);
388 circuit.push_gate_inputs(stack[saved_stack_len..].iter().copied());
389 stack.truncate(saved_stack_len);
390 root
391 }
392 Tree::Leaf(i) => conjuncts[i],
393 }
394 }
395
396 pub fn parse<'a, E>(
397 preamble: Preamble,
398 ) -> impl FnOnce(&'a [u8]) -> IResult<&'a [u8], Problem, E>
399 where
400 E: ParseError<&'a [u8]> + ContextError<&'a [u8]> + FromExternalError<&'a [u8], String>,
401 {
402 move |input| {
403 let Preamble {
404 vars,
405 num_clauses,
406 clause_tree: clause_order_tree,
407 ..
408 } = preamble;
409 let num_vars = vars.len();
410 let mut circuit = Circuit::new(vars);
411 circuit.push_gate(GateKind::Or);
412
413 let mut neg = false;
414
415 let mut it = iterator(input, lex::<E>);
416 for token in &mut it {
417 match token.kind {
418 CNFTokenKind::Int(0) => {
419 circuit.push_gate(GateKind::Or);
420 }
421 CNFTokenKind::Int(n) => {
422 if n > num_vars as u64 {
423 return fail(token.span, "variables must be in range [1, #vars]");
424 }
425 circuit.push_gate_input(Literal::from_input(neg, (n - 1) as usize));
426 neg = false;
427 }
428 CNFTokenKind::Neg if !neg => neg = true,
429 CNFTokenKind::Neg => return fail(token.span, "expected a variable"),
430 CNFTokenKind::Xor => {
431 if let Some(gate) = circuit.last_gate() {
432 if !gate.inputs.is_empty() {
433 return fail(token.span, "XOR clauses must be marked as such at the beginning of the clause");
434 }
435 circuit.set_last_gate_kind(GateKind::Xor);
436 }
437 }
438 }
439 }
440
441 let (input, ()) = it.finish()?;
442 let (input, _) = multispace0(input)?;
443 let (input, _) = context("expected a literal or '0'", eof)(input)?;
444
445 let num_gates = circuit.num_gates();
446 if num_gates != num_clauses {
447 if num_gates == num_clauses + 1 && circuit.last_gate().unwrap().inputs.is_empty() {
450 circuit.pop_gate();
451 } else {
452 return Err(Err::Failure(E::from_external_error(
453 input,
454 ErrorKind::Fail,
455 format!("expected {num_clauses} clauses, got {num_gates}"),
456 )));
457 }
458 }
459 let num_gates = circuit.num_gates(); let root = if num_gates == 0 {
462 Literal::TRUE
463 } else {
464 let mut is_false = false;
465 let mut conj = Vec::with_capacity(num_gates);
466 let mut gate = 0;
467 circuit.retain_gates(|inputs| {
468 if is_false {
469 return false;
470 }
471 match inputs {
472 [] => {
473 is_false = true;
474 false
475 }
476 [l] => {
477 conj.push(*l);
478 false
479 }
480 _ => {
481 conj.push(Literal::from_gate(false, gate));
482 gate += 1;
483 true
484 }
485 }
486 });
487
488 if is_false {
489 circuit.clear_gates();
490 Literal::FALSE
491 } else if let Some(tree) = clause_order_tree {
492 let mut stack = Vec::with_capacity(num_clauses);
493 make_conj_tree(&mut circuit, &conj, tree, &mut stack)
494 } else {
495 let root = circuit.push_gate(GateKind::And);
496 circuit.push_gate_inputs(conj);
497 root
498 }
499 };
500
501 Ok((
502 input,
503 Problem {
504 circuit,
505 details: crate::ProblemDetails::Root(root),
506 },
507 ))
508 }
509 }
510}
511
512mod sat {
513 use nom::branch::alt;
514 use nom::bytes::complete::tag;
515 use nom::character::complete::{char, multispace0, u64};
516 use nom::combinator::{consumed, map, recognize, value};
517 use nom::error::{ContextError, ErrorKind, ParseError};
518 use nom::Err;
519 use nom::IResult;
520
521 use crate::util::{fail, map_res_fail, word};
522 use crate::{Circuit, GateKind, Literal, Problem, ProblemDetails, Var, VarSet};
523
524 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
525 enum TokenKind {
526 Var(Var),
527 Lpar,
528 Rpar,
529 Neg,
530 And,
531 Or,
532 Xor,
533 Eq,
534 }
535
536 #[derive(Clone, PartialEq, Eq, Debug)]
537 struct Token<'a> {
538 span: &'a [u8],
539 kind: TokenKind,
540 }
541
542 macro_rules! match_tok {
543 ($matcher:expr, $tok:ident) => {
544 map(recognize($matcher), |span| {
545 Some(Token {
546 span,
547 kind: TokenKind::$tok,
548 })
549 })
550 };
551 }
552
553 fn lex<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
554 num_vars: usize,
555 ) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Option<Token<'a>>, E> {
556 move |input| {
557 let (input, _) = multispace0(input)?; if input.is_empty() {
559 return Ok((input, None));
560 }
561 alt((
562 map_res_fail(consumed(u64), |(span, n)| {
563 if n == 0 || n > num_vars as u64 {
564 Err((span, "variables must be in range [1, #vars]"))
565 } else {
566 Ok(Some(Token {
567 span,
568 kind: TokenKind::Var(n as usize),
569 }))
570 }
571 }),
572 match_tok!(char('('), Lpar),
573 match_tok!(char(')'), Rpar),
574 match_tok!(char('-'), Neg),
575 match_tok!(char('*'), And),
576 match_tok!(char('+'), Or),
577 match_tok!(word(tag("xor")), Xor),
578 match_tok!(char('='), Eq),
579 ))(input)
580 }
581 }
582
583 #[derive(Debug)]
584 enum SatParserErr<'a, E> {
585 E(E),
586 Rpar { input: &'a [u8], span: &'a [u8] },
587 }
588 impl<'a, E: ParseError<&'a [u8]>> ParseError<&'a [u8]> for SatParserErr<'a, E> {
589 fn from_error_kind(input: &'a [u8], kind: ErrorKind) -> Self {
590 Self::E(E::from_error_kind(input, kind))
591 }
592
593 fn append(input: &'a [u8], kind: ErrorKind, other: Self) -> Self {
594 match other {
595 Self::E(other) => Self::E(E::append(input, kind, other)),
596 Self::Rpar { .. } => unreachable!(),
597 }
598 }
599 }
600 impl<'a, E: ContextError<&'a [u8]>> ContextError<&'a [u8]> for SatParserErr<'a, E> {
601 fn add_context(input: &'a [u8], ctx: &'static str, other: Self) -> Self {
602 match other {
603 Self::E(other) => Self::E(E::add_context(input, ctx, other)),
604 Self::Rpar { .. } => other,
605 }
606 }
607 }
608
609 fn expect<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
610 kind: TokenKind,
611 err: &'static str,
612 num_vars: usize,
613 ) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], (), E> {
614 move |input| {
615 let (input, tok) = lex(num_vars)(input)?;
616 match tok {
617 None => fail(input, err),
618 Some(tok) if tok.kind != kind => fail(tok.span, err),
619 _ => Ok((input, ())),
620 }
621 }
622 }
623
624 fn formula<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
625 allow_xor: bool,
626 allow_eq: bool,
627 circuit: &mut Circuit,
628 stack: &mut Vec<Literal>,
629 input: &'a [u8],
630 ) -> IResult<&'a [u8], Literal, SatParserErr<'a, E>> {
631 let num_vars = circuit.inputs().len();
632 let (input, tok) = lex(num_vars)(input)?;
633 let tok = match tok {
634 Some(tok) => tok,
635 None => return fail(input, "expected a formula"),
636 };
637
638 match tok.kind {
639 TokenKind::Var(n) => Ok((input, Literal::from_input(false, n - 1))),
640 TokenKind::Lpar => {
641 let (input, l) = formula(allow_xor, allow_eq, circuit, stack, input)?;
642 value(l, expect(TokenKind::Rpar, "expected ')'", num_vars))(input)
643 }
644 TokenKind::Rpar => Err(Err::Error(SatParserErr::Rpar {
645 input,
646 span: tok.span,
647 })),
648 TokenKind::Neg => {
649 let (input, tok) = lex(num_vars)(input)?;
650 let tok = match tok {
651 Some(t) => t,
652 None => return fail(input, "expected a variable or '('"),
653 };
654 match tok.kind {
655 TokenKind::Var(n) => Ok((input, Literal::from_input(true, n - 1))),
656 TokenKind::Lpar => {
657 let (input, l) = formula(allow_xor, allow_eq, circuit, stack, input)?;
658 value(!l, expect(TokenKind::Rpar, "expected ')'", num_vars))(input)
659 }
660 _ => fail(tok.span, "expected a variable or '('"),
661 }
662 }
663 TokenKind::Xor if !allow_xor => fail(
664 tok.span,
665 "'xor' is only allowed in formats 'satx' and 'satex'",
666 ),
667 TokenKind::Eq if !allow_eq => fail(
668 tok.span,
669 "'=' is only allowed in formats 'sate' and 'satex'",
670 ),
671 _ => {
672 let (mut input, ()) = expect(TokenKind::Lpar, "expected '('", num_vars)(input)?;
673
674 let saved_stack_len = stack.len();
675 let input = loop {
676 match formula(allow_xor, allow_eq, circuit, stack, input) {
677 Ok((i, sub)) => {
678 input = i;
679 stack.push(sub)
680 }
681 Err(Err::Error(SatParserErr::Rpar { input, .. })) => break input,
682 Err(f) => {
683 stack.truncate(saved_stack_len);
684 return Err(f);
685 }
686 }
687 };
688
689 let children = &stack[saved_stack_len..];
690 let literal = match children {
691 [] => match tok.kind {
692 TokenKind::And | TokenKind::Eq => Literal::TRUE,
693 TokenKind::Or | TokenKind::Xor => Literal::FALSE,
694 _ => unreachable!(),
695 },
696 [l] => *l,
697 _ => {
698 let l = circuit.push_gate(match tok.kind {
699 TokenKind::And => GateKind::And,
700 TokenKind::Or => GateKind::Or,
701 _ => GateKind::Xor,
702 });
703
704 circuit.push_gate_inputs(children.iter().copied());
705
706 if tok.kind == TokenKind::Eq && children.len() % 2 == 0 {
707 !l
708 } else {
709 l
710 }
711 }
712 };
713 stack.truncate(saved_stack_len);
714
715 Ok((input, literal))
716 }
717 }
718 }
719
720 pub fn parse<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
721 vars: VarSet,
722 allow_xor: bool,
723 allow_eq: bool,
724 ) -> impl FnOnce(&'a [u8]) -> IResult<&'a [u8], Problem, E> {
725 let num_vars = vars.len();
726 let mut circuit = Circuit::new(vars);
727 let mut stack = Vec::with_capacity(2 * num_vars);
728 move |input| match formula(allow_xor, allow_eq, &mut circuit, &mut stack, input) {
729 Ok((input, root)) => Ok((
730 input,
731 Problem {
732 circuit,
733 details: ProblemDetails::Root(root),
734 },
735 )),
736 Err(e) => Err(e.map(|e| match e {
737 SatParserErr::E(e) => e,
738 SatParserErr::Rpar { input, span } => E::add_context(
739 span,
740 "expected a formula",
741 E::from_error_kind(input, ErrorKind::Fail),
742 ),
743 })),
744 }
745 }
746}
747
748pub fn parse<'a, E>(options: &ParseOptions) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Problem, E>
750where
751 E: ParseError<&'a [u8]> + ContextError<&'a [u8]> + FromExternalError<&'a [u8], String>,
752{
753 let parse_var_order = options.var_order;
754 let parse_clause_tree = options.clause_tree;
755 move |input| {
756 let (input, preamble) = preamble(parse_var_order, parse_clause_tree)(input)?;
757 match preamble.format {
758 Format::CNF => cnf::parse(preamble)(input),
759 Format::SAT { xor, eq } => {
760 let (input, res) = sat::parse(preamble.vars, xor, eq)(input)?;
761 let (input, _) = context(
762 "expected end of file (SAT files may only contain a single formula)",
763 preceded(multispace0, eof),
764 )(input)?;
765 Ok((input, res))
766 }
767 }
768 }
769}
770
771#[cfg(test)]
772mod tests {
773 use nom::Finish;
774
775 use crate::util::test::*;
776 use crate::{Gate, Literal};
777
778 use super::*;
779
780 #[test]
781 fn example_cnf() {
782 let input = "c Example CNF format file
783c
784p cnf 4 3
7851 3 -4 0
7864 0 2
787-3";
788 let (input, problem) = parse::<()>(&OPTS_NO_ORDER)(input.as_bytes())
789 .finish()
790 .unwrap();
791 assert!(input.is_empty());
792
793 let (circuit, root) = unwrap_problem(problem);
794 let inputs = circuit.inputs();
795 assert_eq!(inputs.len(), 4);
796 assert!(inputs.order().is_none());
797
798 assert_eq!(root, g(2));
799 assert_eq!(circuit.gate(root), Some(Gate::and(&[g(0), v(3), g(1)])));
800 assert_eq!(circuit.gate(g(0)), Some(Gate::or(&[v(0), v(2), !v(3)])));
801 assert_eq!(circuit.gate(g(1)), Some(Gate::or(&[v(1), !v(2)])));
802 }
803
804 #[test]
805 fn example_cnf_0term() {
806 let input = "c Example CNF format file
807c
808p cnf 4 3
8091 3 -4 0
8104 0 2
811-3 0";
812 let (input, problem) = parse::<()>(&OPTS_NO_ORDER)(input.as_bytes())
813 .finish()
814 .unwrap();
815 assert!(input.is_empty());
816
817 let (circuit, root) = unwrap_problem(problem);
818 let inputs = circuit.inputs();
819 assert_eq!(inputs.len(), 4);
820 assert!(inputs.order().is_none());
821
822 assert_eq!(root, g(2));
823 assert_eq!(circuit.gate(root), Some(Gate::and(&[g(0), v(3), g(1)])));
824 assert_eq!(circuit.gate(g(0)), Some(Gate::or(&[v(0), v(2), !v(3)])));
825 assert_eq!(circuit.gate(g(1)), Some(Gate::or(&[v(1), !v(2)])));
826 }
827
828 #[test]
829 fn empty_cnf() {
830 let input = "p cnf 0 0\n";
831 let (input, problem) = parse::<()>(&OPTS_NO_ORDER)(input.as_bytes())
832 .finish()
833 .unwrap();
834 assert!(input.is_empty());
835
836 let (circuit, root) = unwrap_problem(problem);
837 let inputs = circuit.inputs();
838 assert_eq!(inputs.len(), 0);
839
840 assert_eq!(root, Literal::TRUE);
841 }
842
843 #[test]
844 fn example_sat() {
845 let input = "c Sample SAT format
846c
847p sat 4
848(*(+(1 3 -4)
849 +(4)
850 +(2 3)))";
851 let (input, problem) = parse::<()>(&OPTS_NO_ORDER)(input.as_bytes())
852 .finish()
853 .unwrap();
854 assert!(input.is_empty());
855
856 let (circuit, root) = unwrap_problem(problem);
857 let inputs = circuit.inputs();
858 assert_eq!(inputs.len(), 4);
859 assert!(inputs.order().is_none());
860
861 assert_eq!(root, g(2));
862 assert_eq!(circuit.gate(root), Some(Gate::and(&[g(0), v(3), g(1)])));
863 assert_eq!(circuit.gate(g(0)), Some(Gate::or(&[v(0), v(2), !v(3)])));
864 assert_eq!(circuit.gate(g(1)), Some(Gate::or(&[v(1), v(2)])));
865 }
866
867 #[test]
868 fn preamble_satx() {
869 let (input, preamble) = preamble::<()>(false, false)(b"p satx 1337 \n").unwrap();
870 assert!(input.is_empty());
871 assert_eq!(
872 preamble,
873 Preamble {
874 format: SATX,
875 vars: VarSet::new(1337),
876 num_clauses: 0,
877 clause_tree: None
878 }
879 );
880 }
881
882 #[test]
883 fn preamble_sate() {
884 let (input, preamble) = preamble::<()>(false, false)(b"p sate 1\n").unwrap();
885 assert!(input.is_empty());
886 assert_eq!(
887 preamble,
888 Preamble {
889 format: SATE,
890 vars: VarSet::new(1),
891 num_clauses: 0,
892 clause_tree: None
893 }
894 );
895 }
896
897 #[test]
898 fn preamble_satex() {
899 let (input, preamble) = preamble::<()>(false, false)(b"p satex 42 \n").unwrap();
900 assert!(input.is_empty());
901 assert_eq!(
902 preamble,
903 Preamble {
904 format: SATEX,
905 vars: VarSet::new(42),
906 num_clauses: 0,
907 clause_tree: None
908 }
909 );
910 }
911}