commentaires, et verification d'expression booleenne

This commit is contained in:
WanderingPenwing 2024-12-11 17:52:25 +01:00
parent 3d0e04f4fb
commit ec8fa1bcf8
9 changed files with 115 additions and 58 deletions

View file

@ -1,2 +1 @@
{"categories":[{"name":"todo","content":[{"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":"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":"parenthese comparaison","description":"// Hello there","id":1},{"name":"test comparaison","description":"// Hello there","id":4}]},{"name":"bug","content":[]},{"name":"to test","content":[]},{"name":"bonus","content":[{"name":"stop cheating with \"-\"","description":"// Hello there","id":5}]},{"name":"+","content":[]}]} {"categories":[{"name":"todo","content":[{"name":"test correct error","description":"manque point\nmauvaise expression mathematique","id":3},{"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":"parenthese comparaison","description":"// Hello there","id":1},{"name":"test comparaison","description":"// Hello there","id":4},{"name":"error ligne compilation","description":"// Hello there","id":2},{"name":"commentaires","description":"// Hello there","id":3},{"name":"compile time verification","description":"odre des termes rpn","id":1}]},{"name":"bug","content":[]},{"name":"to test","content":[]},{"name":"bonus","content":[{"name":"stop cheating with \"-\"","description":"// Hello there","id":5},{"name":"affiche ligne et position erreur","description":"// Hello there","id":1}]},{"name":"+","content":[]}]}

View file

@ -1,5 +1,6 @@
use std::env; use std::env;
use std::fs; use std::fs;
use std::time::Instant;
mod pendragon; mod pendragon;
use pendragon::*; use pendragon::*;
@ -17,22 +18,34 @@ fn main() {
let chemin_de_fichier = &arguments[1]; let chemin_de_fichier = &arguments[1];
let mut pendragon = Pendragon::nouveau(); let mut pendragon = Pendragon::nouveau();
match fs::read_to_string(chemin_de_fichier) { let lecture = fs::read_to_string(chemin_de_fichier);
Ok(contenu) => {
let Ok(_) = pendragon.compile(contenu) else { if let Err(raison) = lecture {
eprintln!("\n# Échec de la compilation"); eprintln!("Fichier illisible : {}", raison);
return return
};
if debug_mode {
println!("{}\n", pendragon.programme);
}
if let Err(raison) = pendragon.programme.execute() {
eprintln!("Erreur Execution : {}", raison);
return
}
}
Err(raison) => {
eprintln!("Fichier illisible : {}", raison);
}
} }
println!("# Compilation de '{}'.", chemin_de_fichier);
let debut = Instant::now();
if let Err(raison) = pendragon.compile(lecture.unwrap()) {
eprintln!("\n{}", raison);
eprintln!("\n# Échec de la compilation.");
return
}
println!("# Compilation Ok. ({:.2?})\n", debut.elapsed());
if debug_mode {
println!("{}\n", pendragon.programme);
}
println!("# Exécution de '{}'.\n", chemin_de_fichier);
let debut = Instant::now();
if let Err(raison) = pendragon.programme.execute() {
eprintln!("\nErreur : {}", raison);
eprintln!("\n# Échec de l'exécution.");
return
}
println!("\n# Exécution Ok. ({:.2?})", debut.elapsed());
} }

View file

