rsmt2/
parse.rs

1//! SMT-LIB 2 result parsers.
2//!
3//! Depending on the commands you plan to use, your parser will need to implement
4//!
5//! |                  | for                       |
6//! |:----------------:|:-------------------------:|
7//! | [`IdentParser`] | [`Solver::get_model`]      |
8//! | [`ModelParser`] | [`Solver::get_model`]      |
9//! | [`ValueParser`] | [`Solver::get_model`]      |
10//! | [`ExprParser`]  | [`Solver::get_values`]     |
11//! | [`SymParser`]   | [`Solver::get_unsat_core`] |
12//! | [`ProofParser`] | *currently unused*         |
13//!
14//! You can choose the kind of input you want to parse, between
15//!
16//! - `& [u8]`, *e.g.* for [`nom`][nom],
17//! - `& str`, *e.g.* for [`regex`][regex],
18//! - [`& mut SmtParser`](SmtParser), `rmst2`'s own parser which provides simple helpers to parse
19//!   s-expressions.
20//!
21//! The first two are safe in that your parsers will be called on the tokens they are supposed to
22//! parse and nothing else.
23//!
24//!
25//! ## Parsing: `&str` (and `&[u8]`)
26//!
27//!
28//! Here is a first example where we defined a value parser that only recognizes booleans, to
29//! showcase [`ValueParser`] and [`Solver::get_values`]. `Expr`essions are represented as strings,
30//! and `Val`ues are booleans.
31//!
32//! ```rust
33//! # extern crate rsmt2;
34//! use rsmt2::{SmtConf, SmtRes, Solver, parse::ValueParser, parse::ExprParser};
35//!
36//! pub type Expr = String;
37//! pub type Val = bool;
38//!
39//! #[derive(Clone, Copy)]
40//! pub struct Parser;
41//! // Value parser implementation for `&'a str` input.
42//! impl<'a> ValueParser<Val, &'a str> for Parser {
43//!     fn parse_value(self, input: &'a str) -> SmtRes<Val> {
44//!         // When parsing `&str` or `&[u8]`, the input is the actual value.
45//!         match input {
46//!             "true" => Ok(true),
47//!             "false" => Ok(false),
48//!             s => Err(format!("unsupported value `{}`", s).into()),
49//!         }
50//!     }
51//! }
52//! impl<'a> ExprParser<Expr, (), &'a str> for Parser {
53//!     fn parse_expr(self, input: &'a str, _: ()) -> SmtRes<Expr> {
54//!         // When parsing `&str` or `&[u8]`, the input is the actual expression. Here we're not
55//!         // constructing some complex expression, we just want to turn the `&str` into a
56//!         // `String`.
57//!         Ok(input.into())
58//!     }
59//! }
60//!
61//! let mut solver = SmtConf::default_z3().spawn(Parser).unwrap();
62//! solver.declare_const("a", "Bool").unwrap();
63//! solver.declare_const("b", "Bool").unwrap();
64//! solver.assert("(and a (not b))").unwrap();
65//! let is_sat = solver.check_sat().unwrap();
66//! assert!(is_sat);
67//! let values = solver.get_values(&["a", "b", "(and a (not b))"]).unwrap();
68//! assert_eq!(
69//!     &format!("{:?}", values),
70//!     r#"[("a", true), ("b", false), ("(and a (not b))", true)]"#
71//! );
72//! let mut values = values.into_iter();
73//! assert_eq!( values.next(), Some(("a".to_string(), true)) );
74//! assert_eq!( values.next(), Some(("b".to_string(), false)) );
75//! assert_eq!( values.next(), Some(("(and a (not b))".to_string(), true)) );
76//! ```
77//!
78//! Here is a second example where we implement [`ModelParser`] and [`IdentParser`]. We must provide
79//! parsing functions for identifiers, types and values.
80//!
81//! ```rust
82//! # extern crate rsmt2;
83//! # use rsmt2::parse::SmtParser;
84//! # fn main() {
85//! use rsmt2::parse::{ IdentParser, ModelParser };
86//! use rsmt2::SmtRes;
87//! let txt = "\
88//!   ( model (define-fun a () Int (- 17)) )
89//! ";
90//! let mut parser = SmtParser::of_str(txt);
91//!
92//! struct Parser;
93//! impl<'a, 'b> ModelParser<
94//!     String, String, String, & 'a str
95//! > for & 'b Parser {
96//!     fn parse_value(
97//!         self, input: & 'a str,
98//!         _: & String, _: & [ (String, String) ], _: & String,
99//!     ) -> SmtRes<String> {
100//!         Ok(input.into())
101//!     }
102//! }
103//! impl<'a, 'b> IdentParser<String, String, & 'a str> for & 'b Parser {
104//!     fn parse_ident(self, input: & 'a str) -> SmtRes<String> {
105//!         Ok(input.into())
106//!     }
107//!     fn parse_type(self, input: & 'a str) -> SmtRes<String> {
108//!         Ok(input.into())
109//!     }
110//! }
111//!
112//! let model = parser.get_model_const( false, & Parser ).expect("model");
113//! assert_eq!( model, vec![ ("a".into(), "Int".into(), "(- 17)".into()) ] )
114//! # }
115//! ```
116//!
117//!
118//! ## Parsing: [`SmtParser`]
119//!
120//! But a parser taking [`SmtParser`] as input is "unsafe" in the sense that it has access to the
121//! whole input. Note that [`SmtParser`] provides helper parsing functions such as
122//! [`SmtParser::try_int`] and [`SmtParser::try_sym`].
123//!
124//! ```
125//! # extern crate rsmt2;
126//! # use rsmt2::parse::SmtParser;
127//! # fn main() {
128//! use rsmt2::parse::{ IdentParser, ModelParser };
129//! use rsmt2::errors::SmtRes;
130//! let txt = "\
131//!     ( model (define-fun a () Int (- 17)) )
132//! ";
133//! let mut parser = SmtParser::of_str(txt);
134//!
135//! struct Parser;
136//! impl<'a, 'b, Br: ::std::io::BufRead> ModelParser<
137//!     String, String, String, & 'a mut SmtParser<Br>
138//! > for & 'b Parser {
139//!     fn parse_value(
140//!         self, input: & 'a mut SmtParser<Br>,
141//!         _: & String, _: & [ (String, String) ], _: & String,
142//!     ) -> SmtRes<String> {
143//!         input.tag("(- 17))") ?; Ok( "-17".into() )
144//!         //               ^~~~~ eating more input than we should...
145//!     }
146//! }
147//! impl<'a, 'b, Br: ::std::io::BufRead> IdentParser<
148//!     String, String, & 'a mut SmtParser<Br>
149//! > for & 'b Parser {
150//!     fn parse_ident(self, input: & 'a mut SmtParser<Br>) -> SmtRes<String> {
151//!         input.tag("a") ?; Ok( "a".into() )
152//!     }
153//!     fn parse_type(self, input: & 'a mut SmtParser<Br>) -> SmtRes<String> {
154//!         input.tag("Int") ?; Ok( "Int".into() )
155//!     }
156//! }
157//!
158//! use rsmt2::errors::ErrorKind;
159//! let e = parser.get_model_const( false, & Parser ).unwrap_err();
160//! # println!("error:");
161//! # for e in e.iter() {
162//! #     for (idx, line) in e.to_string().lines().enumerate() {
163//! #         if idx == 0 { print!("- ") } else { print!("  ") }
164//! #         println!("{}", line);
165//! #     }
166//! # }
167//! match e.kind() {
168//!     ErrorKind::ParseError(msg, token) => {
169//!         assert_eq!(
170//!             msg, "expected `(` opening define-fun or `)` closing model"
171//!         );
172//!         assert_eq!(token, "eoi")
173//!     },
174//!     error => panic!("unexpected error: {}", error)
175//! }
176//! # }
177//! ```
178//!
179//! [nom]: https://crates.io/crates/nom (nom crate on crates.io)
180//! [regex]: https://crates.io/crates/regex (regex crate on crates.io)
181
182use crate::prelude::*;
183
184use std::io::{BufRead, BufReader, Read};
185use std::process::ChildStdout;
186
187#[allow(unused_imports)]
188use crate::Solver;
189
190/// Alias for the underlying parser.
191pub type RSmtParser = SmtParser<BufReader<ChildStdout>>;
192
193/// Tries a user parser.
194macro_rules! try_apply {
195    ($e:expr => |$res:pat| $do:expr, $msg:expr) => {
196        match $e {
197            Ok($res) => $do,
198            Err(e) => bail!("{}: {}", $msg, e),
199        }
200    };
201}
202
203/// SMT-LIB 2.0 parser.
204pub struct SmtParser<R> {
205    /// Reader being parsed.
206    input: R,
207    /// Buffer we are reading to.
208    buff: String,
209    /// Second buffer for swapping.
210    buff_2: String,
211    /// Current position in the text.
212    cursor: usize,
213}
214
215impl<R: Read> Read for SmtParser<R> {
216    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
217        self.input.read(buf)
218    }
219}
220
221impl<'a> SmtParser<BufReader<&'a [u8]>> {
222    /// Constructor from a string, mostly for doc/test purposes.
223    pub fn of_str(s: &'a str) -> Self {
224        SmtParser::new(BufReader::new(s.as_bytes()))
225    }
226}
227impl<R: BufRead> SmtParser<R> {
228    /// Creates an SMT parser.
229    pub fn new(input: R) -> Self {
230        SmtParser {
231            input,
232            buff: String::with_capacity(5_000),
233            buff_2: String::with_capacity(5_000),
234            cursor: 0,
235        }
236    }
237
238    /// Swaps the input source.
239    pub fn swap(&mut self, nu_input: &mut R) {
240        ::std::mem::swap(&mut self.input, nu_input)
241    }
242
243    /// Immutable access to the buffer.
244    pub fn buff(&self) -> &str {
245        &self.buff
246    }
247    /// Immutable access to the part of the buffer that's not been parsed yet.
248    pub fn buff_rest(&self) -> &str {
249        &self.buff[self.cursor..]
250    }
251    /// The current position in the buffer.
252    pub fn cursor(&self) -> usize {
253        self.cursor
254    }
255
256    /// Reads a line from the input. Returns `true` if something was read.
257    fn read_line(&mut self) -> SmtRes<bool> {
258        let read = self.input.read_line(&mut self.buff)?;
259        Ok(read != 0)
260    }
261
262    /// Returns the next s-expression and positions the cursor directly after it.
263    ///
264    /// An s-expression is an ident, a constant with no parens (`42`, `false`, *etc.*), or something
265    /// between (nested) parens.
266    ///
267    /// ```
268    /// # extern crate rsmt2;
269    /// # use rsmt2::parse::SmtParser;
270    /// # fn main() {
271    /// let txt = "\
272    ///     token ; a comment\n\n next_token; more comments\n\
273    ///     (+ |quoted ident,; a comment\n parens don't count)| 7)42 false\
274    /// ";
275    /// let mut parser = SmtParser::of_str(txt);
276    ///
277    /// assert_eq!( parser.get_sexpr().unwrap(), "token" );
278    /// assert_eq!( parser.buff_rest(), " ; a comment\n" );
279    ///
280    /// assert_eq!( parser.get_sexpr().unwrap(), "next_token" );
281    /// assert_eq!( parser.buff_rest(), "; more comments\n" );
282    ///
283    /// assert_eq!(
284    ///     parser.get_sexpr().unwrap(),
285    ///     "(+ |quoted ident,; a comment\n parens don't count)| 7)"
286    /// );
287    /// assert_eq!( parser.buff_rest(), "42 false" );
288    ///
289    /// assert_eq!( parser.get_sexpr().unwrap(), "42" );
290    /// assert_eq!( parser.buff_rest(), " false" );
291    ///
292    /// assert_eq!( parser.get_sexpr().unwrap(), "false" );
293    /// assert_eq!( parser.buff_rest(), "" );
294    /// # }
295    /// ```
296    pub fn get_sexpr(&mut self) -> SmtRes<&str> {
297        let sexpr_end = self.load_sexpr()?;
298        let sexpr_start = self.cursor;
299        self.cursor = sexpr_end;
300        Ok(&self.buff[sexpr_start..sexpr_end])
301    }
302
303    /// Loads lines until a full s-expr is loaded.
304    ///
305    /// Returns the position following the end of the sexpr. The cursor will be set at its
306    /// beginning.
307    fn try_load_sexpr(&mut self) -> SmtRes<Option<usize>> {
308        self.spc_cmt();
309
310        let (mut op_paren, mut cl_paren) = (0, 0);
311        let mut quoted_ident = false;
312        let mut sexpr_start = self.cursor;
313        let mut sexpr_end = sexpr_start;
314        let mut nempty = false;
315
316        'load: loop {
317            if sexpr_start == self.buff.len() {
318                let eoi = !self.read_line()?;
319                if eoi {
320                    if nempty && !quoted_ident && op_paren == cl_paren {
321                        break 'load;
322                    } else {
323                        return Ok(None);
324                    }
325                }
326            }
327            debug_assert!(op_paren >= cl_paren);
328
329            let mut chars = self.buff[sexpr_start..].chars();
330
331            'chars: while let Some(c) = chars.next() {
332                debug_assert!(op_paren >= cl_paren);
333                sexpr_end += 1;
334
335                if quoted_ident {
336                    quoted_ident = c != '|';
337                    if !quoted_ident && op_paren == 0 {
338                        break 'load;
339                    } else {
340                        continue 'chars;
341                    }
342                }
343
344                match c {
345                    ';' => {
346                        if nempty && op_paren == cl_paren {
347                            sexpr_end -= 1;
348                            break 'load;
349                        }
350                        nempty = true;
351                        // ignore comments in quoted ident
352                        if !quoted_ident {
353                            while let Some(c) = chars.next() {
354                                sexpr_end += 1;
355                                if c == '\n' {
356                                    continue 'chars;
357                                }
358                            }
359                        }
360                    }
361                    '|' => {
362                        if !quoted_ident && nempty && op_paren == cl_paren {
363                            sexpr_end -= 1;
364                            break 'load;
365                        }
366                        nempty = true;
367                        quoted_ident = !quoted_ident;
368                        if !quoted_ident && op_paren == 0 {
369                            // if we're not inside parens and just finished parsing a quoted
370                            // identifier, then the ident is the s-expression and we're done
371                            break 'load;
372                        }
373                    }
374                    '(' => {
375                        if nempty && op_paren == cl_paren {
376                            sexpr_end -= 1;
377                            break 'load;
378                        }
379                        nempty = true;
380                        op_paren += 1
381                    }
382                    ')' => {
383                        if op_paren == cl_paren && nempty {
384                            sexpr_end -= 1;
385                            break 'load;
386                        } else {
387                            cl_paren += 1;
388                            if op_paren == cl_paren {
389                                break 'load;
390                            }
391                        }
392                    }
393                    _ => {
394                        if c.is_whitespace() && op_paren == 0 && nempty == true {
395                            sexpr_end -= 1;
396                            break 'load;
397                        } else if !c.is_whitespace() {
398                            nempty = true
399                        }
400                    }
401                }
402            }
403            if sexpr_start == self.buff.len() {
404                break 'load;
405            }
406            sexpr_start = self.buff.len()
407        }
408
409        self.spc_cmt();
410        Ok(Some(sexpr_end))
411    }
412
413    /// Loads lines until a full s-expr is loaded.
414    ///
415    /// Returns the position following the end of the sexpr. The cursor will be set at its
416    /// beginning.
417    fn load_sexpr(&mut self) -> SmtRes<usize> {
418        if let Some(end) = self.try_load_sexpr()? {
419            Ok(end)
420        } else {
421            bail!("reached eoi")
422        }
423    }
424
425    /// Clears the buffer up to the current position.
426    pub fn clear(&mut self) {
427        self.spc_cmt();
428        if !self.cursor >= self.buff.len() {
429            debug_assert!(self.buff_2.is_empty());
430            self.buff_2.push_str(&self.buff[self.cursor..]);
431            self.buff.clear();
432            ::std::mem::swap(&mut self.buff, &mut self.buff_2);
433            self.cursor = 0
434        } else {
435            self.buff.clear();
436            self.cursor = 0
437        }
438    }
439
440    /// Prints itself, for debugging.
441    pub fn print(&self, pref: &str) {
442        let mut count = 0;
443        let mut printed_cursor = false;
444        for line in self.buff.lines() {
445            println!("{}|`{}`", pref, line);
446            if !printed_cursor {
447                let nu_count = count + line.len() + 1;
448                if self.cursor <= nu_count {
449                    printed_cursor = true;
450                    println!("{0}| {1: >2$}^", pref, "", self.cursor - count)
451                }
452                count = nu_count;
453            }
454        }
455    }
456
457    /// Parses some spaces or some comments.
458    ///
459    /// Parsing a tag or loading an s-expression fetches new lines, this does not.
460    ///
461    /// ```
462    /// # extern crate rsmt2;
463    /// # use rsmt2::parse::SmtParser;
464    /// # fn main() {
465    /// let txt = "  token ; a comment\n\n next token; last comment";
466    /// let mut parser = SmtParser::of_str(txt);
467    ///
468    /// parser.spc_cmt();
469    /// assert_eq!( parser.buff_rest(), "" );
470    /// assert_eq!( parser.buff(), "" );
471    ///
472    /// assert!( parser.try_tag("token").expect("token") );
473    /// assert_eq!( parser.buff_rest(), " ; a comment\n" );
474    /// assert_eq!( parser.buff(), "  token ; a comment\n" );
475    ///
476    /// parser.spc_cmt();
477    /// assert_eq!( parser.buff_rest(), "" );
478    /// assert_eq!( parser.buff(), "  token ; a comment\n" );
479    ///
480    /// assert!( parser.try_tag("next token").expect("token") );
481    /// assert_eq!( parser.buff_rest(), "; last comment" );
482    /// assert_eq!( parser.buff(), txt );
483    ///
484    /// parser.spc_cmt();
485    /// assert_eq!( parser.buff_rest(), "" );
486    /// assert_eq!( parser.buff(), txt );
487    /// # }
488    /// ```
489    pub fn spc_cmt(&mut self) {
490        if self.cursor >= self.buff.len() {
491            return ();
492        }
493        let mut chars = self.buff[self.cursor..].chars();
494        'spc_cmt: while let Some(c) = chars.next() {
495            if !c.is_whitespace() {
496                if c == ';' {
497                    self.cursor += 1;
498                    'skip_line: while let Some(c) = chars.next() {
499                        self.cursor += 1;
500                        if c == '\n' || c == '\r' {
501                            break 'skip_line;
502                        }
503                    }
504                } else {
505                    break 'spc_cmt;
506                }
507            } else {
508                self.cursor += 1;
509            }
510        }
511    }
512
513    /// Tries to parse a tag, `true` if successful. Parse whitespaces and comments if any before the
514    /// token.
515    ///
516    /// If this function returns `false`, then the cursor is at the first non-whitespace
517    /// non-commented character after the original cursor position.
518    ///
519    /// See also [`Self::tag`], [`Self::tag_info`] and [`Self::tags`].
520    ///
521    /// ```
522    /// # extern crate rsmt2;
523    /// # use rsmt2::parse::SmtParser;
524    /// # fn main() {
525    /// let txt = "\
526    ///   a tag is anything  |(>_<)| ; a comment\n\n next token; last comment\
527    /// ";
528    /// let mut parser = SmtParser::of_str(txt);
529    /// assert!( parser.try_tag("a tag is anything").expect("tag") );
530    /// assert_eq!( parser.buff_rest(), "  |(>_<)| ; a comment\n" );
531    /// assert!( ! parser.try_tag("not the token").expect("tag") );
532    /// assert_eq!( parser.buff_rest(), "|(>_<)| ; a comment\n" );
533    /// assert!( parser.try_tag("|(>_<)|").expect("tag") );
534    /// assert!( ! parser.try_tag("not the next token").expect("tag") );
535    /// assert_eq!( parser.buff_rest(), "next token; last comment" );
536    /// assert!( parser.try_tag("next token").expect("tag") );
537    /// # }
538    /// ```
539    pub fn try_tag(&mut self, tag: &str) -> SmtRes<bool> {
540        loop {
541            self.spc_cmt();
542            if self.cursor + tag.len() >= self.buff.len() + 1 {
543                if self.cursor < self.buff.len() {
544                    if self.buff[self.cursor..self.buff.len()]
545                        != tag[0..self.buff.len() - self.cursor]
546                    {
547                        return Ok(false);
548                    } else {
549                        ()
550                    }
551                }
552                let eoi = !self.read_line()?;
553                self.spc_cmt();
554                if eoi {
555                    return Ok(false);
556                }
557            } else if &self.buff[self.cursor..self.cursor + tag.len()] == tag {
558                self.cursor += tag.len();
559                return Ok(true);
560            } else {
561                self.spc_cmt();
562                return Ok(false);
563            }
564        }
565    }
566    /// Parses a tag or fails.
567    ///
568    /// Returns `()` exactly when [`Self::try_tag`] returns `true`, and an error otherwise.
569    pub fn tag(&mut self, tag: &str) -> SmtRes<()> {
570        if self.try_tag(tag)? {
571            Ok(())
572        } else {
573            self.fail_with(format!("expected `{}`", tag))
574        }
575    }
576    /// Parses a tag or fails, appends `err_msg` at the end of the error message.
577    ///
578    /// Returns `()` exactly when [`Self::try_tag`] returns `true`, and an error otherwise.
579    pub fn tag_info(&mut self, tag: &str, err_msg: &str) -> SmtRes<()> {
580        if self.try_tag(tag)? {
581            Ok(())
582        } else {
583            self.fail_with(format!("expected `{}` {}", tag, err_msg))
584        }
585    }
586
587    /// The current position.
588    fn pos(&self) -> usize {
589        self.cursor
590    }
591    /// Backtracks to the position specified.
592    fn backtrack_to(&mut self, pos: usize) {
593        self.cursor = pos
594    }
595
596    /// Parses a tag followed by a whitespace, a paren or a comment.
597    ///
598    /// If this function returns `false`, then the cursor is at the first non-whitespace
599    /// non-commented character after the original cursor position.
600    ///
601    /// ```
602    /// # extern crate rsmt2;
603    /// # use rsmt2::parse::SmtParser;
604    /// # fn main() {
605    /// let txt = "\
606    ///   a word is anything  |(>_<)|  last; comment\
607    /// ";
608    /// let mut parser = SmtParser::of_str(txt);
609    /// assert!( parser.try_word("a word is").expect("word") );
610    /// assert_eq!( parser.buff_rest(), " anything  |(>_<)|  last; comment" );
611    /// assert!( ! parser.try_word("a").expect("word") );
612    /// assert_eq!( parser.buff_rest(), "anything  |(>_<)|  last; comment" );
613    /// assert!( ! parser.try_word("any").expect("word") );
614    /// assert_eq!( parser.buff_rest(), "anything  |(>_<)|  last; comment" );
615    /// assert!( ! parser.try_word("anythin").expect("word") );
616    /// assert_eq!( parser.buff_rest(), "anything  |(>_<)|  last; comment" );
617    /// assert!( parser.try_word("anything").expect("word") );
618    /// assert_eq!( parser.buff_rest(), "  |(>_<)|  last; comment" );
619    /// assert!( parser.try_word("|").expect("word") );
620    /// assert_eq!( parser.buff_rest(), "(>_<)|  last; comment" );
621    /// assert!( parser.try_tag("(").expect("tag") );
622    /// assert_eq!( parser.buff_rest(), ">_<)|  last; comment" );
623    /// assert!( parser.try_word(">_<").expect("word") );
624    /// assert_eq!( parser.buff_rest(), ")|  last; comment" );
625    /// assert!( parser.try_tag(")").expect("tag") );
626    /// assert_eq!( parser.buff_rest(), "|  last; comment" );
627    /// assert!( parser.try_word("|").expect("word") );
628    /// assert_eq!( parser.buff_rest(), "  last; comment" );
629    /// assert!( parser.try_word("last").expect("word") );
630    /// assert_eq!( parser.buff_rest(), "; comment" );
631    /// # }
632    /// ```
633    pub fn try_word(&mut self, word: &str) -> SmtRes<bool> {
634        let start_pos = self.pos();
635        if self.try_tag(word)? {
636            if let Some(c) = self.buff[self.cursor..].chars().next() {
637                if c.is_whitespace() || c == ')' || c == '(' || c == ';' {
638                    return Ok(true);
639                }
640            }
641        }
642        self.backtrack_to(start_pos);
643        self.spc_cmt();
644        Ok(false)
645    }
646
647    /// Tries to parse a sequence of things potentially separated by whitespaces and/or comments.
648    ///
649    /// If this function returns `false`, then the cursor is at the first non-whitespace
650    /// non-commented character after the original cursor position.
651    ///
652    /// ```
653    /// # extern crate rsmt2;
654    /// # use rsmt2::parse::SmtParser;
655    /// # fn main() {
656    /// let txt = "\
657    ///     a tag is anything  |(>_<)| ; a comment\n\n next token; last comment\
658    /// ";
659    /// let mut parser = SmtParser::of_str(txt);
660    /// assert!(
661    ///     parser.try_tags(
662    ///         &[ "a", "tag", "is anything", "|", "(", ">_<", ")", "|" ]
663    ///     ).expect("tags")
664    /// );
665    /// assert_eq!( parser.buff_rest(), " ; a comment\n" );
666    /// assert!(
667    ///     ! parser.try_tags(
668    ///         & [ "next", "token", "something else?" ]
669    ///     ).expect("tags")
670    /// );
671    /// assert_eq!( parser.buff_rest(), "next token; last comment" )
672    /// # }
673    /// ```
674    pub fn try_tags<'a, Tags, S>(&mut self, tags: &'a Tags) -> SmtRes<bool>
675    where
676        &'a Tags: IntoIterator<Item = S>,
677        S: AsRef<str>,
678    {
679        let start_pos = self.pos();
680        for tag in tags {
681            if !self.try_tag(tag.as_ref())? {
682                self.backtrack_to(start_pos);
683                self.spc_cmt();
684                return Ok(false);
685            }
686        }
687        Ok(true)
688    }
689
690    /// Parses a sequence of things potentially separated by whitespaces and/or comments.
691    ///
692    /// Returns `()` exactly when [`Self::try_tags`] returns `true`, and an error otherwise.
693    pub fn tags<'a, Tags, S>(&mut self, tags: &'a Tags) -> SmtRes<()>
694    where
695        &'a Tags: IntoIterator<Item = S>,
696        S: AsRef<str>,
697    {
698        for tag in tags {
699            self.tag(tag.as_ref())?
700        }
701        Ok(())
702    }
703
704    /// Generates a failure at the current position.
705    pub fn fail_with<T, Str: Into<String>>(&mut self, msg: Str) -> SmtRes<T> {
706        self.try_error()?;
707        let sexpr = self.get_sexpr().map(str::to_string).ok();
708        let sexpr = if let Some(e) = sexpr {
709            e
710        } else if self.cursor < self.buff.len() {
711            let mut stuff = self.buff[self.cursor..].trim().split_whitespace();
712            if let Some(stuff) = stuff.next() {
713                stuff.to_string()
714            } else {
715                " ".to_string()
716            }
717        } else {
718            "eoi".to_string()
719        };
720        if sexpr == "unsupported" {
721            bail!(ErrorKind::Unsupported)
722        } else {
723            bail!(ErrorKind::ParseError(msg.into(), sexpr))
724        }
725    }
726
727    /// Tries to parse a boolean.
728    ///
729    /// ```
730    /// # extern crate rsmt2;
731    /// # use rsmt2::parse::SmtParser;
732    /// # fn main() {
733    /// let txt = "\
734    ///     true fls  true_ly_bad_ident false; comment\
735    /// ";
736    /// let mut parser = SmtParser::of_str(txt);
737    /// assert_eq!( parser.try_bool().expect("bool"), Some(true) );
738    /// assert_eq!(
739    ///     parser.buff_rest(), " fls  true_ly_bad_ident false; comment"
740    /// );
741    /// assert_eq!( parser.try_bool().expect("bool"), None );
742    /// assert_eq!(
743    ///     parser.buff_rest(), "fls  true_ly_bad_ident false; comment"
744    /// );
745    /// parser.tag("fls").expect("tag");
746    /// assert_eq!( parser.try_bool().expect("bool"), None );
747    /// assert_eq!(
748    ///     parser.buff_rest(), "true_ly_bad_ident false; comment"
749    /// );
750    /// parser.tag("true_ly_bad_ident").expect("tag");
751    /// assert_eq!( parser.try_bool().expect("bool"), Some(false) );
752    /// assert_eq!(
753    ///     parser.buff_rest(), "; comment"
754    /// );
755    /// # }
756    /// ```
757    pub fn try_bool(&mut self) -> SmtRes<Option<bool>> {
758        if self.try_word("true")? {
759            Ok(Some(true))
760        } else if self.try_word("false")? {
761            Ok(Some(false))
762        } else {
763            Ok(None)
764        }
765    }
766
767    /// Parses a boolean or fails.
768    pub fn bool(&mut self) -> SmtRes<bool> {
769        if let Some(b) = self.try_bool()? {
770            Ok(b)
771        } else {
772            self.fail_with("expected boolean")
773        }
774    }
775
776    /// Tries to parse an unsigned integer. Does **not** load, backtrack, or mark.
777    ///
778    /// Returns start and end positions.
779    #[inline]
780    fn try_uint_indices(&self) -> SmtRes<Option<(usize, usize)>> {
781        let mut end = self.cursor;
782        let (mut zero_first, mut first) = (false, true);
783        for c in self.buff[self.cursor..].chars() {
784            if c.is_numeric() {
785                if first {
786                    first = false;
787                    if c == '0' {
788                        zero_first = true
789                    }
790                } else if zero_first {
791                    return Ok(None);
792                }
793                end += 1
794            } else {
795                break;
796            }
797        }
798        if end > self.cursor {
799            Ok(Some((self.cursor, end)))
800        } else {
801            Ok(None)
802        }
803    }
804
805    /// Tries to parse an unsigned integer.
806    ///
807    /// Does **not** load, backtrack, or mark, but moves the cursor to the end of the integer if
808    /// any.
809    #[inline]
810    fn try_uint(&mut self) -> SmtRes<Option<&str>> {
811        self.spc_cmt();
812        if let Some((res_start, res_end)) = self.try_uint_indices()? {
813            self.cursor = res_end;
814            Ok(Some(&self.buff[res_start..res_end]))
815        } else {
816            Ok(None)
817        }
818    }
819    /// Parses an usigned integer or fails.
820    #[inline]
821    fn uint<F, T>(&mut self, f: F) -> SmtRes<T>
822    where
823        F: Fn(&str) -> T,
824    {
825        if let Some(res) = self.try_uint()?.map(f) {
826            Ok(res)
827        } else {
828            self.fail_with("expected unsigned integer")
829        }
830    }
831
832    /// Tries to parses an integer.
833    ///
834    /// Parameters of the input function:
835    ///
836    /// - the absolute value of the integer parsed,
837    /// - positiveness flag: `true` iff the integer is positive.
838    ///
839    /// **NB**: input function `f` cannot return the input string in any way. Doing so will not
840    /// borrow-check and is completely unsafe as the parser can and in general will discard what's
841    /// in its buffer once it's parsed.
842    ///
843    /// Only recognizes integers of the form
844    ///
845    /// ```bash
846    /// int   ::= usize             # Not followed by a '.'
847    ///         | '(' '-' usize ')'
848    /// usize ::= '0' | [1-9][0-9]*
849    /// ```
850    ///
851    /// # Examples
852    ///
853    /// ```
854    /// # extern crate rsmt2;
855    /// # use rsmt2::parse::SmtParser;
856    /// # fn main() {
857    /// use std::str::FromStr;
858    /// fn to_int(
859    ///     input: & str, positive: bool
860    /// ) -> Result<isize, <isize as FromStr>::Err> {
861    ///     isize::from_str(input).map(
862    ///         |num| if positive { num } else { - num }
863    ///     )
864    /// }
865    /// let txt = "\
866    ///     666 (- 11) false; comment\n(+ 31) (= tru)\
867    /// ";
868    /// let mut parser = SmtParser::of_str(txt);
869    /// println!("666");
870    /// assert_eq!( parser.try_int(to_int).expect("int"), Some(666) );
871    /// assert_eq!(
872    ///     parser.buff_rest(), " (- 11) false; comment\n"
873    /// );
874    ///
875    /// println!("- 11");
876    /// assert_eq!( parser.try_int(to_int).expect("int"), Some(- 11) );
877    /// assert_eq!(
878    ///     parser.buff_rest(), " false; comment\n"
879    /// );
880    ///
881    /// assert_eq!( parser.try_int(to_int).expect("int"), None );
882    /// parser.tag("false").expect("tag");
883    ///
884    /// println!("31");
885    /// assert_eq!( parser.try_int(to_int).expect("int"), Some(31) );
886    /// assert_eq!(
887    ///     parser.buff_rest(), " (= tru)"
888    /// );
889    ///
890    /// assert_eq!( parser.try_int(to_int).expect("int"), None );
891    ///
892    /// let txt = " 7.0 ";
893    /// println!("{}", txt);
894    /// let mut parser = SmtParser::of_str(txt);
895    /// assert_eq!( parser.try_int(to_int).expect("int"), None );
896    /// assert_eq!(
897    ///     parser.buff_rest(), " 7.0 "
898    /// );
899    ///
900    /// let txt = " 00 ";
901    /// println!("{}", txt);
902    /// let mut parser = SmtParser::of_str(txt);
903    /// assert_eq!( parser.try_int(to_int).expect("int"), None );
904    /// assert_eq!(
905    ///     parser.buff_rest(), " 00 "
906    /// );
907    /// # }
908    /// ```
909    pub fn try_int<F, T, Err>(&mut self, f: F) -> SmtRes<Option<T>>
910    where
911        F: FnOnce(&str, bool) -> Result<T, Err>,
912        Err: ::std::fmt::Display,
913    {
914        let start_pos = self.pos();
915        self.load_sexpr()?;
916
917        let mut res = None;
918
919        if let Some((int_start, int_end)) = self.try_uint_indices()? {
920            self.cursor = int_end;
921            if self.try_tag(".")? {
922                self.backtrack_to(start_pos);
923                res = None
924            } else {
925                self.cursor = int_end;
926                let uint = &self.buff[int_start..int_end];
927                try_apply!(
928                  f(uint, true) => |int| res = Some(int),
929                  format!("error parsing integer `{}`", uint)
930                )
931            }
932        } else if self.try_tag("(")? {
933            let pos = if self.try_tag("-")? {
934                false
935            } else if self.try_tag("+")? {
936                true
937            } else {
938                self.backtrack_to(start_pos);
939                return Ok(None);
940            };
941            if let Some(uint) = self.try_uint()? {
942                match f(uint, pos) {
943                    Ok(int) => res = Some(int),
944                    Err(e) => {
945                        let uint = if !pos {
946                            format!("(- {})", uint)
947                        } else {
948                            uint.into()
949                        };
950                        bail!("error parsing integer `{}`: {}", uint, e)
951                    }
952                }
953            }
954            if !(res.is_some() && self.try_tag(")")?) {
955                self.backtrack_to(start_pos);
956                return Ok(None);
957            }
958        }
959        if res.is_none() {
960            self.backtrack_to(start_pos)
961        }
962        Ok(res)
963    }
964
965    /// Tries to parses a rational (called *Real* in SMT-LIB).
966    ///
967    /// Parameters of the input function:
968    ///
969    /// - numerator of the rational parsed (> 0),
970    /// - denominator of the rational parsed (> 0),
971    /// - positiveness flag: `true` iff the rational is positive.
972    ///
973    /// Only recognizes integers of the form
974    ///
975    /// ```bash
976    /// rat   ::= '(' '/' udec udec ')'
977    ///         | '(' '-' '(' '/' udec udec ')' ')'
978    ///         | idec
979    /// idec  ::= '(' '-' udec '.' usize ')' | udec
980    /// udec  ::= usize | usize.0
981    /// usize ::= [0-9][0-9]*
982    /// ```
983    ///
984    /// **NB**: input function `f` cannot return the input strings in any way. Doing so will not
985    /// borrow-check and is completely unsafe as the parser can and in general will discard what's
986    /// in its buffer once it's parsed.
987    ///
988    /// ```
989    /// # extern crate rsmt2;
990    /// # use rsmt2::parse::SmtParser;
991    /// # fn main() {
992    /// use std::str::FromStr;
993    /// fn to_rat(
994    ///     num: & str, den: & str, positive: bool
995    /// ) -> Result<(isize, usize), String> {
996    ///     let num = isize::from_str(num).map(
997    ///         |num| if positive { num } else { - num }
998    ///     ).map_err(|e| format!("{}", e)) ?;
999    ///     let den = usize::from_str(den).map_err(|e| format!("{}", e)) ?;
1000    ///     Ok((num, den))
1001    /// }
1002    /// let txt = "\
1003    ///     0.0 666.0 7.42 (- 11.0) false; comment\n(/ 31 27) (- (/ 63 0)) (= tru)\
1004    /// ";
1005    /// let mut parser = SmtParser::of_str(txt);
1006    /// assert_eq!( parser.try_rat(to_rat).expect("rat"), Some((0, 1)) );
1007    /// assert_eq!(
1008    ///     parser.buff_rest(), " 666.0 7.42 (- 11.0) false; comment\n"
1009    /// );
1010    /// assert_eq!( parser.try_rat(to_rat).expect("rat"), Some((666, 1)) );
1011    /// assert_eq!(
1012    ///     parser.buff_rest(), " 7.42 (- 11.0) false; comment\n"
1013    /// );
1014    /// assert_eq!( parser.try_rat(to_rat).expect("rat"), Some((742, 100)) );
1015    /// assert_eq!(
1016    ///     parser.buff_rest(), " (- 11.0) false; comment\n"
1017    /// );
1018    /// assert_eq!( parser.try_rat(to_rat).expect("rat"), Some((- 11, 1)) );
1019    /// assert_eq!(
1020    ///     parser.buff_rest(), " false; comment\n"
1021    /// );
1022    /// assert_eq!( parser.try_rat(to_rat).expect("rat"), None );
1023    /// parser.tag("false").expect("tag");
1024    /// assert_eq!( parser.try_rat(to_rat).expect("rat"), Some((31, 27)) );
1025    /// assert_eq!(
1026    ///     parser.buff_rest(), " (- (/ 63 0)) (= tru)"
1027    /// );
1028    /// assert_eq!( parser.try_rat(to_rat).expect("rat"), (Some((- 63, 0))) );
1029    ///
1030    /// let txt = " 7 ";
1031    /// let mut parser = SmtParser::of_str(txt);
1032    /// assert_eq!( parser.try_rat(to_rat).expect("rat"), None );
1033    /// assert_eq!(
1034    ///     parser.buff_rest(), " 7 "
1035    /// );
1036    ///
1037    /// let txt = " (- 7) ";
1038    /// let mut parser = SmtParser::of_str(txt);
1039    /// assert_eq!( parser.try_rat(to_rat).expect("rat"), None );
1040    /// assert_eq!(
1041    ///     parser.buff_rest(), " (- 7) "
1042    /// );
1043    /// # }
1044    /// ```
1045    pub fn try_rat<F, T, Err>(&mut self, f: F) -> SmtRes<Option<T>>
1046    where
1047        F: Fn(&str, &str, bool) -> Result<T, Err>,
1048        Err: ::std::fmt::Display,
1049    {
1050        let err = "error parsing rational";
1051        let start_pos = self.pos();
1052        self.load_sexpr()?;
1053
1054        let mut res = None;
1055
1056        let positive = if self.try_tags(&["(", "-"])? {
1057            self.spc_cmt();
1058            false
1059        } else {
1060            true
1061        };
1062
1063        if let Some((fst_start, fst_end)) = self.try_uint_indices()? {
1064            if fst_end + 1 < self.buff.len() && &self.buff[fst_end..(fst_end + 2)] == ".0" {
1065                try_apply!(
1066                  f(
1067                    & self.buff[ fst_start .. fst_end ], "1", positive
1068                  ) => |okay| res = Some(okay), err
1069                );
1070                self.cursor = fst_end + 2
1071            } else if fst_end < self.buff.len() && &self.buff[fst_end..(fst_end + 1)] == "." {
1072                self.cursor = fst_end + 1;
1073                if let Some((snd_start, snd_end)) = self.try_uint_indices()? {
1074                    let num = format!(
1075                        "{}{}",
1076                        &self.buff[fst_start..fst_end],
1077                        &self.buff[snd_start..snd_end],
1078                    );
1079                    let mut den = String::with_capacity(snd_end - snd_start);
1080                    den.push('1');
1081                    for _ in snd_start..snd_end {
1082                        den.push('0')
1083                    }
1084                    try_apply!(
1085                      f(
1086                        & num, & den, positive
1087                      ) => |okay| res = Some(okay), err
1088                    );
1089                    self.cursor = snd_end
1090                } else {
1091                    bail!("ill-formed rational")
1092                }
1093            } else {
1094                self.backtrack_to(start_pos);
1095                return Ok(None);
1096            }
1097        }
1098
1099        if res.is_none() {
1100            if !self.try_tag("(")? {
1101                self.backtrack_to(start_pos);
1102                return Ok(None);
1103            }
1104
1105            if !self.try_tag("/")? {
1106                self.backtrack_to(start_pos);
1107                return Ok(None);
1108            }
1109
1110            self.spc_cmt();
1111            res = if let Some((num_start, num_end)) = self.try_uint_indices()? {
1112                if num_end + 1 < self.buff.len() && &self.buff[num_end..(num_end + 2)] == ".0" {
1113                    self.cursor = num_end + 2
1114                // } else if num_end < self.buff.len()
1115                // && & self.buff[ num_end .. (num_end + 1) ] == "." {
1116                //   self.cursor = num_end + 1
1117                } else {
1118                    self.cursor = num_end
1119                }
1120                self.spc_cmt();
1121                if let Some((den_start, den_end)) = self.try_uint_indices()? {
1122                    let not_eoi = den_end + 1 < self.buff.len();
1123                    let point_zero = &self.buff[den_end..(den_end + 2)] == ".0";
1124                    if not_eoi && point_zero {
1125                        self.cursor = den_end + 2
1126                    // } else if den_end < self.buff.len()
1127                    // && & self.buff[ den_end .. (den_end + 1) ] == "." {
1128                    //   self.cursor = den_end + 1
1129                    } else {
1130                        self.cursor = den_end
1131                    }
1132                    match f(
1133                        &self.buff[num_start..num_end],
1134                        &self.buff[den_start..den_end],
1135                        positive,
1136                    ) {
1137                        Ok(res) => Some(res),
1138                        Err(e) => bail!("error parsing rational: {}", e),
1139                    }
1140                } else {
1141                    None
1142                }
1143            } else {
1144                None
1145            };
1146
1147            if res.is_some() {
1148                self.tag(")")?
1149            }
1150        }
1151
1152        if res.is_some() {
1153            if !positive {
1154                self.tag(")")?
1155            }
1156            Ok(res)
1157        } else {
1158            Ok(None)
1159        }
1160    }
1161
1162    /// Tries to parse a symbol.
1163    ///
1164    /// Quoted symbols (anything but `|` surrounded by `|`) are passed **with** the surrounding `|`.
1165    ///
1166    /// **NB**: input function `f` cannot return the input string in any way. Doing so will not
1167    /// borrow-check and is completely unsafe as the parser can and in general will discard what's
1168    /// in its buffer once it's parsed.
1169    ///
1170    /// ```
1171    /// # extern crate rsmt2;
1172    /// # use rsmt2::parse::SmtParser;
1173    /// # fn main() {
1174    /// fn sym(input: & str) -> Result<String, String> {
1175    ///     Ok( input.into() )
1176    /// }
1177    /// let txt = "\
1178    ///     ident (- 11) +~stuff; comment\n |some stuff \n [{}!+)(}|\
1179    /// ";
1180    /// let mut parser = SmtParser::of_str(txt);
1181    /// assert_eq!( parser.try_sym(sym).expect("sym"), Some("ident".into()) );
1182    /// assert_eq!(
1183    ///     parser.buff_rest(), " (- 11) +~stuff; comment\n"
1184    /// );
1185    /// assert_eq!( parser.try_sym(sym).expect("sym"), None );
1186    /// assert_eq!(
1187    ///     parser.buff_rest(), "(- 11) +~stuff; comment\n"
1188    /// );
1189    /// parser.tag("(- 11)").expect("tag");
1190    /// assert_eq!( parser.try_sym(sym).expect("sym"), Some("+~stuff".into()) );
1191    /// assert_eq!(
1192    ///     parser.buff_rest(), "; comment\n"
1193    /// );
1194    /// assert_eq!(
1195    ///     parser.try_sym(sym).expect("sym"),
1196    ///     Some("|some stuff \n [{}!+)(}|".into())
1197    /// );
1198    /// # }
1199    /// ```
1200    pub fn try_sym<'me, F, T, Err>(&'me mut self, f: F) -> SmtRes<Option<T>>
1201    where
1202        F: FnOnce(&'me str) -> Result<T, Err>,
1203        Err: ::std::fmt::Display,
1204    {
1205        self.spc_cmt();
1206        let err_end = self.load_sexpr()?;
1207        let is_sym = if let Some(c) = self.buff[self.cursor..].chars().next() {
1208            match c {
1209                _ if c.is_alphabetic() => true,
1210                '|' | '~' | '!' | '@' | '$' | '%' | '^' | '&' | '*' | '_' | '-' | '+' | '='
1211                | '<' | '>' | '.' | '?' => true,
1212                _ => false,
1213            }
1214        } else {
1215            false
1216        };
1217        if is_sym {
1218            let ident = &self.buff[self.cursor..err_end];
1219            self.cursor = err_end;
1220            match f(ident) {
1221                Ok(res) => Ok(Some(res)),
1222                Err(e) => bail!(
1223                    "error parsing symbol `{}`: {}",
1224                    &self.buff[self.cursor..err_end],
1225                    e
1226                ),
1227            }
1228        } else {
1229            Ok(None)
1230        }
1231    }
1232
1233    /// Parses `success`.
1234    pub fn success(&mut self) -> SmtRes<()> {
1235        self.tag("success")
1236    }
1237
1238    /// Parses an error.
1239    ///
1240    /// Returns `Ok(())` if no error was parsed, an error otherwise.
1241    ///
1242    /// # Examples
1243    ///
1244    /// ```
1245    /// # extern crate rsmt2;
1246    /// # use rsmt2::parse::SmtParser;
1247    /// # fn main() {
1248    /// use rsmt2::parse::{ IdentParser, ValueParser };
1249    /// use rsmt2::SmtRes;
1250    /// let txt = "\
1251    ///     ( error \"huge panic\n\n'something' () parens\" )
1252    /// ";
1253    /// let mut parser = SmtParser::of_str(txt);
1254    /// if let Err(e) = parser.try_error() {
1255    /// #    for e in e.iter() {
1256    /// #        for line in format!("{}", e).lines() {
1257    /// #            println!("{}", line)
1258    /// #        }
1259    /// #    }
1260    ///     assert_eq! { & format!("{}", e), "solver error: \"huge panic\n\n'something' () parens\"" }
1261    /// } else {
1262    ///     panic!("expected error, got nothing :(")
1263    /// }
1264    /// # }
1265    /// ```
1266    pub fn try_error(&mut self) -> SmtRes<()> {
1267        let start_pos = self.pos();
1268        if self.try_load_sexpr()?.is_none() {
1269            return Ok(());
1270        }
1271        if self.try_tag("(")? {
1272            self.spc_cmt();
1273            if self.try_tag("error")? {
1274                self.spc_cmt();
1275                if self.try_tag("\"")? {
1276                    let err_start = self.pos();
1277                    let mut err_end = err_start;
1278                    while err_end < self.buff.len() {
1279                        if err_end + 1 < self.buff.len() {
1280                            if &self.buff[err_end..err_end + 2] == "\\\"" {
1281                                err_end += 2;
1282                                continue;
1283                            }
1284                        }
1285                        if &self.buff[err_end..err_end + 1] == "\"" {
1286                            break;
1287                        } else {
1288                            err_end += 1;
1289                            continue;
1290                        }
1291                    }
1292                    self.cursor = err_end + 1;
1293                    self.spc_cmt();
1294                    self.tag(")").chain_err(|| "closing error message")?;
1295                    bail!(ErrorKind::SolverError(self.buff[err_start..err_end].into()))
1296                }
1297            }
1298            self.backtrack_to(start_pos)
1299        }
1300        Ok(())
1301    }
1302
1303    /// Parses the result of a check-sat.
1304    ///
1305    /// Returns `None` if the solver reported `unknown`.
1306    pub fn check_sat(&mut self) -> SmtRes<Option<bool>> {
1307        self.spc_cmt();
1308        if self.try_tag("sat")? {
1309            Ok(Some(true))
1310        } else if self.try_tag("unsat")? {
1311            Ok(Some(false))
1312        } else if self.try_tag("unknown")? {
1313            Ok(None)
1314        } else if self.try_tag("timeout")? {
1315            bail!(ErrorKind::Timeout)
1316        } else {
1317            self.try_error()?;
1318            self.fail_with("expected `sat` or `unsat`")
1319        }
1320    }
1321
1322    /// Tries to parse a reserved actlit id.
1323    pub fn try_actlit_id(&mut self) -> SmtRes<bool> {
1324        if self.try_tag(crate::actlit::ACTLIT_PREF)? {
1325            self.uint(|_| ())
1326                .chain_err(|| "while parsing internal actlit identifier")?;
1327            self.tag(crate::actlit::ACTLIT_SUFF)?;
1328            Ok(true)
1329        } else {
1330            Ok(false)
1331        }
1332    }
1333
1334    /// Parses the result of a `get-unsat-core`.
1335    pub fn get_unsat_core<Sym, Parser>(&mut self, parser: Parser) -> SmtRes<Vec<Sym>>
1336    where
1337        Parser: for<'a> SymParser<Sym, &'a mut Self>,
1338    {
1339        self.spc_cmt();
1340        self.try_error()?;
1341        let mut core = Vec::new();
1342        self.tag("(")?;
1343        self.spc_cmt();
1344        while !self.try_tag(")")? {
1345            core.push(parser.parse_sym(self)?);
1346            self.spc_cmt();
1347        }
1348        self.clear();
1349        Ok(core)
1350    }
1351
1352    /// Parses the result of a get-model where all symbols are nullary.
1353    pub fn get_model_const<Ident, Value, Type, Parser>(
1354        &mut self,
1355        prune_actlits: bool,
1356        parser: Parser,
1357    ) -> SmtRes<Vec<(Ident, Type, Value)>>
1358    where
1359        Parser: for<'a> IdentParser<Ident, Type, &'a mut Self>
1360            + for<'a> ModelParser<Ident, Type, Value, &'a mut Self>,
1361    {
1362        self.spc_cmt();
1363        self.try_error()?;
1364        let mut model = Vec::new();
1365        self.tag("(")?;
1366        self.try_tag("model")?;
1367        while !self.try_tag(")")? {
1368            self.tag_info("(", "opening define-fun or `)` closing model")?;
1369            self.tag("define-fun")?;
1370
1371            if prune_actlits && self.try_actlit_id()? {
1372                self.tags(&["(", ")"])?;
1373                self.tag("Bool")?;
1374                self.bool()?;
1375            } else {
1376                let id = parser.parse_ident(self)?;
1377                self.tags(&["(", ")"])?;
1378                let typ = parser.parse_type(self)?;
1379                let value = parser.parse_value(self, &id, &[], &typ)?;
1380                model.push((id, typ, value));
1381            }
1382            self.tag(")")?;
1383        }
1384        self.clear();
1385        Ok(model)
1386    }
1387
1388    /// Parses the result of a `get-model`.
1389    pub fn get_model<Ident, Value, Type, Parser>(
1390        &mut self,
1391        prune_actlits: bool,
1392        parser: Parser,
1393    ) -> SmtRes<Model<Ident, Type, Value>>
1394    where
1395        Parser: for<'a> IdentParser<Ident, Type, &'a mut Self>
1396            + for<'a> ModelParser<Ident, Type, Value, &'a mut Self>,
1397    {
1398        self.spc_cmt();
1399        self.try_error()?;
1400        let mut model = Vec::new();
1401        self.tag("(")?;
1402        self.try_tag("model")?;
1403        while !self.try_tag(")")? {
1404            self.tag_info("(", "opening define-fun or `)` closing model")?;
1405            self.tag("define-fun")?;
1406
1407            if prune_actlits && self.try_actlit_id()? {
1408                self.tags(&["(", ")"])?;
1409                self.tag("Bool")?;
1410                self.bool()?;
1411            } else {
1412                let id = parser.parse_ident(self)?;
1413                self.tag("(")?;
1414                let mut args = Vec::new();
1415                while self.try_tag("(")? {
1416                    self.spc_cmt();
1417                    let id = parser.parse_ident(self)?;
1418                    self.spc_cmt();
1419                    let typ = parser.parse_type(self)?;
1420                    self.spc_cmt();
1421                    self.tag(")")?;
1422                    args.push((id, typ))
1423                }
1424                self.tag(")")?;
1425                self.spc_cmt();
1426                let typ = parser.parse_type(self)?;
1427                self.spc_cmt();
1428                let value = parser.parse_value(self, &id, &args, &typ)?;
1429                model.push((id, args, typ, value));
1430            }
1431            self.tag(")")?;
1432        }
1433        self.clear();
1434        Ok(model)
1435    }
1436
1437    /// Parses the result of a `get-value`.
1438    pub fn get_values<Val, Info: Clone, Expr, Parser>(
1439        &mut self,
1440        parser: Parser,
1441        info: Info,
1442    ) -> SmtRes<Vec<(Expr, Val)>>
1443    where
1444        Parser:
1445            for<'a> ValueParser<Val, &'a mut Self> + for<'a> ExprParser<Expr, Info, &'a mut Self>,
1446    {
1447        self.spc_cmt();
1448        self.try_error()?;
1449        let mut values = Vec::new();
1450        self.tag("(")?;
1451        while !self.try_tag(")")? {
1452            self.tag_info("(", "opening expr/value pair or `)` closing value list")?;
1453            let expr = parser.parse_expr(self, info.clone())?;
1454            let value = parser.parse_value(self)?;
1455            values.push((expr, value));
1456            self.tag(")")?;
1457        }
1458        self.clear();
1459        Ok(values)
1460    }
1461
1462    /// Parses the result of a `get-interpolant`.
1463    pub fn get_interpolant<Expr, Info, Parser>(
1464        &mut self,
1465        parser: Parser,
1466        info: Info,
1467    ) -> SmtRes<Expr>
1468    where
1469        Parser: for<'a> ExprParser<Expr, Info, &'a mut Self>,
1470    {
1471        self.spc_cmt();
1472        self.try_error()?;
1473        let expr = parser.parse_expr(self, info)?;
1474        self.clear();
1475        Ok(expr)
1476    }
1477}
1478
1479/// Can parse symbols.
1480pub trait SymParser<Sym, Input>: Copy {
1481    /// Parses a symbol.
1482    fn parse_sym(self, i: Input) -> SmtRes<Sym>;
1483}
1484impl<'a, Sym, T> SymParser<Sym, &'a str> for T
1485where
1486    T: SymParser<Sym, &'a [u8]>,
1487{
1488    fn parse_sym(self, input: &'a str) -> SmtRes<Sym> {
1489        self.parse_sym(input.as_bytes())
1490    }
1491}
1492impl<'a, Sym, T, Br> SymParser<Sym, &'a mut SmtParser<Br>> for T
1493where
1494    T: SymParser<Sym, &'a str>,
1495    Br: BufRead,
1496{
1497    fn parse_sym(self, input: &'a mut SmtParser<Br>) -> SmtRes<Sym> {
1498        self.parse_sym(input.get_sexpr()?)
1499    }
1500}
1501impl<'a, Br> SymParser<&'a str, &'a mut SmtParser<Br>> for ()
1502where
1503    Br: BufRead,
1504{
1505    fn parse_sym(self, input: &'a mut SmtParser<Br>) -> SmtRes<&'a str> {
1506        input
1507            .try_sym(|s| SmtRes::Ok(s))
1508            .and_then(|sym_opt| sym_opt.ok_or_else(|| "expected symbol".into()))
1509    }
1510}
1511impl<'a, Br> SymParser<String, &'a mut SmtParser<Br>> for ()
1512where
1513    Br: BufRead,
1514{
1515    fn parse_sym(self, input: &'a mut SmtParser<Br>) -> SmtRes<String> {
1516        input
1517            .try_sym(|s| SmtRes::Ok(s.into()))
1518            .and_then(|sym_opt| sym_opt.ok_or_else(|| "expected symbol".into()))
1519    }
1520}
1521
1522/// Can parse identifiers and types. Used for [`Solver::get_model`][crate::Solver::get_model].
1523///
1524/// For more information refer to the [module-level documentation](self).
1525pub trait IdentParser<Ident, Type, Input>: Copy {
1526    /// Parses an identifier.
1527    fn parse_ident(self, i: Input) -> SmtRes<Ident>;
1528    /// Parses a type.
1529    fn parse_type(self, i: Input) -> SmtRes<Type>;
1530}
1531impl<'a, Ident, Type, T> IdentParser<Ident, Type, &'a str> for T
1532where
1533    T: IdentParser<Ident, Type, &'a [u8]>,
1534{
1535    fn parse_ident(self, input: &'a str) -> SmtRes<Ident> {
1536        self.parse_ident(input.as_bytes())
1537    }
1538    fn parse_type(self, input: &'a str) -> SmtRes<Type> {
1539        self.parse_type(input.as_bytes())
1540    }
1541}
1542impl<'a, Ident, Type, T, Br> IdentParser<Ident, Type, &'a mut SmtParser<Br>> for T
1543where
1544    T: IdentParser<Ident, Type, &'a str>,
1545    Br: BufRead,
1546{
1547    fn parse_ident(self, input: &'a mut SmtParser<Br>) -> SmtRes<Ident> {
1548        self.parse_ident(input.get_sexpr()?)
1549    }
1550    fn parse_type(self, input: &'a mut SmtParser<Br>) -> SmtRes<Type> {
1551        self.parse_type(input.get_sexpr()?)
1552    }
1553}
1554impl<'a, Br> IdentParser<&'a str, &'a str, &'a mut SmtParser<Br>> for ()
1555where
1556    Br: BufRead,
1557{
1558    fn parse_ident(self, input: &'a mut SmtParser<Br>) -> SmtRes<&'a str> {
1559        input.get_sexpr()
1560    }
1561    fn parse_type(self, input: &'a mut SmtParser<Br>) -> SmtRes<&'a str> {
1562        input.get_sexpr()
1563    }
1564}
1565impl<'a, Br> IdentParser<String, String, &'a mut SmtParser<Br>> for ()
1566where
1567    Br: BufRead,
1568{
1569    fn parse_ident(self, input: &'a mut SmtParser<Br>) -> SmtRes<String> {
1570        input.get_sexpr().map(String::from)
1571    }
1572    fn parse_type(self, input: &'a mut SmtParser<Br>) -> SmtRes<String> {
1573        input.get_sexpr().map(String::from)
1574    }
1575}
1576
1577/// Can parse models. Used for [`Solver::get_model`][crate::Solver::get_model].
1578///
1579/// For more information refer to the [module-level documentation](self).
1580pub trait ModelParser<Ident, Type, Value, Input>: Copy {
1581    /// Parses a value in the context of a `get-model` command.
1582    ///
1583    /// When rsmt2 parses a value for some symbol `id` in a model, it will call this function so
1584    /// that it knows what to construct the value with. Remember that in a model, values are usually
1585    /// presented as
1586    ///
1587    /// ```lisp
1588    /// (define-fun <symbol> ( (<arg> <arg_sort>) ... ) <out_sort> <value>)
1589    /// ```
1590    ///
1591    /// This function's purpose is to parse `<value>` and construct an actual `Value`, given all the
1592    /// information preceeding the `<value>` token. So, parameter
1593    ///
1594    /// - `i` is the "Text input", the actual value token tree (`<value>`);
1595    /// - `id` is the symbol (`symbol`) we're parsing the value of;
1596    /// - `args` is `id`'s "input signature" (`(<arg> <arg_sort>) ...`);
1597    /// - `out` is `id`'s output sort (`<out_sort>`).
1598    fn parse_value(self, i: Input, id: &Ident, args: &[(Ident, Type)], out: &Type)
1599        -> SmtRes<Value>;
1600}
1601impl<'a, Ident, Type, Value, T> ModelParser<Ident, Type, Value, &'a str> for T
1602where
1603    T: ModelParser<Ident, Type, Value, &'a [u8]>,
1604{
1605    fn parse_value(
1606        self,
1607        input: &'a str,
1608        name: &Ident,
1609        inputs: &[(Ident, Type)],
1610        output: &Type,
1611    ) -> SmtRes<Value> {
1612        self.parse_value(input.as_bytes(), name, inputs, output)
1613    }
1614}
1615impl<'a, Ident, Type, Value, T, Br> ModelParser<Ident, Type, Value, &'a mut SmtParser<Br>> for T
1616where
1617    T: ModelParser<Ident, Type, Value, &'a str>,
1618    Br: BufRead,
1619{
1620    fn parse_value(
1621        self,
1622        input: &'a mut SmtParser<Br>,
1623        name: &Ident,
1624        inputs: &[(Ident, Type)],
1625        output: &Type,
1626    ) -> SmtRes<Value> {
1627        self.parse_value(input.get_sexpr()?, name, inputs, output)
1628    }
1629}
1630impl<'a, Br> ModelParser<&'a str, &'a str, &'a str, &'a mut SmtParser<Br>> for ()
1631where
1632    Br: BufRead,
1633{
1634    fn parse_value(
1635        self,
1636        input: &'a mut SmtParser<Br>,
1637        _name: &&'a str,
1638        _inputs: &[(&'a str, &'a str)],
1639        _output: &&'a str,
1640    ) -> SmtRes<&'a str> {
1641        input.get_sexpr()
1642    }
1643}
1644impl<'a, Br> ModelParser<String, String, String, &'a mut SmtParser<Br>> for ()
1645where
1646    Br: BufRead,
1647{
1648    fn parse_value(
1649        self,
1650        input: &'a mut SmtParser<Br>,
1651        _name: &String,
1652        _inputs: &[(String, String)],
1653        _output: &String,
1654    ) -> SmtRes<String> {
1655        input.get_sexpr().map(String::from)
1656    }
1657}
1658
1659/// Can parse values. Used for [`Solver::get_values`][crate::Solver::get_values].
1660///
1661/// For more information refer to the [module-level documentation](self).
1662pub trait ValueParser<Value, Input>: Copy {
1663    /// Parses a plain value.
1664    fn parse_value(self, i: Input) -> SmtRes<Value>;
1665}
1666impl<'a, Value, T> ValueParser<Value, &'a str> for T
1667where
1668    T: ValueParser<Value, &'a [u8]>,
1669{
1670    fn parse_value(self, input: &'a str) -> SmtRes<Value> {
1671        self.parse_value(input.as_bytes())
1672    }
1673}
1674impl<'a, Value, T, Br> ValueParser<Value, &'a mut SmtParser<Br>> for T
1675where
1676    T: ValueParser<Value, &'a str>,
1677    Br: BufRead,
1678{
1679    fn parse_value(self, input: &'a mut SmtParser<Br>) -> SmtRes<Value> {
1680        self.parse_value(input.get_sexpr()?)
1681    }
1682}
1683impl<'a, Br> ValueParser<&'a str, &'a mut SmtParser<Br>> for ()
1684where
1685    Br: BufRead,
1686{
1687    fn parse_value(self, input: &'a mut SmtParser<Br>) -> SmtRes<&'a str> {
1688        input.get_sexpr()
1689    }
1690}
1691impl<'a, Br> ValueParser<String, &'a mut SmtParser<Br>> for ()
1692where
1693    Br: BufRead,
1694{
1695    fn parse_value(self, input: &'a mut SmtParser<Br>) -> SmtRes<String> {
1696        input.get_sexpr().map(String::from)
1697    }
1698}
1699
1700/// Can parse expressions. Used for [`Solver::get_values`][crate::Solver::get_values].
1701///
1702/// For more information refer to the [module-level documentation](self).
1703pub trait ExprParser<Expr, Info, Input>: Copy {
1704    /// Parses an expression given some info.
1705    fn parse_expr(self, i: Input, info: Info) -> SmtRes<Expr>;
1706}
1707impl<'a, Expr, Info, T> ExprParser<Expr, Info, &'a str> for T
1708where
1709    T: ExprParser<Expr, Info, &'a [u8]>,
1710{
1711    fn parse_expr(self, input: &'a str, info: Info) -> SmtRes<Expr> {
1712        self.parse_expr(input.as_bytes(), info)
1713    }
1714}
1715impl<'a, Expr, Info, T, Br> ExprParser<Expr, Info, &'a mut SmtParser<Br>> for T
1716where
1717    T: ExprParser<Expr, Info, &'a str>,
1718    Br: BufRead,
1719{
1720    fn parse_expr(self, input: &'a mut SmtParser<Br>, info: Info) -> SmtRes<Expr> {
1721        self.parse_expr(input.get_sexpr()?, info)
1722    }
1723}
1724impl<'a, Br> ExprParser<&'a str, (), &'a mut SmtParser<Br>> for ()
1725where
1726    Br: BufRead,
1727{
1728    fn parse_expr(self, input: &'a mut SmtParser<Br>, _info: ()) -> SmtRes<&'a str> {
1729        input.get_sexpr()
1730    }
1731}
1732impl<'a, Br> ExprParser<String, (), &'a mut SmtParser<Br>> for ()
1733where
1734    Br: BufRead,
1735{
1736    fn parse_expr(self, input: &'a mut SmtParser<Br>, _info: ()) -> SmtRes<String> {
1737        input.get_sexpr().map(String::from)
1738    }
1739}
1740
1741/// Can parse proofs. Currenly unused.
1742///
1743/// For more information refer to the [module-level documentation](self).
1744pub trait ProofParser<Proof, Input>: Copy {
1745    /// Parses a proof.
1746    fn parse_proof(self, i: Input) -> SmtRes<Proof>;
1747}
1748impl<'a, Proof, T> ProofParser<Proof, &'a str> for T
1749where
1750    T: ProofParser<Proof, &'a [u8]>,
1751{
1752    fn parse_proof(self, input: &'a str) -> SmtRes<Proof> {
1753        self.parse_proof(input.as_bytes())
1754    }
1755}
1756impl<'a, Proof, T, Br> ProofParser<Proof, &'a mut SmtParser<Br>> for T
1757where
1758    T: ProofParser<Proof, &'a str>,
1759    Br: BufRead,
1760{
1761    fn parse_proof(self, input: &'a mut SmtParser<Br>) -> SmtRes<Proof> {
1762        self.parse_proof(input.get_sexpr()?)
1763    }
1764}