comparaison logic

This commit is contained in:
WanderingPenwing 2024-12-10 17:20:13 +01:00
parent 989f1f17fd
commit b82fdb8073
3 changed files with 138 additions and 34 deletions

View file

@ -4,17 +4,19 @@ impl Pendragon {
pub fn elements_booleen(&self, arguments: &str) -> Result<Vec<Element>, ErreurPendragon> { pub fn elements_booleen(&self, arguments: &str) -> Result<Vec<Element>, ErreurPendragon> {
let texte = arguments let texte = arguments
.replace("ouvre la parenthèse", "ouvre-la-parenthese") .replace("ouvre la parenthèse", "ouvre-la-parenthese")
.replace("ferme la parenthèse", "ferme-la-parenthese"); .replace("ferme la parenthèse", "ferme-la-parenthese")
.replace("est égal à", "est-egal-a"); .replace("est égal à", "est-egal-a")
.replace("est différent de", "est-different-de"); .replace("est différent de", "est-different-de")
.replace("est supérieur ou égal à", "est-superieur-ou-egal-a"); .replace("est supérieur ou égal à", "est-superieur-ou-egal-a")
.replace("est inférieur ou égal à", "est-inferieur-ou-egal-a"); .replace("est inférieur ou égal à", "est-inferieur-ou-egal-a")
.replace("est supérieur à", "est-superieur-a"); .replace("est supérieur à", "est-superieur-a")
.replace("est inférieur à", "est-inferieur-a"); .replace("est inférieur à", "est-inferieur-a");
let elements_texte: Vec<&str> = texte.split(" ").collect(); let elements_texte: Vec<&str> = texte.split(" ").collect();
let mut expression: Vec<Element> = Vec::new(); let mut expression: Vec<Element> = Vec::new();
let mut pile_operateurs: Vec<Operateur> = Vec::new(); let mut pile_operateurs: Vec<Operateur> = Vec::new();
let mut comparaison: Vec<Element> = Vec::new();
let mut pile_inconnu: Vec<String> = Vec::new();
let mut possible_comparaison: Option<Comparaison> = None;
for element in elements_texte { for element in elements_texte {
match element { match element {
@ -51,13 +53,37 @@ impl Pendragon {
} }
} }
autre => { autre => {
if !format_de_variable(autre) { if format_de_variable(autre) {
return Err(ErreurPendragon::MauvaisArgument(format!("{}", autre))) if let Ok(_) = self.programme.variable_est_de_type(autre, TypeElement::Booleen) {
expression.push(Element::Variable(autre.into(), TypeElement::Booleen));
} else {
pile_inconnu.push(autre.into());
continue;
}
} else if let Ok(type_comparaison) = texte_comme_comparaison(autre) {
if let Some(comparaison) = possible_comparaison {
return Err(ErreurPendragon::BooleenInvalide(format!("besoin d'un operateur booleen entre {:?} et {:?}", comparaison, type_comparaison)))
}
let mut comparaison = Comparaison::nouvelle();
self.ajoute_comparaison_membre(&mut comparaison, &pile_inconnu.join(" "))?;
comparaison.ajoute_type(type_comparaison)?;
pile_inconnu = Vec::new();
continue;
} else {
pile_inconnu.push(autre.into());
continue;
} }
self.programme.variable_est_de_type(autre, TypeElement::Booleen)?;
expression.push(Element::Variable(autre.into(), TypeElement::Booleen));
} }
} }
if !pile_inconnu.is_empty() {
let Some(mut comparaison) = possible_comparaison else {
return Err(ErreurPendragon::BooleenInvalide(format!("{:?}", pile_inconnu)))
};
self.ajoute_comparaison_membre(&mut comparaison, &pile_inconnu.join(" "))?;
expression.push(Element::Comparaison(comparaison.clone()));
pile_inconnu = Vec::new();
possible_comparaison = None;
}
} }
while let Some(operateur) = pile_operateurs.pop() { while let Some(operateur) = pile_operateurs.pop() {
@ -66,6 +92,35 @@ impl Pendragon {
Ok(expression) Ok(expression)
} }
pub fn ajoute_comparaison_membre(&self, comparaison: &mut Comparaison, texte: &str) -> Result<(), ErreurPendragon> {
let membre = if let Ok(elements_nombre) = self.elements_nombre(texte) {
elements_nombre
} else if let Ok(elements_booleen) = self.elements_booleen(texte) {
elements_booleen
} else if let Ok(elements_texte) = self.elements_texte(texte) {
elements_texte
} else {
return Err(ErreurPendragon::MauvaisArgument(texte.to_string()));
};
let Some(element) = membre.first() else {
return Err(ErreurPendragon::ComparaisonInvalide("il n'y a pas de d'élément dans le membre ajouté".into()))
};
if comparaison.type_comparaison.is_none() {
comparaison.membre_a = membre;
return Ok(());
}
let Some(element_de_comparaison) = comparaison.membre_a.first() else {
return Err(ErreurPendragon::ComparaisonInvalide("il n'y a pas de premier membre".into()))
};
if element_de_comparaison.type_element() != element.type_element() {
return Err(ErreurPendragon::MauvaisType(
format!("{:?}", element), element.type_element().nom(),
element_de_comparaison.type_element().nom()))
}
comparaison.membre_b = membre;
Ok(())
}
} }
pub fn affiche_booleen(expression: Vec<Element>, variables: &HashMap<String, Element>) -> Result<String, ErreurPendragon> { pub fn affiche_booleen(expression: Vec<Element>, variables: &HashMap<String, Element>) -> Result<String, ErreurPendragon> {
@ -139,6 +194,18 @@ pub fn texte_comme_booleen(texte: &str) -> Result<Element, ErreurPendragon> {
} }
} }
pub fn texte_comme_comparaison(texte: &str) -> Result<TypeComparaison, ErreurPendragon> {
match texte {
"est-egal-a" => Ok(TypeComparaison::Egal),
"est-different-de" => Ok(TypeComparaison::Different),
"est-superieur-ou-egal-a" => Ok(TypeComparaison::SuperieurEgal),
"est-inferieur-ou-egal-a" => Ok(TypeComparaison::InferieurEgal),
"est-superieur-a" => Ok(TypeComparaison::Superieur),
"est-inferieur-a" => Ok(TypeComparaison::Inferieur),
_ => Err(ErreurPendragon::ComparaisonInvalide(format!("\"{}\" n'est pas un type de comparaison", texte))),
}
}
@ -170,16 +237,16 @@ mod test {
let pendragon = Pendragon::nouveau(); let pendragon = Pendragon::nouveau();
let mut configurations = Vec::new(); let mut configurations = Vec::new();
for b1 in [true, false] { for b1 in [true, false] {
for b2 in [true, false] { for b2 in [true, false] {
for b3 in [true, false] { for b3 in [true, false] {
for b4 in [true, false] { for b4 in [true, false] {
for b5 in [true, false] { for b5 in [true, false] {
configurations.push((b1, b2, b3, b4, b5)); configurations.push((b1, b2, b3, b4, b5));
} }
} }
} }
} }
} }
for configuration in configurations { for configuration in configurations {
let possible_expression = pendragon.elements_booleen(&format!("{} et non ouvre la parenthèse {} ou non {} ferme la parenthèse ou non {} et {}", let possible_expression = pendragon.elements_booleen(&format!("{} et non ouvre la parenthèse {} ou non {} ferme la parenthèse ou non {} et {}",
booleen_comme_texte(configuration.0), booleen_comme_texte(configuration.0),

View file

@ -7,6 +7,7 @@ pub enum ErreurPendragon {
NombreInvalide(String), NombreInvalide(String),
BooleenInvalide(String), BooleenInvalide(String),
TexteInvalide(String), TexteInvalide(String),
ComparaisonInvalide(String),
MauvaisArgument(String), MauvaisArgument(String),
VariableInconnue(String), VariableInconnue(String),
MauvaisType(String, String, String), MauvaisType(String, String, String),
@ -23,10 +24,11 @@ impl fmt::Display for ErreurPendragon {
Self::ManqueArgument => write!(f, "Il manque un argument."), Self::ManqueArgument => write!(f, "Il manque un argument."),
Self::NombreInvalide(nombre) => write!(f, "Le nombre \"{}\" est mal orthographié.", nombre), Self::NombreInvalide(nombre) => write!(f, "Le nombre \"{}\" est mal orthographié.", nombre),
Self::TexteInvalide(raison) => write!(f, "Le texte est invalide, {}.", raison), Self::TexteInvalide(raison) => write!(f, "Le texte est invalide, {}.", raison),
Self::BooleenInvalide(booleen) => write!(f, "Le booleen \"{}\" est mal orthographié.", booleen), Self::BooleenInvalide(booleen) => write!(f, "Le booleen \"{}\" est ivalide.", booleen),
Self::ComparaisonInvalide(raison) => write!(f, "La comparaison est invalide, {}.", raison),
Self::MauvaisArgument(message) => write!(f, "La commande a reçu un mauvais argument, {}.", message), Self::MauvaisArgument(message) => write!(f, "La commande a reçu un mauvais argument, {}.", message),
Self::VariableInconnue(nom) => write!(f, "La variable \"{}\" est inconnue.", nom), Self::VariableInconnue(nom) => write!(f, "La variable \"{}\" est inconnue.", nom),
Self::MauvaisType(nom, type_variable, type_attendu) => write!(f, "La variable {} est du mauvais type ({}), attendais {}.", nom, type_variable, type_attendu), Self::MauvaisType(nom, type_variable, type_attendu) => write!(f, "La {} est du mauvais type ({}), attendais {}.", nom, type_variable, type_attendu),
Self::ManquePoint => write!(f, "Il manque un point."), Self::ManquePoint => write!(f, "Il manque un point."),
Self::Lecture(raison) => write!(f, "Lecture d'entrées utilisateur impossible : {}.", raison), Self::Lecture(raison) => write!(f, "Lecture d'entrées utilisateur impossible : {}.", raison),
Self::CalculBooleen(raison) => write!(f, "Calcul booleen échoué, {}.", raison), Self::CalculBooleen(raison) => write!(f, "Calcul booleen échoué, {}.", raison),

View file

@ -160,7 +160,7 @@ impl Element {
match self { match self {
Self::Entier(_) => TypeElement::Entier, Self::Entier(_) => TypeElement::Entier,
Self::Texte(_) => TypeElement::Texte, Self::Texte(_) => TypeElement::Texte,
Self::Booleen(_) || Self::Comparaison(_) => TypeElement::Booleen, Self::Booleen(_) | Self::Comparaison(_) => TypeElement::Booleen,
Self::Variable(_, type_element) => type_element.clone(), Self::Variable(_, type_element) => type_element.clone(),
Self::Operateur(operateur) => operateur.type_element(), Self::Operateur(operateur) => operateur.type_element(),
} }
@ -191,16 +191,51 @@ impl Operateur {
} }
} }
pub enum Comparaison { #[derive(Clone, Debug, PartialEq)]
Egal(Element, Element), pub struct Comparaison {
Different(Element, Element), pub type_comparaison: Option<TypeComparaison>,
Superieur(Element, Element), pub membre_a: Vec<Element>,
Inferieur(Element, Element), pub membre_b: Vec<Element>,
SuperieurEgal(Element, Element), }
InferieurEgal(Element, Element)
impl Comparaison {
pub fn nouvelle() -> Self {
Self {
type_comparaison: None,
membre_a: vec![],
membre_b: vec![]
}
}
pub fn ajoute_type(&mut self, type_comparaison: TypeComparaison) -> Result<(), ErreurPendragon> {
let Some(element) = self.membre_a.first() else {
return Err(ErreurPendragon::ComparaisonInvalide("il n'y a pas de premier membre".into()))
};
if let TypeComparaison::Egal = type_comparaison {
self.type_comparaison = Some(type_comparaison);
return Ok(());
}
if let TypeComparaison::Different = type_comparaison {
self.type_comparaison = Some(type_comparaison);
return Ok(());
}
if let TypeElement::Entier = element.type_element() {
self.type_comparaison = Some(type_comparaison);
return Ok(());
}
return Err(ErreurPendragon::ComparaisonInvalide(format!("voulait comparer {} avec {:?}", element.type_element().nom(), type_comparaison)))
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum TypeComparaison {
Egal,
Different,
SuperieurEgal,
InferieurEgal,
Superieur,
Inferieur,
} }