@ -383,7 +383,7 @@ mod test {
nombre::nombre_comme_texte(e), nombre::nombre_comme_texte(e),
)); ));
let bonne_reponse = !((6+a) > 2*b) && (c/2 < (d-1) || !(e == 2)); let bonne_reponse = !((6+a) > 2*b) && (c/2 < (d-1) || !(e == 2));
match possible_expression{ match possible_expression {
Ok(expression) => { Ok(expression) => {
match calcule_booleen(expression.clone(), &HashMap::new()) { match calcule_booleen(expression.clone(), &HashMap::new()) {
Ok(booleen) => { Ok(booleen) => {

View file

@ -1,6 +1,27 @@
use std::fmt; use std::fmt;
use super::*; use super::*;
pub struct ErreurCompilation {
index_ligne: usize,
erreur: ErreurPendragon,
}
impl ErreurCompilation {
pub fn nouvelle(index_ligne: usize, erreur: ErreurPendragon) -> Self {
Self {
index_ligne,
erreur,
}
}
}
impl fmt::Display for ErreurCompilation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {//'
write!(f, "Erreur ligne {} : {}", self.index_ligne + 1, self.erreur)
}
}
pub enum ErreurPendragon { pub enum ErreurPendragon {
CommandeInconnue(String), CommandeInconnue(String),
ManqueArgument, ManqueArgument,
@ -11,7 +32,7 @@ pub enum ErreurPendragon {
MauvaisArgument(String), MauvaisArgument(String),
VariableInconnue(String), VariableInconnue(String),
MauvaisType(String, String, String), MauvaisType(String, String, String),
ManquePoint, ManquePonctuation,
Lecture(String), Lecture(String),
CalculBooleen(String), CalculBooleen(String),
CalculEntier(String), CalculEntier(String),
@ -29,7 +50,7 @@ impl fmt::Display for ErreurPendragon {
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 {} 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::ManquePonctuation => write!(f, "Il manque la ponctuation de la phrase."),
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),
Self::CalculEntier(raison) => write!(f, "Calcul entier échoué, {}.", raison), Self::CalculEntier(raison) => write!(f, "Calcul entier échoué, {}.", raison),

View file

@ -1,5 +1,4 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::time::Instant;
pub mod nombre; pub mod nombre;
pub mod texte; pub mod texte;
@ -20,38 +19,42 @@ impl Pendragon {
} }
} }
pub fn compile(&mut self, contenu: String) -> Result<(), ErreurPendragon> { pub fn compile(&mut self, contenu: String) -> Result<(), ErreurCompilation> {
println!(); let texte: Vec<&str> = contenu.split('\n').collect();
let debut = Instant::now(); for (index_ligne, ligne) in texte.iter().enumerate() {
let contenu_propre = contenu.replace("\n", " "); let ligne = ligne.trim();
let mut texte: Vec<&str> = contenu_propre.split('.').collect(); let phrases: Vec<&str> = ligne.split_inclusive(|c| c == ',' || c == '.').collect();
let reste = texte.pop(); let Some(derniere_phrase) = phrases.last() else {
if reste != Some("") { continue
eprintln!("Erreur Compilation, phrase {} : Il manque un point.", texte.len() + 1); };
return Err(ErreurPendragon::ManquePoint) if !derniere_phrase.ends_with('.') && !derniere_phrase.ends_with(',') {
} return Err(ErreurCompilation::nouvelle(index_ligne, ErreurPendragon::ManquePonctuation))
for (index_phrase, phrase) in texte.iter().enumerate() { }
let phrase = phrase.trim(); for phrase in phrases {
match self.compile_phrase(phrase) { if phrase.ends_with(".") {
Ok(commande) => {self.programme.ajoute_commande(commande)}, if phrase.starts_with("Nota Bene :") {
Err(raison) => { continue
eprintln!("Erreur phrase {} : {}", index_phrase + 1, raison); }
return Err(raison) match self.compile_commande(&phrase[..phrase.len() - 1]) {
Ok(commande) => self.programme.ajoute_commande(commande),
Err(raison) => return Err(ErreurCompilation::nouvelle(index_ligne, raison)),
}
continue;
} }
println!("todo : {}", phrase);
} }
} }
println!("# Compilation Ok. ({:.2?})\n", debut.elapsed());
Ok(()) Ok(())
} }
fn compile_phrase(&mut self, phrase: &str) -> Result<Commande, ErreurPendragon> { fn compile_commande(&mut self, phrase: &str) -> Result<Commande, ErreurPendragon> {
let phrase = phrase.trim(); let phrase = phrase.trim();
let parties: Vec<&str> = phrase.splitn(2, ' ').collect(); let parties: Vec<&str> = phrase.splitn(2, ' ').collect();
if parties.len() == 1 { if parties.len() == 1 {
return Err(ErreurPendragon::ManqueArgument) return Err(ErreurPendragon::ManqueArgument)
} }
if parties[1].contains("Définis") || parties[1].contains("Modifie") || parties[1].contains("Affiche") || parties[1].contains("Demande") { if parties[1].contains("Définis") || parties[1].contains("Modifie") || parties[1].contains("Affiche") || parties[1].contains("Demande") {
return Err(ErreurPendragon::ManquePoint) return Err(ErreurPendragon::ManquePonctuation)
} }
match parties[0] { match parties[0] {
"Définis" => self.definis(parties[1]), "Définis" => self.definis(parties[1]),

View file

@ -15,6 +15,7 @@ impl Pendragon {
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 precede_par_operation: bool = true;
for element in elements_texte { for element in elements_texte {
match element { match element {
@ -58,24 +59,43 @@ impl Pendragon {
} }
pile_operateurs.push(Operateur::Divise); pile_operateurs.push(Operateur::Divise);
} }
"ouvre-la-parenthese" => pile_operateurs.push(Operateur::ParentheseEntier), "ouvre-la-parenthese" => {
if !precede_par_operation {
return Err(ErreurPendragon::CalculEntier("il manque un opérateur avant l'ouverture de parenthèse".into()))
}
pile_operateurs.push(Operateur::ParentheseEntier);
continue
}
"ferme-la-parenthese" => { "ferme-la-parenthese" => {
if precede_par_operation {
return Err(ErreurPendragon::CalculEntier("il manque un nombre avant la fermeture de parenthèse".into()))
}
while let Some(operateur) = pile_operateurs.pop() { while let Some(operateur) = pile_operateurs.pop() {
if operateur == Operateur::ParentheseEntier { if operateur == Operateur::ParentheseEntier {
break; break;
} }
expression.push(Element::Operateur(operateur)); expression.push(Element::Operateur(operateur));
} }
continue
} }
autre => { autre => {
if !precede_par_operation {
return Err(ErreurPendragon::CalculEntier(format!("il manque un opérateur avant le nombre '{}'", autre)))
}
precede_par_operation = false;
if format_de_variable(autre) { if format_de_variable(autre) {
self.programme.variable_est_de_type(autre, TypeElement::Entier)?; self.programme.variable_est_de_type(autre, TypeElement::Entier)?;
expression.push(Element::Variable(autre.into(), TypeElement::Entier)); expression.push(Element::Variable(autre.into(), TypeElement::Entier));
} else { } else {
expression.push(texte_comme_nombre(autre)?); expression.push(texte_comme_nombre(autre)?);
} }
continue;
} }
} }
if precede_par_operation {
return Err(ErreurPendragon::CalculEntier(format!("il manque un nombre avant l'opérateur '{}'", element)))
}
precede_par_operation = true;
} }
while let Some(operateur) = pile_operateurs.pop() { while let Some(operateur) = pile_operateurs.pop() {
@ -124,6 +144,9 @@ pub fn calcule_nombre(expression: Vec<Element>, variables: &HashMap<String, Elem
pile.push(nombre_b + nombre_a); pile.push(nombre_b + nombre_a);
} }
Operateur::Moins => { Operateur::Moins => {
if nombre_b < nombre_a {
return Err(ErreurPendragon::CalculEntier(format!("a essayé de soustraire {} à {}", nombre_a, nombre_b)))
}
pile.push(nombre_b - nombre_a); pile.push(nombre_b - nombre_a);
} }
Operateur::Fois => { Operateur::Fois => {

View file

@ -1,6 +1,5 @@
use std::io; use std::io;
use std::collections::HashMap; use std::collections::HashMap;
use std::time::Instant;
use super::*; use super::*;
@ -54,8 +53,6 @@ impl Programme {
} }
pub fn execute(&self) -> Result<(), ErreurPendragon> { pub fn execute(&self) -> Result<(), ErreurPendragon> {
let debut = Instant::now();
println!("# Execution...\n");
let mut variables_globales: HashMap<String, Element> = HashMap::new(); let mut variables_globales: HashMap<String, Element> = HashMap::new();
for commande in &self.commandes { for commande in &self.commandes {
match commande { match commande {
@ -79,7 +76,6 @@ impl Programme {
} }
} }
} }
println!("\n# Exécution Ok. ({:.2?})", debut.elapsed());
Ok(()) Ok(())
} }
} }

View file

@ -4,7 +4,7 @@ impl Pendragon {
pub fn elements_texte(&self, arguments: &str) -> Result<Vec<Element>, ErreurPendragon> { pub fn elements_texte(&self, arguments: &str) -> Result<Vec<Element>, ErreurPendragon> {
let mut expression: Vec<Element> = Vec::new(); let mut expression: Vec<Element> = Vec::new();
for argument in arguments.split(',').map(|arg| arg.trim()) { for argument in arguments.split("puis").map(|arg| arg.trim()) {
if expression.len() > 0 { if expression.len() > 0 {
expression.push(Element::Operateur(Operateur::Virgule)); expression.push(Element::Operateur(Operateur::Virgule));
} }
@ -93,7 +93,7 @@ mod test {
let a = 2345678; let a = 2345678;
let b = 987654; let b = 987654;
let possible_expression = pendragon.elements_texte(&format!("\"hello\", {} fois {}, \"there\", vrai ou faux", let possible_expression = pendragon.elements_texte(&format!("\"hello\" puis {} fois {} puis \"there\" puis vrai ou faux",
nombre::nombre_comme_texte(a), nombre::nombre_comme_texte(a),
nombre::nombre_comme_texte(b))); nombre::nombre_comme_texte(b)));
match possible_expression { match possible_expression {

16
test.dr
View file

@ -1,8 +1,10 @@
Affiche soixante-dix. Définis A comme entier.
Affiche soixante-et-onze. Définis B comme entier.
<<<<<<< HEAD Définis C comme entier.
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. Nota Bene : A est la variable pour un polynôme.
=======
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.
>>>>>>> main Modifie A avec dix-sept.
Demande C.
Modifie B avec trois fois A fois A plus deux fois A plus C.
Affiche "Résultat : " puis B.