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}