use std::io::{Error, ErrorKind};
use logos::Lexer;
use veripb_formula::prelude::*;
use crate::substitution_token::SubstitutionToken;
pub fn parse_substitution(
lex: &mut Lexer<SubstitutionToken>,
var_names: &mut VarNameManager,
) -> Result<Substitution, Error> {
let mut sub = Substitution::default();
while let Some(token) = lex.next() {
let var = match token {
Ok(SubstitutionToken::PositiveLit) => var_names.add_by_name(lex.slice()),
Ok(SubstitutionToken::Semicolon) => break,
Ok(_) => return Err(Error::new(ErrorKind::InvalidData, "Expected variable.")),
Err(_) => return Err(Error::new(ErrorKind::InvalidData, "Unrecognized token.")),
};
if let Some(token) = lex.next() {
let already_set = match token {
Ok(SubstitutionToken::Zero) => sub.set(var, SubstitutionValue::FALSE),
Ok(SubstitutionToken::One) => sub.set(var, SubstitutionValue::TRUE),
Ok(SubstitutionToken::PositiveLit) => sub.set(
var,
SubstitutionValue::lit(Lit::from_var(
var_names.add_by_name(lex.slice()),
false,
)),
),
Ok(SubstitutionToken::NegativeLit) => sub.set(
var,
SubstitutionValue::lit(Lit::from_var(
var_names.add_by_name(&lex.slice()[1..]),
true,
)),
),
Ok(_) => {
return Err(Error::new(
ErrorKind::InvalidData,
"Expected '0', '1', or literal.",
))
}
Err(_) => return Err(Error::new(ErrorKind::InvalidData, "Unrecognized token.")),
};
if already_set {
return Err(Error::new(
ErrorKind::InvalidData,
"A variable is assigned twice in the substitution.",
));
}
} else {
return Err(Error::new(
ErrorKind::InvalidData,
"Substitution ended unexpectedly after variable.",
));
}
}
Ok(sub)
}