#![cfg_attr(not(feature = "std"), no_std)]
#![forbid(unsafe_code)]
mod lexer;
mod token;
#[cfg(test)]
mod tests;
pub use self::{
lexer::Error,
token::{
Literal,
Problem,
},
};
use self::{
lexer::Lexer,
token::Token,
};
pub trait Input {
fn read_byte(&mut self) -> Option<u8>;
}
impl<'a> Input for &'a [u8] {
fn read_byte(&mut self) -> Option<u8> {
let len = self.len();
if len == 0 {
return None
}
let byte = self[0];
*self = &self[1..];
Some(byte)
}
}
#[cfg(feature = "std")]
pub struct IoReader<R>(pub R)
where
R: std::io::Read;
#[cfg(feature = "std")]
impl<R> Input for IoReader<R>
where
R: std::io::Read,
{
fn read_byte(&mut self) -> Option<u8> {
let mut buf = [0x00];
self.0.read_exact(&mut buf).ok().map(|_| buf[0])
}
}
pub trait Output {
type Error;
fn problem(
&mut self,
num_variables: u32,
num_clauses: u32,
) -> Result<(), Self::Error>;
fn literal(&mut self, literal: Literal) -> Result<(), Self::Error>;
fn finalize_clause(&mut self) -> Result<(), Self::Error>;
fn finish(&mut self) -> Result<(), Self::Error>;
}
pub fn parse_cnf<I, O>(
input: &mut I,
output: &mut O,
) -> Result<(), Error<<O as Output>::Error>>
where
I: Input,
O: Output,
{
let mut lexer = <Lexer<I, O>>::new(input);
loop {
match lexer.next_token()? {
Some(Token::Problem(problem)) => {
output
.problem(problem.num_variables, problem.num_clauses)
.map_err(Error::from_output)?
}
Some(Token::Literal(literal)) => {
output.literal(literal).map_err(Error::from_output)?
}
Some(Token::ClauseEnd) => {
output.finalize_clause().map_err(Error::from_output)?
}
None => break,
}
}
output.finish().map_err(Error::from_output)?;
Ok(())
}