use crate::{
lexer,
visitors::{
CommandVisitor, ConstantVisitor, KeywordVisitor, QualIdentifierVisitor, SExprVisitor,
Smt2Visitor, SortVisitor, SymbolKind, SymbolVisitor, TermVisitor,
},
Binary, Decimal, Hexadecimal, Numeral, Position,
};
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
pub enum Constant {
Numeral(Numeral),
Decimal(Decimal),
Hexadecimal(Hexadecimal),
Binary(Binary),
String(String),
}
#[derive(Debug, PartialEq, Eq, Clone, Hash, Ord, PartialOrd, Serialize, Deserialize)]
pub struct Symbol(pub String);
#[derive(Debug, PartialEq, Eq, Clone, Hash, Ord, PartialOrd, Serialize, Deserialize)]
pub struct Keyword(pub String);
pub use crate::visitors::Identifier;
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
pub enum SExpr<Constant = self::Constant, Symbol = self::Symbol, Keyword = self::Keyword> {
Constant(Constant),
Symbol(Symbol),
Keyword(Keyword),
Application(Vec<Self>),
}
pub use crate::visitors::{AttributeValue, DatatypeDec, FunctionDec};
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
pub enum Sort<Identifier = self::Identifier> {
Simple {
identifier: Identifier,
},
Parameterized {
identifier: Identifier,
parameters: Vec<Self>,
},
}
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
pub enum QualIdentifier<Identifier = self::Identifier, Sort = self::Sort> {
Simple { identifier: Identifier },
Sorted { identifier: Identifier, sort: Sort },
}
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
pub enum Term<
Constant = self::Constant,
QualIdentifier = self::QualIdentifier,
Keyword = self::Keyword,
SExpr = self::SExpr,
Symbol = self::Symbol,
Sort = self::Sort,
> {
Constant(Constant),
QualIdentifier(QualIdentifier),
Application {
qual_identifier: QualIdentifier,
arguments: Vec<Self>,
},
Let {
var_bindings: Vec<(Symbol, Self)>,
term: Box<Self>,
},
Forall {
vars: Vec<(Symbol, Sort)>,
term: Box<Self>,
},
Exists {
vars: Vec<(Symbol, Sort)>,
term: Box<Self>,
},
Match {
term: Box<Self>,
cases: Vec<(Vec<Symbol>, Self)>,
},
Attributes {
term: Box<Self>,
attributes: Vec<(Keyword, AttributeValue<Constant, Symbol, SExpr>)>,
},
}
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
pub enum Command<
Term = self::Term,
Symbol = self::Symbol,
Sort = self::Sort,
Keyword = self::Keyword,
Constant = self::Constant,
SExpr = self::SExpr,
> {
Assert {
term: Term,
},
CheckSat,
CheckSatAssuming {
literals: Vec<(Symbol, bool)>,
},
DeclareConst {
symbol: Symbol,
sort: Sort,
},
DeclareDatatype {
symbol: Symbol,
datatype: DatatypeDec<Symbol, Sort>,
},
DeclareDatatypes {
datatypes: Vec<(Symbol, Numeral, DatatypeDec<Symbol, Sort>)>,
},
DeclareFun {
symbol: Symbol,
parameters: Vec<Sort>,
sort: Sort,
},
DeclareSort {
symbol: Symbol,
arity: Numeral,
},
DefineFun {
sig: FunctionDec<Symbol, Sort>,
term: Term,
},
DefineFunRec {
sig: FunctionDec<Symbol, Sort>,
term: Term,
},
DefineFunsRec {
funs: Vec<(FunctionDec<Symbol, Sort>, Term)>,
},
DefineSort {
symbol: Symbol,
parameters: Vec<Symbol>,
sort: Sort,
},
Echo {
message: String,
},
Exit,
GetAssertions,
GetAssignment,
GetInfo {
flag: Keyword,
},
GetModel,
GetOption {
keyword: Keyword,
},
GetProof,
GetUnsatAssumptions,
GetUnsatCore,
GetValue {
terms: Vec<Term>,
},
Pop {
level: Numeral,
},
Push {
level: Numeral,
},
Reset,
ResetAssertions,
SetInfo {
keyword: Keyword,
value: AttributeValue<Constant, Symbol, SExpr>,
},
SetLogic {
symbol: Symbol,
},
SetOption {
keyword: Keyword,
value: AttributeValue<Constant, Symbol, SExpr>,
},
}
#[derive(Default, Debug, Eq, PartialEq, Clone, Hash, Serialize, Deserialize)]
pub struct SyntaxBuilder;
#[derive(Error, Debug)]
pub enum Error {
#[error("error: {1}\n --> {0}")]
SyntaxError(Position, String),
#[error("error: {1}\n --> {0}")]
ParsingError(Position, String),
}
impl ConstantVisitor for SyntaxBuilder {
type T = Constant;
type E = Error;
fn visit_numeral_constant(&mut self, value: Numeral) -> Result<Self::T, Self::E> {
Ok(Constant::Numeral(value))
}
fn visit_decimal_constant(&mut self, value: Decimal) -> Result<Self::T, Self::E> {
Ok(Constant::Decimal(value))
}
fn visit_hexadecimal_constant(&mut self, value: Hexadecimal) -> Result<Self::T, Self::E> {
Ok(Constant::Hexadecimal(value))
}
fn visit_binary_constant(&mut self, value: Binary) -> Result<Self::T, Self::E> {
Ok(Constant::Binary(value))
}
fn visit_string_constant(&mut self, value: String) -> Result<Self::T, Self::E> {
Ok(Constant::String(value))
}
}
impl Constant {
pub fn accept<V>(self, visitor: &mut V) -> Result<V::T, V::E>
where
V: ConstantVisitor,
{
use Constant::*;
match self {
Numeral(value) => visitor.visit_numeral_constant(value),
Decimal(value) => visitor.visit_decimal_constant(value),
Hexadecimal(value) => visitor.visit_hexadecimal_constant(value),
Binary(value) => visitor.visit_binary_constant(value),
String(value) => visitor.visit_string_constant(value),
}
}
}
impl SymbolVisitor for SyntaxBuilder {
type T = Symbol;
type E = Error;
fn visit_fresh_symbol(&mut self, value: String, _kind: SymbolKind) -> Result<Self::T, Self::E> {
Ok(Symbol(value))
}
}
impl KeywordVisitor for SyntaxBuilder {
type T = Keyword;
type E = Error;
fn visit_keyword(&mut self, value: String) -> Result<Self::T, Self::E> {
Ok(Keyword(value))
}
}
impl Keyword {
pub fn accept<V>(self, visitor: &mut V) -> Result<V::T, V::E>
where
V: KeywordVisitor,
{
visitor.visit_keyword(self.0)
}
}
impl<Constant, Symbol, Keyword> SExprVisitor<Constant, Symbol, Keyword> for SyntaxBuilder {
type T = SExpr<Constant, Symbol, Keyword>;
type E = Error;
fn visit_constant_s_expr(&mut self, value: Constant) -> Result<Self::T, Self::E> {
Ok(SExpr::Constant(value))
}
fn visit_symbol_s_expr(&mut self, value: Symbol) -> Result<Self::T, Self::E> {
Ok(SExpr::Symbol(value))
}
fn visit_keyword_s_expr(&mut self, value: Keyword) -> Result<Self::T, Self::E> {
Ok(SExpr::Keyword(value))
}
fn visit_application_s_expr(&mut self, values: Vec<Self::T>) -> Result<Self::T, Self::E> {
Ok(SExpr::Application(values))
}
}
impl SExpr {
pub fn accept<V, T, C, S, K, E>(self, visitor: &mut V) -> Result<T, E>
where
V: SExprVisitor<C, S, K, T = T, E = E>
+ ConstantVisitor<T = C, E = E>
+ SymbolVisitor<T = S, E = E>
+ KeywordVisitor<T = K, E = E>,
{
use SExpr::*;
match self {
Constant(value) => {
let c = value.accept(visitor)?;
visitor.visit_constant_s_expr(c)
}
Symbol(value) => {
let s = visitor.visit_bound_symbol(value.0)?;
visitor.visit_symbol_s_expr(s)
}
Keyword(value) => {
let k = value.accept(visitor)?;
visitor.visit_keyword_s_expr(k)
}
Application(values) => {
let ts = values
.into_iter()
.map(|e| e.accept(visitor))
.collect::<Result<_, E>>()?;
visitor.visit_application_s_expr(ts)
}
}
}
}
impl<Symbol> SortVisitor<Symbol> for SyntaxBuilder {
type T = Sort<Identifier<Symbol>>;
type E = Error;
fn visit_simple_sort(&mut self, identifier: Identifier<Symbol>) -> Result<Self::T, Self::E> {
Ok(Sort::Simple { identifier })
}
fn visit_parameterized_sort(
&mut self,
identifier: Identifier<Symbol>,
parameters: Vec<Self::T>,
) -> Result<Self::T, Self::E> {
Ok(Sort::Parameterized {
identifier,
parameters,
})
}
}
impl Sort {
pub fn accept<V, T, S, E>(self, visitor: &mut V) -> Result<T, E>
where
V: SortVisitor<S, T = T, E = E> + SymbolVisitor<T = S, E = E>,
{
use Sort::*;
match self {
Simple { identifier } => {
let i = identifier.remap(visitor, |v, s: Symbol| v.visit_bound_symbol(s.0))?;
visitor.visit_simple_sort(i)
}
Parameterized {
identifier,
parameters,
} => {
let i = identifier.remap(visitor, |v, s: Symbol| v.visit_bound_symbol(s.0))?;
let ts = parameters
.into_iter()
.map(|s| s.accept(visitor))
.collect::<Result<_, E>>()?;
visitor.visit_parameterized_sort(i, ts)
}
}
}
}
impl<Identifier, Sort> QualIdentifierVisitor<Identifier, Sort> for SyntaxBuilder {
type T = QualIdentifier<Identifier, Sort>;
type E = Error;
fn visit_simple_identifier(&mut self, identifier: Identifier) -> Result<Self::T, Self::E> {
Ok(QualIdentifier::Simple { identifier })
}
fn visit_sorted_identifier(
&mut self,
identifier: Identifier,
sort: Sort,
) -> Result<Self::T, Self::E> {
Ok(QualIdentifier::Sorted { identifier, sort })
}
}
impl QualIdentifier {
pub fn accept<V, T, E, S1, S2>(self, visitor: &mut V) -> Result<T, E>
where
V: SortVisitor<S1, T = S2, E = E>
+ SymbolVisitor<T = S1, E = E>
+ QualIdentifierVisitor<Identifier<S1>, S2, T = T, E = E>,
{
use QualIdentifier::*;
match self {
Simple { identifier } => {
let i = identifier.remap(visitor, |v, s: Symbol| v.visit_bound_symbol(s.0))?;
visitor.visit_simple_identifier(i)
}
Sorted { identifier, sort } => {
let i = identifier.remap(visitor, |v, s: Symbol| v.visit_bound_symbol(s.0))?;
let s = sort.accept(visitor)?;
visitor.visit_sorted_identifier(i, s)
}
}
}
}
impl<Constant, QualIdentifier, Keyword, SExpr, Symbol, Sort>
TermVisitor<Constant, QualIdentifier, Keyword, SExpr, Symbol, Sort> for SyntaxBuilder
{
type T = Term<Constant, QualIdentifier, Keyword, SExpr, Symbol, Sort>;
type E = Error;
fn visit_constant(&mut self, constant: Constant) -> Result<Self::T, Self::E> {
Ok(Term::Constant(constant))
}
fn visit_qual_identifier(
&mut self,
qual_identifier: QualIdentifier,
) -> Result<Self::T, Self::E> {
Ok(Term::QualIdentifier(qual_identifier))
}
fn visit_application(
&mut self,
qual_identifier: QualIdentifier,
arguments: Vec<Self::T>,
) -> Result<Self::T, Self::E> {
Ok(Term::Application {
qual_identifier,
arguments,
})
}
fn visit_let(
&mut self,
var_bindings: Vec<(Symbol, Self::T)>,
term: Self::T,
) -> Result<Self::T, Self::E> {
let term = Box::new(term);
Ok(Term::Let { var_bindings, term })
}
fn visit_forall(
&mut self,
vars: Vec<(Symbol, Sort)>,
term: Self::T,
) -> Result<Self::T, Self::E> {
let term = Box::new(term);
Ok(Term::Forall { vars, term })
}
fn visit_exists(
&mut self,
vars: Vec<(Symbol, Sort)>,
term: Self::T,
) -> Result<Self::T, Self::E> {
let term = Box::new(term);
Ok(Term::Exists { vars, term })
}
fn visit_match(
&mut self,
term: Self::T,
cases: Vec<(Vec<Symbol>, Self::T)>,
) -> Result<Self::T, Self::E> {
let term = Box::new(term);
Ok(Term::Match { term, cases })
}
fn visit_attributes(
&mut self,
term: Self::T,
attributes: Vec<(Keyword, AttributeValue<Constant, Symbol, SExpr>)>,
) -> Result<Self::T, Self::E> {
let term = Box::new(term);
Ok(Term::Attributes { term, attributes })
}
}
impl Term {
pub fn accept<V, T, E, S1, S2, S3, S4, S5, S6>(self, visitor: &mut V) -> Result<T, E>
where
V: SortVisitor<S1, T = S2, E = E>
+ SymbolVisitor<T = S1, E = E>
+ QualIdentifierVisitor<Identifier<S1>, S2, T = S3, E = E>
+ ConstantVisitor<T = S4, E = E>
+ KeywordVisitor<T = S5, E = E>
+ SExprVisitor<S4, S1, S5, T = S6, E = E>
+ TermVisitor<S4, S3, S5, S6, S1, S2, T = T, E = E>,
{
use Term::*;
match self {
Constant(value) => {
let c = value.accept(visitor)?;
visitor.visit_constant(c)
}
QualIdentifier(value) => {
let qi = value.accept(visitor)?;
visitor.visit_qual_identifier(qi)
}
Application {
qual_identifier,
arguments,
} => {
let qi = qual_identifier.accept(visitor)?;
let mut ts = Vec::new();
for t in arguments {
ts.push(t.accept(visitor)?);
}
visitor.visit_application(qi, ts)
}
Let { var_bindings, term } => {
let bs = var_bindings
.into_iter()
.map(|(s, t)| {
Ok((
visitor.visit_fresh_symbol(s.0, SymbolKind::Variable)?,
t.accept(visitor)?,
))
})
.collect::<Result<Vec<_>, E>>()?;
bs.iter().for_each(|(s, _)| visitor.bind_symbol(s));
let t = term.accept(visitor)?;
bs.iter().for_each(|(s, _)| visitor.unbind_symbol(s));
visitor.visit_let(bs, t)
}
Forall { vars, term } => {
let vs = vars
.into_iter()
.map(|(v, s)| {
Ok((
visitor.visit_fresh_symbol(v.0, SymbolKind::Variable)?,
s.accept(visitor)?,
))
})
.collect::<Result<Vec<_>, E>>()?;
vs.iter().for_each(|(s, _)| visitor.bind_symbol(s));
let t = term.accept(visitor)?;
vs.iter().for_each(|(s, _)| visitor.unbind_symbol(s));
visitor.visit_forall(vs, t)
}
Exists { vars, term } => {
let vs = vars
.into_iter()
.map(|(v, s)| {
Ok((
visitor.visit_fresh_symbol(v.0, SymbolKind::Variable)?,
s.accept(visitor)?,
))
})
.collect::<Result<Vec<_>, E>>()?;
vs.iter().for_each(|(s, _)| visitor.bind_symbol(s));
let t = term.accept(visitor)?;
vs.iter().for_each(|(s, _)| visitor.unbind_symbol(s));
visitor.visit_exists(vs, t)
}
Match { term, cases } => {
let t = term.accept(visitor)?;
let cs = cases
.into_iter()
.map(|(ss, t)| {
let mut symbols = Vec::new();
let mut ss = ss.into_iter();
let mut has_fresh_first_symbol = false;
if let Some(s) = ss.next() {
symbols.push(visitor.visit_bound_symbol(s.0.clone()).or_else(
|_| {
has_fresh_first_symbol = true;
let s = visitor
.visit_fresh_symbol(s.0.clone(), SymbolKind::Variable)?;
visitor.bind_symbol(&s);
Ok(s)
},
)?);
}
for s in ss {
let s = visitor.visit_fresh_symbol(s.0, SymbolKind::Variable)?;
visitor.bind_symbol(&s);
symbols.push(s);
}
let term = t.accept(visitor)?;
let mut ss = symbols.iter();
if let Some(s) = ss.next() {
if has_fresh_first_symbol {
visitor.unbind_symbol(s);
}
}
for s in ss {
visitor.unbind_symbol(s);
}
Ok((symbols, term))
})
.collect::<Result<_, E>>()?;
visitor.visit_match(t, cs)
}
Attributes { term, attributes } => {
let t = term.accept(visitor)?;
let xs = attributes
.into_iter()
.map(|(k, x)| {
Ok((
k.accept(visitor)?,
x.remap(
visitor,
|v, c: self::Constant| c.accept(v),
|v, s: Symbol| v.visit_bound_symbol(s.0),
|v, e: SExpr| e.accept(v),
)?,
))
})
.collect::<Result<_, E>>()?;
visitor.visit_attributes(t, xs)
}
}
}
}
impl<Term, Symbol, Sort, Keyword, Constant, SExpr>
CommandVisitor<Term, Symbol, Sort, Keyword, Constant, SExpr> for SyntaxBuilder
{
type T = Command<Term, Symbol, Sort, Keyword, Constant, SExpr>;
type E = Error;
fn visit_assert(&mut self, term: Term) -> Result<Self::T, Self::E> {
Ok(Command::Assert { term })
}
fn visit_check_sat(&mut self) -> Result<Self::T, Self::E> {
Ok(Command::CheckSat)
}
fn visit_check_sat_assuming(
&mut self,
literals: Vec<(Symbol, bool)>,
) -> Result<Self::T, Self::E> {
Ok(Command::CheckSatAssuming { literals })
}
fn visit_declare_const(&mut self, symbol: Symbol, sort: Sort) -> Result<Self::T, Self::E> {
Ok(Command::DeclareConst { symbol, sort })
}
fn visit_declare_datatype(
&mut self,
symbol: Symbol,
datatype: DatatypeDec<Symbol, Sort>,
) -> Result<Self::T, Self::E> {
Ok(Command::DeclareDatatype { symbol, datatype })
}
fn visit_declare_datatypes(
&mut self,
datatypes: Vec<(Symbol, Numeral, DatatypeDec<Symbol, Sort>)>,
) -> Result<Self::T, Self::E> {
Ok(Command::DeclareDatatypes { datatypes })
}
fn visit_declare_fun(
&mut self,
symbol: Symbol,
parameters: Vec<Sort>,
sort: Sort,
) -> Result<Self::T, Self::E> {
Ok(Command::DeclareFun {
symbol,
parameters,
sort,
})
}
fn visit_declare_sort(&mut self, symbol: Symbol, arity: Numeral) -> Result<Self::T, Self::E> {
Ok(Command::DeclareSort { symbol, arity })
}
fn visit_define_fun(
&mut self,
sig: FunctionDec<Symbol, Sort>,
term: Term,
) -> Result<Self::T, Self::E> {
Ok(Command::DefineFun { sig, term })
}
fn visit_define_fun_rec(
&mut self,
sig: FunctionDec<Symbol, Sort>,
term: Term,
) -> Result<Self::T, Self::E> {
Ok(Command::DefineFunRec { sig, term })
}
fn visit_define_funs_rec(
&mut self,
funs: Vec<(FunctionDec<Symbol, Sort>, Term)>,
) -> Result<Self::T, Self::E> {
Ok(Command::DefineFunsRec { funs })
}
fn visit_define_sort(
&mut self,
symbol: Symbol,
parameters: Vec<Symbol>,
sort: Sort,
) -> Result<Self::T, Self::E> {
Ok(Command::DefineSort {
symbol,
parameters,
sort,
})
}
fn visit_echo(&mut self, message: String) -> Result<Self::T, Self::E> {
Ok(Command::Echo { message })
}
fn visit_exit(&mut self) -> Result<Self::T, Self::E> {
Ok(Command::Exit)
}
fn visit_get_assertions(&mut self) -> Result<Self::T, Self::E> {
Ok(Command::GetAssertions)
}
fn visit_get_assignment(&mut self) -> Result<Self::T, Self::E> {
Ok(Command::GetAssignment)
}
fn visit_get_info(&mut self, flag: Keyword) -> Result<Self::T, Self::E> {
Ok(Command::GetInfo { flag })
}
fn visit_get_model(&mut self) -> Result<Self::T, Self::E> {
Ok(Command::GetModel)
}
fn visit_get_option(&mut self, keyword: Keyword) -> Result<Self::T, Self::E> {
Ok(Command::GetOption { keyword })
}
fn visit_get_proof(&mut self) -> Result<Self::T, Self::E> {
Ok(Command::GetProof)
}
fn visit_get_unsat_assumptions(&mut self) -> Result<Self::T, Self::E> {
Ok(Command::GetUnsatAssumptions)
}
fn visit_get_unsat_core(&mut self) -> Result<Self::T, Self::E> {
Ok(Command::GetUnsatCore)
}
fn visit_get_value(&mut self, terms: Vec<Term>) -> Result<Self::T, Self::E> {
Ok(Command::GetValue { terms })
}
fn visit_pop(&mut self, level: Numeral) -> Result<Self::T, Self::E> {
Ok(Command::Pop { level })
}
fn visit_push(&mut self, level: Numeral) -> Result<Self::T, Self::E> {
Ok(Command::Push { level })
}
fn visit_reset(&mut self) -> Result<Self::T, Self::E> {
Ok(Command::Reset)
}
fn visit_reset_assertions(&mut self) -> Result<Self::T, Self::E> {
Ok(Command::ResetAssertions)
}
fn visit_set_info(
&mut self,
keyword: Keyword,
value: AttributeValue<Constant, Symbol, SExpr>,
) -> Result<Self::T, Self::E> {
Ok(Command::SetInfo { keyword, value })
}
fn visit_set_logic(&mut self, symbol: Symbol) -> Result<Self::T, Self::E> {
Ok(Command::SetLogic { symbol })
}
fn visit_set_option(
&mut self,
keyword: Keyword,
value: AttributeValue<Constant, Symbol, SExpr>,
) -> Result<Self::T, Self::E> {
Ok(Command::SetOption { keyword, value })
}
}
impl Command {
pub fn accept<V, T, E, S1, S2, S3, S4, S5, S6, S7>(self, visitor: &mut V) -> Result<T, E>
where
V: SortVisitor<S1, T = S2, E = E>
+ SymbolVisitor<T = S1, E = E>
+ QualIdentifierVisitor<Identifier<S1>, S2, T = S3, E = E>
+ ConstantVisitor<T = S4, E = E>
+ KeywordVisitor<T = S5, E = E>
+ SExprVisitor<S4, S1, S5, T = S6, E = E>
+ TermVisitor<S4, S3, S5, S6, S1, S2, T = S7, E = E>
+ CommandVisitor<S7, S1, S2, S5, S4, S6, T = T, E = E>,
{
use Command::*;
match self {
Assert { term } => {
let t = term.accept(visitor)?;
visitor.visit_assert(t)
}
CheckSat => visitor.visit_check_sat(),
CheckSatAssuming { literals } => {
let ls = literals
.into_iter()
.map(|(s, b)| Ok((visitor.visit_bound_symbol(s.0)?, b)))
.collect::<Result<_, E>>()?;
visitor.visit_check_sat_assuming(ls)
}
DeclareConst { symbol, sort } => {
let symb = visitor.visit_fresh_symbol(symbol.0, SymbolKind::Constant)?;
let sort = sort.accept(visitor)?;
visitor.bind_symbol(&symb);
visitor.visit_declare_const(symb, sort)
}
DeclareDatatype { symbol, datatype } => {
let s = visitor.visit_fresh_symbol(symbol.0, SymbolKind::Datatype)?;
visitor.bind_symbol(&s);
let dt = datatype.remap(
visitor,
|_, _| panic!("unexpected type parameters in DeclareDatatype"),
|v, s| v.visit_fresh_symbol(s.0, SymbolKind::Constructor),
|v, s| v.visit_fresh_symbol(s.0, SymbolKind::Selector),
|v, sort| sort.accept(v),
)?;
dt.constructors.iter().for_each(|c| {
visitor.bind_symbol(&c.symbol);
c.selectors.iter().for_each(|(s, _)| visitor.bind_symbol(s));
});
visitor.visit_declare_datatype(s, dt)
}
DeclareDatatypes { datatypes } => {
let dts = datatypes
.into_iter()
.map(|(s, n, dt)| {
let s = visitor.visit_fresh_symbol(s.0, SymbolKind::Datatype)?;
visitor.bind_symbol(&s);
Ok((s, n, dt))
})
.collect::<Result<Vec<_>, E>>()?;
let dts = dts
.into_iter()
.map(|(s, n, dt)| {
let dt = dt.remap(
visitor,
|v, s| {
let s = v.visit_fresh_symbol(s.0, SymbolKind::TypeVar)?;
v.bind_symbol(&s);
Ok(s)
},
|v, s| v.visit_fresh_symbol(s.0, SymbolKind::Constructor),
|v, s| v.visit_fresh_symbol(s.0, SymbolKind::Selector),
|v, sort| sort.accept(v),
)?;
dt.parameters.iter().for_each(|s| visitor.unbind_symbol(s));
dt.constructors.iter().for_each(|c| {
visitor.bind_symbol(&c.symbol);
c.selectors.iter().for_each(|(s, _)| visitor.bind_symbol(s));
});
Ok((s, n, dt))
})
.collect::<Result<_, E>>()?;
visitor.visit_declare_datatypes(dts)
}
DeclareFun {
symbol,
parameters,
sort,
} => {
let symb = visitor.visit_fresh_symbol(symbol.0, SymbolKind::Function)?;
let ps = parameters
.into_iter()
.map(|s| s.accept(visitor))
.collect::<Result<_, E>>()?;
let sort = sort.accept(visitor)?;
visitor.bind_symbol(&symb);
visitor.visit_declare_fun(symb, ps, sort)
}
DeclareSort { symbol, arity } => {
let s = visitor.visit_fresh_symbol(symbol.0, SymbolKind::Sort)?;
visitor.bind_symbol(&s);
visitor.visit_declare_sort(s, arity)
}
DefineFun { sig, term } => {
let sig = sig.remap(
visitor,
|v, s| v.visit_fresh_symbol(s.0, SymbolKind::Function),
|v, s| v.visit_fresh_symbol(s.0, SymbolKind::Variable),
|v, s| s.accept(v),
)?;
sig.parameters
.iter()
.for_each(|(s, _)| visitor.bind_symbol(s));
let t = term.accept(visitor)?;
sig.parameters
.iter()
.for_each(|(s, _)| visitor.unbind_symbol(s));
visitor.bind_symbol(&sig.name);
visitor.visit_define_fun(sig, t)
}
DefineFunRec { sig, term } => {
let sig = sig.remap(
visitor,
|v, s| v.visit_fresh_symbol(s.0, SymbolKind::Function),
|v, s| v.visit_fresh_symbol(s.0, SymbolKind::Variable),
|v, s| s.accept(v),
)?;
visitor.bind_symbol(&sig.name);
sig.parameters
.iter()
.for_each(|(s, _)| visitor.bind_symbol(s));
let t = term.accept(visitor)?;
sig.parameters
.iter()
.for_each(|(s, _)| visitor.unbind_symbol(s));
visitor.visit_define_fun_rec(sig, t)
}
DefineFunsRec { funs } => {
let funs = funs
.into_iter()
.map(|(sig, t)| {
let sig = sig.remap(
visitor,
|v, s| v.visit_fresh_symbol(s.0, SymbolKind::Function),
|v, s| v.visit_fresh_symbol(s.0, SymbolKind::Variable),
|v, s| s.accept(v),
)?;
visitor.bind_symbol(&sig.name);
sig.parameters
.iter()
.for_each(|(s, _)| visitor.bind_symbol(s));
Ok((sig, t))
})
.collect::<Result<Vec<_>, E>>()?;
let funs = funs
.into_iter()
.map(|(sig, t)| {
let t = t.accept(visitor)?;
sig.parameters
.iter()
.for_each(|(s, _)| visitor.unbind_symbol(s));
Ok((sig, t))
})
.collect::<Result<_, E>>()?;
visitor.visit_define_funs_rec(funs)
}
DefineSort {
symbol,
parameters,
sort,
} => {
let symbol = visitor.visit_fresh_symbol(symbol.0, SymbolKind::Sort)?;
let ps = parameters
.into_iter()
.map(|s| visitor.visit_fresh_symbol(s.0, SymbolKind::TypeVar))
.collect::<Result<Vec<_>, E>>()?;
ps.iter().for_each(|s| visitor.bind_symbol(s));
let sort = sort.accept(visitor)?;
ps.iter().for_each(|s| visitor.unbind_symbol(s));
visitor.bind_symbol(&symbol);
visitor.visit_define_sort(symbol, ps, sort)
}
Echo { message } => visitor.visit_echo(message),
Exit => visitor.visit_exit(),
GetAssertions => visitor.visit_get_assertions(),
GetAssignment => visitor.visit_get_assignment(),
GetInfo { flag } => {
let k = flag.accept(visitor)?;
visitor.visit_get_info(k)
}
GetModel => visitor.visit_get_model(),
GetOption { keyword } => {
let k = keyword.accept(visitor)?;
visitor.visit_get_option(k)
}
GetProof => visitor.visit_get_proof(),
GetUnsatAssumptions => visitor.visit_get_unsat_assumptions(),
GetUnsatCore => visitor.visit_get_unsat_core(),
GetValue { terms } => {
let ts = terms
.into_iter()
.map(|t| t.accept(visitor))
.collect::<Result<_, E>>()?;
visitor.visit_get_value(ts)
}
Pop { level } => visitor.visit_pop(level),
Push { level } => visitor.visit_push(level),
Reset => visitor.visit_reset(),
ResetAssertions => visitor.visit_reset_assertions(),
SetInfo { keyword, value } => {
let k = keyword.accept(visitor)?;
let v = value.remap(
visitor,
|v, c: self::Constant| c.accept(v),
|v, s: Symbol| v.visit_bound_symbol(s.0),
|v, e: SExpr| e.accept(v),
)?;
visitor.visit_set_info(k, v)
}
SetLogic { symbol } => {
let s = visitor.visit_bound_symbol(symbol.0)?;
visitor.visit_set_logic(s)
}
SetOption { keyword, value } => {
let k = keyword.accept(visitor)?;
let v = value.remap(
visitor,
|v, c: self::Constant| c.accept(v),
|v, s: Symbol| v.visit_bound_symbol(s.0),
|v, e: SExpr| e.accept(v),
)?;
visitor.visit_set_option(k, v)
}
}
}
}
impl Smt2Visitor for SyntaxBuilder {
type Error = Error;
type Constant = Constant;
type QualIdentifier = QualIdentifier;
type Keyword = Keyword;
type Sort = Sort;
type SExpr = SExpr;
type Symbol = Symbol;
type Term = Term;
type Command = Command;
fn syntax_error(&mut self, position: crate::Position, s: String) -> Self::Error {
Error::SyntaxError(position, s)
}
fn parsing_error(&mut self, position: crate::Position, s: String) -> Self::Error {
Error::ParsingError(position, s)
}
}
impl std::fmt::Display for Constant {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use Constant::*;
match self {
Numeral(num) => write!(f, "{}", num),
Decimal(dec) => {
let nom = dec.trunc();
let mut denom = dec.fract();
while !denom.is_integer() {
denom *= num::BigInt::from(10u32);
}
write!(f, "{}.{}", nom, denom)
}
Hexadecimal(hex) => {
write!(f, "#x")?;
for digit in hex {
write!(f, "{:x}", digit)?;
}
Ok(())
}
Binary(bin) => {
write!(f, "#b")?;
for digit in bin {
if *digit {
write!(f, "1")?;
} else {
write!(f, "0")?;
}
}
Ok(())
}
String(value) => {
for s in value.split('"') {
write!(f, "\"{}\"", s)?;
}
Ok(())
}
}
}
}
impl std::fmt::Display for Symbol {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let c = self.0.as_bytes().get(0);
if c.is_some()
&& lexer::is_non_digit_symbol_byte(*c.unwrap())
&& self.0.as_bytes().iter().all(|c| lexer::is_symbol_byte(*c))
{
write!(f, "{}", self.0)
} else {
write!(f, "|{}|", self.0)
}
}
}
impl std::fmt::Display for Keyword {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, ":{}", self.0)
}
}
impl<Constant, Symbol, Keyword> std::fmt::Display for SExpr<Constant, Symbol, Keyword>
where
Constant: std::fmt::Display,
Symbol: std::fmt::Display,
Keyword: std::fmt::Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use SExpr::*;
match self {
Constant(c) => write!(f, "{}", c),
Symbol(s) => write!(f, "{}", s),
Keyword(k) => write!(f, "{}", k),
Application(values) => write!(f, "({})", values.iter().format(" ")),
}
}
}
impl<Identifier> std::fmt::Display for Sort<Identifier>
where
Identifier: std::fmt::Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use Sort::*;
match self {
Simple { identifier } => write!(f, "{}", identifier),
Parameterized {
identifier,
parameters,
} => write!(f, "({} {})", identifier, parameters.iter().format(" ")),
}
}
}
impl<Identifier> std::fmt::Display for QualIdentifier<Identifier>
where
Identifier: std::fmt::Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use QualIdentifier::*;
match self {
Simple { identifier } => write!(f, "{}", identifier),
Sorted { identifier, sort } => write!(f, "(as {} {})", identifier, sort),
}
}
}
impl<Constant, QualIdentifier, Keyword, SExpr, Symbol, Sort> std::fmt::Display
for Term<Constant, QualIdentifier, Keyword, SExpr, Symbol, Sort>
where
Constant: std::fmt::Display,
QualIdentifier: std::fmt::Display,
Keyword: std::fmt::Display,
SExpr: std::fmt::Display,
Symbol: std::fmt::Display,
Sort: std::fmt::Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use Term::*;
match self {
Constant(c) => {
write!(f, "{}", c)
}
QualIdentifier(id) => {
write!(f, "{}", id)
}
Application {
qual_identifier,
arguments,
} => {
write!(f, "({} {})", qual_identifier, arguments.iter().format(" "))
}
Let { var_bindings, term } => {
write!(
f,
"(let ({}) {})",
var_bindings
.iter()
.format_with(" ", |(v, t), f| f(&format_args!("({} {})", v, t))),
term
)
}
Forall { vars, term } => {
write!(
f,
"(forall ({}) {})",
vars.iter()
.format_with(" ", |(v, s), f| f(&format_args!("({} {})", v, s))),
term
)
}
Exists { vars, term } => {
write!(
f,
"(exists ({}) {})",
vars.iter()
.format_with(" ", |(v, s), f| f(&format_args!("({} {})", v, s))),
term
)
}
Match { term, cases } => {
write!(
f,
"(match {} ({}))",
term,
cases.iter().format_with(" ", |(pattern, term), f| {
if pattern.len() == 1 {
f(&format_args!("({} {})", &pattern[0], term))
} else {
f(&format_args!("(({}) {})", pattern.iter().format(" "), term))
}
})
)
}
Attributes { term, attributes } => {
write!(
f,
"(! {} {})",
term,
attributes
.iter()
.format_with(" ", |(key, value), f| match value {
AttributeValue::None => f(key),
_ => f(&format_args!("{} {}", key, value)),
})
)
}
}
}
}
impl<Term, Symbol, Sort, Keyword, Constant, SExpr> std::fmt::Display
for Command<Term, Symbol, Sort, Keyword, Constant, SExpr>
where
Term: std::fmt::Display,
Symbol: std::fmt::Display,
Sort: std::fmt::Display,
Keyword: std::fmt::Display,
Constant: std::fmt::Display,
SExpr: std::fmt::Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use Command::*;
match self {
Assert { term } => write!(f, "(assert {})", term),
CheckSat => write!(f, "(check-sat)"),
CheckSatAssuming { literals } => {
write!(
f,
"(check-sat-assuming ({}))",
literals.iter().format_with(" ", |(s, b), f| {
if *b {
f(s)
} else {
f(&format_args!("(not {})", s))
}
})
)
}
DeclareConst { symbol, sort } => write!(f, "(declare-const {} {})", symbol, sort),
DeclareDatatype { symbol, datatype } => {
write!(f, "(declare-datatype {} {})", symbol, datatype)
}
DeclareDatatypes { datatypes } => {
let sorts = datatypes.iter().format_with(" ", |(sym, num, _), f| {
f(&format_args!("({} {})", sym, num))
});
let types = datatypes.iter().format_with(" ", |(_, _, ty), f| f(ty));
write!(f, "(declare-datatypes ({}) ({}))", sorts, types)
}
DeclareFun {
symbol,
parameters,
sort,
} => {
write!(
f,
"(declare-fun {} ({}) {})",
symbol,
parameters.iter().format(" "),
sort
)
}
DeclareSort { symbol, arity } => write!(
f,
"(declare-sort {} {})",
symbol,
self::Constant::Numeral(arity.clone())
),
DefineFun { sig, term } => {
write!(f, "(define-fun {} {})", sig, term)
}
DefineFunRec { sig, term } => {
write!(f, "(define-fun {} {})", sig, term)
}
DefineFunsRec { funs } => {
let sigs = funs.iter().format_with(" ", |(sig, _), f| f(sig));
let terms = funs.iter().format_with(" ", |(_, t), f| f(t));
write!(f, "(define-funs-rec ({}) ({}))", sigs, terms)
}
DefineSort {
symbol,
parameters,
sort,
} => {
write!(
f,
"(define-sort {} ({}) {})",
symbol,
parameters.iter().format(" "),
sort
)
}
Echo { message } => write!(f, "(echo {})", self::Constant::String(message.clone())),
Exit => write!(f, "(exit)"),
GetAssertions => write!(f, "(get-assertions)"),
GetAssignment => write!(f, "(get-assignment)"),
GetInfo { flag } => write!(f, "(get-info {})", flag),
GetModel => write!(f, "(get-model)"),
GetOption { keyword } => write!(f, "(get-info {})", keyword),
GetProof => write!(f, "(get-proof)"),
GetUnsatAssumptions => write!(f, "(get-unsat-assumptions)"),
GetUnsatCore => write!(f, "(get-unsat-core)"),
GetValue { terms } => {
write!(f, "(get-value ({}))", terms.iter().format(" "))
}
Pop { level } => write!(f, "(pop {})", self::Constant::Numeral(level.clone())),
Push { level } => write!(f, "(push {})", self::Constant::Numeral(level.clone())),
Reset => write!(f, "(reset)"),
ResetAssertions => write!(f, "(reset-assertions)"),
SetInfo { keyword, value } => write!(f, "(set-info {} {})", keyword, value),
SetLogic { symbol } => write!(f, "(set-logic {})", symbol),
SetOption { keyword, value } => write!(f, "(set-option {} {})", keyword, value),
}
}
}
pub fn parse_simple_attribute_value(input: &str) -> Option<AttributeValue> {
use crate::parser::Token;
let token = lexer::Lexer::new(input.as_bytes()).next()?;
match token {
Token::Numeral(x) => Some(AttributeValue::Constant(Constant::Numeral(x))),
Token::Decimal(x) => Some(AttributeValue::Constant(Constant::Decimal(x))),
Token::String(x) => Some(AttributeValue::Constant(Constant::String(x))),
Token::Binary(x) => Some(AttributeValue::Constant(Constant::Binary(x))),
Token::Hexadecimal(x) => Some(AttributeValue::Constant(Constant::Hexadecimal(x))),
Token::Symbol(x) => Some(AttributeValue::Symbol(Symbol(x))),
_ => None,
}
}
#[test]
fn test_syntax_visitor() {
let command = Command::Assert {
term: Term::Let {
var_bindings: vec![(
Symbol("x".into()),
Term::Application {
qual_identifier: QualIdentifier::Simple {
identifier: Identifier::Simple {
symbol: Symbol("f".into()),
},
},
arguments: vec![
Term::QualIdentifier(QualIdentifier::Simple {
identifier: Identifier::Simple {
symbol: Symbol("x".into()),
},
}),
Term::Constant(Constant::Numeral(num::BigUint::from(2u32))),
],
},
)],
term: Box::new(Term::Application {
qual_identifier: QualIdentifier::Simple {
identifier: Identifier::Simple {
symbol: Symbol("=".into()),
},
},
arguments: vec![
Term::QualIdentifier(QualIdentifier::Simple {
identifier: Identifier::Simple {
symbol: Symbol("x".into()),
},
}),
Term::Constant(Constant::Numeral(num::BigUint::from(3u32))),
],
}),
},
};
let mut builder = SyntaxBuilder::default();
let command2 = command.clone().accept(&mut builder).unwrap();
assert_eq!(command, command2);
}