diff --git a/src/pendragon/booleen.rs b/src/pendragon/booleen.rs index d005ac4..2b8b7ad 100644 --- a/src/pendragon/booleen.rs +++ b/src/pendragon/booleen.rs @@ -4,17 +4,19 @@ impl Pendragon { pub fn elements_booleen(&self, arguments: &str) -> Result, ErreurPendragon> { let texte = arguments .replace("ouvre la parenthèse", "ouvre-la-parenthese") - .replace("ferme la parenthèse", "ferme-la-parenthese"); - .replace("est égal à", "est-egal-a"); - .replace("est différent de", "est-different-de"); - .replace("est supérieur ou égal à", "est-superieur-ou-egal-a"); - .replace("est inférieur ou égal à", "est-inferieur-ou-egal-a"); - .replace("est supérieur à", "est-superieur-a"); + .replace("ferme la parenthèse", "ferme-la-parenthese") + .replace("est égal à", "est-egal-a") + .replace("est différent de", "est-different-de") + .replace("est supérieur ou égal à", "est-superieur-ou-egal-a") + .replace("est inférieur ou égal à", "est-inferieur-ou-egal-a") + .replace("est supérieur à", "est-superieur-a") .replace("est inférieur à", "est-inferieur-a"); let elements_texte: Vec<&str> = texte.split(" ").collect(); let mut expression: Vec = Vec::new(); let mut pile_operateurs: Vec = Vec::new(); - let mut comparaison: Vec = Vec::new(); + + let mut pile_inconnu: Vec = Vec::new(); + let mut possible_comparaison: Option = None; for element in elements_texte { match element { @@ -51,13 +53,37 @@ impl Pendragon { } } autre => { - if !format_de_variable(autre) { - return Err(ErreurPendragon::MauvaisArgument(format!("{}", autre))) + if format_de_variable(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() { @@ -66,6 +92,35 @@ impl Pendragon { 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, variables: &HashMap) -> Result { @@ -139,6 +194,18 @@ pub fn texte_comme_booleen(texte: &str) -> Result { } } +pub fn texte_comme_comparaison(texte: &str) -> Result { + 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 mut configurations = Vec::new(); for b1 in [true, false] { - for b2 in [true, false] { - for b3 in [true, false] { - for b4 in [true, false] { - for b5 in [true, false] { - configurations.push((b1, b2, b3, b4, b5)); - } - } - } - } - } + for b2 in [true, false] { + for b3 in [true, false] { + for b4 in [true, false] { + for b5 in [true, false] { + configurations.push((b1, b2, b3, b4, b5)); + } + } + } + } + } 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 {}", booleen_comme_texte(configuration.0), diff --git a/src/pendragon/debug.rs b/src/pendragon/debug.rs index f2075a5..6c27975 100644 --- a/src/pendragon/debug.rs +++ b/src/pendragon/debug.rs @@ -7,6 +7,7 @@ pub enum ErreurPendragon { NombreInvalide(String), BooleenInvalide(String), TexteInvalide(String), + ComparaisonInvalide(String), MauvaisArgument(String), VariableInconnue(String), MauvaisType(String, String, String), @@ -23,10 +24,11 @@ impl fmt::Display for ErreurPendragon { Self::ManqueArgument => write!(f, "Il manque un argument."), Self::NombreInvalide(nombre) => write!(f, "Le nombre \"{}\" est mal orthographié.", nombre), 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::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::Lecture(raison) => write!(f, "Lecture d'entrées utilisateur impossible : {}.", raison), Self::CalculBooleen(raison) => write!(f, "Calcul booleen échoué, {}.", raison), diff --git a/src/pendragon/structure.rs b/src/pendragon/structure.rs index 335e98d..718299d 100644 --- a/src/pendragon/structure.rs +++ b/src/pendragon/structure.rs @@ -160,7 +160,7 @@ impl Element { match self { Self::Entier(_) => TypeElement::Entier, Self::Texte(_) => TypeElement::Texte, - Self::Booleen(_) || Self::Comparaison(_) => TypeElement::Booleen, + Self::Booleen(_) | Self::Comparaison(_) => TypeElement::Booleen, Self::Variable(_, type_element) => type_element.clone(), Self::Operateur(operateur) => operateur.type_element(), } @@ -191,16 +191,51 @@ impl Operateur { } } -pub enum Comparaison { - Egal(Element, Element), - Different(Element, Element), - Superieur(Element, Element), - Inferieur(Element, Element), - SuperieurEgal(Element, Element), - InferieurEgal(Element, Element) +#[derive(Clone, Debug, PartialEq)] +pub struct Comparaison { + pub type_comparaison: Option, + pub membre_a: Vec, + pub membre_b: Vec, +} + +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, } - -