diff --git a/pendragon.project b/pendragon.project index 7181274..5e9df80 100644 --- a/pendragon.project +++ b/pendragon.project @@ -1 +1 @@ -{"categories":[{"name":"todo","content":[{"name":"booleen type","description":"// Hello there","id":4},{"name":"if","description":"implémente if avec des guillemets de délimitation","id":1},{"name":"while","description":"implémente un while","id":2},{"name":"compilation","description":"// Hello there","id":3},{"name":"soixante-dix","description":"// Hello there","id":1}]},{"name":"in progress","content":[]},{"name":"done","content":[]},{"name":"bug","content":[]},{"name":"to test","content":[]},{"name":"+","content":[]}]} \ No newline at end of file +{"categories":[{"name":"todo","content":[{"name":"parenthese comparaison","description":"// Hello there","id":1},{"name":"commentaires","description":"// Hello there","id":3},{"name":"compile time verification","description":"odre des termes rpn","id":1},{"name":"error context","description":"// Hello there","id":2},{"name":"test correct error","description":"// Hello there","id":3},{"name":"test comparaison","description":"// Hello there","id":4},{"name":"stop cheating with \"-\"","description":"// Hello there","id":5},{"name":"if","description":"implémente if avec des guillemets de délimitation","id":1},{"name":"scope variable","description":"// Hello there","id":6},{"name":"while","description":"implémente un while","id":2},{"name":"else","description":"// Hello there","id":7},{"name":"break","description":"// Hello there","id":8},{"name":"continue","description":"// Hello there","id":9},{"name":"compilation","description":"// Hello there","id":3}]},{"name":"in progress","content":[]},{"name":"done","content":[{"name":"comparaison","description":"// Hello there","id":2},{"name":"booleen type","description":"// Hello there","id":4},{"name":"soixante-dix","description":"// Hello there","id":1}]},{"name":"bug","content":[]},{"name":"to test","content":[]},{"name":"+","content":[]}]} \ No newline at end of file diff --git a/src/pendragon/booleen.rs b/src/pendragon/booleen.rs index 698d6f0..e376939 100644 --- a/src/pendragon/booleen.rs +++ b/src/pendragon/booleen.rs @@ -10,7 +10,8 @@ impl Pendragon { .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"); + .replace("est inférieur à", "est-inferieur-a") + .replace("divisé par", "divise-par"); let elements_texte: Vec<&str> = texte.split(" ").collect(); let mut expression: Vec = Vec::new(); let mut pile_operateurs: Vec = Vec::new(); @@ -20,10 +21,20 @@ impl Pendragon { for element in elements_texte { match element { - "vrai" => expression.push(Element::Booleen(true)), - "faux" => expression.push(Element::Booleen(false)), - "non" => pile_operateurs.push(Operateur::Non), + "vrai" => { + self.fin_comparaison("vrai", &mut pile_inconnu, &mut pile_operateurs, &mut expression, &mut possible_comparaison)?; + expression.push(Element::Booleen(true)); + }, + "faux" => { + self.fin_comparaison("faux", &mut pile_inconnu, &mut pile_operateurs, &mut expression, &mut possible_comparaison)?; + expression.push(Element::Booleen(false)); + } + "non" => { + self.fin_comparaison("non", &mut pile_inconnu, &mut pile_operateurs, &mut expression, &mut possible_comparaison)?; + pile_operateurs.push(Operateur::Non); + } "et" => { + self.fin_comparaison("et", &mut pile_inconnu, &mut pile_operateurs, &mut expression, &mut possible_comparaison)?; while let Some(operateur) = pile_operateurs.last() { if *operateur == Operateur::Non || *operateur == Operateur::Et { expression.push(Element::Operateur(pile_operateurs.pop().unwrap())); @@ -34,6 +45,7 @@ impl Pendragon { pile_operateurs.push(Operateur::Et); } "ou" => { + self.fin_comparaison("ou", &mut pile_inconnu, &mut pile_operateurs, &mut expression, &mut possible_comparaison)?; while let Some(operateur) = pile_operateurs.last() { if *operateur == Operateur::Non || *operateur == Operateur::Et || *operateur == Operateur::Ou { expression.push(Element::Operateur(pile_operateurs.pop().unwrap())); @@ -43,8 +55,16 @@ impl Pendragon { } pile_operateurs.push(Operateur::Ou); } - "ouvre-la-parenthese" => pile_operateurs.push(Operateur::ParentheseBooleen), + "ouvre-la-parenthese" => { + pile_inconnu.push("ouvre-la-parenthese".into()); + } "ferme-la-parenthese" => { + let nombre_parenthese = compare_parentheses(&pile_inconnu); + if nombre_parenthese.0 > nombre_parenthese.1 { + pile_inconnu.push("ferme-la-parenthese".into()); + continue + } + self.fin_comparaison("ferme-la-parenthese", &mut pile_inconnu, &mut pile_operateurs, &mut expression, &mut possible_comparaison)?; while let Some(operateur) = pile_operateurs.pop() { if operateur == Operateur::ParentheseBooleen { break; @@ -55,36 +75,30 @@ impl Pendragon { autre => { if format_de_variable(autre) { if let Ok(_) = self.programme.variable_est_de_type(autre, TypeElement::Booleen) { + self.fin_comparaison(autre, &mut pile_inconnu, &mut pile_operateurs, &mut expression, &mut possible_comparaison)?; 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(); + let nombre_parenthese = compare_parentheses(&pile_inconnu); + if pile_inconnu[0] == "ouvre-la-parenthese" && nombre_parenthese.0 > nombre_parenthese.1 { + pile_inconnu.remove(0); + pile_operateurs.push(Operateur::ParentheseBooleen); + } self.ajoute_comparaison_membre(&mut comparaison, &pile_inconnu.join(" "))?; comparaison.ajoute_type(type_comparaison)?; possible_comparaison = Some(comparaison); pile_inconnu = Vec::new(); - continue; } else { pile_inconnu.push(autre.into()); - continue; } } } - 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; - } } if !pile_inconnu.is_empty() { let Some(mut comparaison) = possible_comparaison else { @@ -101,6 +115,25 @@ impl Pendragon { Ok(expression) } + pub fn fin_comparaison(&self, _element: &str, pile_inconnu: &mut Vec, pile_operateurs: &mut Vec, expression: &mut Vec, possible_comparaison: &mut Option) -> Result<(), ErreurPendragon> { + if pile_inconnu.len() == 1 && pile_inconnu[0] == "ouvre-la-parenthese" { + pile_operateurs.push(Operateur::ParentheseBooleen); + *pile_inconnu = Vec::new(); + } + if pile_inconnu.is_empty() { + return Ok(()); + } + let Some(ancienne_comparaison) = possible_comparaison else { + return Err(ErreurPendragon::BooleenInvalide(format!("{:?}", pile_inconnu))) + }; + let mut comparaison = ancienne_comparaison.clone(); + self.ajoute_comparaison_membre(&mut comparaison, &pile_inconnu.join(" "))?; + expression.push(Element::Comparaison(comparaison.clone())); + *pile_inconnu = Vec::new(); + *possible_comparaison = None; + Ok(()) + } + 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 @@ -131,6 +164,13 @@ impl Pendragon { } } +fn compare_parentheses(strings: &Vec) -> (usize, usize) { + let ouvre_count = strings.iter().filter(|s| *s == "ouvre-la-parenthese").count(); + let ferme_count = strings.iter().filter(|s| *s == "ferme-la-parenthese").count(); + + (ouvre_count, ferme_count) +} + pub fn affiche_booleen(expression: Vec, variables: &HashMap) -> Result { let booleen = calcule_booleen(expression.clone(), variables)?; Ok(booleen_comme_texte(booleen)) @@ -284,4 +324,84 @@ mod test { } } } + + #[test] + fn teste_comparaison() { + let pendragon = Pendragon::nouveau(); + for (a, b) in [(1, 4), (2, 2), (3, 1), (0, 3)] { + let possible_expressions = vec![ + pendragon.elements_booleen(&format!("non six plus {} est supérieur à deux fois {}", nombre::nombre_comme_texte(a), nombre::nombre_comme_texte(b))), + pendragon.elements_booleen(&format!("six plus {} est inférieur à deux fois {}", nombre::nombre_comme_texte(a), nombre::nombre_comme_texte(b))), + pendragon.elements_booleen(&format!("six plus {} est supérieur ou égal à deux fois {}", nombre::nombre_comme_texte(a), nombre::nombre_comme_texte(b))), + pendragon.elements_booleen(&format!("non six plus {} est inférieur ou égal à deux fois {}", nombre::nombre_comme_texte(a), nombre::nombre_comme_texte(b))), + pendragon.elements_booleen(&format!("non \"deux\" est égal à \"{}\"", nombre::nombre_comme_texte(a))), + pendragon.elements_booleen(&format!("\"trois\" est différent de \"{}\"", nombre::nombre_comme_texte(a))), + ]; + let bonne_reponses = vec![ + !(6+a > 2*b), + (6+a < 2*b), + (6+a >= 2*b), + !(6+a <= 2*b), + !(a == 2), + (a != 3), + ]; + for index in 0..possible_expressions.len() { + match &possible_expressions[index] { + Ok(expression) => { + match calcule_booleen(expression.clone(), &HashMap::new()) { + Ok(booleen) => { + let reponse = bonne_reponses[index]; + assert_eq!(booleen, reponse, "Calcul d'expression (booleen) n°{} ({},{}) donne un mauvais résultat : {}, attendais {}", index, a, b, booleen, reponse); + } + Err(raison) => { + panic!("Calcul d'expression (booleen) échoué, avec l'erreur : {}", raison); + } + } + } + Err(raison) => { + panic!("Détermination d'expression (booleen) échouée : {}", raison); + } + } + } + } + } + + #[test] + fn teste_combinaison() { + let pendragon = Pendragon::nouveau(); + for a in 0..5 { + for b in 0..5 { + for c in 0..5 { + for d in 1..5 { + for e in 0..5 { + println!(); + let possible_expression = pendragon.elements_booleen(&format!("non ouvre la parenthèse six plus {} ferme la parenthèse est supérieur à deux fois {} et ouvre la parenthèse {} divisé par deux est inférieur à ouvre la parenthèse {} moins un ferme la parenthèse ou non \"deux\" est égal à \"{}\" ferme la parenthèse", + nombre::nombre_comme_texte(a), + nombre::nombre_comme_texte(b), + nombre::nombre_comme_texte(c), + nombre::nombre_comme_texte(d), + nombre::nombre_comme_texte(e), + )); + let bonne_reponse = !((6+a) > 2*b) && (c/2 < (d-1) || !(e == 2)); + match possible_expression{ + Ok(expression) => { + match calcule_booleen(expression.clone(), &HashMap::new()) { + Ok(booleen) => { + assert_eq!(booleen, bonne_reponse, "Calcul d'expression (booleen) ({},{},{},{},{}) donne un mauvais résultat : {}, attendais {}", a, b, c, d, e, booleen, bonne_reponse); + } + Err(raison) => { + panic!("Calcul d'expression (booleen) échoué, avec l'erreur : {}", raison); + } + } + } + Err(raison) => { + panic!("Détermination d'expression (booleen) échouée : {}", raison); + } + } + } + } + } + } + } + } } diff --git a/src/pendragon/nombre.rs b/src/pendragon/nombre.rs index 338a37f..6a78c55 100644 --- a/src/pendragon/nombre.rs +++ b/src/pendragon/nombre.rs @@ -213,7 +213,7 @@ fn petit_nombre_comme_texte(nombre: usize) -> String { let séparation = if unité == 1 && ![0, 1, 8, 9].contains(&dizaine) {UNION.to_string() + "et"} else {"".to_string()}; - let unité_union = if nombre - unité > 0 && unité > 0 && (nombre%100 > 16 || nombre%100 < 10) { + let unité_union = if (nombre - unité > 0 && unité > 0 && (nombre%100 > 16 || nombre%100 < 10)) || (unité == 0 && dizaine == 7) { UNION.to_string() } else { "".to_string() @@ -347,7 +347,7 @@ mod test { use super::*; #[test] fn teste_conversion_nombres_texte() { - for i in [0, 1, 42, 123, 999, 1031, 1_001_091, 72_036_854_775_807usize].iter() { + for i in [0, 1, 42, 70, 123, 999, 1031, 1_001_091, 72_036_854_775_807usize].iter() { let texte = nombre_comme_texte(*i); // Convert number to text match texte_comme_nombre(&texte) { // Convert text back to number Ok(nombre) => { diff --git a/test.dr b/test.dr index 0f33650..94c3f1b 100644 --- a/test.dr +++ b/test.dr @@ -1,5 +1,4 @@ -Définis A comme entier. -Modifie A avec dix-huit. -Définis B comme booléen. -Modifie B avec non faux et ouvre la parenthèse trois-mille-un divisé par A est supérieur ou égal à sept ou faux ferme la parenthèse. -Affiche B. \ No newline at end of file +Affiche soixante-dix. +Affiche soixante-et-onze. +Affiche vrai et ouvre la parenthèse six plus un est supérieur à ouvre la parenthèse deux fois deux ferme la parenthèse ferme la parenthèse. +