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