variables
This commit is contained in:
parent
8275503f9d
commit
5d100ec8f7
251
src/main.rs
251
src/main.rs
|
@ -1,14 +1,16 @@
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
mod nombres;
|
mod nombres;
|
||||||
|
|
||||||
enum ErreurSophie {
|
enum ErreurSophie {
|
||||||
CommandeInconnue(String),
|
CommandeInconnue(String),
|
||||||
PhraseVide,
|
PhraseVide,
|
||||||
ManqueArgument,
|
ManqueArgument(String),
|
||||||
OrthographeNombre(String),
|
OrthographeNombre(String),
|
||||||
|
MauvaisArgument(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ErreurSophie {
|
impl fmt::Display for ErreurSophie {
|
||||||
|
@ -16,12 +18,131 @@ impl fmt::Display for ErreurSophie {
|
||||||
match self {
|
match self {
|
||||||
Self::CommandeInconnue(commande) => write!(f, "La commande \"{}\" est inconnue.", commande),
|
Self::CommandeInconnue(commande) => write!(f, "La commande \"{}\" est inconnue.", commande),
|
||||||
Self::PhraseVide => write!(f, "La phrase est vide."),
|
Self::PhraseVide => write!(f, "La phrase est vide."),
|
||||||
Self::ManqueArgument => write!(f, "Il manque un argument."),
|
Self::ManqueArgument(commande) => write!(f, "Il manque un argument pour \"{}\".", commande),
|
||||||
Self::OrthographeNombre(nombre) => write!(f, "Le nombre \"{}\" est mal orthographié.", nombre),
|
Self::OrthographeNombre(nombre) => write!(f, "Le nombre \"{}\" est mal orthographié.", nombre),
|
||||||
|
Self::MauvaisArgument(message) => write!(f, "La commande a reçu un mauvais argument, {}.", message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Sophie {
|
||||||
|
variables: HashMap<String, usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sophie {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
variables: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn execute(&mut self, contenu: String) {
|
||||||
|
let contenu_propre = contenu.replace("\n", "");
|
||||||
|
let mut texte: Vec<&str> = contenu_propre.split('.').collect();
|
||||||
|
texte.pop(); // remove empty phrase after last dot
|
||||||
|
for (index_phrase, phrase) in texte.iter().enumerate() {
|
||||||
|
match self.execute_phrase(phrase) {
|
||||||
|
Ok(_) => {},
|
||||||
|
Err(raison) => {
|
||||||
|
eprintln!("Erreur phrase {} : {}", index_phrase + 1, raison);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute_phrase(&mut self, phrase: &str) -> Result<(), ErreurSophie> {
|
||||||
|
let phrase = phrase.trim();
|
||||||
|
let parties: Vec<&str> = phrase.splitn(2, ' ').collect();
|
||||||
|
|
||||||
|
if parties.is_empty() {
|
||||||
|
return Err(ErreurSophie::PhraseVide)
|
||||||
|
}
|
||||||
|
|
||||||
|
if parties.len() == 1 {
|
||||||
|
return Err(ErreurSophie::ManqueArgument(parties[0].to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
match parties[0] {
|
||||||
|
"Modifie" => {
|
||||||
|
self.modifie(parties[1])?;
|
||||||
|
},
|
||||||
|
"Affiche" => {
|
||||||
|
self.affiche(parties[1])?;
|
||||||
|
},
|
||||||
|
"Demande" => {
|
||||||
|
self.demande(parties[1])?;
|
||||||
|
}
|
||||||
|
autre_commande => {
|
||||||
|
return Err(ErreurSophie::CommandeInconnue(autre_commande.to_string()))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn modifie(&mut self, arguments: &str) -> Result<(), ErreurSophie> {
|
||||||
|
let parties: Vec<&str> = arguments.splitn(2, "avec").collect();
|
||||||
|
if parties.len() == 1 {
|
||||||
|
return Err(ErreurSophie::ManqueArgument(format!("Modifie {}", parties[0])))
|
||||||
|
}
|
||||||
|
let variable: String = parties[0].trim().to_string();
|
||||||
|
|
||||||
|
let Some(first_char) = variable.chars().next() else {
|
||||||
|
return Err(ErreurSophie::MauvaisArgument("il n'y a pas de variable pour la commande Modifie".to_string()))
|
||||||
|
};
|
||||||
|
if !first_char.is_uppercase() {
|
||||||
|
return Err(ErreurSophie::MauvaisArgument("il manque une majuscule à la variable pour la commande Modifie".to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
let valeur = self.operation(parties[1].trim())?;
|
||||||
|
self.variables.insert(variable, valeur);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn affiche(&self, arguments: &str) -> Result<(), ErreurSophie> {
|
||||||
|
let liste_arguments: Vec<&str> = arguments.split(',').collect();
|
||||||
|
|
||||||
|
let mut texte = "".to_string();
|
||||||
|
|
||||||
|
for argument in liste_arguments {
|
||||||
|
let argument: &str = argument.trim();
|
||||||
|
if argument.starts_with('"') {
|
||||||
|
if argument.ends_with('"') {
|
||||||
|
texte += &argument[1..argument.len()-1];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let resultat = self.operation(argument)?;
|
||||||
|
texte += &nombres::nombre_comme_texte(resultat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("{}", texte);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn demande(&self, arguments: &str) -> Result<(), ErreurSophie> {
|
||||||
|
println!("- demande : {}", arguments);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn operation(&self, arguments: &str) -> Result<usize, ErreurSophie> {
|
||||||
|
let somme_texte: Vec<&str> = arguments.split("plus").collect();
|
||||||
|
let mut somme : usize = 0;
|
||||||
|
for element in somme_texte {
|
||||||
|
let element_propre: &str = element.trim();
|
||||||
|
let Some(first_char) = element_propre.chars().next() else {
|
||||||
|
return Err(ErreurSophie::MauvaisArgument("il y a un argument vide pour l'operation".to_string()))
|
||||||
|
};
|
||||||
|
let nombre = if first_char.is_uppercase() {
|
||||||
|
self.variables[element_propre]
|
||||||
|
} else {
|
||||||
|
nombres::texte_comme_nombre(element_propre)?
|
||||||
|
};
|
||||||
|
somme += nombre;
|
||||||
|
}
|
||||||
|
Ok(somme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let arguments: Vec<String> = env::args().collect();
|
let arguments: Vec<String> = env::args().collect();
|
||||||
|
|
||||||
|
@ -31,10 +152,11 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
let chemin_de_fichier = &arguments[1];
|
let chemin_de_fichier = &arguments[1];
|
||||||
|
let mut sophie = Sophie::new();
|
||||||
|
|
||||||
match fs::read_to_string(chemin_de_fichier) {
|
match fs::read_to_string(chemin_de_fichier) {
|
||||||
Ok(contenu) => {
|
Ok(contenu) => {
|
||||||
execute(contenu);
|
sophie.execute(contenu);
|
||||||
}
|
}
|
||||||
Err(raison) => {
|
Err(raison) => {
|
||||||
eprintln!("Fichier illisible : {}", raison);
|
eprintln!("Fichier illisible : {}", raison);
|
||||||
|
@ -42,80 +164,6 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(contenu: String) {
|
|
||||||
let contenu_propre = contenu.replace("\n", "");
|
|
||||||
let mut texte: Vec<&str> = contenu_propre.split('.').collect();
|
|
||||||
texte.pop(); // remove empty phrase after last dot
|
|
||||||
for (index_phrase, phrase) in texte.iter().enumerate() {
|
|
||||||
match execute_phrase(phrase) {
|
|
||||||
Ok(_) => {},
|
|
||||||
Err(raison) => {
|
|
||||||
eprintln!("Erreur phrase {} : {}", index_phrase + 1, raison);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn execute_phrase(phrase: &str) -> Result<(), ErreurSophie> {
|
|
||||||
let phrase = phrase.trim();
|
|
||||||
let parties: Vec<&str> = phrase.splitn(2, ' ').collect();
|
|
||||||
|
|
||||||
if parties.is_empty() {
|
|
||||||
return Err(ErreurSophie::PhraseVide)
|
|
||||||
}
|
|
||||||
|
|
||||||
if parties.len() == 1 {
|
|
||||||
return Err(ErreurSophie::ManqueArgument)
|
|
||||||
}
|
|
||||||
|
|
||||||
match parties[0] {
|
|
||||||
"Modifie" => {
|
|
||||||
modifie(parties[1])?;
|
|
||||||
},
|
|
||||||
"Affiche" => {
|
|
||||||
affiche(parties[1])?;
|
|
||||||
},
|
|
||||||
"Demande" => {
|
|
||||||
demande(parties[1])?;
|
|
||||||
}
|
|
||||||
autre_commande => {
|
|
||||||
return Err(ErreurSophie::CommandeInconnue(autre_commande.to_string()))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn modifie(arguments: &str) -> Result<(), ErreurSophie> {
|
|
||||||
println!("- modifie : {}", arguments);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn affiche(arguments: &str) -> Result<(), ErreurSophie> {
|
|
||||||
let liste_arguments: Vec<&str> = arguments.split(',').collect();
|
|
||||||
|
|
||||||
let mut texte = "".to_string();
|
|
||||||
|
|
||||||
for argument in liste_arguments {
|
|
||||||
let argument: &str = argument.trim();
|
|
||||||
if argument.starts_with('"') {
|
|
||||||
if argument.ends_with('"') {
|
|
||||||
texte += &argument[1..argument.len()-1];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let resultat = nombres::operation(argument)?;
|
|
||||||
texte += &nombres::nombre_comme_texte(resultat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("{}", texte);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn demande(arguments: &str) -> Result<(), ErreurSophie> {
|
|
||||||
println!("- demande : {}", arguments);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)] // Compile and run only during testing
|
#[cfg(test)] // Compile and run only during testing
|
||||||
|
@ -129,10 +177,10 @@ mod tests {
|
||||||
let texte = nombres::nombre_comme_texte(*i); // Convert number to text
|
let texte = nombres::nombre_comme_texte(*i); // Convert number to text
|
||||||
match nombres::texte_comme_nombre(&texte) { // Convert text back to number
|
match nombres::texte_comme_nombre(&texte) { // Convert text back to number
|
||||||
Ok(nombre) => {
|
Ok(nombre) => {
|
||||||
assert_eq!(*i, nombre, "Mismatch for number: {}, text: {}", i, texte);
|
assert_eq!(*i, nombre, "Nombre inexact : {}, texte : {}", i, texte);
|
||||||
}
|
}
|
||||||
Err(raison) => {
|
Err(raison) => {
|
||||||
panic!("Conversion failed for number: {} with error: {}", i, raison);
|
panic!("Conversion échouée pour : {}, avec l'erreur : {}", i, raison);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,18 +188,55 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn teste_somme() {
|
fn teste_somme() {
|
||||||
for (a, b) in [(5, 7), (1467,45678), (1001, 0), (72_036_854_775_807usize, 14_036_567_775_807usize)] {
|
for (a, b) in [(0, 0), (5, 7), (1467,45678), (1001, 0), (72_036_854_775_807usize, 14_036_567_775_807usize)] {
|
||||||
let texte_a = nombres::nombre_comme_texte(a);
|
let texte_a = nombres::nombre_comme_texte(a);
|
||||||
let texte_b = nombres::nombre_comme_texte(b);
|
let texte_b = nombres::nombre_comme_texte(b);
|
||||||
let resultat = nombres::operation(&format!("{} plus {}", texte_a, texte_b));
|
let sophie = Sophie::new();
|
||||||
|
let resultat = sophie.operation(&format!("{} plus {}", texte_a, texte_b));
|
||||||
match resultat { // Convert text back to number
|
match resultat { // Convert text back to number
|
||||||
Ok(nombre) => {
|
Ok(nombre) => {
|
||||||
assert_eq!(a+b, nombre, "Mismatch for {}+{}, got: {}", a, b, nombre);
|
assert_eq!(a+b, nombre, "Résultat inexact pour {}+{} : {}", a, b, nombre);
|
||||||
}
|
}
|
||||||
Err(raison) => {
|
Err(raison) => {
|
||||||
panic!("Conversion failed for number: ({},{}) with error: {}", a, b, raison);
|
panic!("Conversion échouée pour : ({},{}), avec l'erreur : {}", a, b, raison);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn teste_initialisation_variable() {
|
||||||
|
let mut sophie = Sophie::new();
|
||||||
|
let phrase = "Modifie Variable avec trois plus cent-deux";
|
||||||
|
let resultat = sophie.execute_phrase(phrase);
|
||||||
|
match resultat {
|
||||||
|
Ok(_) => {
|
||||||
|
assert_eq!(sophie.variables["Variable"], 105, "Echec d'initialisation de variable");
|
||||||
|
}
|
||||||
|
Err(raison) => {
|
||||||
|
panic!("Execution échouée pour \"{}\", avec l'erreur : {}", phrase, raison);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn teste_operation_variable() {
|
||||||
|
let mut sophie = Sophie::new();
|
||||||
|
let a = 2345678;
|
||||||
|
let b = 987654;
|
||||||
|
let phrase = format!("Modifie Variable avec {}", nombres::nombre_comme_texte(a));
|
||||||
|
if let Err(raison) = sophie.execute_phrase(&phrase) {
|
||||||
|
panic!("Execution échouée pour \"{}\", avec l'erreur : {}", phrase, raison);
|
||||||
|
}
|
||||||
|
let resultat = sophie.operation(&format!("Variable plus {}", nombres::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);
|
||||||
|
}
|
||||||
|
Err(raison) => {
|
||||||
|
panic!("Execution échouée pour \"Variable plus {}\", avec l'erreur : {}", nombres::nombre_comme_texte(b), raison);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,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 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 {
|
let unité_union = if nombre - unité > 0 && unité > 0 && nombre > 16 {
|
||||||
UNION.to_string()
|
UNION.to_string()
|
||||||
} else {
|
} else {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
|
@ -93,7 +93,6 @@ fn petit_nombre_comme_texte(nombre: usize) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn texte_comme_nombre(texte: &str) -> Result<usize, ErreurSophie> {
|
pub fn texte_comme_nombre(texte: &str) -> Result<usize, ErreurSophie> {
|
||||||
println!("texte:{}", texte);
|
|
||||||
if texte == "zéro" {
|
if texte == "zéro" {
|
||||||
return Ok(0)
|
return Ok(0)
|
||||||
}
|
}
|
||||||
|
@ -124,7 +123,6 @@ pub fn texte_comme_nombre(texte: &str) -> Result<usize, ErreurSophie> {
|
||||||
}
|
}
|
||||||
texte_modifie = texte_separe[1].trim_start_matches(UNION);
|
texte_modifie = texte_separe[1].trim_start_matches(UNION);
|
||||||
}
|
}
|
||||||
println!("{}/{:?}", &texte_modifie, petits_nombres_texte);
|
|
||||||
}
|
}
|
||||||
let petit_nombre_texte = texte_modifie
|
let petit_nombre_texte = texte_modifie
|
||||||
.trim_start_matches(&pluriel)
|
.trim_start_matches(&pluriel)
|
||||||
|
@ -132,8 +130,6 @@ pub fn texte_comme_nombre(texte: &str) -> Result<usize, ErreurSophie> {
|
||||||
.trim_end_matches(UNION);
|
.trim_end_matches(UNION);
|
||||||
petits_nombres_texte.push(petit_nombre_texte);
|
petits_nombres_texte.push(petit_nombre_texte);
|
||||||
|
|
||||||
println!("ptn:{:?}", petits_nombres_texte);
|
|
||||||
|
|
||||||
let mut nombre: usize = 0;
|
let mut nombre: usize = 0;
|
||||||
|
|
||||||
for (index, petit_nombre_texte) in petits_nombres_texte.iter().enumerate() {
|
for (index, petit_nombre_texte) in petits_nombres_texte.iter().enumerate() {
|
||||||
|
@ -203,13 +199,3 @@ fn texte_comme_petit_nombre(texte: &str) -> Result<usize, ErreurSophie> {
|
||||||
|
|
||||||
Ok(nombre)
|
Ok(nombre)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn operation(arguments: &str) -> Result<usize, ErreurSophie> {
|
|
||||||
let somme_texte: Vec<&str> = arguments.split("plus").collect();
|
|
||||||
let mut somme : usize = 0;
|
|
||||||
for element in somme_texte {
|
|
||||||
let element_propre: &str = element.trim();
|
|
||||||
somme += texte_comme_nombre(element_propre)?
|
|
||||||
}
|
|
||||||
Ok(somme)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue