Skip to main content

oxidd_parser/
dimacs.rs

1//! DIMACS CNF/SAT parser based on the paper
2//! "[Satisfiability Suggested Format][spec]"
3//!
4//! The parsers perform some trivial simplifications on the CNF or the SAT
5//! formula: CNFs with empty clauses become
6//! [`Literal::FALSE`][crate::Literal::FALSE], empty CNFs become
7//! [`Literal::TRUE`][crate::Literal::TRUE]. Likewise, empty disjunctions,
8//! conjunctions, etc., in SAT formulas are replaced by the respective constant.
9//! Equivalence operators are replaced by XOR and negation (since
10//! [`Circuit`s][crate::Circuit] do not support equivalence). Conjunction,
11//! disjunction, and XOR operators with just a single operand are discarded.
12//!
13//! In addition to regular OR clauses, the CNF parser also supports [XOR
14//! clauses][xcnf] (XCNF).
15//!
16//! [spec]: https://www21.in.tum.de/~lammich/2015_SS_Seminar_SAT/resources/dimacs-cnf.pdf
17//! [xcnf]: https://www.msoos.org/xor-clauses/
18
19// spell-checker:ignore multispace
20
21use 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::{ContextError, ErrorKind, FromExternalError, ParseError, context};
27use nom::multi::many0_count;
28use nom::sequence::{preceded, terminated};
29use nom::{Err, IResult};
30
31use crate::util::{
32    self, MAX_CAPACITY, context_loc, eol, fail, fail_with_contexts, line_span, word, word_span,
33};
34use crate::{ParseOptions, Problem, Tree, Var, VarSet};
35
36// spell-checker:ignore SATX,SATEX
37
38#[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
72/// Parses a problem line, i.e., `p cnf <#vars> <#clauses>` or
73/// `p sat[e][x] <#vars>`
74///
75/// Returns the format, number of vars and in case of `cnf` format the number of
76/// clauses together with their spans.
77fn 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    /// Number of clauses (CNF format, otherwise 0)
124    num_clauses: usize,
125    clause_tree: Option<Tree<usize>>,
126}
127
128/// Parses the preamble, i.e., all `c` and `p` lines at the beginning of the
129/// file
130///
131/// Note: `parse_orders` only instructs the parser to treat comment lines as
132/// order lines. In case a var or a clause order is given, this function ensures
133/// that they are valid. However, if no var order is given, then the returned
134/// var order is empty, and if no clause order is given, then the returned
135/// clause order is empty.
136fn 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        // TODO: `parse_clause_tree` currently requires a valid (or empty)
145        // variable order. Is this what we want?
146        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(); // in the name mapping / linear order
155            let mut tree_max_var = ([].as_slice(), 0); // dummy value
156            let mut name_set: FxHashSet<&str> = Default::default();
157
158            // clause order
159            let mut clause_tree = None;
160            let mut clause_order_span = [].as_slice();
161            let mut max_clause = ([].as_slice(), 0); // dummy value
162
163            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                    // variable order tree
186                    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                    // The variable order tree takes precedence (and determines the linear order)
195                    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                    // var order line
203                    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                    // always write Some to mark the variable as present
222                    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            // cleanup: we used `Some(String::new())` to mark unnamed variables as present
291            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::{ContextError, ErrorKind, FromExternalError, ParseError, context};
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(
434                                    token.span,
435                                    "XOR clauses must be marked as such at the beginning of the clause",
436                                );
437                            }
438                            circuit.set_last_gate_kind(GateKind::Xor);
439                        }
440                    }
441                }
442            }
443
444            let (input, ()) = it.finish()?;
445            let (input, _) = multispace0(input)?;
446            let (input, _) = context("expected a literal or '0'", eof)(input)?;
447
448            let num_gates = circuit.num_gates();
449            if num_gates != num_clauses {
450                // The last clause may or may not be terminated by 0. In case it is, we called
451                // `push_clause()` once too often.
452                if num_gates == num_clauses + 1 && circuit.last_gate().unwrap().inputs.is_empty() {
453                    circuit.pop_gate();
454                } else {
455                    return Err(Err::Failure(E::from_external_error(
456                        input,
457                        ErrorKind::Fail,
458                        format!("expected {num_clauses} clauses, got {num_gates}"),
459                    )));
460                }
461            }
462            let num_gates = circuit.num_gates(); // may have been decremented above
463
464            let root = if num_gates == 0 {
465                Literal::TRUE
466            } else {
467                let mut is_false = false;
468                let mut conj = Vec::with_capacity(num_gates);
469                let mut gate = 0;
470                circuit.retain_gates(|inputs| {
471                    if is_false {
472                        return false;
473                    }
474                    match inputs {
475                        [] => {
476                            is_false = true;
477                            false
478                        }
479                        [l] => {
480                            conj.push(*l);
481                            false
482                        }
483                        _ => {
484                            conj.push(Literal::from_gate(false, gate));
485                            gate += 1;
486                            true
487                        }
488                    }
489                });
490
491                if is_false {
492                    circuit.clear_gates();
493                    Literal::FALSE
494                } else if let Some(tree) = clause_order_tree {
495                    let mut stack = Vec::with_capacity(num_clauses);
496                    make_conj_tree(&mut circuit, &conj, tree, &mut stack)
497                } else {
498                    let root = circuit.push_gate(GateKind::And);
499                    circuit.push_gate_inputs(conj);
500                    root
501                }
502            };
503
504            Ok((
505                input,
506                Problem {
507                    circuit,
508                    details: crate::ProblemDetails::Root(root),
509                },
510            ))
511        }
512    }
513}
514
515mod sat {
516    use nom::Err;
517    use nom::IResult;
518    use nom::branch::alt;
519    use nom::bytes::complete::tag;
520    use nom::character::complete::{char, multispace0, u64};
521    use nom::combinator::{consumed, map, recognize, value};
522    use nom::error::{ContextError, ErrorKind, ParseError};
523
524    use crate::util::{fail, map_res_fail, word};
525    use crate::{Circuit, GateKind, Literal, Problem, ProblemDetails, Var, VarSet};
526
527    #[derive(Clone, Copy, PartialEq, Eq, Debug)]
528    enum TokenKind {
529        Var(Var),
530        Lpar,
531        Rpar,
532        Neg,
533        And,
534        Or,
535        Xor,
536        Eq,
537    }
538
539    #[derive(Clone, PartialEq, Eq, Debug)]
540    struct Token<'a> {
541        span: &'a [u8],
542        kind: TokenKind,
543    }
544
545    macro_rules! match_tok {
546        ($matcher:expr, $tok:ident) => {
547            map(recognize($matcher), |span| {
548                Some(Token {
549                    span,
550                    kind: TokenKind::$tok,
551                })
552            })
553        };
554    }
555
556    fn lex<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
557        num_vars: usize,
558    ) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Option<Token<'a>>, E> {
559        move |input| {
560            let (input, _) = multispace0(input)?; // should never fail
561            if input.is_empty() {
562                return Ok((input, None));
563            }
564            alt((
565                map_res_fail(consumed(u64), |(span, n)| {
566                    if n == 0 || n > num_vars as u64 {
567                        Err((span, "variables must be in range [1, #vars]"))
568                    } else {
569                        Ok(Some(Token {
570                            span,
571                            kind: TokenKind::Var(n as usize),
572                        }))
573                    }
574                }),
575                match_tok!(char('('), Lpar),
576                match_tok!(char(')'), Rpar),
577                match_tok!(char('-'), Neg),
578                match_tok!(char('*'), And),
579                match_tok!(char('+'), Or),
580                match_tok!(word(tag("xor")), Xor),
581                match_tok!(char('='), Eq),
582            ))(input)
583        }
584    }
585
586    #[derive(Debug)]
587    enum SatParserErr<'a, E> {
588        E(E),
589        Rpar { input: &'a [u8], span: &'a [u8] },
590    }
591    impl<'a, E: ParseError<&'a [u8]>> ParseError<&'a [u8]> for SatParserErr<'a, E> {
592        fn from_error_kind(input: &'a [u8], kind: ErrorKind) -> Self {
593            Self::E(E::from_error_kind(input, kind))
594        }
595
596        fn append(input: &'a [u8], kind: ErrorKind, other: Self) -> Self {
597            match other {
598                Self::E(other) => Self::E(E::append(input, kind, other)),
599                Self::Rpar { .. } => unreachable!(),
600            }
601        }
602    }
603    impl<'a, E: ContextError<&'a [u8]>> ContextError<&'a [u8]> for SatParserErr<'a, E> {
604        fn add_context(input: &'a [u8], ctx: &'static str, other: Self) -> Self {
605            match other {
606                Self::E(other) => Self::E(E::add_context(input, ctx, other)),
607                Self::Rpar { .. } => other,
608            }
609        }
610    }
611
612    fn expect<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
613        kind: TokenKind,
614        err: &'static str,
615        num_vars: usize,
616    ) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], (), E> {
617        move |input| {
618            let (input, tok) = lex(num_vars)(input)?;
619            match tok {
620                None => fail(input, err),
621                Some(tok) if tok.kind != kind => fail(tok.span, err),
622                _ => Ok((input, ())),
623            }
624        }
625    }
626
627    fn formula<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
628        allow_xor: bool,
629        allow_eq: bool,
630        circuit: &mut Circuit,
631        stack: &mut Vec<Literal>,
632        input: &'a [u8],
633    ) -> IResult<&'a [u8], Literal, SatParserErr<'a, E>> {
634        let num_vars = circuit.inputs().len();
635        let (input, tok) = lex(num_vars)(input)?;
636        let tok = match tok {
637            Some(tok) => tok,
638            None => return fail(input, "expected a formula"),
639        };
640
641        match tok.kind {
642            TokenKind::Var(n) => Ok((input, Literal::from_input(false, n - 1))),
643            TokenKind::Lpar => {
644                let (input, l) = formula(allow_xor, allow_eq, circuit, stack, input)?;
645                value(l, expect(TokenKind::Rpar, "expected ')'", num_vars))(input)
646            }
647            TokenKind::Rpar => Err(Err::Error(SatParserErr::Rpar {
648                input,
649                span: tok.span,
650            })),
651            TokenKind::Neg => {
652                let (input, tok) = lex(num_vars)(input)?;
653                let tok = match tok {
654                    Some(t) => t,
655                    None => return fail(input, "expected a variable or '('"),
656                };
657                match tok.kind {
658                    TokenKind::Var(n) => Ok((input, Literal::from_input(true, n - 1))),
659                    TokenKind::Lpar => {
660                        let (input, l) = formula(allow_xor, allow_eq, circuit, stack, input)?;
661                        value(!l, expect(TokenKind::Rpar, "expected ')'", num_vars))(input)
662                    }
663                    _ => fail(tok.span, "expected a variable or '('"),
664                }
665            }
666            TokenKind::Xor if !allow_xor => fail(
667                tok.span,
668                "'xor' is only allowed in formats 'satx' and 'satex'",
669            ),
670            TokenKind::Eq if !allow_eq => fail(
671                tok.span,
672                "'=' is only allowed in formats 'sate' and 'satex'",
673            ),
674            _ => {
675                let (mut input, ()) = expect(TokenKind::Lpar, "expected '('", num_vars)(input)?;
676
677                let saved_stack_len = stack.len();
678                let input = loop {
679                    match formula(allow_xor, allow_eq, circuit, stack, input) {
680                        Ok((i, sub)) => {
681                            input = i;
682                            stack.push(sub)
683                        }
684                        Err(Err::Error(SatParserErr::Rpar { input, .. })) => break input,
685                        Err(f) => {
686                            stack.truncate(saved_stack_len);
687                            return Err(f);
688                        }
689                    }
690                };
691
692                let children = &stack[saved_stack_len..];
693                let literal = match children {
694                    [] => match tok.kind {
695                        TokenKind::And | TokenKind::Eq => Literal::TRUE,
696                        TokenKind::Or | TokenKind::Xor => Literal::FALSE,
697                        _ => unreachable!(),
698                    },
699                    [l] => *l,
700                    _ => {
701                        let l = circuit.push_gate(match tok.kind {
702                            TokenKind::And => GateKind::And,
703                            TokenKind::Or => GateKind::Or,
704                            _ => GateKind::Xor,
705                        });
706
707                        circuit.push_gate_inputs(children.iter().copied());
708
709                        if tok.kind == TokenKind::Eq && children.len().is_multiple_of(2) {
710                            !l
711                        } else {
712                            l
713                        }
714                    }
715                };
716                stack.truncate(saved_stack_len);
717
718                Ok((input, literal))
719            }
720        }
721    }
722
723    pub fn parse<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
724        vars: VarSet,
725        allow_xor: bool,
726        allow_eq: bool,
727    ) -> impl FnOnce(&'a [u8]) -> IResult<&'a [u8], Problem, E> {
728        let num_vars = vars.len();
729        let mut circuit = Circuit::new(vars);
730        let mut stack = Vec::with_capacity(2 * num_vars);
731        move |input| match formula(allow_xor, allow_eq, &mut circuit, &mut stack, input) {
732            Ok((input, root)) => Ok((
733                input,
734                Problem {
735                    circuit,
736                    details: ProblemDetails::Root(root),
737                },
738            )),
739            Err(e) => Err(e.map(|e| match e {
740                SatParserErr::E(e) => e,
741                SatParserErr::Rpar { input, span } => E::add_context(
742                    span,
743                    "expected a formula",
744                    E::from_error_kind(input, ErrorKind::Fail),
745                ),
746            })),
747        }
748    }
749}
750
751/// Parse a DIMACS CNF/SAT file
752pub fn parse<'a, E>(options: &ParseOptions) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Problem, E>
753where
754    E: ParseError<&'a [u8]> + ContextError<&'a [u8]> + FromExternalError<&'a [u8], String>,
755{
756    let parse_var_order = options.var_order;
757    let parse_clause_tree = options.clause_tree;
758    move |input| {
759        let (input, preamble) = preamble(parse_var_order, parse_clause_tree)(input)?;
760        match preamble.format {
761            Format::CNF => cnf::parse(preamble)(input),
762            Format::SAT { xor, eq } => {
763                let (input, res) = sat::parse(preamble.vars, xor, eq)(input)?;
764                let (input, _) = context(
765                    "expected end of file (SAT files may only contain a single formula)",
766                    preceded(multispace0, eof),
767                )(input)?;
768                Ok((input, res))
769            }
770        }
771    }
772}
773
774#[cfg(test)]
775mod tests {
776    use nom::Finish;
777
778    use crate::util::test::*;
779    use crate::{Gate, Literal};
780
781    use super::*;
782
783    #[test]
784    fn example_cnf() {
785        let input = "c Example CNF format file
786c
787p cnf 4 3
7881 3 -4 0
7894 0 2
790-3";
791        let (input, problem) = parse::<()>(&OPTS_NO_ORDER)(input.as_bytes())
792            .finish()
793            .unwrap();
794        assert!(input.is_empty());
795
796        let (circuit, root) = unwrap_problem(problem);
797        let inputs = circuit.inputs();
798        assert_eq!(inputs.len(), 4);
799        assert!(inputs.order().is_none());
800
801        assert_eq!(root, g(2));
802        assert_eq!(circuit.gate(root), Some(Gate::and(&[g(0), v(3), g(1)])));
803        assert_eq!(circuit.gate(g(0)), Some(Gate::or(&[v(0), v(2), !v(3)])));
804        assert_eq!(circuit.gate(g(1)), Some(Gate::or(&[v(1), !v(2)])));
805    }
806
807    #[test]
808    fn example_cnf_0term() {
809        let input = "c Example CNF format file
810c
811p cnf 4 3
8121 3 -4 0
8134 0 2
814-3 0";
815        let (input, problem) = parse::<()>(&OPTS_NO_ORDER)(input.as_bytes())
816            .finish()
817            .unwrap();
818        assert!(input.is_empty());
819
820        let (circuit, root) = unwrap_problem(problem);
821        let inputs = circuit.inputs();
822        assert_eq!(inputs.len(), 4);
823        assert!(inputs.order().is_none());
824
825        assert_eq!(root, g(2));
826        assert_eq!(circuit.gate(root), Some(Gate::and(&[g(0), v(3), g(1)])));
827        assert_eq!(circuit.gate(g(0)), Some(Gate::or(&[v(0), v(2), !v(3)])));
828        assert_eq!(circuit.gate(g(1)), Some(Gate::or(&[v(1), !v(2)])));
829    }
830
831    #[test]
832    fn empty_cnf() {
833        let input = "p cnf 0 0\n";
834        let (input, problem) = parse::<()>(&OPTS_NO_ORDER)(input.as_bytes())
835            .finish()
836            .unwrap();
837        assert!(input.is_empty());
838
839        let (circuit, root) = unwrap_problem(problem);
840        let inputs = circuit.inputs();
841        assert_eq!(inputs.len(), 0);
842
843        assert_eq!(root, Literal::TRUE);
844    }
845
846    #[test]
847    fn example_sat() {
848        let input = "c Sample SAT format
849c
850p sat 4
851(*(+(1 3 -4)
852    +(4)
853    +(2 3)))";
854        let (input, problem) = parse::<()>(&OPTS_NO_ORDER)(input.as_bytes())
855            .finish()
856            .unwrap();
857        assert!(input.is_empty());
858
859        let (circuit, root) = unwrap_problem(problem);
860        let inputs = circuit.inputs();
861        assert_eq!(inputs.len(), 4);
862        assert!(inputs.order().is_none());
863
864        assert_eq!(root, g(2));
865        assert_eq!(circuit.gate(root), Some(Gate::and(&[g(0), v(3), g(1)])));
866        assert_eq!(circuit.gate(g(0)), Some(Gate::or(&[v(0), v(2), !v(3)])));
867        assert_eq!(circuit.gate(g(1)), Some(Gate::or(&[v(1), v(2)])));
868    }
869
870    #[test]
871    fn preamble_satx() {
872        let (input, preamble) = preamble::<()>(false, false)(b"p satx 1337 \n").unwrap();
873        assert!(input.is_empty());
874        assert_eq!(
875            preamble,
876            Preamble {
877                format: SATX,
878                vars: VarSet::new(1337),
879                num_clauses: 0,
880                clause_tree: None
881            }
882        );
883    }
884
885    #[test]
886    fn preamble_sate() {
887        let (input, preamble) = preamble::<()>(false, false)(b"p sate 1\n").unwrap();
888        assert!(input.is_empty());
889        assert_eq!(
890            preamble,
891            Preamble {
892                format: SATE,
893                vars: VarSet::new(1),
894                num_clauses: 0,
895                clause_tree: None
896            }
897        );
898    }
899
900    #[test]
901    fn preamble_satex() {
902        let (input, preamble) = preamble::<()>(false, false)(b"p satex 42 \n").unwrap();
903        assert!(input.is_empty());
904        assert_eq!(
905            preamble,
906            Preamble {
907                format: SATEX,
908                vars: VarSet::new(42),
909                num_clauses: 0,
910                clause_tree: None
911            }
912        );
913    }
914}