#![forbid(unsafe_code)]
use smt2parser::{
concrete::SyntaxBuilder,
renaming::{SymbolNormalizer, SymbolNormalizerConfig, TesterModernizer},
stats::Smt2Counters,
CommandStream,
};
use std::path::PathBuf;
use structopt::StructOpt;
use strum::IntoEnumIterator;
#[derive(Debug, StructOpt)]
#[structopt(
name = "smt2bin",
about = "Demo tool for processing files with smt2parser"
)]
struct Options {
#[structopt(subcommand)]
operation: Operation,
}
#[derive(Debug, StructOpt)]
enum Operation {
Print {
#[structopt(long)]
normalize_symbols: bool,
#[structopt(long, default_value = "0")]
max_randomized_symbols: usize,
#[structopt(long)]
symbol_randomization_seed: Option<u64>,
#[structopt(parse(from_os_str))]
inputs: Vec<PathBuf>,
},
Count {
#[structopt(long, parse(from_os_str))]
keywords: Option<PathBuf>,
#[structopt(long, parse(from_os_str))]
symbols: Option<PathBuf>,
#[structopt(parse(from_os_str))]
inputs: Vec<PathBuf>,
},
}
fn process_file<T, F>(state: T, file_path: PathBuf, mut f: F) -> std::io::Result<T>
where
T: smt2parser::visitors::Smt2Visitor,
F: FnMut(T::Command),
T::Error: std::fmt::Display,
{
let file = std::io::BufReader::new(std::fs::File::open(&file_path)?);
let mut stream = CommandStream::new(file, state, file_path.to_str().map(String::from));
for result in &mut stream {
match result {
Ok(command) => f(command),
Err(error) => {
eprintln!("{}", error);
break;
}
}
}
Ok(stream.into_visitor())
}
fn read_words(path: Option<PathBuf>) -> std::io::Result<Vec<String>> {
match path {
None => Ok(Vec::new()),
Some(path) => {
use std::io::BufRead;
let file = std::io::BufReader::new(std::fs::File::open(&path)?);
file.lines().collect()
}
}
}
fn main() -> std::io::Result<()> {
let options = Options::from_args();
match options.operation {
Operation::Print {
normalize_symbols,
max_randomized_symbols,
symbol_randomization_seed,
inputs,
} => {
let randomization_space = smt2parser::visitors::SymbolKind::iter()
.map(|k| (k, max_randomized_symbols))
.collect();
let randomization_seed = symbol_randomization_seed.unwrap_or_else(rand::random);
let config = SymbolNormalizerConfig {
randomization_space,
randomization_seed,
};
if normalize_symbols {
let mut normalizer = SymbolNormalizer::new(SyntaxBuilder, config);
for input in inputs {
process_file(TesterModernizer::new(SyntaxBuilder), input, |command| {
let command = command.accept(&mut normalizer).unwrap();
println!("{}", command);
})?;
}
} else {
for input in inputs {
process_file(SyntaxBuilder, input, |command| println!("{}", command))?;
}
}
}
Operation::Count {
keywords,
symbols,
inputs,
} => {
let keywords = read_words(keywords)?;
let symbols = read_words(symbols)?;
let mut state = Smt2Counters::new(keywords, symbols);
for input in inputs {
state = process_file(state, input, |_| {})?;
}
println!("{:#?}", state)
}
}
Ok(())
}