From f326c7d3a86e905ca6964adcd781596dc9df1d92 Mon Sep 17 00:00:00 2001 From: Feelzor Date: Mon, 4 Nov 2019 18:05:56 +0100 Subject: [PATCH 01/10] feature-variables-typees: ajout de Valeur et ValeurEntiere --- SymboleValue.cpp | 12 ++++++--- SymboleValue.h | 13 +++++----- Valeur.h | 44 +++++++++++++++++++++++++++++++ ValeurEntiere.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++ ValeurEntiere.h | 30 +++++++++++++++++++++ VisiteurExecuter.cpp | 29 +++++++++++---------- VisiteurExecuter.h | 3 ++- main.cpp | 2 ++ 8 files changed, 171 insertions(+), 24 deletions(-) create mode 100644 Valeur.h create mode 100644 ValeurEntiere.cpp create mode 100644 ValeurEntiere.h diff --git a/SymboleValue.cpp b/SymboleValue.cpp index 12a2260..ad75c88 100644 --- a/SymboleValue.cpp +++ b/SymboleValue.cpp @@ -2,14 +2,14 @@ #include "Exceptions.h" #include "Visiteur.h" #include +#include "ValeurEntiere.h" SymboleValue::SymboleValue(const Symbole & s) : Symbole(s.getChaine()) { if (s == "") { - m_valeur = atoi(s.getChaine().c_str()); // c_str convertit une string en char* - m_defini = true; + setValeur(atoi(s.getChaine().c_str())); // c_str convertit une string en char* } else if (s == "") { - m_valeur = -1; + setValeur(-1); m_defini = true; } else { m_defini = false; @@ -26,3 +26,9 @@ ostream & operator<<(ostream & cout, const SymboleValue & symbole) { else cout << "indefinie "; return cout; } + + +void SymboleValue::setValeur(int valeur) { + this->m_valeur=new ValeurEntiere(valeur); + m_defini=true; +} \ No newline at end of file diff --git a/SymboleValue.h b/SymboleValue.h index ae430ca..64554fe 100644 --- a/SymboleValue.h +++ b/SymboleValue.h @@ -7,6 +7,7 @@ using namespace std; #include "Symbole.h" #include "ArbreAbstrait.h" +#include "Valeur.h" class Visiteur; @@ -16,16 +17,16 @@ class SymboleValue : public Symbole, // Un symbole valué est un symbole qui a SymboleValue(const Symbole & s); // Construit un symbole valué à partir d'un symbole existant s ~SymboleValue( ) {} void accepter(Visiteur& visiteur) override; - inline void setValeur(int valeur) { this->m_valeur=valeur; m_defini=true; } // accesseur - inline int getValeur() const { return this->m_valeur; } // accesseur - inline bool estDefini() { return m_defini; } // accesseur - inline int getValeur() { return m_valeur; } // accesseur + void setValeur(int valeur); + inline void setValeur(Valeur* v) { m_valeur = v; m_defini = true; } + inline Valeur* getValeur() const { return this->m_valeur; } // accesseur + inline bool estDefini() { return m_defini; } // accesseur friend ostream & operator << (ostream & cout, const SymboleValue & symbole); // affiche un symbole value sur cout private: - bool m_defini; // indique si la valeur du symbole est définie - int m_valeur; // valeur du symbole si elle est définie, zéro sinon + bool m_defini; // indique si la valeur du symbole est définie + Valeur* m_valeur; // valeur du symbole si elle est définie, zéro sinon }; diff --git a/Valeur.h b/Valeur.h new file mode 100644 index 0000000..82dd4da --- /dev/null +++ b/Valeur.h @@ -0,0 +1,44 @@ +#ifndef VALEUR_H +#define VALEUR_H + +#include +#include + +class Valeur { +public: + virtual int getEntier() const = 0; + virtual float getReel() const = 0; + virtual std::string getChaine() const = 0; + virtual bool isVrai() const = 0; + + virtual Valeur* const operator+(const Valeur* v) const = 0; + virtual Valeur* const operator-(const Valeur* v) const = 0; + virtual Valeur* const operator*(const Valeur* v) const = 0; + virtual Valeur* const operator/(const Valeur* v) const = 0; + virtual bool operator> (const Valeur* v) const = 0; + virtual bool operator>=(const Valeur* v) const = 0; + virtual bool operator< (const Valeur* v) const = 0; + virtual bool operator<=(const Valeur* v) const = 0; + virtual bool operator==(const Valeur* v) const = 0; + virtual bool operator!=(const Valeur* v) const = 0; + + bool operator&&(Valeur* v) { + return isVrai() && v->isVrai(); + } + + bool operator||(Valeur* v) { + return isVrai() || v->isVrai(); + } + + bool operator!() { + return !isVrai(); + } +}; + +inline std::ostream& operator<<(std::ostream& out, Valeur* v) { + out << v->getChaine(); + return out; +} + +#endif /* VALEUR_H */ + diff --git a/ValeurEntiere.cpp b/ValeurEntiere.cpp new file mode 100644 index 0000000..ac625a5 --- /dev/null +++ b/ValeurEntiere.cpp @@ -0,0 +1,62 @@ +#include "ValeurEntiere.h" +#include "Valeur.h" + +#include + +ValeurEntiere::ValeurEntiere(int valeur) : m_valeur(valeur) {} + +bool ValeurEntiere::isVrai() const { + return m_valeur != 0; +} + +int ValeurEntiere::getEntier() const { + return m_valeur; +} + +float ValeurEntiere::getReel() const { + return ((float) m_valeur); +} + +std::string ValeurEntiere::getChaine() const { + return std::to_string(m_valeur); +} + +Valeur* const ValeurEntiere::operator+(const Valeur* v) const { + return new ValeurEntiere(m_valeur + v->getEntier()); +} + +Valeur* const ValeurEntiere::operator-(const Valeur* v) const { + return new ValeurEntiere(m_valeur - v->getEntier()); +} + +Valeur* const ValeurEntiere::operator*(const Valeur* v) const { + return new ValeurEntiere(m_valeur * v->getEntier()); +} + +Valeur* const ValeurEntiere::operator/(const Valeur* v) const { + return new ValeurEntiere(m_valeur / v->getEntier()); +} + +bool ValeurEntiere::operator>(const Valeur* v) const { + return m_valeur > v->getEntier(); +} + +bool ValeurEntiere::operator>=(const Valeur* v) const { + return m_valeur >= v->getEntier(); +} + +bool ValeurEntiere::operator<(const Valeur* v) const { + return m_valeur < v->getEntier(); +} + +bool ValeurEntiere::operator<=(const Valeur* v) const { + return m_valeur <= v->getEntier(); +} + +bool ValeurEntiere::operator==(const Valeur* v) const { + return m_valeur == v->getEntier(); +} + +bool ValeurEntiere::operator!=(const Valeur* v) const { + return m_valeur != v->getEntier(); +} \ No newline at end of file diff --git a/ValeurEntiere.h b/ValeurEntiere.h new file mode 100644 index 0000000..bf1d0a0 --- /dev/null +++ b/ValeurEntiere.h @@ -0,0 +1,30 @@ +#ifndef VALEURENTIERE_H +#define VALEURENTIERE_H + +#include "Valeur.h" +#include + +class ValeurEntiere : public Valeur { +public: + ValeurEntiere(int valeur); + int getEntier() const override; + float getReel() const override; + std::string getChaine() const override; + bool isVrai() const override; + + Valeur* const operator+(const Valeur* v) const override; + Valeur* const operator-(const Valeur* v) const override; + Valeur* const operator*(const Valeur* v) const override; + Valeur* const operator/(const Valeur* v) const override; + bool operator> (const Valeur* v) const override; + bool operator>=(const Valeur* v) const override; + bool operator< (const Valeur* v) const override; + bool operator<=(const Valeur* v) const override; + bool operator==(const Valeur* v) const override; + bool operator!=(const Valeur* v) const override; +private: + int m_valeur; +}; + +#endif /* VALEURENTIERE_H */ + diff --git a/VisiteurExecuter.cpp b/VisiteurExecuter.cpp index 6c98456..8e09ffd 100644 --- a/VisiteurExecuter.cpp +++ b/VisiteurExecuter.cpp @@ -1,4 +1,5 @@ #include "VisiteurExecuter.h" +#include "ValeurEntiere.h" void VisiteurExecuter::visiterNoeudSeqInst(NoeudSeqInst* noeud) { for (unsigned int i = 0; i < noeud->getInstructions().size(); i++) @@ -11,7 +12,7 @@ void VisiteurExecuter::visiterNoeudAffectation(NoeudAffectation* noeud) { } void VisiteurExecuter::visiterNoeudOperateurBinaire(NoeudOperateurBinaire* noeud) { - int og, od, valeur; + Valeur *og, *od, *valeur; if (noeud->getOperandeGauche() != nullptr) { noeud->getOperandeGauche()->accepter(*this); // On évalue l'opérande gauche og = m_derniereValeur; @@ -21,21 +22,21 @@ void VisiteurExecuter::visiterNoeudOperateurBinaire(NoeudOperateurBinaire* noeud od = m_derniereValeur; } // Et on combine les deux opérandes en fonctions de l'opérateur - if (noeud->getOperateur() == "+") valeur = (og + od); - else if (noeud->getOperateur() == "-") valeur = (og - od); - else if (noeud->getOperateur() == "*") valeur = (og * od); - else if (noeud->getOperateur() == "==") valeur = (og == od); - else if (noeud->getOperateur() == "!=") valeur = (og != od); - else if (noeud->getOperateur() == "<") valeur = (og < od); - else if (noeud->getOperateur() == ">") valeur = (og > od); - else if (noeud->getOperateur() == "<=") valeur = (og <= od); - else if (noeud->getOperateur() == ">=") valeur = (og >= od); - else if (noeud->getOperateur() == "et") valeur = (og && od); - else if (noeud->getOperateur() == "ou") valeur = (og || od); - else if (noeud->getOperateur() == "non") valeur = (!og); + if (noeud->getOperateur() == "+") valeur = (*og + od); + else if (noeud->getOperateur() == "-") valeur = (*og - od); + else if (noeud->getOperateur() == "*") valeur = (*og * od); + else if (noeud->getOperateur() == "==") valeur = new ValeurEntiere(*og == od); + else if (noeud->getOperateur() == "!=") valeur = new ValeurEntiere(*og != od); + else if (noeud->getOperateur() == "<") valeur = new ValeurEntiere(*og < od); + else if (noeud->getOperateur() == ">") valeur = new ValeurEntiere(*og > od); + else if (noeud->getOperateur() == "<=") valeur = new ValeurEntiere(*og <= od); + else if (noeud->getOperateur() == ">=") valeur = new ValeurEntiere(*og >= od); + else if (noeud->getOperateur() == "et") valeur = new ValeurEntiere(*og && od); + else if (noeud->getOperateur() == "ou") valeur = new ValeurEntiere(*og || od); + else if (noeud->getOperateur() == "non") valeur = new ValeurEntiere(!*og); else if (noeud->getOperateur() == "/") { if (od == 0) throw DivParZeroException(); - valeur = og / od; + valeur = *og / od; } m_derniereValeur = valeur; } diff --git a/VisiteurExecuter.h b/VisiteurExecuter.h index cf3c12d..4f376c1 100644 --- a/VisiteurExecuter.h +++ b/VisiteurExecuter.h @@ -2,6 +2,7 @@ #define VISITEUREXECUTER_H #include "Visiteur.h" +#include "Valeur.h" class VisiteurExecuter : public Visiteur { public: @@ -16,7 +17,7 @@ class VisiteurExecuter : public Visiteur { void visiterNoeudInstEcrire(NoeudInstEcrire* noeud) override; void visiterSymboleValue(SymboleValue* symbole) override; private: - int m_derniereValeur = 0; + Valeur* m_derniereValeur = 0; }; #endif /* VISITEUREXECUTER_H */ diff --git a/main.cpp b/main.cpp index 997fa4f..ff15b60 100644 --- a/main.cpp +++ b/main.cpp @@ -6,6 +6,8 @@ using namespace std; #include "VisiteurExecuter.h" #include "VisiteurCompiler.h" +#include "ValeurEntiere.h" + void compiler(ostream& out, const TableSymboles& symboles, Noeud* arbre); int main(int argc, char* argv[]) { From 34afc6ad32733e37e710a11c2966e071b21ce51c Mon Sep 17 00:00:00 2001 From: Feelzor Date: Mon, 4 Nov 2019 18:20:01 +0100 Subject: [PATCH 02/10] =?UTF-8?q?feature-variables-typees:=20ajout=20des?= =?UTF-8?q?=20variables=20r=C3=A9elles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Interpreteur.cpp | 4 +-- Interpreteur.h | 2 +- Lecteur.cpp | 2 +- Symbole.cpp | 3 +++ Symbole.h | 2 +- SymboleValue.cpp | 3 +++ ValeurReelle.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++++ ValeurReelle.h | 30 ++++++++++++++++++++++ testAffectation.txt | 6 +++++ 9 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 ValeurReelle.cpp create mode 100644 ValeurReelle.h diff --git a/Interpreteur.cpp b/Interpreteur.cpp index a77a15c..04a6ca8 100644 --- a/Interpreteur.cpp +++ b/Interpreteur.cpp @@ -182,9 +182,9 @@ Noeud* Interpreteur::expMult(){ } Noeud* Interpreteur::facteur() { - // ::= | | - | non | ( ) + // ::= | | | - | non | ( ) Noeud* fact = nullptr; - if (m_lecteur.getSymbole() == "" || m_lecteur.getSymbole() == "") { + if (m_lecteur.getSymbole() == "" || m_lecteur.getSymbole() == "" || m_lecteur.getSymbole() == "") { fact = m_table.chercheAjoute(m_lecteur.getSymbole()); // on ajoute la variable ou l'entier à la table m_lecteur.avancer(); } else if (m_lecteur.getSymbole() == "-") { // - diff --git a/Interpreteur.h b/Interpreteur.h index c10a453..2caa13a 100644 --- a/Interpreteur.h +++ b/Interpreteur.h @@ -37,7 +37,7 @@ class Interpreteur { Noeud* expComp(); // ::= { == | != | < | <= | > | >= } Noeud* expAdd(); // ::= { + | - } Noeud* expMult(); // ::= { * | / } - Noeud* facteur(); // ::= | | - | non | ( ) + Noeud* facteur(); // ::= | | | - | non | ( ) // ::= + | - | * | / | < | > | <= | >= | == | != | et | ou Noeud* instSi(); // ::= si ( ) { sinonsi () } [ sinon ] finsi Noeud* instPour(); // ::= pour ( [ ] ; ; [ ]) finpour diff --git a/Lecteur.cpp b/Lecteur.cpp index 6194c68..9614332 100644 --- a/Lecteur.cpp +++ b/Lecteur.cpp @@ -61,7 +61,7 @@ string Lecteur::motSuivant() { do { s = s + m_lecteurCar.getCaractere(); m_lecteurCar.avancer(); - } while (isdigit(m_lecteurCar.getCaractere())); + } while (isdigit(m_lecteurCar.getCaractere()) || m_lecteurCar.getCaractere() == '.'); else if (isalpha(m_lecteurCar.getCaractere())) // c'est le début d'un mot diff --git a/Symbole.cpp b/Symbole.cpp index a8b8beb..75cd708 100644 --- a/Symbole.cpp +++ b/Symbole.cpp @@ -11,6 +11,7 @@ const char * Symbole::FICHIER_MOTS_CLES = "motsCles.txt"; Symbole::Symbole(const string & s) : m_chaine(s) { // attention : l'ordre des tests ci-dessous n'est pas innocent ! if (s == "") this->m_categorie = FINDEFICHIER; + else if (isdigit(s[0]) && s.find('.') != string::npos) this->m_categorie = REEL; else if (isdigit(s[0])) this->m_categorie = ENTIER; else if (s.size() >= 2 && s[0] == '"' && s[s.size() - 1] == '"') this->m_categorie = CHAINE; else if (isMotCle(s)) this->m_categorie = MOTCLE; @@ -22,6 +23,7 @@ bool Symbole::operator==(const string & ch) const { return this->m_chaine == ch || (this->m_categorie == VARIABLE && (ch == "" || ch == "")) || (this->m_categorie == ENTIER && (ch == "" || ch == "")) || + (this->m_categorie == REEL && (ch == "" || ch == "")) || (this->m_categorie == CHAINE && (ch == "" || ch == "")) || (this->m_categorie == INDEFINI && (ch == "" || ch == "")) || (this->m_categorie == FINDEFICHIER && (ch == "" || ch == "")); @@ -56,6 +58,7 @@ ostream & operator<<(ostream & cout, const Symbole & symbole) { if (symbole.m_categorie == Symbole::MOTCLE) cout << " "; else if (symbole.m_categorie == Symbole::VARIABLE) cout << " "; else if (symbole.m_categorie == Symbole::ENTIER) cout << " "; + else if (symbole.m_categorie == Symbole::REEL) cout << " "; else if (symbole.m_categorie == Symbole::CHAINE) cout << " "; else if (symbole.m_categorie == Symbole::INDEFINI) cout << " "; else if (symbole.m_categorie == Symbole::FINDEFICHIER) cout << ""; diff --git a/Symbole.h b/Symbole.h index 71929d5..3ade486 100644 --- a/Symbole.h +++ b/Symbole.h @@ -16,7 +16,7 @@ class Symbole { friend ostream & operator <<(ostream & cout, const Symbole & symbole); // Fonction amie pour pouvoir afficher un symbole sur cout private: - enum m_categorie { MOTCLE, VARIABLE, ENTIER, CHAINE, INDEFINI, FINDEFICHIER }; + enum m_categorie { MOTCLE, VARIABLE, ENTIER, REEL, CHAINE, INDEFINI, FINDEFICHIER }; string m_chaine; // Chaîne du symbole m_categorie m_categorie; // Categorie du symbole (voir type énuméré ci-dessus) bool isMotCle(const string & s) const; // Renvoie vrai si s est un mot clé du langage diff --git a/SymboleValue.cpp b/SymboleValue.cpp index ad75c88..bfe2319 100644 --- a/SymboleValue.cpp +++ b/SymboleValue.cpp @@ -3,6 +3,7 @@ #include "Visiteur.h" #include #include "ValeurEntiere.h" +#include "ValeurReelle.h" SymboleValue::SymboleValue(const Symbole & s) : Symbole(s.getChaine()) { @@ -10,6 +11,8 @@ Symbole(s.getChaine()) { setValeur(atoi(s.getChaine().c_str())); // c_str convertit une string en char* } else if (s == "") { setValeur(-1); + } else if (s == "") { + this->m_valeur = new ValeurReelle(stof(s.getChaine())); m_defini = true; } else { m_defini = false; diff --git a/ValeurReelle.cpp b/ValeurReelle.cpp new file mode 100644 index 0000000..133dea1 --- /dev/null +++ b/ValeurReelle.cpp @@ -0,0 +1,61 @@ +#include "ValeurReelle.h" + +#include + +ValeurReelle::ValeurReelle(float valeur) : m_valeur(valeur) {} + +bool ValeurReelle::isVrai() const { + return m_valeur != 0; +} + +int ValeurReelle::getEntier() const { + return ((int) m_valeur); +} + +float ValeurReelle::getReel() const { + return m_valeur; +} + +std::string ValeurReelle::getChaine() const { + return std::to_string(m_valeur); +} + +Valeur* const ValeurReelle::operator+(const Valeur* v) const { + return new ValeurReelle(m_valeur + v->getReel()); +} + +Valeur* const ValeurReelle::operator-(const Valeur* v) const { + return new ValeurReelle(m_valeur - v->getReel()); +} + +Valeur* const ValeurReelle::operator*(const Valeur* v) const { + return new ValeurReelle(m_valeur * v->getReel()); +} + +Valeur* const ValeurReelle::operator/(const Valeur* v) const { + return new ValeurReelle(m_valeur / v->getReel()); +} + +bool ValeurReelle::operator>(const Valeur* v) const { + return m_valeur > v->getReel(); +} + +bool ValeurReelle::operator>=(const Valeur* v) const { + return m_valeur >= v->getReel(); +} + +bool ValeurReelle::operator<(const Valeur* v) const { + return m_valeur < v->getReel(); +} + +bool ValeurReelle::operator<=(const Valeur* v) const { + return m_valeur <= v->getReel(); +} + +bool ValeurReelle::operator==(const Valeur* v) const { + return m_valeur == v->getReel(); +} + +bool ValeurReelle::operator!=(const Valeur* v) const { + return m_valeur != v->getReel(); +} \ No newline at end of file diff --git a/ValeurReelle.h b/ValeurReelle.h new file mode 100644 index 0000000..74c7b51 --- /dev/null +++ b/ValeurReelle.h @@ -0,0 +1,30 @@ +#ifndef VALEURREELLE_H +#define VALEURREELLE_H + +#include "Valeur.h" +#include + +class ValeurReelle : public Valeur { +public: + ValeurReelle(float valeur); + int getEntier() const override; + float getReel() const override; + std::string getChaine() const override; + bool isVrai() const override; + + Valeur* const operator+(const Valeur* v) const override; + Valeur* const operator-(const Valeur* v) const override; + Valeur* const operator*(const Valeur* v) const override; + Valeur* const operator/(const Valeur* v) const override; + bool operator> (const Valeur* v) const override; + bool operator>=(const Valeur* v) const override; + bool operator< (const Valeur* v) const override; + bool operator<=(const Valeur* v) const override; + bool operator==(const Valeur* v) const override; + bool operator!=(const Valeur* v) const override; +private: + float m_valeur; +}; + +#endif /* VALEURREELLE_H */ + diff --git a/testAffectation.txt b/testAffectation.txt index 6d6adb1..52314ac 100644 --- a/testAffectation.txt +++ b/testAffectation.txt @@ -2,9 +2,15 @@ # Résultat attendu : # i = 6 # j = 3 +# k = 2.3 +# l = 5.3 +# m = 5 procedure principale() i = 6; j = i / 2; + k = 2.3; + l = k + j; + m = j + k; finproc From a1967ecf13d36fac976e6615a62c8a24aadc2041 Mon Sep 17 00:00:00 2001 From: Feelzor Date: Mon, 4 Nov 2019 18:35:21 +0100 Subject: [PATCH 03/10] feature-variables-typees: ajout type string --- Interpreteur.cpp | 4 +-- Interpreteur.h | 2 +- SymboleValue.cpp | 4 ++- ValeurChaine.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++ ValeurChaine.h | 30 ++++++++++++++++++++ VisiteurExecuter.cpp | 11 ++------ testAffectation.txt | 2 ++ 7 files changed, 107 insertions(+), 12 deletions(-) create mode 100644 ValeurChaine.cpp create mode 100644 ValeurChaine.h diff --git a/Interpreteur.cpp b/Interpreteur.cpp index 04a6ca8..f4efbaa 100644 --- a/Interpreteur.cpp +++ b/Interpreteur.cpp @@ -182,9 +182,9 @@ Noeud* Interpreteur::expMult(){ } Noeud* Interpreteur::facteur() { - // ::= | | | - | non | ( ) + // ::= | | | | - | non | ( ) Noeud* fact = nullptr; - if (m_lecteur.getSymbole() == "" || m_lecteur.getSymbole() == "" || m_lecteur.getSymbole() == "") { + if (m_lecteur.getSymbole() == "" || m_lecteur.getSymbole() == "" || m_lecteur.getSymbole() == "" || m_lecteur.getSymbole() == "") { fact = m_table.chercheAjoute(m_lecteur.getSymbole()); // on ajoute la variable ou l'entier à la table m_lecteur.avancer(); } else if (m_lecteur.getSymbole() == "-") { // - diff --git a/Interpreteur.h b/Interpreteur.h index 2caa13a..8c9a6a6 100644 --- a/Interpreteur.h +++ b/Interpreteur.h @@ -37,7 +37,7 @@ class Interpreteur { Noeud* expComp(); // ::= { == | != | < | <= | > | >= } Noeud* expAdd(); // ::= { + | - } Noeud* expMult(); // ::= { * | / } - Noeud* facteur(); // ::= | | | - | non | ( ) + Noeud* facteur(); // ::= | | | | - | non | ( ) // ::= + | - | * | / | < | > | <= | >= | == | != | et | ou Noeud* instSi(); // ::= si ( ) { sinonsi () } [ sinon ] finsi Noeud* instPour(); // ::= pour ( [ ] ; ; [ ]) finpour diff --git a/SymboleValue.cpp b/SymboleValue.cpp index bfe2319..3f356ce 100644 --- a/SymboleValue.cpp +++ b/SymboleValue.cpp @@ -4,13 +4,15 @@ #include #include "ValeurEntiere.h" #include "ValeurReelle.h" +#include "ValeurChaine.h" SymboleValue::SymboleValue(const Symbole & s) : Symbole(s.getChaine()) { if (s == "") { setValeur(atoi(s.getChaine().c_str())); // c_str convertit une string en char* } else if (s == "") { - setValeur(-1); + this->m_valeur = new ValeurChaine(s.getChaine().substr(1, s.getChaine().size() - 2)); + m_defini = true; } else if (s == "") { this->m_valeur = new ValeurReelle(stof(s.getChaine())); m_defini = true; diff --git a/ValeurChaine.cpp b/ValeurChaine.cpp new file mode 100644 index 0000000..75d8f1b --- /dev/null +++ b/ValeurChaine.cpp @@ -0,0 +1,66 @@ +#include "ValeurChaine.h" +#include "ValeurReelle.h" + +#include + +ValeurChaine::ValeurChaine(std::string valeur) : m_valeur(valeur) {} + +bool ValeurChaine::isVrai() const { + return m_valeur.size() > 0; +} + +int ValeurChaine::getEntier() const { + return std::stoi(m_valeur); +} + +float ValeurChaine::getReel() const { + return std::stof(m_valeur); +} + +std::string ValeurChaine::getChaine() const { + return m_valeur; +} + +Valeur* const ValeurChaine::operator+(const Valeur* v) const { + return new ValeurChaine(m_valeur + v->getChaine()); +} + +Valeur* const ValeurChaine::operator-(const Valeur* v) const { + return new ValeurReelle(std::stof(m_valeur) - v->getReel()); +} + +Valeur* const ValeurChaine::operator*(const Valeur* v) const { + std::string val = ""; + for (int i = 0; i < v->getEntier(); i++) { + val += m_valeur; + } + return new ValeurChaine(val); +} + +Valeur* const ValeurChaine::operator/(const Valeur* v) const { + return new ValeurReelle(std::stof(m_valeur) / v->getReel()); +} + +bool ValeurChaine::operator>(const Valeur* v) const { + return m_valeur > v->getChaine(); +} + +bool ValeurChaine::operator>=(const Valeur* v) const { + return m_valeur >= v->getChaine(); +} + +bool ValeurChaine::operator<(const Valeur* v) const { + return m_valeur < v->getChaine(); +} + +bool ValeurChaine::operator<=(const Valeur* v) const { + return m_valeur <= v->getChaine(); +} + +bool ValeurChaine::operator==(const Valeur* v) const { + return m_valeur == v->getChaine(); +} + +bool ValeurChaine::operator!=(const Valeur* v) const { + return m_valeur != v->getChaine(); +} \ No newline at end of file diff --git a/ValeurChaine.h b/ValeurChaine.h new file mode 100644 index 0000000..e9499b3 --- /dev/null +++ b/ValeurChaine.h @@ -0,0 +1,30 @@ +#ifndef VALEURCHAINE_H +#define VALEURCHAINE_H + +#include "Valeur.h" +#include + +class ValeurChaine : public Valeur { +public: + ValeurChaine(std::string valeur); + int getEntier() const override; + float getReel() const override; + std::string getChaine() const override; + bool isVrai() const override; + + Valeur* const operator+(const Valeur* v) const override; + Valeur* const operator-(const Valeur* v) const override; + Valeur* const operator*(const Valeur* v) const override; + Valeur* const operator/(const Valeur* v) const override; + bool operator> (const Valeur* v) const override; + bool operator>=(const Valeur* v) const override; + bool operator< (const Valeur* v) const override; + bool operator<=(const Valeur* v) const override; + bool operator==(const Valeur* v) const override; + bool operator!=(const Valeur* v) const override; +private: + std::string m_valeur; +}; + +#endif /* VALEURCHAINE_H */ + diff --git a/VisiteurExecuter.cpp b/VisiteurExecuter.cpp index 8e09ffd..0f87efb 100644 --- a/VisiteurExecuter.cpp +++ b/VisiteurExecuter.cpp @@ -97,14 +97,9 @@ void VisiteurExecuter::visiterNoeudInstLire(NoeudInstLire* noeud) { void VisiteurExecuter::visiterNoeudInstEcrire(NoeudInstEcrire* noeud) { for (Noeud* inst : noeud->getEcritures()) { - if ((typeid (*inst) == typeid (SymboleValue) && *((SymboleValue*) inst) == "")) { - string s = ((SymboleValue*) inst)->getChaine(); - cout << s.substr(1, s.size() - 2); // On retire le premier et le dernier caractère (les ") - } else { - m_derniereValeur = 0; - inst->accepter(*this); - cout << m_derniereValeur; - } + m_derniereValeur = 0; + inst->accepter(*this); + cout << m_derniereValeur; } } diff --git a/testAffectation.txt b/testAffectation.txt index 52314ac..b99bec6 100644 --- a/testAffectation.txt +++ b/testAffectation.txt @@ -5,12 +5,14 @@ # k = 2.3 # l = 5.3 # m = 5 +# n = BlaBlaCar procedure principale() i = 6; j = i / 2; k = 2.3; l = k + j; m = j + k; + n = "Bla" * 2 + "Car"; finproc From d9c6ccb53137755fb353d2f551df13c363f80f0c Mon Sep 17 00:00:00 2001 From: Feelzor Date: Mon, 4 Nov 2019 19:31:01 +0100 Subject: [PATCH 04/10] feature-variables-typees: ajout compilation --- VisiteurCompiler.cpp | 87 ++++++++++++++++++++------------------------ main.cpp | 13 +------ 2 files changed, 42 insertions(+), 58 deletions(-) diff --git a/VisiteurCompiler.cpp b/VisiteurCompiler.cpp index 13abcf7..bb3e4b2 100644 --- a/VisiteurCompiler.cpp +++ b/VisiteurCompiler.cpp @@ -12,11 +12,6 @@ void VisiteurCompiler::visiterNoeudSeqInst(NoeudSeqInst* noeud) { } void VisiteurCompiler::visiterNoeudAffectation(NoeudAffectation* noeud) { - bool instructionSeule = true; - if (m_indentation < 0) { - instructionSeule = false; - } - int indent = m_indentation; m_indentation = -1; noeud->getVariable()->accepter(*this); @@ -24,7 +19,6 @@ void VisiteurCompiler::visiterNoeudAffectation(NoeudAffectation* noeud) { noeud->getExpression()->accepter(*this); m_indentation = indent; - if (instructionSeule) m_out << ";"; } void VisiteurCompiler::visiterNoeudOperateurBinaire(NoeudOperateurBinaire* noeud) { @@ -34,11 +28,11 @@ void VisiteurCompiler::visiterNoeudOperateurBinaire(NoeudOperateurBinaire* noeud m_out << "("; if (op == "non") { - m_out << "!"; + m_out << "not "; noeud->getOperandeGauche()->accepter(*this); } else { - if (op == "et") op = "&&"; - else if (op == "ou") op = "||"; + if (op == "et") op = " and "; + else if (op == "ou") op = " or "; noeud->getOperandeGauche()->accepter(*this); m_out << op; @@ -52,23 +46,22 @@ void VisiteurCompiler::visiterNoeudOperateurBinaire(NoeudOperateurBinaire* noeud void VisiteurCompiler::visiterNoeudInstSi(NoeudInstSi* noeud) { std::string indent(m_indentation * 4, ' '); if (noeud->getCondition() != nullptr) { - if (!noeud->isPremiereCondition()) { m_out << ' '; } - m_out << "if ("; + m_out << "if "; int indentOrigine = m_indentation; m_indentation = -1; noeud->getCondition()->accepter(*this); m_indentation = indentOrigine; - m_out << ")"; + } else { + m_out << "se"; } - m_out << " {" << endl; + m_out << ":" << endl; m_indentation++; noeud->getSequence()->accepter(*this); m_indentation--; - m_out << indent << "}"; if (noeud->getProchaineCondition() != nullptr) { - m_out << " else"; + m_out << "el"; noeud->getProchaineCondition()->accepter(*this); } else { m_out << endl; @@ -77,73 +70,73 @@ void VisiteurCompiler::visiterNoeudInstSi(NoeudInstSi* noeud) { void VisiteurCompiler::visiterNoeudInstRepeter(NoeudInstRepeter* noeud) { std::string indent(m_indentation * 4, ' '); - m_out << "do {" << endl; - m_indentation++; - noeud->getSequence()->accepter(*this); - m_indentation--; - m_out << indent << "} while (!("; + m_out << indent << "transpilation_dowhile_boolean = 0" << endl; + m_out << "while not ("; int indentOrigine = m_indentation; m_indentation = -1; noeud->getCondition()->accepter(*this); m_indentation = indentOrigine; - m_out << "));" << endl; + m_out << ") or transpilation_dowhile_boolean == 0:" << endl; + m_indentation++; + m_out << indent << " transpilation_dowhile_boolean+=1" << endl; + noeud->getSequence()->accepter(*this); + m_indentation--; } void VisiteurCompiler::visiterNoeudInstPour(NoeudInstPour* noeud) { std::string indent(4 * m_indentation, ' '); int indentOrigine = m_indentation; - m_indentation = -1; - m_out << "for ("; + if (noeud->getInit() != nullptr) noeud->getInit()->accepter(*this); - m_out << ";"; + m_out << endl; + m_indentation = -1; + m_out << "while"; noeud->getCondition()->accepter(*this); - m_out << ";"; - if (noeud->getAffectation() != nullptr) noeud->getAffectation()->accepter(*this); - m_out << ") {" << endl; + m_out << ":" << endl; m_indentation = indentOrigine + 1; noeud->getSequence()->accepter(*this); + m_out << indent << " "; + if (noeud->getAffectation() != nullptr) noeud->getAffectation()->accepter(*this); m_indentation--; - m_out << indent << "}" << endl; } void VisiteurCompiler::visiterNoeudInstTantQue(NoeudInstTantQue* noeud) { std::string indent(m_indentation * 4, ' '); m_out << "while " ; noeud->getCondition()->accepter(*this); - m_out << " {" << endl; + m_out << ":" << endl; m_indentation++; noeud->getSequence()->accepter(*this); m_indentation--; - m_out << indent << "}" << endl; } void VisiteurCompiler::visiterNoeudInstLire(NoeudInstLire* noeud) { - m_out << "std::cin"; + std::string indent(m_indentation * 4, ' '); for (Noeud* var : noeud->getVariables()) { - m_out << " >> "; - int indent = m_indentation; + m_out << indent; + int currIndent = m_indentation; m_indentation = -1; var->accepter(*this); - m_indentation = indent; + m_indentation = currIndent; + m_out << " = input()" << endl; } - - m_out << ";"; } void VisiteurCompiler::visiterNoeudInstEcrire(NoeudInstEcrire* noeud) { - m_out << "std::cout"; + std::string indent(m_indentation * 4, ' '); + bool first = true; for (Noeud* inst : noeud->getEcritures()) { - m_out << " << "; - if ((typeid (*inst) == typeid (SymboleValue) && *((SymboleValue*) inst) == "")) { - m_out << ((SymboleValue*) inst)->getChaine(); - } else { - int indent = m_indentation; - m_indentation = -1; - inst->accepter(*this); - m_indentation = indent; - } + if (first) m_out << "print("; + else m_out << indent << "print("; + + int currIndent = m_indentation; + m_indentation = -1; + inst->accepter(*this); + m_indentation = currIndent; + m_out << ", end = '')" << endl; + first = false; } - m_out << ";"; + m_out << indent << "print('')" << endl; } void VisiteurCompiler::visiterSymboleValue(SymboleValue* symbole) { diff --git a/main.cpp b/main.cpp index ff15b60..33bf8da 100644 --- a/main.cpp +++ b/main.cpp @@ -44,6 +44,7 @@ int main(int argc, char* argv[]) { cout << endl << "================ Syntaxe Correcte" << endl; } else { cout << endl << "================ Syntaxe Incorrecte" << endl; + return 1; } if (compile) { compiler(*out, interpreteur.getTable(), interpreteur.getArbre()); @@ -71,16 +72,6 @@ int main(int argc, char* argv[]) { } void compiler(ostream& out, const TableSymboles& symboles, Noeud* arbre) { - std::string indentationBasique(4, ' '); - out << "#include " << endl << endl; - out << "int main() {" << endl; - for (int i = 0; i < symboles.getTaille(); i++) { - const SymboleValue s = symboles[i]; - if (s == "") { - out << indentationBasique << "int " << s.getChaine() << ";" << endl; - } - } - VisiteurCompiler visiteur(out, 1); + VisiteurCompiler visiteur(out, 0); arbre->accepter(visiteur); - out << "}" << endl; } \ No newline at end of file From e9273e9669b863deb79187daf3856de8959d6030 Mon Sep 17 00:00:00 2001 From: Feelzor Date: Mon, 4 Nov 2019 19:33:52 +0100 Subject: [PATCH 05/10] feature-variables-typees: correction bug avec derniereValeur ne valant jamais faux --- VisiteurExecuter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/VisiteurExecuter.cpp b/VisiteurExecuter.cpp index 0f87efb..b237e92 100644 --- a/VisiteurExecuter.cpp +++ b/VisiteurExecuter.cpp @@ -44,7 +44,7 @@ void VisiteurExecuter::visiterNoeudOperateurBinaire(NoeudOperateurBinaire* noeud void VisiteurExecuter::visiterNoeudInstSi(NoeudInstSi* noeud) { if (noeud->getCondition() != nullptr) { noeud->getCondition()->accepter(*this); - if (m_derniereValeur) { + if (m_derniereValeur->isVrai()) { noeud->getSequence()->accepter(*this); } else if (noeud->getProchaineCondition() != nullptr) { noeud->getProchaineCondition()->accepter(*this); @@ -64,7 +64,7 @@ void VisiteurExecuter::visiterNoeudInstRepeter(NoeudInstRepeter* noeud) { void VisiteurExecuter::visiterNoeudInstPour(NoeudInstPour* noeud) { if (noeud->getInit() != nullptr) noeud->getInit()->accepter(*this); noeud->getCondition()->accepter(*this); - while (m_derniereValeur) { + while (m_derniereValeur->isVrai()) { noeud->getSequence()->accepter(*this); if (noeud->getAffectation() != nullptr) noeud->getAffectation()->accepter(*this); noeud->getCondition()->accepter(*this); @@ -73,7 +73,7 @@ void VisiteurExecuter::visiterNoeudInstPour(NoeudInstPour* noeud) { void VisiteurExecuter::visiterNoeudInstTantQue(NoeudInstTantQue* noeud) { noeud->getCondition()->accepter(*this); - while (m_derniereValeur) { + while (m_derniereValeur->isVrai()) { noeud->getSequence()->accepter(*this); noeud->getCondition()->accepter(*this); } From 858e054741122574a6649deddabda2ef7b545657 Mon Sep 17 00:00:00 2001 From: Feelzor Date: Mon, 4 Nov 2019 19:34:46 +0100 Subject: [PATCH 06/10] feature-variable-typees: ajout commentaire pour indiquer qu'on transpile en Python3 --- VisiteurCompiler.h | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/VisiteurCompiler.h b/VisiteurCompiler.h index 7b5d885..bdb8c6f 100644 --- a/VisiteurCompiler.h +++ b/VisiteurCompiler.h @@ -1,21 +1,9 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - -/* - * File: VisiteurCompiler.h - * Author: feelzor - * - * Created on October 30, 2019, 3:10 PM - */ - #ifndef VISITEURCOMPILER_H #define VISITEURCOMPILER_H #include "Visiteur.h" +// Cette classe permet de transpiler le code en Python3 class VisiteurCompiler : public Visiteur { public: VisiteurCompiler(std::ostream& out, int indentation); From e19fee6928187c842c3d71785aa0761ddd1bd512 Mon Sep 17 00:00:00 2001 From: Feelzor Date: Mon, 4 Nov 2019 22:27:59 +0100 Subject: [PATCH 07/10] =?UTF-8?q?feature-procedures:=20ajout=20des=20proc?= =?UTF-8?q?=C3=A9dures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ArbreAbstrait.cpp | 12 +++++++ ArbreAbstrait.h | 19 +++++++++++ Instruction.cpp | 2 +- Instruction.h | 2 +- Interpreteur.cpp | 77 ++++++++++++++++++++++++++++++++++++++------ Interpreteur.h | 8 +++-- Procedure.cpp | 14 ++++++++ Procedure.h | 21 ++++++++++++ TableProcedures.cpp | 33 +++++++++++++++++++ TableProcedures.h | 25 ++++++++++++++ Visiteur.h | 1 + VisiteurCompiler.cpp | 9 ++++++ VisiteurCompiler.h | 1 + VisiteurExecuter.cpp | 5 +++ VisiteurExecuter.h | 5 ++- motsCles.txt | 1 + testProcedure.txt | 9 ++++++ 17 files changed, 228 insertions(+), 16 deletions(-) create mode 100644 Procedure.cpp create mode 100644 Procedure.h create mode 100644 TableProcedures.cpp create mode 100644 TableProcedures.h create mode 100644 testProcedure.txt diff --git a/ArbreAbstrait.cpp b/ArbreAbstrait.cpp index 5e95d9e..8adcd63 100644 --- a/ArbreAbstrait.cpp +++ b/ArbreAbstrait.cpp @@ -134,4 +134,16 @@ void NoeudInstEcrire::ajoute(Noeud* instruction) { void NoeudInstEcrire::accepter(Visiteur& visiteur) { visiteur.visiterNoeudInstEcrire(this); +} + +//////////////////////////////////////////////////////////////////////////////// +// NoeudInstAppel +//////////////////////////////////////////////////////////////////////////////// + +NoeudInstAppel::NoeudInstAppel(Symbole nom, vector parametres) +: m_nom(nom), m_parametres(parametres) { +} + +void NoeudInstAppel::accepter(Visiteur& visiteur) { + visiteur.visiterNoeudInstAppel(this); } \ No newline at end of file diff --git a/ArbreAbstrait.h b/ArbreAbstrait.h index c325c9c..4b2f014 100644 --- a/ArbreAbstrait.h +++ b/ArbreAbstrait.h @@ -198,4 +198,23 @@ class NoeudInstEcrire : public Noeud { vector m_ecritures; }; +//////////////////////////////////////////////////////////////////////////////// +class NoeudInstAppel : public Noeud { + // Classe pour représenter un noeud "instruction appel" +public: + NoeudInstAppel(Symbole nom, vector parametres); + // Construit une "instruction appel" avec sa condition et sa séquence d'instruction + + ~NoeudInstAppel() { + } // A cause du destructeur virtuel de la classe Noeud + void accepter(Visiteur& visiteur) override; + + inline Symbole getNom() const { return m_nom; } + inline vector getParametres() const { return m_parametres; } + +private: + Symbole m_nom; + vector m_parametres; +}; + #endif /* ARBREABSTRAIT_H */ diff --git a/Instruction.cpp b/Instruction.cpp index 483d757..492b612 100644 --- a/Instruction.cpp +++ b/Instruction.cpp @@ -5,7 +5,7 @@ Instruction::Instruction() { bool Instruction::isInstruction(Symbole sym) { int i = 0; - while (i < 7 && !(sym == m_instructions[i])) { + while (i < 8 && !(sym == m_instructions[i])) { i++; } return sym == m_instructions[i]; diff --git a/Instruction.h b/Instruction.h index 6e38df4..eb45b67 100644 --- a/Instruction.h +++ b/Instruction.h @@ -22,7 +22,7 @@ class Instruction { Instruction(); bool isInstruction(Symbole sym); private: - string m_instructions[7] = {"","ecrire","si","pour","tantque","repeter","lire"}; + string m_instructions[8] = {"","ecrire","si","pour","tantque","repeter","lire","appel"}; }; diff --git a/Interpreteur.cpp b/Interpreteur.cpp index f4efbaa..8560e56 100644 --- a/Interpreteur.cpp +++ b/Interpreteur.cpp @@ -1,5 +1,6 @@ #include "Interpreteur.h" #include "Instruction.h" +#include "TableProcedures.h" #include #include using namespace std; @@ -44,17 +45,49 @@ void Interpreteur::erreur(const string & message) const { } Noeud* Interpreteur::programme() { - // ::= procedure principale() finproc FIN_FICHIER - testerEtAvancer("procedure"); - testerEtAvancer("principale"); - testerEtAvancer("("); - testerEtAvancer(")"); - Noeud* sequence = seqInst(); - testerEtAvancer("finproc"); - tester(""); - return sequence; + // ::= {procedure } procedure principale() finproc FIN_FICHIER + Noeud* sequence = nullptr; + while (sequence == nullptr) { + testerEtAvancer("procedure"); + if (m_lecteur.getSymbole() == "") { + procedure(); + } else { + testerEtAvancer("principale"); + testerEtAvancer("("); + testerEtAvancer(")"); + sequence = seqInst(); + testerEtAvancer("finproc"); + tester(""); + } + } + return sequence; } +void Interpreteur::procedure() { + // ::= ([ {, }]) finproc + TableSymboles table = m_table; + m_table = TableSymboles(); + std::vector parametres; + + tester(""); + Symbole nom = m_lecteur.getSymbole(); + m_lecteur.avancer(); + testerEtAvancer("("); + if (m_lecteur.getSymbole() == "") { + parametres.push_back(m_table.chercheAjoute(m_lecteur.getSymbole())); + m_lecteur.avancer(); + while (m_lecteur.verifierPourAvancer(",")) { + tester(""); + parametres.push_back(m_table.chercheAjoute(m_lecteur.getSymbole())); + } + } + testerEtAvancer(")"); + Noeud* sequence = seqInst(); + testerEtAvancer("finproc"); + TableProcedures::getTable()->ajoutProcedure(nom, new Procedure(m_table, sequence, parametres)); + m_table = table; +} + Noeud* Interpreteur::seqInst() { // ::= { } Instruction* instructions = new Instruction(); @@ -101,6 +134,9 @@ Noeud* Interpreteur::inst() { else if(m_lecteur.getSymbole() == "lire"){ return instLire(); } + else if(m_lecteur.getSymbole() == "appel"){ + return instAppel(); + } else { erreur("Instruction incorrecte"); return nullptr; @@ -320,4 +356,25 @@ Noeud* Interpreteur::instLire(){ testerEtAvancer(")"); testerEtAvancer(";"); return var; -} \ No newline at end of file +} + +Noeud* Interpreteur::instAppel() { + // ::= appel ([ {, }]); + testerEtAvancer("appel"); + tester(""); + Symbole nom = m_lecteur.getSymbole(); + m_lecteur.avancer(); + testerEtAvancer("("); + + std::vector parametres; + if (m_lecteur.getSymbole() != ")") { + parametres.push_back(expression()); + while (m_lecteur.verifierPourAvancer(",")) { + parametres.push_back(expression()); + } + } + testerEtAvancer(")"); + testerEtAvancer(";"); + + return new NoeudInstAppel(nom, parametres); +} \ No newline at end of file diff --git a/Interpreteur.h b/Interpreteur.h index 8c9a6a6..666cdc8 100644 --- a/Interpreteur.h +++ b/Interpreteur.h @@ -24,10 +24,11 @@ class Interpreteur { Lecteur m_lecteur; // Le lecteur de symboles utilisé pour analyser le fichier TableSymboles m_table; // La table des symboles valués Noeud* m_arbre; // L'arbre abstrait - bool m_erreur; // Etat de l'intrpreteur + bool m_erreur; // Etat de l'interpreteur // Implémentation de la grammaire - Noeud* programme(); // ::= procedure principale() finproc FIN_FICHIER + Noeud* programme(); // ::= {procedure } procedure principale() finproc FIN_FICHIER + void procedure(); // ::= ([ {, }]) finproc Noeud* seqInst(); // ::= { } Noeud* inst(); // ::= ; | @@ -42,9 +43,10 @@ class Interpreteur { Noeud* instSi(); // ::= si ( ) { sinonsi () } [ sinon ] finsi Noeud* instPour(); // ::= pour ( [ ] ; ; [ ]) finpour Noeud* instTantQue(); // ::= tantque ( ) fintantque - Noeud* instLire(); // ::= lire (variable {, variable}); + Noeud* instLire(); // ::= lire ( {, }); Noeud* instEcrire(); // ::= ecrire ( | {, | } ); Noeud* instRepeter(); // ::= repeter jusqua ( ) + Noeud* instAppel(); // ::= appel ([ {, }]); // outils pour simplifier l'analyse syntaxique void tester (const string & symboleAttendu) const; // Si symbole courant != symboleAttendu, on lève une exception diff --git a/Procedure.cpp b/Procedure.cpp new file mode 100644 index 0000000..962cc60 --- /dev/null +++ b/Procedure.cpp @@ -0,0 +1,14 @@ +#include "Procedure.h" + +Procedure::Procedure(TableSymboles table, Noeud* sequence, std::vector parametres) +: m_table(table), m_sequence(sequence), m_params(parametres) {} + +void Procedure::accepter(Visiteur& visiteur) { + m_sequence->accepter(visiteur); +} + +void Procedure::empiler(std::vector parametres) { + for (int i = 0; i < parametres.size() && i < m_params.size(); i++) { + m_params[i]->setValeur(parametres[i]); + } +} \ No newline at end of file diff --git a/Procedure.h b/Procedure.h new file mode 100644 index 0000000..896ef3b --- /dev/null +++ b/Procedure.h @@ -0,0 +1,21 @@ +#ifndef PROCEDURE_H +#define PROCEDURE_H + +#include "ArbreAbstrait.h" +#include "TableSymboles.h" +#include "SymboleValue.h" +#include + +class Procedure : public Noeud { +public: + Procedure(TableSymboles table, Noeud* sequence, std::vector parametres); + void accepter(Visiteur& visiteur) override; + void empiler(std::vector parametres); +private: + TableSymboles m_table; + Noeud* m_sequence; + std::vector m_params; +}; + +#endif /* PROCEDURE_H */ + diff --git a/TableProcedures.cpp b/TableProcedures.cpp new file mode 100644 index 0000000..e129d29 --- /dev/null +++ b/TableProcedures.cpp @@ -0,0 +1,33 @@ +#include "TableProcedures.h" +#include "Procedure.h" +#include + +TableProcedures* TableProcedures::table = nullptr; + +TableProcedures::TableProcedures() {} + +TableProcedures* TableProcedures::getTable() { + if (table == nullptr) { + table = new TableProcedures(); + } + + return table; +} + +void TableProcedures::ajoutProcedure(Symbole nom, Procedure* procedure) { + std::string nomProcedure(nom.getChaine()); + m_procedures.push_back(procedure); + m_noms.push_back(nom.getChaine()); +} + +void TableProcedures::executerProcedure(Symbole nom, std::vector parametres, VisiteurExecuter& v) { + long i = std::distance(m_noms.begin(), std::find(m_noms.begin(), m_noms.end(), nom.getChaine())); + Procedure* p = m_procedures[i]; + std::vector params; + for (Noeud* noeud : parametres) { + noeud->accepter(v); + params.push_back(v.getDerniereValeur()); + } + p->empiler(params); + p->accepter(v); +} \ No newline at end of file diff --git a/TableProcedures.h b/TableProcedures.h new file mode 100644 index 0000000..6cb4489 --- /dev/null +++ b/TableProcedures.h @@ -0,0 +1,25 @@ +#ifndef TABLEPROCEDURES_H +#define TABLEPROCEDURES_H + +#include +#include +#include +#include "Symbole.h" +#include "Procedure.h" +#include "VisiteurExecuter.h" + +class TableProcedures { +public: + static TableProcedures* getTable(); + void ajoutProcedure(Symbole nom, Procedure* procedure); + void executerProcedure(Symbole nom, std::vector parametres, VisiteurExecuter& v); +private: + TableProcedures(); + static TableProcedures* table; + + std::vector m_procedures; + std::vector m_noms; +}; + +#endif /* TABLEPROCEDURES_H */ + diff --git a/Visiteur.h b/Visiteur.h index 33a25bd..eb85727 100644 --- a/Visiteur.h +++ b/Visiteur.h @@ -28,6 +28,7 @@ class Visiteur { virtual void visiterNoeudInstTantQue(NoeudInstTantQue* noeud) = 0; virtual void visiterNoeudInstLire(NoeudInstLire* noeud) = 0; virtual void visiterNoeudInstEcrire(NoeudInstEcrire* noeud) = 0; + virtual void visiterNoeudInstAppel(NoeudInstAppel* noeud) = 0; virtual void visiterSymboleValue(SymboleValue* symbole) = 0; }; diff --git a/VisiteurCompiler.cpp b/VisiteurCompiler.cpp index bb3e4b2..56a4977 100644 --- a/VisiteurCompiler.cpp +++ b/VisiteurCompiler.cpp @@ -139,6 +139,15 @@ void VisiteurCompiler::visiterNoeudInstEcrire(NoeudInstEcrire* noeud) { m_out << indent << "print('')" << endl; } +void VisiteurCompiler::visiterNoeudInstAppel(NoeudInstAppel* noeud) { + m_out << noeud->getNom().getChaine() << "("; + for(int i = 0; i < noeud->getParametres().size(); i++) { + if (i != 0) { m_out << ", "; } + noeud->getParametres()[i]->accepter(*this); + } + m_out << ")" << endl; +} + void VisiteurCompiler::visiterSymboleValue(SymboleValue* symbole) { m_out << symbole->getChaine(); } \ No newline at end of file diff --git a/VisiteurCompiler.h b/VisiteurCompiler.h index bdb8c6f..ccd2f4c 100644 --- a/VisiteurCompiler.h +++ b/VisiteurCompiler.h @@ -17,6 +17,7 @@ class VisiteurCompiler : public Visiteur { void visiterNoeudInstTantQue(NoeudInstTantQue* noeud) override; void visiterNoeudInstLire(NoeudInstLire* noeud) override; void visiterNoeudInstEcrire(NoeudInstEcrire* noeud) override; + void visiterNoeudInstAppel(NoeudInstAppel* noeud) override; void visiterSymboleValue(SymboleValue* symbole) override; private: diff --git a/VisiteurExecuter.cpp b/VisiteurExecuter.cpp index b237e92..5987261 100644 --- a/VisiteurExecuter.cpp +++ b/VisiteurExecuter.cpp @@ -1,5 +1,6 @@ #include "VisiteurExecuter.h" #include "ValeurEntiere.h" +#include "TableProcedures.h" void VisiteurExecuter::visiterNoeudSeqInst(NoeudSeqInst* noeud) { for (unsigned int i = 0; i < noeud->getInstructions().size(); i++) @@ -103,6 +104,10 @@ void VisiteurExecuter::visiterNoeudInstEcrire(NoeudInstEcrire* noeud) { } } +void VisiteurExecuter::visiterNoeudInstAppel(NoeudInstAppel* noeud) { + TableProcedures::getTable()->executerProcedure(noeud->getNom(), noeud->getParametres(), *this); +} + void VisiteurExecuter::visiterSymboleValue(SymboleValue* symbole) { if (!symbole->estDefini()) throw IndefiniException(); // on lève une exception si valeur non définie m_derniereValeur = symbole->getValeur(); diff --git a/VisiteurExecuter.h b/VisiteurExecuter.h index 4f376c1..6c5abf3 100644 --- a/VisiteurExecuter.h +++ b/VisiteurExecuter.h @@ -15,9 +15,12 @@ class VisiteurExecuter : public Visiteur { void visiterNoeudInstTantQue(NoeudInstTantQue* noeud) override; void visiterNoeudInstLire(NoeudInstLire* noeud) override; void visiterNoeudInstEcrire(NoeudInstEcrire* noeud) override; + void visiterNoeudInstAppel(NoeudInstAppel* noeud) override; void visiterSymboleValue(SymboleValue* symbole) override; + + inline Valeur* getDerniereValeur() { return m_derniereValeur; } private: - Valeur* m_derniereValeur = 0; + Valeur* m_derniereValeur; }; #endif /* VISITEUREXECUTER_H */ diff --git a/motsCles.txt b/motsCles.txt index df58fd9..7e5f609 100644 --- a/motsCles.txt +++ b/motsCles.txt @@ -33,3 +33,4 @@ ecrire et ou non +appel diff --git a/testProcedure.txt b/testProcedure.txt new file mode 100644 index 0000000..a80f3c6 --- /dev/null +++ b/testProcedure.txt @@ -0,0 +1,9 @@ +# Résultat attendu : 9 + +procedure carre(a) + ecrire(a * a); +finproc + +procedure principale() + appel carre(3); +finproc \ No newline at end of file From f6af41192b292f5fb75ab518c9df2451b1f126db Mon Sep 17 00:00:00 2001 From: Feelzor Date: Mon, 4 Nov 2019 22:43:32 +0100 Subject: [PATCH 08/10] feature-demo: renommage des fichiers de test et correction du test CPPUnit --- testSi.txt => test01-SiSinonSi.txt | 0 testTantQue.txt => test02-TantQue.txt | 0 testRepeter.txt => test03-Repeter.txt | 0 testPour.txt => test04-Pour.txt | 0 testEcrire.txt => test05-Ecrire.txt | 0 testLire.txt => test06-Lire.txt | 0 testPourErreurSyntaxe.txt => test07-PourErreurSyntaxe.txt | 0 testProcedure.txt => test09-Procedure.txt | 0 tests/TestInstPour.cpp | 8 ++++---- 9 files changed, 4 insertions(+), 4 deletions(-) rename testSi.txt => test01-SiSinonSi.txt (100%) rename testTantQue.txt => test02-TantQue.txt (100%) rename testRepeter.txt => test03-Repeter.txt (100%) rename testPour.txt => test04-Pour.txt (100%) rename testEcrire.txt => test05-Ecrire.txt (100%) rename testLire.txt => test06-Lire.txt (100%) rename testPourErreurSyntaxe.txt => test07-PourErreurSyntaxe.txt (100%) rename testProcedure.txt => test09-Procedure.txt (100%) diff --git a/testSi.txt b/test01-SiSinonSi.txt similarity index 100% rename from testSi.txt rename to test01-SiSinonSi.txt diff --git a/testTantQue.txt b/test02-TantQue.txt similarity index 100% rename from testTantQue.txt rename to test02-TantQue.txt diff --git a/testRepeter.txt b/test03-Repeter.txt similarity index 100% rename from testRepeter.txt rename to test03-Repeter.txt diff --git a/testPour.txt b/test04-Pour.txt similarity index 100% rename from testPour.txt rename to test04-Pour.txt diff --git a/testEcrire.txt b/test05-Ecrire.txt similarity index 100% rename from testEcrire.txt rename to test05-Ecrire.txt diff --git a/testLire.txt b/test06-Lire.txt similarity index 100% rename from testLire.txt rename to test06-Lire.txt diff --git a/testPourErreurSyntaxe.txt b/test07-PourErreurSyntaxe.txt similarity index 100% rename from testPourErreurSyntaxe.txt rename to test07-PourErreurSyntaxe.txt diff --git a/testProcedure.txt b/test09-Procedure.txt similarity index 100% rename from testProcedure.txt rename to test09-Procedure.txt diff --git a/tests/TestInstPour.cpp b/tests/TestInstPour.cpp index ed66fb2..c09bb1c 100644 --- a/tests/TestInstPour.cpp +++ b/tests/TestInstPour.cpp @@ -32,7 +32,7 @@ void TestInstPour::tearDown() { } void TestInstPour::testPour() { - std::ifstream fichier("testPour.txt"); + std::ifstream fichier("test04-Pour.txt"); if (!fichier) { CPPUNIT_ASSERT_MESSAGE("Fichier impossible à ouvrir", false); } @@ -43,12 +43,12 @@ void TestInstPour::testPour() { interpreteur.getArbre()->accepter(visiteur); const TableSymboles& table = interpreteur.getTable(); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Test valeur i", 11, table[3].getValeur()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("Test valeur j", 385, table[4].getValeur()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Test valeur i", 11, table[3].getValeur()->getEntier()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Test valeur j", 385, table[4].getValeur()->getEntier()); } void TestInstPour::testPourErreur() { - std::ifstream fichier("testPourErreurSyntaxe.txt"); + std::ifstream fichier("test07-PourErreurSyntaxe.txt"); if (!fichier) { CPPUNIT_ASSERT_MESSAGE("Fichier impossible à ouvrir", false); } From 9e336c9e992dc31814e7cf2c7a3ea9e8142de064 Mon Sep 17 00:00:00 2001 From: Feelzor Date: Mon, 4 Nov 2019 23:04:57 +0100 Subject: [PATCH 09/10] feature-demo: ajout instruction random --- ArbreAbstrait.cpp | 10 ++++++++++ ArbreAbstrait.h | 20 +++++++++++++++++++- Interpreteur.cpp | 16 +++++++++++++++- Interpreteur.h | 3 ++- Visiteur.h | 1 + VisiteurCompiler.cpp | 8 ++++++++ VisiteurCompiler.h | 1 + VisiteurExecuter.cpp | 8 ++++++++ VisiteurExecuter.h | 1 + main.cpp | 2 ++ motsCles.txt | 1 + testAffectation.txt | 1 + 12 files changed, 69 insertions(+), 3 deletions(-) diff --git a/ArbreAbstrait.cpp b/ArbreAbstrait.cpp index 8adcd63..3f3b1c3 100644 --- a/ArbreAbstrait.cpp +++ b/ArbreAbstrait.cpp @@ -146,4 +146,14 @@ NoeudInstAppel::NoeudInstAppel(Symbole nom, vector parametres) void NoeudInstAppel::accepter(Visiteur& visiteur) { visiteur.visiterNoeudInstAppel(this); +} + +//////////////////////////////////////////////////////////////////////////////// +// NoeudInstAlea +//////////////////////////////////////////////////////////////////////////////// + +NoeudAlea::NoeudAlea(Noeud* min, Noeud* max) : m_min(min), m_max(max) {} + +void NoeudAlea::accepter(Visiteur& visiteur) { + visiteur.visiterNoeudAlea(this); } \ No newline at end of file diff --git a/ArbreAbstrait.h b/ArbreAbstrait.h index 4b2f014..99155c0 100644 --- a/ArbreAbstrait.h +++ b/ArbreAbstrait.h @@ -203,7 +203,7 @@ class NoeudInstAppel : public Noeud { // Classe pour représenter un noeud "instruction appel" public: NoeudInstAppel(Symbole nom, vector parametres); - // Construit une "instruction appel" avec sa condition et sa séquence d'instruction + // Construit une "instruction appel" avec son nom et ses paramètres ~NoeudInstAppel() { } // A cause du destructeur virtuel de la classe Noeud @@ -217,4 +217,22 @@ class NoeudInstAppel : public Noeud { vector m_parametres; }; +//////////////////////////////////////////////////////////////////////////////// +class NoeudAlea : public Noeud { + // Classe pour représenter un noeud "alea" +public: + NoeudAlea(Noeud* min, Noeud* max); + // Construit un "alea" avec son min et son max + + ~NoeudAlea() { + } // A cause du destructeur virtuel de la classe Noeud + void accepter(Visiteur& visiteur) override; + + inline Noeud* getMin() const { return m_min; } + inline Noeud* getMax() const { return m_max; } + +private: + Noeud* m_min; + Noeud* m_max; +}; #endif /* ARBREABSTRAIT_H */ diff --git a/Interpreteur.cpp b/Interpreteur.cpp index 8560e56..6f2834b 100644 --- a/Interpreteur.cpp +++ b/Interpreteur.cpp @@ -218,7 +218,7 @@ Noeud* Interpreteur::expMult(){ } Noeud* Interpreteur::facteur() { - // ::= | | | | - | non | ( ) + // ::= | | | | - | non | ( ) | Noeud* fact = nullptr; if (m_lecteur.getSymbole() == "" || m_lecteur.getSymbole() == "" || m_lecteur.getSymbole() == "" || m_lecteur.getSymbole() == "") { fact = m_table.chercheAjoute(m_lecteur.getSymbole()); // on ajoute la variable ou l'entier à la table @@ -235,6 +235,8 @@ Noeud* Interpreteur::facteur() { m_lecteur.avancer(); fact = expression(); testerEtAvancer(")"); + } else if (m_lecteur.getSymbole() == "alea") { + fact = alea(); } else erreur("Facteur incorrect"); return fact; @@ -377,4 +379,16 @@ Noeud* Interpreteur::instAppel() { testerEtAvancer(";"); return new NoeudInstAppel(nom, parametres); +} + +Noeud* Interpreteur::alea() { + // ::= alea(, ) + testerEtAvancer("alea"); + testerEtAvancer("("); + Noeud* min = expression(); + testerEtAvancer(","); + Noeud* max = expression(); + testerEtAvancer(")"); + + return new NoeudAlea(min, max); } \ No newline at end of file diff --git a/Interpreteur.h b/Interpreteur.h index 666cdc8..bca525c 100644 --- a/Interpreteur.h +++ b/Interpreteur.h @@ -38,7 +38,7 @@ class Interpreteur { Noeud* expComp(); // ::= { == | != | < | <= | > | >= } Noeud* expAdd(); // ::= { + | - } Noeud* expMult(); // ::= { * | / } - Noeud* facteur(); // ::= | | | | - | non | ( ) + Noeud* facteur(); // ::= | | | | - | non | ( ) | // ::= + | - | * | / | < | > | <= | >= | == | != | et | ou Noeud* instSi(); // ::= si ( ) { sinonsi () } [ sinon ] finsi Noeud* instPour(); // ::= pour ( [ ] ; ; [ ]) finpour @@ -47,6 +47,7 @@ class Interpreteur { Noeud* instEcrire(); // ::= ecrire ( | {, | } ); Noeud* instRepeter(); // ::= repeter jusqua ( ) Noeud* instAppel(); // ::= appel ([ {, }]); + Noeud* alea(); // ::= alea(, ) // outils pour simplifier l'analyse syntaxique void tester (const string & symboleAttendu) const; // Si symbole courant != symboleAttendu, on lève une exception diff --git a/Visiteur.h b/Visiteur.h index eb85727..050546d 100644 --- a/Visiteur.h +++ b/Visiteur.h @@ -29,6 +29,7 @@ class Visiteur { virtual void visiterNoeudInstLire(NoeudInstLire* noeud) = 0; virtual void visiterNoeudInstEcrire(NoeudInstEcrire* noeud) = 0; virtual void visiterNoeudInstAppel(NoeudInstAppel* noeud) = 0; + virtual void visiterNoeudAlea(NoeudAlea* noeud) = 0; virtual void visiterSymboleValue(SymboleValue* symbole) = 0; }; diff --git a/VisiteurCompiler.cpp b/VisiteurCompiler.cpp index 56a4977..9d59365 100644 --- a/VisiteurCompiler.cpp +++ b/VisiteurCompiler.cpp @@ -148,6 +148,14 @@ void VisiteurCompiler::visiterNoeudInstAppel(NoeudInstAppel* noeud) { m_out << ")" << endl; } +void VisiteurCompiler::visiterNoeudAlea(NoeudAlea* noeud) { + m_out << "random.randint("; + noeud->getMin()->accepter(*this); + m_out << ","; + noeud->getMax()->accepter(*this); + m_out << ")" << endl; +} + void VisiteurCompiler::visiterSymboleValue(SymboleValue* symbole) { m_out << symbole->getChaine(); } \ No newline at end of file diff --git a/VisiteurCompiler.h b/VisiteurCompiler.h index ccd2f4c..df75399 100644 --- a/VisiteurCompiler.h +++ b/VisiteurCompiler.h @@ -18,6 +18,7 @@ class VisiteurCompiler : public Visiteur { void visiterNoeudInstLire(NoeudInstLire* noeud) override; void visiterNoeudInstEcrire(NoeudInstEcrire* noeud) override; void visiterNoeudInstAppel(NoeudInstAppel* noeud) override; + void visiterNoeudAlea(NoeudAlea* noeud) override; void visiterSymboleValue(SymboleValue* symbole) override; private: diff --git a/VisiteurExecuter.cpp b/VisiteurExecuter.cpp index 5987261..ecd2d20 100644 --- a/VisiteurExecuter.cpp +++ b/VisiteurExecuter.cpp @@ -108,6 +108,14 @@ void VisiteurExecuter::visiterNoeudInstAppel(NoeudInstAppel* noeud) { TableProcedures::getTable()->executerProcedure(noeud->getNom(), noeud->getParametres(), *this); } +void VisiteurExecuter::visiterNoeudAlea(NoeudAlea* noeud) { + noeud->getMin()->accepter(*this); + int min = m_derniereValeur->getEntier(); + noeud->getMax()->accepter(*this); + int max = m_derniereValeur->getEntier(); + m_derniereValeur = new ValeurEntiere(rand() % (max - min) + min); +} + void VisiteurExecuter::visiterSymboleValue(SymboleValue* symbole) { if (!symbole->estDefini()) throw IndefiniException(); // on lève une exception si valeur non définie m_derniereValeur = symbole->getValeur(); diff --git a/VisiteurExecuter.h b/VisiteurExecuter.h index 6c5abf3..bdaa9f9 100644 --- a/VisiteurExecuter.h +++ b/VisiteurExecuter.h @@ -16,6 +16,7 @@ class VisiteurExecuter : public Visiteur { void visiterNoeudInstLire(NoeudInstLire* noeud) override; void visiterNoeudInstEcrire(NoeudInstEcrire* noeud) override; void visiterNoeudInstAppel(NoeudInstAppel* noeud) override; + void visiterNoeudAlea(NoeudAlea* noeud) override; void visiterSymboleValue(SymboleValue* symbole) override; inline Valeur* getDerniereValeur() { return m_derniereValeur; } diff --git a/main.cpp b/main.cpp index 33bf8da..09ee76f 100644 --- a/main.cpp +++ b/main.cpp @@ -11,6 +11,7 @@ using namespace std; void compiler(ostream& out, const TableSymboles& symboles, Noeud* arbre); int main(int argc, char* argv[]) { + srand (time(NULL)); bool compile = false; string nomFich; ofstream o; @@ -72,6 +73,7 @@ int main(int argc, char* argv[]) { } void compiler(ostream& out, const TableSymboles& symboles, Noeud* arbre) { + out << "import random" << endl; VisiteurCompiler visiteur(out, 0); arbre->accepter(visiteur); } \ No newline at end of file diff --git a/motsCles.txt b/motsCles.txt index 7e5f609..2699be0 100644 --- a/motsCles.txt +++ b/motsCles.txt @@ -34,3 +34,4 @@ et ou non appel +alea \ No newline at end of file diff --git a/testAffectation.txt b/testAffectation.txt index b99bec6..cb02f7f 100644 --- a/testAffectation.txt +++ b/testAffectation.txt @@ -13,6 +13,7 @@ procedure principale() l = k + j; m = j + k; n = "Bla" * 2 + "Car"; + o = alea(3, 100); finproc From 4656e85443a3596e1dec0e6401e7e3b3ecea187f Mon Sep 17 00:00:00 2001 From: Feelzor Date: Mon, 4 Nov 2019 23:11:29 +0100 Subject: [PATCH 10/10] feature-demo: ajout test alea et plus ou moins --- pom.txt | 18 ++++++++++++++++++ test08-alea.txt | 6 ++++++ 2 files changed, 24 insertions(+) create mode 100644 pom.txt create mode 100644 test08-alea.txt diff --git a/pom.txt b/pom.txt new file mode 100644 index 0000000..a4068eb --- /dev/null +++ b/pom.txt @@ -0,0 +1,18 @@ +procedure principale() + ecrire("Entrez le minimum et le maximum : "); + lire(min, max); + nbMyst = alea(min, max); + nbDevin = nbMyst - 1; + nbCoups = 0; + tantque (nbDevin != nbMyst) + lire(nbDevin); + nbCoups = nbCoups + 1; + si (nbMyst > nbDevin) + ecrire("C'est plus"); + sinonsi (nbMyst < nbDevin) + ecrire("C'est moins"); + finsi + fintantque + + ecrire("Bravo, vous avez trouvé en ", nbCoups, " coup(s)"); +finproc \ No newline at end of file diff --git a/test08-alea.txt b/test08-alea.txt new file mode 100644 index 0000000..c744db8 --- /dev/null +++ b/test08-alea.txt @@ -0,0 +1,6 @@ +# Résultat attendu : +# i : Nombre entre 1 et 100 + +procedure principale() + i = alea(1, 100); +finproc