From a8b1110f972006b63ee84a953b8ef6d0e2ceba9c Mon Sep 17 00:00:00 2001 From: WanderingPenwing Date: Mon, 9 Dec 2024 12:05:18 +0100 Subject: [PATCH] structure --- src/sophie/booleen.rs | 6 +-- src/sophie/mod.rs | 80 ++++++------------------------ src/sophie/nombre.rs | 6 +-- src/sophie/structure.rs | 105 ++++++++++++++++++++++++++++++++++++++++ src/sophie/tests.rs | 34 ++++++------- src/sophie/texte.rs | 6 +-- 6 files changed, 146 insertions(+), 91 deletions(-) create mode 100644 src/sophie/structure.rs diff --git a/src/sophie/booleen.rs b/src/sophie/booleen.rs index 34926ec..a73bf47 100644 --- a/src/sophie/booleen.rs +++ b/src/sophie/booleen.rs @@ -1,6 +1,6 @@ use super::Sophie; use super::ErreurSophie; -use super::Variable; +use super::Element; impl Sophie { pub fn condition(&self, arguments: &str) -> Result { @@ -64,8 +64,8 @@ impl Sophie { pub fn texte_comme_booleen(&self, texte: &str) -> Result { if texte.chars().next().map_or(false, |c| c.is_uppercase()) { if self.variables.contains_key(texte) { - let Variable::Booleen(booleen) = self.variables[texte] else { - return Err(ErreurSophie::MauvaisType(texte.into(), self.variables[texte].nom_type(), "booleen".into())) + let Element::Booleen(booleen) = self.variables[texte] else { + return Err(ErreurSophie::MauvaisType(texte.into(), self.variables[texte].type_element().nom(), "booleen".into())) }; return Ok(booleen); } else { diff --git a/src/sophie/mod.rs b/src/sophie/mod.rs index 700be1d..0644f20 100644 --- a/src/sophie/mod.rs +++ b/src/sophie/mod.rs @@ -1,67 +1,17 @@ -use std::fmt; use std::io; use std::collections::HashMap; pub mod nombre; pub mod texte; pub mod booleen; +pub mod structure; +use structure::*; #[cfg(test)] mod tests; -#[derive(PartialEq, Debug, Clone)] -pub enum Variable { - Entier(usize), - Texte(String), - Booleen(bool), -} - -impl Variable { - pub fn nom_type(&self) -> String { - match self { - Self::Entier(_) => "entier".into(), - Self::Texte(_) => "texte".into(), - Self::Booleen(_) => "booléen".into(), - } - } -} - -pub enum ErreurSophie { - CommandeInconnue(String), - PhraseVide, - ManqueArgument, - NombreInvalide(String), - BooleenInvalide(String), - TexteInvalide(String), - MauvaisArgument(String), - DesequilibreParenthese, - VariableInconnue(String), - MauvaisType(String, String, String), - ProblemeTerminal(String), - ManquePoint, -} - -impl fmt::Display for ErreurSophie { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {//' - match self { - Self::CommandeInconnue(commande) => write!(f, "La commande \"{}\" est inconnue.", commande), - Self::PhraseVide => write!(f, "La phrase est vide."), - 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::MauvaisArgument(message) => write!(f, "La commande a reçu un mauvais argument, {}.", message), - Self::DesequilibreParenthese => write!(f, "Les parenthèses sont déséquilibrés."), - 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::ProblemeTerminal(probleme) => write!(f, "Problème d'accès terminal : {}.", probleme), - Self::ManquePoint => write!(f, "Il manque un point."), - } - } -} - pub struct Sophie { - variables: HashMap, + variables: HashMap, } impl Sophie { @@ -140,9 +90,9 @@ impl Sophie { }; let contenu = match variable_type.as_str() { - "entier" => Variable::Entier(0), - "texte" => Variable::Texte("".to_string()), - "booléen" => Variable::Booleen(false), + "entier" => Element::Entier(0), + "texte" => Element::Texte("".to_string()), + "booléen" => Element::Booleen(false), _ => return Err(ErreurSophie::MauvaisArgument(format!("type de variable \"{}\" inconnu", variable_type))), }; @@ -154,10 +104,10 @@ impl Sophie { let (variable_nom, contenu) = self.nom_de_variable(arguments, "avec")?; let variable = self.recupere_variable(&variable_nom)?; - let valeur = match variable { - Variable::Entier(_) => Variable::Entier(self.operation(&contenu)?), - Variable::Texte(_) => Variable::Texte(self.texte(&contenu)?), - Variable::Booleen(_) => Variable::Booleen(self.condition(&contenu)?), + let valeur = match variable.type_element() { + TypeElement::Entier => Element::Entier(self.operation(&contenu)?), + TypeElement::Texte => Element::Texte(self.texte(&contenu)?), + TypeElement::Booleen => Element::Booleen(self.condition(&contenu)?), }; self.variables.insert(variable_nom, valeur); @@ -177,17 +127,17 @@ impl Sophie { let contenu = reponse.trim(); - let valeur = match self.variables[&variable_nom] { - Variable::Entier(_) => Variable::Entier(nombre::texte_comme_nombre(contenu)?), - Variable::Texte(_) => Variable::Texte(contenu.into()), - Variable::Booleen(_) => Variable::Booleen(booleen::texte_comme_booleen(contenu)?), + let valeur = match self.variables[&variable_nom].type_element() { + TypeElement::Entier => Element::Entier(nombre::texte_comme_nombre(contenu)?), + TypeElement::Texte => Element::Texte(contenu.into()), + TypeElement::Booleen => Element::Booleen(booleen::texte_comme_booleen(contenu)?) }; self.variables.insert(variable_nom, valeur); Ok(()) } - fn recupere_variable(&self, nom: &str) -> Result { + fn recupere_variable(&self, nom: &str) -> Result { let Some(first_char) = nom.chars().next() else { return Err(ErreurSophie::MauvaisArgument("il n'y a pas de variable".to_string())) }; diff --git a/src/sophie/nombre.rs b/src/sophie/nombre.rs index 58e35b3..10a65f7 100644 --- a/src/sophie/nombre.rs +++ b/src/sophie/nombre.rs @@ -1,6 +1,6 @@ use super::ErreurSophie; use super::Sophie; -use super::Variable; +use super::Element; const NOMS_UNITES: [&str; 10] = ["", "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf"]; const NOMS_UNITES_DIX: [&str; 10] = ["dix", "onze", "douze", "treize", "quatorze", "quinze", "seize", "dix-sept", "dix-huit", "dix-neuf"]; @@ -100,8 +100,8 @@ impl Sophie { pub fn texte_comme_nombre(&self, texte: &str) -> Result { if texte.chars().next().map_or(false, |c| c.is_uppercase()) { if self.variables.contains_key(texte) { - let Variable::Entier(nombre) = self.variables[texte] else { - return Err(ErreurSophie::MauvaisType(texte.into(), self.variables[texte].nom_type(), "entier".into())) + let Element::Entier(nombre) = self.variables[texte] else { + return Err(ErreurSophie::MauvaisType(texte.into(), self.variables[texte].type_element().nom(), "entier".into())) }; return Ok(nombre); } else { diff --git a/src/sophie/structure.rs b/src/sophie/structure.rs new file mode 100644 index 0000000..3f37b97 --- /dev/null +++ b/src/sophie/structure.rs @@ -0,0 +1,105 @@ +use std::fmt; + +pub enum Commande { + Definis(String, TypeElement), + Demande(String), + Modifie(String, Expression), + Affiche(Expression), +} + +#[derive(PartialEq, Debug, Clone)] +pub struct Expression { + type_expression: TypeElement, + contenu: Vec +} + +impl Expression { + fn nouvelle(type_expression: TypeElement) -> Self { + Self { + type_expression, + contenu: vec![] + } + } + fn ajoute(&mut self, element: Element) -> Result<(), ErreurSophie> { + let type_element = element.type_element(); + if self.type_expression != type_element { + return Err(ErreurSophie::MauvaisType("inconnue".into(), type_element.nom(), self.type_expression.nom())) + } + self.contenu.push(element); + Ok(()) + } +} + +#[derive(PartialEq, Debug, Clone)] +pub enum TypeElement { + Entier, + Texte, + Booleen, +} + +impl TypeElement { + pub fn nom(&self) -> String { + match self { + Self::Entier => "entier".into(), + Self::Texte => "texte".into(), + Self::Booleen => "booléen".into(), + } + } +} + +#[derive(PartialEq, Debug, Clone)] +pub enum Element { + Entier(usize), + Texte(String), + Booleen(bool), + Variable(String, TypeElement), + Operateur(String, TypeElement), + Expression(Expression, TypeElement), +} + +impl Element { + pub fn type_element(&self) -> TypeElement { + match self { + Self::Entier(_) => TypeElement::Entier, + Self::Texte(_) => TypeElement::Texte, + Self::Booleen(_) => TypeElement::Booleen, + Self::Variable(_, type_element) => type_element.clone(), + Self::Operateur(_, type_element) => type_element.clone(), + Self::Expression(_, type_element) => type_element.clone(), + } + } +} + +pub enum ErreurSophie { + CommandeInconnue(String), + PhraseVide, + ManqueArgument, + NombreInvalide(String), + BooleenInvalide(String), + TexteInvalide(String), + MauvaisArgument(String), + DesequilibreParenthese, + VariableInconnue(String), + MauvaisType(String, String, String), + ProblemeTerminal(String), + ManquePoint, +} + +impl fmt::Display for ErreurSophie { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {//' + match self { + Self::CommandeInconnue(commande) => write!(f, "La commande \"{}\" est inconnue.", commande), + Self::PhraseVide => write!(f, "La phrase est vide."), + 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::MauvaisArgument(message) => write!(f, "La commande a reçu un mauvais argument, {}.", message), + Self::DesequilibreParenthese => write!(f, "Les parenthèses sont déséquilibrés."), + 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::ProblemeTerminal(probleme) => write!(f, "Problème d'accès terminal : {}.", probleme), + Self::ManquePoint => write!(f, "Il manque un point."), + } + } +} \ No newline at end of file diff --git a/src/sophie/tests.rs b/src/sophie/tests.rs index bea733d..57e2ef6 100644 --- a/src/sophie/tests.rs +++ b/src/sophie/tests.rs @@ -36,10 +36,10 @@ fn teste_somme() { #[test] fn teste_definition_variable() { let mut sophie = Sophie::new(); - let resultat = sophie.execute_phrase("Définie Variable comme entier"); + let resultat = sophie.execute_phrase("Définis Element comme entier"); match resultat { Ok(_) => { - assert_eq!(sophie.variables["Variable"], Variable::Entier(0), "Variable mal définie"); + assert_eq!(sophie.variables["Element"], Element::Entier(0), "Element mal définie"); } Err(raison) => { panic!("Définition de variable échouée : {}", raison); @@ -50,14 +50,14 @@ fn teste_definition_variable() { #[test] fn teste_modification_variable() { let mut sophie = Sophie::new(); - if let Err(raison) = sophie.execute_phrase("Définie Variable comme entier") { + if let Err(raison) = sophie.execute_phrase("Définis Element comme entier") { panic!("Définition de variable échouée : {}", raison); } let a = 2345678; - let resultat = sophie.execute_phrase(&format!("Modifie Variable avec {} ", nombre::nombre_comme_texte(a))); + let resultat = sophie.execute_phrase(&format!("Modifie Element avec {} ", nombre::nombre_comme_texte(a))); match resultat { Ok(_) => { - assert_eq!(sophie.variables["Variable"], Variable::Entier(a), "Variable mal modifiée"); + assert_eq!(sophie.variables["Element"], Element::Entier(a), "Element mal modifiée"); } Err(raison) => { panic!("Modification de variable échouée : {}", raison); @@ -68,15 +68,15 @@ fn teste_modification_variable() { #[test] fn teste_operation_variable() { let mut sophie = Sophie::new(); - if let Err(raison) = sophie.execute_phrase("Définie Variable comme entier") { + if let Err(raison) = sophie.execute_phrase("Définis Element comme entier") { panic!("Définition de variable échouée : {}", raison); } let a = 2345678; - if let Err(raison) = sophie.execute_phrase(&format!("Modifie Variable avec {} ", nombre::nombre_comme_texte(a))) { + if let Err(raison) = sophie.execute_phrase(&format!("Modifie Element avec {} ", nombre::nombre_comme_texte(a))) { panic!("Modification de variable échouée : {}", raison); } let b = 987654; - let resultat = sophie.operation(&format!("Variable plus {}", nombre::nombre_comme_texte(b))); + let resultat = sophie.operation(&format!("Element plus {}", nombre::nombre_comme_texte(b))); match resultat { Ok(nombre) => { assert_eq!(nombre, a+b, "Echec de la somme d'un entier et d'une variable, attendais {}, a reçu {}", a+b, nombre); @@ -114,14 +114,14 @@ fn teste_maths() { #[test] fn teste_texte() { let mut sophie = Sophie::new(); - if let Err(raison) = sophie.execute_phrase("Définie A comme entier") { + if let Err(raison) = sophie.execute_phrase("Définis A comme entier") { panic!("Définition de variable échouée : {}", raison); } let a = 2345678; if let Err(raison) = sophie.execute_phrase(&format!("Modifie A avec {} ", nombre::nombre_comme_texte(a))) { panic!("Modification de variable échouée : {}", raison); } - if let Err(raison) = sophie.execute_phrase("Définie B comme texte") { + if let Err(raison) = sophie.execute_phrase("Définis B comme texte") { panic!("Définition de variable échouée : {}", raison); } if let Err(raison) = sophie.execute_phrase("Modifie B avec \"hello there\", \" general\", \" Kenobi\"") { @@ -140,14 +140,14 @@ fn teste_texte() { #[test] fn teste_redefinition_variable() { let mut sophie = Sophie::new(); - if let Err(raison) = sophie.execute_phrase("Définie Variable comme entier") { + if let Err(raison) = sophie.execute_phrase("Définis Element comme entier") { panic!("Définition de variable échouée : {}", raison); }; - let Err(raison) = sophie.execute_phrase("Définie Variable comme texte") else { + let Err(raison) = sophie.execute_phrase("Définis Element comme texte") else { panic!("Ne devrais pas pouvoir redéfinir une variable"); }; if let ErreurSophie::MauvaisArgument(ref texte) = raison { - assert_eq!(texte, "la variable \"Variable\" existe déjà", "Définition échouée avec erreur imprévue : {}", raison); + assert_eq!(texte, "la variable \"Element\" existe déjà", "Définition échouée avec erreur imprévue : {}", raison); } else { panic!("Définition échouée avec erreur imprévue : {}", raison); } @@ -156,12 +156,12 @@ fn teste_redefinition_variable() { #[test] fn teste_echec_modification() { let mut sophie = Sophie::new(); - let resultat = sophie.execute_phrase("Modifie Variable avec deux"); + let resultat = sophie.execute_phrase("Modifie Element avec deux"); let Err(raison) = resultat else { panic!("Ne devrais pas pouvoir modifier une variable non définie"); }; if let ErreurSophie::VariableInconnue(nom) = raison { - assert_eq!(nom, "Variable", "Mauvais nom de variable reconnu : {}", nom); + assert_eq!(nom, "Element", "Mauvais nom de variable reconnu : {}", nom); } else { panic!("Modification échouée avec erreur imprévue : {}", raison); } @@ -170,7 +170,7 @@ fn teste_echec_modification() { #[test] fn teste_majuscule_variable() { let mut sophie = Sophie::new(); - let resultat = sophie.execute_phrase("Définie variable comme entier"); + let resultat = sophie.execute_phrase("Définis variable comme entier"); let Err(raison) = resultat else { panic!("Ne devrais pas pouvoir definir une variable sans majuscule"); }; @@ -184,7 +184,7 @@ fn teste_majuscule_variable() { #[test] fn teste_point_phrase() { let mut sophie = Sophie::new(); - let resultat = sophie.execute("Définie Variable comme entier".into()); + let resultat = sophie.execute("Définis Element comme entier".into()); let Err(raison) = resultat else { panic!("Ne devrais pas pouvoir faire de commande sans point à la fin"); }; diff --git a/src/sophie/texte.rs b/src/sophie/texte.rs index be404f4..1a4a4cf 100644 --- a/src/sophie/texte.rs +++ b/src/sophie/texte.rs @@ -1,6 +1,6 @@ use super::Sophie; use super::ErreurSophie; -use super::Variable; +use super::Element; use super::nombre; use super::booleen; @@ -33,8 +33,8 @@ impl Sophie { let variable = self.recupere_variable(argument)?; - let Variable::Texte(contenu) = variable else { - return Err(ErreurSophie::MauvaisType(argument.into(), variable.nom_type(), "texte".into())) + let Element::Texte(contenu) = variable else { + return Err(ErreurSophie::MauvaisType(argument.into(), variable.type_element().nom(), "texte".into())) }; texte += &contenu;