better structuure
This commit is contained in:
parent
797b9991ea
commit
7ad8b8106b
17
src/main.rs
17
src/main.rs
|
@ -12,12 +12,25 @@ fn main() {
|
|||
return
|
||||
}
|
||||
|
||||
let debug_mode = arguments.contains(&"--debug".to_string());
|
||||
|
||||
let chemin_de_fichier = &arguments[1];
|
||||
let mut pendragon = Pendragon::new();
|
||||
let mut pendragon = Pendragon::nouveau();
|
||||
|
||||
match fs::read_to_string(chemin_de_fichier) {
|
||||
Ok(contenu) => {
|
||||
let _ = pendragon.compile(contenu);
|
||||
let Ok(_) = pendragon.compile(contenu) else {
|
||||
eprintln!("Compilation interrompue");
|
||||
return
|
||||
};
|
||||
if debug_mode {
|
||||
println!("{}\n-----------", pendragon.programme);
|
||||
}
|
||||
if let Err(raison) = pendragon.programme.execute() {
|
||||
eprintln!("Erreur Execution : {}", raison);
|
||||
return
|
||||
}
|
||||
println!("\n# Success");
|
||||
}
|
||||
Err(raison) => {
|
||||
eprintln!("Fichier illisible : {}", raison);
|
||||
|
|
|
@ -1,79 +1,119 @@
|
|||
use super::Pendragon;
|
||||
use super::ErreurPendragon;
|
||||
use super::Element;
|
||||
use super::*;
|
||||
|
||||
impl Pendragon {
|
||||
pub fn condition(&self, arguments: &str) -> Result<bool, ErreurPendragon> {
|
||||
self.condition_elementaire(arguments)
|
||||
}
|
||||
pub fn elements_booleen(&self, arguments: &str) -> Result<Vec<Element>, ErreurPendragon> {
|
||||
let texte = arguments
|
||||
.replace("ouvre la parenthèse", "ouvre-la-parenthese")
|
||||
.replace("ferme la parenthèse", "ferme-la-parenthese");
|
||||
let elements_texte: Vec<&str> = texte.split(" ").collect();
|
||||
let mut expression: Vec<Element> = Vec::new();
|
||||
let mut pile_operateurs: Vec<Operateur> = Vec::new();
|
||||
|
||||
pub fn condition_elementaire(&self, texte: &str) -> Result<bool, ErreurPendragon> {
|
||||
let mut expression: Vec<String> = texte.split(" ").map(String::from).collect();
|
||||
|
||||
let mut index = 0;
|
||||
while index < expression.len() {
|
||||
if expression[index] != "non" {
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
if index == expression.len() - 1 {
|
||||
return Err(ErreurPendragon::ManqueArgument);
|
||||
}
|
||||
let a = self.texte_comme_booleen(&expression[index + 1])?;
|
||||
expression[index] = booleen_comme_texte(!a);
|
||||
expression.remove(index + 1);
|
||||
}
|
||||
let mut index = 0;
|
||||
while index < expression.len() {
|
||||
if expression[index] != "et" {
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
if index == 0 || index == expression.len() - 1 {
|
||||
return Err(ErreurPendragon::ManqueArgument);
|
||||
}
|
||||
let a = self.texte_comme_booleen(&expression[index - 1])?;
|
||||
let b = self.texte_comme_booleen(&expression[index + 1])?;
|
||||
index -= 1;
|
||||
expression[index] = booleen_comme_texte(a && b);
|
||||
expression.remove(index + 1);
|
||||
expression.remove(index + 1);
|
||||
}
|
||||
let mut index = 0;
|
||||
while index < expression.len() {
|
||||
if expression[index] != "ou" {
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
if index == 0 || index == expression.len() - 1 {
|
||||
return Err(ErreurPendragon::ManqueArgument);
|
||||
}
|
||||
let a = self.texte_comme_booleen(&expression[index - 1])?;
|
||||
let b = self.texte_comme_booleen(&expression[index + 1])?;
|
||||
index -= 1;
|
||||
expression[index] = booleen_comme_texte(a || b);
|
||||
expression.remove(index + 1);
|
||||
expression.remove(index + 1);
|
||||
}
|
||||
if expression.len() > 1 {
|
||||
return Err(ErreurPendragon::MauvaisArgument("expression booléenne".to_string()))
|
||||
}
|
||||
self.texte_comme_booleen(&expression[0])
|
||||
}
|
||||
|
||||
pub fn texte_comme_booleen(&self, texte: &str) -> Result<bool, ErreurPendragon> {
|
||||
if texte.chars().next().map_or(false, |c| c.is_uppercase()) {
|
||||
if self.variables.contains_key(texte) {
|
||||
let Element::Booleen(booleen) = self.variables[texte] else {
|
||||
return Err(ErreurPendragon::MauvaisType(texte.into(), self.variables[texte].type_element().nom(), "booleen".into()))
|
||||
};
|
||||
return Ok(booleen);
|
||||
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),
|
||||
"et" => {
|
||||
while let Some(operateur) = pile_operateurs.last() {
|
||||
if *operateur == Operateur::Non || *operateur == Operateur::Et {
|
||||
expression.push(Element::Operateur(pile_operateurs.pop().unwrap()));
|
||||
} else {
|
||||
return Err(ErreurPendragon::VariableInconnue(texte.to_string()))
|
||||
break;
|
||||
}
|
||||
}
|
||||
texte_comme_booleen(texte)
|
||||
pile_operateurs.push(Operateur::Et);
|
||||
}
|
||||
"ou" => {
|
||||
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()));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
pile_operateurs.push(Operateur::Ou);
|
||||
}
|
||||
"ouvre-la-parenthese" => pile_operateurs.push(Operateur::ParentheseBooleen),
|
||||
"ferme-la-parenthese" => {
|
||||
while let Some(operateur) = pile_operateurs.pop() {
|
||||
if operateur == Operateur::ParentheseBooleen {
|
||||
break;
|
||||
}
|
||||
expression.push(Element::Operateur(operateur));
|
||||
}
|
||||
}
|
||||
autre => {
|
||||
if !format_de_variable(autre) {
|
||||
return Err(ErreurPendragon::MauvaisArgument(format!("{}", autre)))
|
||||
}
|
||||
self.programme.variable_est_de_type(autre, TypeElement::Booleen)?;
|
||||
expression.push(Element::Variable(autre.into(), TypeElement::Booleen));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while let Some(operateur) = pile_operateurs.pop() {
|
||||
expression.push(Element::Operateur(operateur));
|
||||
}
|
||||
|
||||
Ok(expression)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn affiche_booleen(expression: Vec<Element>, variables: &HashMap<String, Element>) -> Result<String, ErreurPendragon> {
|
||||
let booleen = calcule_booleen(expression.clone(), variables)?;
|
||||
Ok(booleen_comme_texte(booleen))
|
||||
}
|
||||
|
||||
pub fn calcule_booleen(expression: Vec<Element>, variables: &HashMap<String, Element>) -> Result<bool, ErreurPendragon> {
|
||||
let mut pile: Vec<bool> = Vec::new();
|
||||
|
||||
for element in expression {
|
||||
if let Element::Booleen(booleen) = element {
|
||||
pile.push(booleen);
|
||||
continue;
|
||||
}
|
||||
if let Element::Variable(nom, _) = element {
|
||||
let Some(variable) = variables.get(&nom) else {
|
||||
return Err(ErreurPendragon::VariableInconnue(nom.into()))
|
||||
};
|
||||
if let Element::Booleen(booleen) = variable {
|
||||
pile.push(*booleen);
|
||||
continue
|
||||
} else {
|
||||
return Err(ErreurPendragon::MauvaisType(nom.into(), variable.type_element().nom(), "booleen".into()))
|
||||
}
|
||||
}
|
||||
let Element::Operateur(ref operateur) = element else {
|
||||
return Err(ErreurPendragon::MauvaisArgument(format!("{:?}, attendais un opérateur", element)))
|
||||
};
|
||||
let Some(booleen_a) = pile.pop() else {
|
||||
return Err(ErreurPendragon::CalculBooleen("la pile est vide".into()))
|
||||
};
|
||||
match operateur {
|
||||
Operateur::Non => {
|
||||
pile.push(!booleen_a);
|
||||
}
|
||||
Operateur::Et => {
|
||||
let Some(booleen_b) = pile.pop() else {
|
||||
return Err(ErreurPendragon::CalculBooleen("la pile est vide".into()))
|
||||
};
|
||||
pile.push(booleen_a && booleen_b);
|
||||
}
|
||||
Operateur::Ou => {
|
||||
let Some(booleen_b) = pile.pop() else {
|
||||
return Err(ErreurPendragon::CalculBooleen("la pile est vide".into()))
|
||||
};
|
||||
pile.push(booleen_a || booleen_b);
|
||||
}
|
||||
_ => return Err(ErreurPendragon::MauvaisArgument(format!("{:?}, attendais un opérateur booléen", element)))
|
||||
}
|
||||
}
|
||||
if pile.len() > 1 {
|
||||
return Err(ErreurPendragon::CalculBooleen("la pile n'est pas vide".into()))
|
||||
}
|
||||
Ok(pile[0])
|
||||
}
|
||||
|
||||
pub fn booleen_comme_texte(booleen: bool) -> String {
|
||||
|
@ -84,10 +124,10 @@ pub fn booleen_comme_texte(booleen: bool) -> String {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn texte_comme_booleen(texte: &str) -> Result<bool, ErreurPendragon> {
|
||||
pub fn texte_comme_booleen(texte: &str) -> Result<Element, ErreurPendragon> {
|
||||
match texte {
|
||||
"vrai" => Ok(true),
|
||||
"faux" => Ok(false),
|
||||
"vrai" => Ok(Element::Booleen(true)),
|
||||
"faux" => Ok(Element::Booleen(false)),
|
||||
_ => Err(ErreurPendragon::BooleenInvalide(texte.into())),
|
||||
}
|
||||
}
|
57
src/pendragon/debug.rs
Normal file
57
src/pendragon/debug.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
use std::fmt;
|
||||
use super::*;
|
||||
|
||||
pub enum ErreurPendragon {
|
||||
CommandeInconnue(String),
|
||||
ManqueArgument,
|
||||
NombreInvalide(String),
|
||||
BooleenInvalide(String),
|
||||
TexteInvalide(String),
|
||||
MauvaisArgument(String),
|
||||
VariableInconnue(String),
|
||||
MauvaisType(String, String, String),
|
||||
ManquePoint,
|
||||
Lecture(String),
|
||||
CalculBooleen(String),
|
||||
CalculEntier(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for ErreurPendragon {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {//'
|
||||
match self {
|
||||
Self::CommandeInconnue(commande) => write!(f, "La commande \"{}\" est inconnue.", commande),
|
||||
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::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::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),
|
||||
Self::CalculEntier(raison) => write!(f, "Calcul entier échoué, {}.", raison),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Commande {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {//'
|
||||
match self {
|
||||
Self::Definis(nom, type_element) => write!(f, "Definis {} comme {}.", nom, type_element.nom()),
|
||||
Self::Demande(nom) => write!(f, "Demande {}.", nom),
|
||||
Self::Modifie(nom, expression) => write!(f, "Modifie {} avec {:?}.", nom, expression),
|
||||
Self::Affiche(expression) => write!(f, "Affiche {:?}.", expression),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Programme {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {//'
|
||||
let mut texte: String = format!("variables : {:?}", self.variables);
|
||||
for (index, commande) in self.commandes.iter().enumerate() {
|
||||
texte += &format!("\n#{:2}-{}", index+1, commande);
|
||||
}
|
||||
write!(f, "{}", texte)
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
use std::io;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub mod nombre;
|
||||
|
@ -6,149 +5,93 @@ pub mod texte;
|
|||
pub mod booleen;
|
||||
pub mod structure;
|
||||
use structure::*;
|
||||
pub mod debug;
|
||||
use debug::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub struct Pendragon {
|
||||
variables: HashMap<String, Element>,
|
||||
pub programme: Programme,
|
||||
}
|
||||
|
||||
impl Pendragon {
|
||||
pub fn new() -> Self {
|
||||
pub fn nouveau() -> Self {
|
||||
Self {
|
||||
variables: HashMap::new(),
|
||||
programme: Programme::nouveau(),
|
||||
}
|
||||
}
|
||||
pub fn compile(&mut self, contenu: String) -> Result<Vec<Commande>, ErreurPendragon> {
|
||||
|
||||
pub fn compile(&mut self, contenu: String) -> Result<(), ErreurPendragon> {
|
||||
let contenu_propre = contenu.replace("\n", "");
|
||||
let mut texte: Vec<&str> = contenu_propre.split('.').collect();
|
||||
let reste = texte.pop();
|
||||
if reste != Some("") {
|
||||
eprintln!("Erreur phrase {} : Il manque un point.", texte.len() + 1);
|
||||
eprintln!("Erreur Compilation, phrase {} : Il manque un point.", texte.len() + 1);
|
||||
return Err(ErreurPendragon::ManquePoint)
|
||||
}
|
||||
let mut liste_commandes = Vec<Commande> = vec![];
|
||||
for (index_phrase, phrase) in texte.iter().enumerate() {
|
||||
match self.compile_phrase(phrase) {
|
||||
Ok(commande) => {liste_commandes.push(commande)},
|
||||
Ok(commande) => {self.programme.ajoute_commande(commande)},
|
||||
Err(raison) => {
|
||||
eprintln!("Erreur phrase {} : {}", index_phrase + 1, raison);
|
||||
return Err(raison)
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(liste_commande)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compile_phrase(&self, phrase: &str) -> Result<Commande, ErreurPendragon> {
|
||||
fn compile_phrase(&mut self, phrase: &str) -> Result<Commande, ErreurPendragon> {
|
||||
let phrase = phrase.trim();
|
||||
let parties: Vec<&str> = phrase.splitn(2, ' ').collect();
|
||||
|
||||
if parties.len() == 1 {
|
||||
return Err(ErreurPendragon::ManqueArgument)
|
||||
}
|
||||
match parties[0] {
|
||||
"Définis" => {
|
||||
self.definis(parties[1])
|
||||
},
|
||||
"Modifie" => {
|
||||
self.modifie(parties[1])
|
||||
},
|
||||
"Affiche" => {
|
||||
self.affiche(parties[1])
|
||||
},
|
||||
"Demande" => {
|
||||
self.demande(parties[1])
|
||||
}
|
||||
autre_commande => {
|
||||
return Err(ErreurPendragon::CommandeInconnue(autre_commande.to_string()))
|
||||
}
|
||||
"Définis" => self.definis(parties[1]),
|
||||
"Modifie" => self.modifie(parties[1]),
|
||||
"Affiche" => self.affiche(parties[1]),
|
||||
"Demande" => self.demande(parties[1]),
|
||||
autre => Err(ErreurPendragon::CommandeInconnue(autre.into())),
|
||||
}
|
||||
}
|
||||
|
||||
fn affiche(&self, arguments: &str) -> Result<Commande, ErreurPendragon> {
|
||||
println!("{}", self.texte(arguments)?);
|
||||
|
||||
let commande = Affiche(Expression::avec_arguments(TypeElement::Texte, arguments)?)
|
||||
Ok(commande)
|
||||
Ok(Commande::Affiche(self.elements_texte(arguments)?))
|
||||
}
|
||||
|
||||
fn definis(&mut self, arguments: &str) -> Result<Commande, ErreurPendragon> {
|
||||
let (variable_nom, variable_type) = self.nom_de_variable(arguments, "comme")?;
|
||||
let (variable_nom, variable_type_texte) = nom_de_variable(arguments, "comme")?;
|
||||
let variable_type = TypeElement::texte_comme_type(&variable_type_texte)?;
|
||||
|
||||
let possible_variable = self.recupere_variable(&variable_nom);
|
||||
self.programme.ajoute_variable(variable_nom.clone(), variable_type.clone())?;
|
||||
|
||||
let Err(raison) = possible_variable else {
|
||||
return Err(ErreurPendragon::MauvaisArgument(format!("la variable \"{}\" existe déjà", variable_nom)))
|
||||
};
|
||||
let ErreurPendragon::VariableInconnue(_) = raison else {
|
||||
return Err(raison)
|
||||
};
|
||||
|
||||
let contenu = match variable_type.as_str() {
|
||||
"entier" => Element::Entier(0),
|
||||
"texte" => Element::Texte("".to_string()),
|
||||
"booléen" => Element::Booleen(false),
|
||||
_ => return Err(ErreurPendragon::MauvaisArgument(format!("type de variable \"{}\" inconnu", variable_type))),
|
||||
};
|
||||
|
||||
self.variables.insert(variable_nom, contenu);
|
||||
|
||||
let commande = Definis(variable_nom.into(), contenu.type_element());
|
||||
Ok(commande)
|
||||
Ok(Commande::Definis(variable_nom.into(), variable_type))
|
||||
}
|
||||
|
||||
fn modifie(&mut self, arguments: &str) -> Result<Commande, ErreurPendragon> {
|
||||
let (variable_nom, contenu) = self.nom_de_variable(arguments, "avec")?;
|
||||
let variable = self.recupere_variable(&variable_nom)?;
|
||||
let (variable_nom, contenu) = nom_de_variable(arguments, "avec")?;
|
||||
let variable = self.programme.variable(&variable_nom)?;
|
||||
|
||||
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)?),
|
||||
let elements = match variable {
|
||||
TypeElement::Entier => self.elements_nombre(&contenu)?,
|
||||
TypeElement::Texte => self.elements_texte(&contenu)?,
|
||||
TypeElement::Booleen => self.elements_booleen(&contenu)?,
|
||||
};
|
||||
self.variables.insert(variable_nom, valeur);
|
||||
|
||||
let commande = Modifie(variable_nom, Expression::avec_arguments(variable.type_element(), arguments)?),
|
||||
Ok(commande)
|
||||
Ok(Commande::Modifie(variable_nom, elements))
|
||||
}
|
||||
|
||||
fn demande(&mut self, arguments: &str) -> Result<Commande, ErreurPendragon> {
|
||||
let (variable_nom, _) = self.nom_de_variable(arguments, "")?;
|
||||
let (variable_nom, _) = nom_de_variable(arguments, "")?;
|
||||
let _ = self.programme.variable(&variable_nom)?;
|
||||
|
||||
let _ = self.recupere_variable(&variable_nom)?;
|
||||
|
||||
println!("Quelle valeur pour {} ?", variable_nom);
|
||||
let mut reponse: String = String::new();
|
||||
if let Err(_) = io::stdin().read_line(&mut reponse) {
|
||||
return Err(ErreurPendragon::ProblemeTerminal("lecture d'entrées utilisateur impossible".into()))
|
||||
Ok(Commande::Demande(variable_nom.into()))
|
||||
}
|
||||
}
|
||||
|
||||
let contenu = reponse.trim();
|
||||
|
||||
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);
|
||||
|
||||
let commande = Demande(variable_nom.into());
|
||||
Ok(commande)
|
||||
}
|
||||
|
||||
fn recupere_variable(&self, nom: &str) -> Result<Element, ErreurPendragon> {
|
||||
let Some(first_char) = nom.chars().next() else {
|
||||
return Err(ErreurPendragon::MauvaisArgument("il n'y a pas de variable".to_string()))
|
||||
};
|
||||
if !first_char.is_uppercase() {
|
||||
return Err(ErreurPendragon::MauvaisArgument("il manque une majuscule à la variable".to_string()))
|
||||
}
|
||||
if !self.variables.contains_key(nom) {
|
||||
return Err(ErreurPendragon::VariableInconnue(nom.into()))
|
||||
}
|
||||
Ok(self.variables[nom].clone())
|
||||
}
|
||||
|
||||
fn nom_de_variable(&self, arguments: &str, separateur: &str) -> Result<(String, String), ErreurPendragon> {
|
||||
fn nom_de_variable(arguments: &str, separateur: &str) -> Result<(String, String), ErreurPendragon> {
|
||||
let parties = if separateur == "" {
|
||||
vec![arguments, ""]
|
||||
} else {
|
||||
|
@ -162,4 +105,13 @@ impl Pendragon {
|
|||
}
|
||||
Ok((nom_variable, parties[1].trim().to_string()))
|
||||
}
|
||||
|
||||
pub fn format_de_variable(nom: &str) -> bool {
|
||||
let Some(first_char) = nom.chars().next() else {
|
||||
return false
|
||||
};
|
||||
if !first_char.is_uppercase() {
|
||||
return false
|
||||
}
|
||||
true
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
use super::ErreurPendragon;
|
||||
use super::Pendragon;
|
||||
use super::Element;
|
||||
use super::*;
|
||||
|
||||
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"];
|
||||
|
@ -9,107 +7,138 @@ const NOMS_SEPARATEURS: [&str; 7] = ["", "mille", "million", "milliard", "billio
|
|||
const UNION: &str = "-";
|
||||
|
||||
impl Pendragon {
|
||||
pub fn operation(&self, arguments: &str) -> Result<usize, ErreurPendragon> {
|
||||
//return self.operation_elementaire(arguments);
|
||||
pub fn elements_nombre(&self, arguments: &str) -> Result<Vec<Element>, ErreurPendragon> {
|
||||
let texte = arguments
|
||||
.replace("ouvre la parenthèse", "ouvre-la-parenthese")
|
||||
.replace("ferme la parenthèse", "ferme-la-parenthese")
|
||||
.replace("divisé par", "divise-par");
|
||||
let mut expression: Vec<String> = texte.split(" ").map(String::from).collect();
|
||||
let elements_texte: Vec<&str> = texte.split(" ").collect();
|
||||
let mut expression: Vec<Element> = Vec::new();
|
||||
let mut pile_operateurs: Vec<Operateur> = Vec::new();
|
||||
|
||||
while expression.contains(&"ouvre-la-parenthese".to_string()) {
|
||||
let mut ouverture: Option<usize> = None;
|
||||
let mut fermeture: Option<usize> = None;
|
||||
for index in 0..expression.len() {
|
||||
if expression[index] == "ouvre-la-parenthese" {
|
||||
ouverture = Some(index);
|
||||
}
|
||||
if expression[index] == "ferme-la-parenthese" && ouverture.is_some() {
|
||||
fermeture = Some(index);
|
||||
for element in elements_texte {
|
||||
match element {
|
||||
"plus" => {
|
||||
while let Some(operateur) = pile_operateurs.last() {
|
||||
if *operateur == Operateur::Plus || *operateur == Operateur::Moins || *operateur == Operateur::Fois || *operateur == Operateur::Divise {
|
||||
expression.push(Element::Operateur(pile_operateurs.pop().unwrap()));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let Some(index_ouverture) = ouverture else {
|
||||
return Err(ErreurPendragon::DesequilibreParenthese);
|
||||
};
|
||||
let Some(index_fermeture) = fermeture else {
|
||||
return Err(ErreurPendragon::DesequilibreParenthese);
|
||||
};
|
||||
let contenu: String = expression[(index_ouverture+1)..(index_fermeture)].join(" ");
|
||||
let nombre = self.operation_elementaire(&contenu)?;
|
||||
let nombre_texte = nombre_comme_texte(nombre);
|
||||
expression[index_ouverture] = nombre_texte;
|
||||
for _ in 0..(index_fermeture-index_ouverture) {
|
||||
expression.remove(index_ouverture+1);
|
||||
pile_operateurs.push(Operateur::Plus);
|
||||
}
|
||||
}
|
||||
if expression.contains(&"ferme-la-parenthese".to_string()) {
|
||||
return Err(ErreurPendragon::DesequilibreParenthese);
|
||||
}
|
||||
self.operation_elementaire(&expression.join(" "))
|
||||
}
|
||||
|
||||
pub fn operation_elementaire(&self, arguments: &str) -> Result<usize, ErreurPendragon> {
|
||||
let texte = arguments.replace("divisé par", "divise-par");
|
||||
let mut expression: Vec<String> = texte.split(" ").map(String::from).collect();
|
||||
|
||||
let mut index = 0;
|
||||
while index < expression.len() {
|
||||
if expression[index] != "fois" && expression[index] != "divise-par" {
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
if index == 0 || index == expression.len() - 1 {
|
||||
return Err(ErreurPendragon::ManqueArgument);
|
||||
}
|
||||
let a = self.texte_comme_nombre(&expression[index - 1])?;
|
||||
let b = self.texte_comme_nombre(&expression[index + 1])?;
|
||||
let produit = if expression[index] == "fois" {a*b} else {a/b};
|
||||
let produit_texte: String = nombre_comme_texte(produit);
|
||||
index -= 1;
|
||||
expression[index] = produit_texte;
|
||||
expression.remove(index + 1);
|
||||
expression.remove(index + 1);
|
||||
}
|
||||
|
||||
let mut index = 0;
|
||||
while index < expression.len() {
|
||||
if expression[index] != "plus" && expression[index] != "moins" {
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
if index == 0 || index == expression.len() - 1 {
|
||||
return Err(ErreurPendragon::ManqueArgument);
|
||||
}
|
||||
let a = self.texte_comme_nombre(&expression[index - 1])?;
|
||||
let b = self.texte_comme_nombre(&expression[index + 1])?;
|
||||
let somme = if expression[index] == "plus" {a+b} else {a-b};
|
||||
let somme_texte: String = nombre_comme_texte(somme);
|
||||
index -= 1;
|
||||
expression[index] = somme_texte;
|
||||
expression.remove(index + 1);
|
||||
expression.remove(index + 1);
|
||||
}
|
||||
|
||||
if expression.len() > 1 {
|
||||
return Err(ErreurPendragon::MauvaisArgument("expression mathématique".to_string()))
|
||||
}
|
||||
self.texte_comme_nombre(&expression[0])
|
||||
}
|
||||
|
||||
pub fn texte_comme_nombre(&self, texte: &str) -> Result<usize, ErreurPendragon> {
|
||||
if texte.chars().next().map_or(false, |c| c.is_uppercase()) {
|
||||
if self.variables.contains_key(texte) {
|
||||
let Element::Entier(nombre) = self.variables[texte] else {
|
||||
return Err(ErreurPendragon::MauvaisType(texte.into(), self.variables[texte].type_element().nom(), "entier".into()))
|
||||
};
|
||||
return Ok(nombre);
|
||||
"moins" => {
|
||||
while let Some(operateur) = pile_operateurs.last() {
|
||||
if *operateur == Operateur::Plus || *operateur == Operateur::Moins || *operateur == Operateur::Fois || *operateur == Operateur::Divise {
|
||||
expression.push(Element::Operateur(pile_operateurs.pop().unwrap()));
|
||||
} else {
|
||||
return Err(ErreurPendragon::VariableInconnue(texte.to_string()))
|
||||
break;
|
||||
}
|
||||
}
|
||||
texte_comme_nombre(texte)
|
||||
pile_operateurs.push(Operateur::Moins);
|
||||
}
|
||||
"fois" => {
|
||||
while let Some(operateur) = pile_operateurs.last() {
|
||||
if *operateur == Operateur::Fois || *operateur == Operateur::Divise {
|
||||
expression.push(Element::Operateur(pile_operateurs.pop().unwrap()));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
pile_operateurs.push(Operateur::Fois);
|
||||
}
|
||||
"divise-par" => {
|
||||
while let Some(operateur) = pile_operateurs.last() {
|
||||
if *operateur == Operateur::Fois || *operateur == Operateur::Divise {
|
||||
expression.push(Element::Operateur(pile_operateurs.pop().unwrap()));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
pile_operateurs.push(Operateur::Divise);
|
||||
}
|
||||
"ouvre-la-parenthese" => pile_operateurs.push(Operateur::ParentheseEntier),
|
||||
"ferme-la-parenthese" => {
|
||||
while let Some(operateur) = pile_operateurs.pop() {
|
||||
if operateur == Operateur::ParentheseEntier {
|
||||
break;
|
||||
}
|
||||
expression.push(Element::Operateur(operateur));
|
||||
}
|
||||
}
|
||||
autre => {
|
||||
if format_de_variable(autre) {
|
||||
self.programme.variable_est_de_type(autre, TypeElement::Entier)?;
|
||||
expression.push(Element::Variable(autre.into(), TypeElement::Entier));
|
||||
} else {
|
||||
expression.push(texte_comme_nombre(autre)?);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while let Some(operateur) = pile_operateurs.pop() {
|
||||
expression.push(Element::Operateur(operateur));
|
||||
}
|
||||
|
||||
Ok(expression)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn affiche_nombre(expression: Vec<Element>, variables: &HashMap<String, Element>) -> Result<String, ErreurPendragon> {
|
||||
let nombre = calcule_nombre(expression.clone(), variables)?;
|
||||
Ok(nombre_comme_texte(nombre))
|
||||
}
|
||||
|
||||
pub fn calcule_nombre(expression: Vec<Element>, variables: &HashMap<String, Element>) -> Result<usize, ErreurPendragon> {
|
||||
let mut pile: Vec<usize> = Vec::new();
|
||||
|
||||
for element in expression {
|
||||
if let Element::Entier(nombre) = element {
|
||||
pile.push(nombre);
|
||||
continue;
|
||||
}
|
||||
if let Element::Variable(nom, _) = element {
|
||||
let Some(variable) = variables.get(&nom) else {
|
||||
return Err(ErreurPendragon::VariableInconnue(nom.into()))
|
||||
};
|
||||
if let Element::Entier(nombre) = variable {
|
||||
pile.push(*nombre);
|
||||
continue
|
||||
} else {
|
||||
return Err(ErreurPendragon::MauvaisType(nom.into(), variable.type_element().nom(), "entier".into()))
|
||||
}
|
||||
}
|
||||
let Element::Operateur(ref operateur) = element else {
|
||||
return Err(ErreurPendragon::MauvaisArgument(format!("{:?}, attendais un opérateur", element)))
|
||||
};
|
||||
let Some(nombre_a) = pile.pop() else {
|
||||
return Err(ErreurPendragon::CalculEntier("la pile est vide".into()))
|
||||
};
|
||||
let Some(nombre_b) = pile.pop() else {
|
||||
return Err(ErreurPendragon::CalculEntier("la pile est vide".into()))
|
||||
};
|
||||
match operateur {
|
||||
Operateur::Plus => {
|
||||
pile.push(nombre_b + nombre_b);
|
||||
}
|
||||
Operateur::Moins => {
|
||||
pile.push(nombre_b - nombre_a);
|
||||
}
|
||||
Operateur::Fois => {
|
||||
pile.push(nombre_b * nombre_a);
|
||||
}
|
||||
Operateur::Divise => {
|
||||
pile.push(nombre_b / nombre_a);
|
||||
}
|
||||
_ => return Err(ErreurPendragon::MauvaisArgument(format!("{:?}, attendais un opérateur d'entiers", element)))
|
||||
}
|
||||
}
|
||||
if pile.len() > 1 {
|
||||
return Err(ErreurPendragon::CalculEntier("la pile n'est pas vide".into()))
|
||||
}
|
||||
Ok(pile[0])
|
||||
}
|
||||
|
||||
pub fn nombre_comme_texte(nombre: usize) -> String {
|
||||
|
@ -198,9 +227,9 @@ fn petit_nombre_comme_texte(nombre: usize) -> String {
|
|||
format!("{}{}{}{}{}", centaine_texte, dizaine_union, dizaine_texte, séparation, unité_texte)
|
||||
}
|
||||
|
||||
pub fn texte_comme_nombre(texte: &str) -> Result<usize, ErreurPendragon> {
|
||||
pub fn texte_comme_nombre(texte: &str) -> Result<Element, ErreurPendragon> {
|
||||
if texte == "zéro" {
|
||||
return Ok(0)
|
||||
return Ok(Element::Entier(0))
|
||||
}
|
||||
let pluriel = format!("s{}", UNION);
|
||||
let mut petits_nombres_texte: Vec<&str> = vec![];
|
||||
|
@ -243,7 +272,7 @@ pub fn texte_comme_nombre(texte: &str) -> Result<usize, ErreurPendragon> {
|
|||
nombre += petit_nombre * 1000usize.pow((petits_nombres_texte.len() - index - 1) as u32);
|
||||
}
|
||||
|
||||
Ok(nombre)
|
||||
Ok(Element::Entier(nombre))
|
||||
}
|
||||
|
||||
fn texte_comme_petit_nombre(texte: &str) -> Result<usize, ErreurPendragon> {
|
||||
|
|
|
@ -1,43 +1,90 @@
|
|||
use std::fmt;
|
||||
use std::io;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub struct Programme {
|
||||
pub variables: HashMap<String, TypeElement>,
|
||||
pub commandes: Vec<Commande>,
|
||||
}
|
||||
|
||||
impl Programme {
|
||||
pub fn nouveau() -> Self {
|
||||
Self {
|
||||
variables: HashMap::new(),
|
||||
commandes: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ajoute_commande(&mut self, commande: Commande) {
|
||||
self.commandes.push(commande);
|
||||
}
|
||||
|
||||
pub fn ajoute_variable(&mut self, nom: String, type_variable: TypeElement) -> Result<(), ErreurPendragon> {
|
||||
let Err(raison) = self.variable(&nom) else {
|
||||
return Err(ErreurPendragon::MauvaisArgument(format!("la variable \"{}\" existe déjà", nom)))
|
||||
};
|
||||
let ErreurPendragon::VariableInconnue(_) = raison else {
|
||||
return Err(raison)
|
||||
};
|
||||
self.variables.insert(nom, type_variable);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn variable(&self, nom: &str) -> Result<TypeElement, ErreurPendragon> {
|
||||
let Some(first_char) = nom.chars().next() else {
|
||||
return Err(ErreurPendragon::MauvaisArgument("il n'y a pas de variable".to_string()))
|
||||
};
|
||||
if !first_char.is_uppercase() {
|
||||
return Err(ErreurPendragon::MauvaisArgument("il manque une majuscule à la variable".to_string()))
|
||||
}
|
||||
if !self.variables.contains_key(nom) {
|
||||
return Err(ErreurPendragon::VariableInconnue(nom.into()))
|
||||
}
|
||||
Ok(self.variables[nom].clone())
|
||||
}
|
||||
|
||||
pub fn variable_est_de_type(&self, nom: &str, type_element: TypeElement) -> Result<(), ErreurPendragon> {
|
||||
let type_variable = self.variable(nom)?;
|
||||
if type_variable != type_element {
|
||||
return Err(ErreurPendragon::MauvaisType(nom.into(), type_variable.nom(), type_element.nom()))
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn execute(&self) -> Result<(), ErreurPendragon> {
|
||||
let mut variables_globales: HashMap<String, Element> = HashMap::new();
|
||||
for commande in &self.commandes {
|
||||
match commande {
|
||||
Commande::Definis(nom, type_element) => {
|
||||
variables_globales.insert(nom.to_string(), type_element.comme_element());
|
||||
}
|
||||
Commande::Demande(nom) => {
|
||||
let valeur = variables_globales[nom].type_element().demande_valeur(&nom)?;
|
||||
variables_globales.insert(nom.to_string(), valeur);
|
||||
}
|
||||
Commande::Modifie(nom, expression) => {
|
||||
let valeur = match variables_globales[nom].type_element() {
|
||||
TypeElement::Entier => Element::Entier(nombre::calcule_nombre(expression.clone(), &variables_globales)?),
|
||||
TypeElement::Texte => Element::Texte(texte::calcule_texte(expression.clone(), &variables_globales)?),
|
||||
TypeElement::Booleen => Element::Booleen(booleen::calcule_booleen(expression.clone(), &variables_globales)?),
|
||||
};
|
||||
variables_globales.insert(nom.to_string(), valeur);
|
||||
}
|
||||
Commande::Affiche(expression) => {
|
||||
println!("{}", texte::calcule_texte(expression.to_vec(), &variables_globales)?);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
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<Element>
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
fn nouvelle(type_expression: TypeElement) -> Self {
|
||||
Self {
|
||||
type_expression,
|
||||
contenu: vec![]
|
||||
}
|
||||
}
|
||||
|
||||
fn avec_arguments(type_expression: TypeElement, arguments: &str) -> Result<Self, ErreurPendragon> {
|
||||
let expression = Self {
|
||||
type_expression,
|
||||
contenu: vec![]
|
||||
}
|
||||
|
||||
Ok(expression)
|
||||
}
|
||||
|
||||
fn ajoute(&mut self, element: Element) -> Result<(), ErreurPendragon> {
|
||||
let type_element = element.type_element();
|
||||
if self.type_expression != type_element {
|
||||
return Err(ErreurPendragon::MauvaisType("inconnue".into(), type_element.nom(), self.type_expression.nom()))
|
||||
}
|
||||
self.contenu.push(element);
|
||||
Ok(())
|
||||
}
|
||||
Modifie(String, Vec<Element>),
|
||||
Affiche(Vec<Element>),
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
|
@ -55,6 +102,47 @@ impl TypeElement {
|
|||
Self::Booleen => "booléen".into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn texte_comme_type(texte: &str) -> Result<Self, ErreurPendragon> {
|
||||
match texte.trim() {
|
||||
"entier" => Ok(TypeElement::Entier),
|
||||
"texte" => Ok(TypeElement::Texte),
|
||||
"booléen" => Ok(TypeElement::Booleen),
|
||||
autre => return Err(ErreurPendragon::MauvaisArgument(format!("type de variable \"{}\" inconnu", autre))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn comme_element(&self) -> Element {
|
||||
match self {
|
||||
Self::Entier => Element::Entier(0),
|
||||
Self::Texte => Element::Texte("".into()),
|
||||
Self::Booleen => Element::Booleen(false),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn texte_comme_element(&self, texte: &str) -> Result<Element, ErreurPendragon> {
|
||||
match self {
|
||||
Self::Entier => nombre::texte_comme_nombre(texte),
|
||||
Self::Texte => Ok(Element::Texte(texte.into())),
|
||||
Self::Booleen => booleen::texte_comme_booleen(texte),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn demande_valeur(&self, nom: &str) -> Result<Element, ErreurPendragon> {
|
||||
loop {
|
||||
println!("Quelle valeur pour {} ({}) ?", nom, self.nom());
|
||||
|
||||
let mut reponse = String::new();
|
||||
if let Err(raison) = io::stdin().read_line(&mut reponse) {
|
||||
return Err(ErreurPendragon::Lecture(format!("{}", raison)));
|
||||
}
|
||||
|
||||
match self.texte_comme_element(reponse.trim()) {
|
||||
Ok(element) => return Ok(element),
|
||||
Err(raison) => eprintln!("Erreur : {}", raison),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
|
@ -63,8 +151,7 @@ pub enum Element {
|
|||
Texte(String),
|
||||
Booleen(bool),
|
||||
Variable(String, TypeElement),
|
||||
Operateur(String, TypeElement),
|
||||
Expression(Expression, TypeElement),
|
||||
Operateur(Operateur),
|
||||
}
|
||||
|
||||
impl Element {
|
||||
|
@ -74,42 +161,31 @@ impl Element {
|
|||
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(),
|
||||
Self::Operateur(operateur) => operateur.type_element(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ErreurPendragon {
|
||||
CommandeInconnue(String),
|
||||
PhraseVide,
|
||||
ManqueArgument,
|
||||
NombreInvalide(String),
|
||||
BooleenInvalide(String),
|
||||
TexteInvalide(String),
|
||||
MauvaisArgument(String),
|
||||
DesequilibreParenthese,
|
||||
VariableInconnue(String),
|
||||
MauvaisType(String, String, String),
|
||||
ProblemeTerminal(String),
|
||||
ManquePoint,
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Operateur {
|
||||
Ou,
|
||||
Et,
|
||||
Non,
|
||||
ParentheseBooleen,
|
||||
Virgule,
|
||||
Plus,
|
||||
Moins,
|
||||
Fois,
|
||||
Divise,
|
||||
ParentheseEntier,
|
||||
}
|
||||
|
||||
impl fmt::Display for ErreurPendragon {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {//'
|
||||
impl Operateur {
|
||||
pub fn type_element(&self) -> TypeElement {
|
||||
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."),
|
||||
Self::Ou | Self::Et | Self::Non | Self::ParentheseBooleen => TypeElement::Booleen,
|
||||
Self::Virgule => TypeElement::Texte,
|
||||
Self::Plus | Self::Moins | Self::Fois | Self::Divise | Self::ParentheseEntier => TypeElement::Entier,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,44 +1,78 @@
|
|||
use super::Pendragon;
|
||||
use super::ErreurPendragon;
|
||||
use super::Element;
|
||||
use super::nombre;
|
||||
use super::booleen;
|
||||
use super::*;
|
||||
|
||||
impl Pendragon {
|
||||
pub fn texte(&self, arguments: &str) -> Result<String, ErreurPendragon> {
|
||||
let liste_arguments: Vec<&str> = arguments.split(',').collect();
|
||||
pub fn elements_texte(&self, arguments: &str) -> Result<Vec<Element>, ErreurPendragon> {
|
||||
let mut expression: Vec<Element> = Vec::new();
|
||||
|
||||
let mut texte = "".to_string();
|
||||
|
||||
for argument in liste_arguments {
|
||||
let argument: &str = argument.trim();
|
||||
for argument in arguments.split(',').map(|arg| arg.trim()) {
|
||||
if expression.len() > 0 {
|
||||
expression.push(Element::Operateur(Operateur::Virgule));
|
||||
}
|
||||
if argument.starts_with('"') {
|
||||
if argument.ends_with('"') {
|
||||
texte += &argument[1..argument.len()-1];
|
||||
expression.push(Element::Texte(argument[1..argument.len() - 1].into()));
|
||||
} else {
|
||||
return Err(ErreurPendragon::TexteInvalide("guillemet mal refermé".into()))
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Ok(nombre) = self.operation(argument) {
|
||||
texte += &nombre::nombre_comme_texte(nombre);
|
||||
if format_de_variable(argument) && !argument.contains(" ") {
|
||||
expression.push(Element::Variable(argument.into(), self.programme.variable(argument)?));
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Ok(booleen) = self.condition(argument) {
|
||||
texte += &booleen::booleen_comme_texte(booleen);
|
||||
continue;
|
||||
if let Ok(elements_nombre) = self.elements_nombre(argument) {
|
||||
expression.extend(elements_nombre);
|
||||
} else if let Ok(elements_booleen) = self.elements_booleen(argument) {
|
||||
expression.extend(elements_booleen);
|
||||
} else {
|
||||
return Err(ErreurPendragon::MauvaisArgument(argument.to_string()));
|
||||
}
|
||||
}
|
||||
expression.push(Element::Operateur(Operateur::Virgule));
|
||||
Ok(expression)
|
||||
}
|
||||
}
|
||||
|
||||
let variable = self.recupere_variable(argument)?;
|
||||
pub fn calcule_texte(expression: Vec<Element>, variables: &HashMap<String, Element>) -> Result<String, ErreurPendragon> {
|
||||
let mut pile: Vec<Element> = Vec::new();
|
||||
let mut texte: String = String::new();
|
||||
|
||||
let Element::Texte(contenu) = variable else {
|
||||
return Err(ErreurPendragon::MauvaisType(argument.into(), variable.type_element().nom(), "texte".into()))
|
||||
for element in expression {
|
||||
let Element::Operateur(ref operateur) = element else {
|
||||
pile.push(element);
|
||||
continue;
|
||||
};
|
||||
let Operateur::Virgule = operateur else {
|
||||
pile.push(element);
|
||||
continue;
|
||||
};
|
||||
let Some(element_pile) = pile.last() else {
|
||||
continue;
|
||||
};
|
||||
if let TypeElement::Booleen = element_pile.type_element() {
|
||||
texte += &booleen::affiche_booleen(pile.clone(), variables)?;
|
||||
continue;
|
||||
}
|
||||
if let TypeElement::Entier = element_pile.type_element() {
|
||||
texte += &nombre::affiche_nombre(pile.clone(), variables)?;
|
||||
continue;
|
||||
}
|
||||
match element_pile {
|
||||
Element::Texte(contenu) => texte += contenu,
|
||||
Element::Variable(nom, type_element) => {
|
||||
let Some(variable) = variables.get(nom) else {
|
||||
return Err(ErreurPendragon::VariableInconnue(nom.into()))
|
||||
};
|
||||
let Element::Texte(contenu) = variable else {
|
||||
return Err(ErreurPendragon::MauvaisType(nom.into(), type_element.nom(), "texte".into()))
|
||||
};
|
||||
|
||||
texte += &contenu;
|
||||
}
|
||||
autre => {
|
||||
return Err(ErreurPendragon::MauvaisArgument(format!("{:?}", autre)))
|
||||
}
|
||||
}
|
||||
pile = Vec::new();
|
||||
}
|
||||
Ok(texte)
|
||||
}
|
||||
}
|
14
test.dr
14
test.dr
|
@ -1,7 +1,9 @@
|
|||
Définis A comme entier.
|
||||
Modifie A avec mille-cinq-cent-cinquante-cinq fois treize.
|
||||
Affiche A.
|
||||
Définis B comme booléen.
|
||||
Affiche "B ou : ", B ou vrai.
|
||||
Affiche "B et : ", B et vrai.
|
||||
Affiche dix fois dix fois dix.
|
||||
Définis C comme booléen.
|
||||
Définis D comme booléen.
|
||||
Modifie B avec vrai et ouvre la parenthèse non C ou D ferme la parenthèse ou faux.
|
||||
Affiche "B : ", B.
|
||||
Définis E comme entier.
|
||||
Modifie E avec mille-cinq-cent-cinquante-cinq fois ouvre la parenthèse un plus six ferme la parenthèse plus quarante-deux.
|
||||
Affiche mille-cinq-cent-cinquante-cinq fois ouvre la parenthèse un plus six ferme la parenthèse plus quarante-deux.
|
||||
Affiche "E : ", E fois dix.
|
Loading…
Reference in a new issue