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}