mirror of
https://github.com/LucasVbr/interpreteur-lir.git
synced 2026-07-09 15:08:05 +00:00
Codes sources prototype 1
This commit is contained in:
@@ -0,0 +1,165 @@
|
|||||||
|
/**
|
||||||
|
* Analyseur.java 9 mai 2021
|
||||||
|
* IUT Rodez info1 2020-2021, pas de copyright, aucun droit
|
||||||
|
*/
|
||||||
|
package interpreteurlir;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
import interpreteurlir.expressions.Expression;
|
||||||
|
import interpreteurlir.motscles.Commande;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analyseur de l'entrée standard du programme interpréteur LIR.
|
||||||
|
* @author Nicolas Caminade
|
||||||
|
* @author Sylvan Courtiol
|
||||||
|
* @author Pierre Debas
|
||||||
|
* @author Heïa Dexter
|
||||||
|
* @author Lucas Vabre
|
||||||
|
*/
|
||||||
|
public class Analyseur {
|
||||||
|
|
||||||
|
/** Symbole d'invite de commande */
|
||||||
|
public static final String INVITE = "? ";
|
||||||
|
|
||||||
|
/** Message feedback ok */
|
||||||
|
public static final String OK_FEEDBACK = "ok";
|
||||||
|
|
||||||
|
/** Message feedback not ok */
|
||||||
|
public static final String NOK_FEEDBACK = "nok : ";
|
||||||
|
|
||||||
|
/** analyseur de l'entrée standard */
|
||||||
|
private Scanner entree;
|
||||||
|
|
||||||
|
/** contexte de cet analyseur */
|
||||||
|
private Contexte contexteGlobal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise un analyseur ayant son propre contexte.
|
||||||
|
*/
|
||||||
|
public Analyseur() {
|
||||||
|
super();
|
||||||
|
entree = new Scanner(System.in);
|
||||||
|
contexteGlobal = new Contexte();
|
||||||
|
Expression.referencerContexte(contexteGlobal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lance la boucle qui demande puis exécute des commandes ou instructions
|
||||||
|
* saisies par l'utilisateur.
|
||||||
|
*/
|
||||||
|
public void mainLoop() {
|
||||||
|
String ligneSaisie;
|
||||||
|
for (;;) {
|
||||||
|
System.out.print(INVITE);
|
||||||
|
ligneSaisie = entree.nextLine().trim();
|
||||||
|
|
||||||
|
String[] decoupage = ligneSaisie.split(" ", 2);
|
||||||
|
String motCle = decoupage.length >= 1 ? decoupage[0] : "";
|
||||||
|
String arguments = decoupage.length >= 2 ? decoupage[1] : "";
|
||||||
|
|
||||||
|
executerCommande(motCle, arguments.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recherche la commande et exécute cette commande si présente.
|
||||||
|
* Affiche un feedback si la commande ne s'en occupe pas ou erreur.
|
||||||
|
* @param motCle chaîne contenant le mot clé de la commande/instruction
|
||||||
|
* @param arguments reste de la ligne saisie après le mot clé
|
||||||
|
*/
|
||||||
|
private void executerCommande(String motCle, String arguments) {
|
||||||
|
Class<?> aExecuter;
|
||||||
|
|
||||||
|
/* recherche de la class */
|
||||||
|
try {
|
||||||
|
aExecuter = rechercheCommande(motCle);
|
||||||
|
|
||||||
|
Class<?> classeArg = String.class;
|
||||||
|
Class<?> classeContexte = Contexte.class;
|
||||||
|
Commande cmd = (Commande)aExecuter
|
||||||
|
.getConstructor(classeArg, classeContexte)
|
||||||
|
.newInstance(arguments, contexteGlobal);
|
||||||
|
feedback(cmd.executer());
|
||||||
|
} catch ( InvocationTargetException | IllegalAccessException
|
||||||
|
| InstantiationException | NoSuchMethodException
|
||||||
|
| InterpreteurException lancee) {
|
||||||
|
|
||||||
|
System.err.println(NOK_FEEDBACK
|
||||||
|
+ (lancee.getMessage() != null
|
||||||
|
? lancee.getMessage()
|
||||||
|
: lancee.getCause().getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Affiche feedback de bon déroulement
|
||||||
|
* d'une commande si celle ci n'affiche rien.
|
||||||
|
* @param afficheRien true si feedback déjà fait par la commande sinon false
|
||||||
|
*/
|
||||||
|
private static void feedback(boolean afficheRien) {
|
||||||
|
if (!afficheRien) {
|
||||||
|
System.out.println(OK_FEEDBACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recherche la commande ou instruction correspondant au mot clé.
|
||||||
|
* <ul><li>Les commandes doivent être
|
||||||
|
* dans le package interpreteurlir.motscles</li>
|
||||||
|
* <li>Les instructions doivent être
|
||||||
|
* dans le package interpreteurlir.motscles.instructions</li>
|
||||||
|
* <ul>
|
||||||
|
* La classe correspondant doit avoir un nom qui se finit avec le mot clé
|
||||||
|
* (première lettre en majuscule)
|
||||||
|
* @param motCle mot clé de la commande/ instruction
|
||||||
|
* @return Classe de cette commande.
|
||||||
|
* @throws InterpreteurException si motCle est vide, null ou non reconnue
|
||||||
|
*/
|
||||||
|
private static Class<?> rechercheCommande(String motCle) {
|
||||||
|
final String ERREUR_VIDE = "ligne vide";
|
||||||
|
final String ERREUR_INCONNU = "mot clé inconnu";
|
||||||
|
final String CLASS_PATH_CMD = "interpreteurlir.motscles.Commande";
|
||||||
|
final String CLASS_PATH_INST =
|
||||||
|
"interpreteurlir.motscles.instructions.Instruction";
|
||||||
|
|
||||||
|
if (motCle == null || motCle.isBlank()) {
|
||||||
|
throw new InterpreteurException(ERREUR_VIDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
motCle = (Character.toUpperCase(motCle.charAt(0)))
|
||||||
|
+ (motCle.length() > 1 ? motCle.substring(1) : "");
|
||||||
|
|
||||||
|
Class<?> aChercher;
|
||||||
|
try {
|
||||||
|
aChercher = Class.forName(CLASS_PATH_CMD + motCle);
|
||||||
|
} catch(ClassNotFoundException nonCmd) {
|
||||||
|
try {
|
||||||
|
aChercher = Class.forName(CLASS_PATH_INST + motCle);
|
||||||
|
} catch(ClassNotFoundException nonInst) {
|
||||||
|
throw new InterpreteurException(ERREUR_INCONNU);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return aChercher;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lancement de l'interpréteur LIR.
|
||||||
|
* Un analyseur est créé.
|
||||||
|
* @param args non utilisé
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
final String MESSAGE_LANCEMENT =
|
||||||
|
"Interpréteur Langage IUT de Rodez, bienvenue !\n"
|
||||||
|
+ "Entrez vos commandes et instructions après l’invite "
|
||||||
|
+ INVITE + "\n";
|
||||||
|
|
||||||
|
System.out.println(MESSAGE_LANCEMENT);
|
||||||
|
new Analyseur().mainLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
package interpreteurlir.donnees;
|
package interpreteurlir.donnees;
|
||||||
|
|
||||||
|
import interpreteurlir.InterpreteurException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nicolas Caminade
|
* @author Nicolas Caminade
|
||||||
* @author Sylvan Courtiol
|
* @author Sylvan Courtiol
|
||||||
@@ -29,7 +31,7 @@ implements Comparable<Identificateur> {
|
|||||||
public Identificateur(String identificateur) {
|
public Identificateur(String identificateur) {
|
||||||
super();
|
super();
|
||||||
if(!isIdentificateur(identificateur)) {
|
if(!isIdentificateur(identificateur)) {
|
||||||
throw new IllegalArgumentException(identificateur
|
throw new InterpreteurException(identificateur
|
||||||
+ " n'est pas un identificateur");
|
+ " n'est pas un identificateur");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
package interpreteurlir.donnees;
|
package interpreteurlir.donnees;
|
||||||
|
|
||||||
|
import interpreteurlir.InterpreteurException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identificateur de chaîne
|
* Identificateur de chaîne
|
||||||
* @author Nicolas Caminade
|
* @author Nicolas Caminade
|
||||||
@@ -19,13 +21,14 @@ public class IdentificateurChaine extends Identificateur {
|
|||||||
/**
|
/**
|
||||||
* Instantiation d'identificateur de chaîne
|
* Instantiation d'identificateur de chaîne
|
||||||
* @param identificateur a instancier
|
* @param identificateur a instancier
|
||||||
* @throws IllegalAccessException si l'identificateur est invalide
|
* @throws InterpreteurException si l'identificateur est invalide
|
||||||
*/
|
*/
|
||||||
public IdentificateurChaine(String identificateur) {
|
public IdentificateurChaine(String identificateur) {
|
||||||
super(identificateur);
|
super(identificateur.trim());
|
||||||
|
|
||||||
|
identificateur = identificateur.trim();
|
||||||
if(!isIdentificateurChaine(identificateur)) {
|
if(!isIdentificateurChaine(identificateur)) {
|
||||||
throw new IllegalArgumentException(identificateur
|
throw new InterpreteurException(identificateur
|
||||||
+ " n'est pas un identificateur"
|
+ " n'est pas un identificateur"
|
||||||
+ " de chaine");
|
+ " de chaine");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
package interpreteurlir.donnees;
|
package interpreteurlir.donnees;
|
||||||
|
|
||||||
|
import interpreteurlir.InterpreteurException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identificateur d'entier
|
* Identificateur d'entier
|
||||||
* @author Nicolas Caminade
|
* @author Nicolas Caminade
|
||||||
@@ -19,15 +21,15 @@ public class IdentificateurEntier extends Identificateur {
|
|||||||
/**
|
/**
|
||||||
* Instantiation d'identificateur d'entier
|
* Instantiation d'identificateur d'entier
|
||||||
* @param identificateur a instancier
|
* @param identificateur a instancier
|
||||||
* @throws IllegalAccessException si l'identificateur est invalide
|
* @throws InterpreteurException si l'identificateur est invalide
|
||||||
*/
|
*/
|
||||||
public IdentificateurEntier(String identificateur) {
|
public IdentificateurEntier(String identificateur) {
|
||||||
super(identificateur);
|
super(identificateur);
|
||||||
|
|
||||||
if(!isIdentificateurEntier(identificateur)) {
|
if(!isIdentificateurEntier(identificateur)) {
|
||||||
throw new IllegalArgumentException(identificateur
|
throw new InterpreteurException(identificateur
|
||||||
+ " n'est pas un identificateur"
|
+ " n'est pas un identificateur"
|
||||||
+ " d'entier");
|
+ " d'entier");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,80 +1,93 @@
|
|||||||
/**
|
/**
|
||||||
* Variable.java 8 mai 2021
|
* Variable.java 8 mai 2021
|
||||||
* IUT Rodez info1 2020-2021, pas de copyright, aucun droit
|
* IUT-Rodez info1 2020-2021, pas de droits, pas de copyrights
|
||||||
*/
|
*/
|
||||||
package interpreteurlir.donnees;
|
package interpreteurlir.donnees;
|
||||||
|
|
||||||
|
import interpreteurlir.donnees.litteraux.Chaine;
|
||||||
import interpreteurlir.donnees.litteraux.Litteral;
|
import interpreteurlir.donnees.litteraux.Litteral;
|
||||||
|
import interpreteurlir.InterpreteurException;
|
||||||
|
|
||||||
/** TODO commenter la responsabilité de cette classe
|
/**
|
||||||
* BOUCHON
|
* Associe un littéral à un identificateur
|
||||||
|
*
|
||||||
* @author Nicolas Caminade
|
* @author Nicolas Caminade
|
||||||
* @author Sylvan Courtiol
|
* @author Sylvan Courtiol
|
||||||
* @author Pierre Debas
|
* @author Pierre Debas
|
||||||
* @author Heïa Dexter
|
* @author Heia Dexter
|
||||||
* @author Lucas Vabre
|
* @author Lucas Vabre
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public class Variable implements Comparable<Variable> {
|
public class Variable extends Object implements Comparable<Variable> {
|
||||||
|
|
||||||
/** BOUCHON identificateurs car Identificateurs non finis */
|
/** Identificateur de cette variable */
|
||||||
private Identificateur identificateur;
|
private Identificateur identificateur;
|
||||||
|
|
||||||
/** BOUCHON valeur*/
|
/** Valeur de cette variable */
|
||||||
private Litteral valeur;
|
private Litteral valeur;
|
||||||
|
|
||||||
/** TODO commenter l'état initial
|
|
||||||
* @param id
|
/**
|
||||||
* @param valeur
|
* Initialise une variable
|
||||||
|
* @param identificateur associé à cette variable
|
||||||
|
* @param valeur associé à cette variable
|
||||||
|
* @throws InterpreteurException en cas d'incompatibilité entre
|
||||||
|
* l'identificateur et le type de la valeur à lui associer
|
||||||
*/
|
*/
|
||||||
public Variable(Identificateur id, Litteral valeur) {
|
public Variable(Identificateur identificateur, Litteral valeur) {
|
||||||
super();
|
if (!isVariable(identificateur, valeur)) {
|
||||||
this.identificateur = id;
|
throw new InterpreteurException("Identificateur '"
|
||||||
|
+ identificateur.toString()
|
||||||
|
+ "' et type de "
|
||||||
|
+ valeur.toString()
|
||||||
|
+ "incompatible.");
|
||||||
|
}
|
||||||
|
this.identificateur = identificateur;
|
||||||
this.valeur = valeur;
|
this.valeur = valeur;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static boolean isVariable(Identificateur id, Litteral valeur) {
|
||||||
|
return id instanceof IdentificateurChaine && valeur instanceof Chaine
|
||||||
|
/* || id instanceof IdentificateurEntier && valeur instanceof Entier */;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return valeur de valeur
|
* @return la valeur de cette variable
|
||||||
*/
|
*/
|
||||||
public Litteral getValeur() {
|
public Litteral getValeur() {
|
||||||
return valeur;
|
return valeur;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param valeur nouvelle valeur de valeur
|
* Modifie la valeur de cette variable
|
||||||
|
* @param nouvelleValeur
|
||||||
*/
|
*/
|
||||||
public void setValeur(Litteral valeur) {
|
public void setValeur(Litteral nouvelleValeur) {
|
||||||
this.valeur = valeur;
|
if (isVariable(identificateur, nouvelleValeur)) {
|
||||||
}
|
this.valeur = nouvelleValeur;
|
||||||
|
}
|
||||||
/* non javadoc
|
|
||||||
* @see java.lang.Comparable#compareTo(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int compareTo(Variable o) {
|
|
||||||
// bouchon
|
|
||||||
return identificateur.compareTo(o.identificateur);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return valeur de id
|
* @return l'identificateur de cette variable
|
||||||
*/
|
*/
|
||||||
public Identificateur getIdentificateur() {
|
public Identificateur getIdentificateur() {
|
||||||
return identificateur;
|
return identificateur;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* non javadoc
|
/* non javadoc @see java.lang.Object#toString() */
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return identificateur + " = " + valeur;
|
return identificateur.toString() + " = " + valeur.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compareTo(Variable aComparer) {
|
||||||
|
return identificateur.compareTo(aComparer.identificateur);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,7 @@ public class Chaine extends Litteral {
|
|||||||
* @param uneValeur
|
* @param uneValeur
|
||||||
*/
|
*/
|
||||||
public Chaine(String uneValeur) {
|
public Chaine(String uneValeur) {
|
||||||
|
uneValeur = uneValeur.trim();
|
||||||
if (!uneValeur.startsWith("\"") || !uneValeur.endsWith("\"")) {
|
if (!uneValeur.startsWith("\"") || !uneValeur.endsWith("\"")) {
|
||||||
throw new InterpreteurException(ERREUR_INVALIDE
|
throw new InterpreteurException(ERREUR_INVALIDE
|
||||||
+ uneValeur);
|
+ uneValeur);
|
||||||
@@ -61,7 +61,7 @@ public class Chaine extends Litteral {
|
|||||||
*/
|
*/
|
||||||
public static Chaine concatener(Chaine a, Chaine b) {
|
public static Chaine concatener(Chaine a, Chaine b) {
|
||||||
|
|
||||||
return null;
|
return new Chaine("\"" + a.valeur + b.valeur + "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* non javadoc
|
/* non javadoc
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ package interpreteurlir.donnees.litteraux.tests;
|
|||||||
import interpreteurlir.InterpreteurException;
|
import interpreteurlir.InterpreteurException;
|
||||||
import interpreteurlir.donnees.litteraux.Chaine;
|
import interpreteurlir.donnees.litteraux.Chaine;
|
||||||
|
|
||||||
|
import static info1.outils.glg.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests unitaires de Chaine
|
* Tests unitaires de Chaine
|
||||||
* @author Nicolas Caminade
|
* @author Nicolas Caminade
|
||||||
@@ -111,6 +113,32 @@ public class TestChaine {
|
|||||||
System.out.println("==>test terminé\n");
|
System.out.println("==>test terminé\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests unitaires de concaténer
|
||||||
|
*/
|
||||||
|
public void testConcatener() {
|
||||||
|
final Chaine[] ATTENDU = {
|
||||||
|
new Chaine(),
|
||||||
|
new Chaine("\"Bonjour le monde ! \""),
|
||||||
|
new Chaine("\" \""),
|
||||||
|
new Chaine("\"3,1415\""),
|
||||||
|
};
|
||||||
|
|
||||||
|
final Chaine[][] A_CONCATENER = {
|
||||||
|
{new Chaine(), new Chaine("\"\"")},
|
||||||
|
{new Chaine("\"Bonjour \""), new Chaine("\"le monde ! \"")},
|
||||||
|
{new Chaine("\"\""), new Chaine("\" \"")},
|
||||||
|
{new Chaine("\"3,\""), new Chaine("\"1415\"")},
|
||||||
|
};
|
||||||
|
|
||||||
|
System.out.println("\tExécution du test de concaténer");
|
||||||
|
for (int numTest = 0 ; numTest < ATTENDU.length ; numTest++ ) {
|
||||||
|
assertTrue(ATTENDU[numTest].compareTo(Chaine.concatener(
|
||||||
|
A_CONCATENER[numTest][0], A_CONCATENER[numTest][1]))
|
||||||
|
== 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lancement des tests
|
* Lancement des tests
|
||||||
* @param args non utilisés
|
* @param args non utilisés
|
||||||
|
|||||||
@@ -0,0 +1,210 @@
|
|||||||
|
/**
|
||||||
|
* TestVariable.java 8 mai 2021
|
||||||
|
* IUT-Rodez info1 2020-2021, pas de droits, pas de copyrights
|
||||||
|
*/
|
||||||
|
package interpreteurlir.donnees.tests;
|
||||||
|
|
||||||
|
import interpreteurlir.donnees.Variable;
|
||||||
|
import interpreteurlir.donnees.IdentificateurChaine;
|
||||||
|
import interpreteurlir.donnees.IdentificateurEntier;
|
||||||
|
import interpreteurlir.donnees.litteraux.*;
|
||||||
|
import interpreteurlir.InterpreteurException;
|
||||||
|
|
||||||
|
import static info1.outils.glg.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests unitaires de la classe Variable
|
||||||
|
*
|
||||||
|
* @author Nicolas Caminade
|
||||||
|
* @author Sylvan Courtiol
|
||||||
|
* @author Pierre Debas
|
||||||
|
* @author Heia Dexter
|
||||||
|
* @author Lucàs Vabre
|
||||||
|
*/
|
||||||
|
public class TestVariable {
|
||||||
|
|
||||||
|
/** Jeu d'identificateurs de chaîne valides */
|
||||||
|
private static final IdentificateurChaine[] ID_CHAINE = {
|
||||||
|
new IdentificateurChaine("$a"),
|
||||||
|
new IdentificateurChaine("$B"),
|
||||||
|
new IdentificateurChaine("$alpha"),
|
||||||
|
new IdentificateurChaine("$Alpha"),
|
||||||
|
new IdentificateurChaine("$Alpha5"),
|
||||||
|
new IdentificateurChaine("$jeSuisUnTresLongIdentifi"),
|
||||||
|
new IdentificateurChaine("$R2D2"),
|
||||||
|
new IdentificateurChaine("$MichelSardou"),
|
||||||
|
new IdentificateurChaine("$PhilippePoutou2022")
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Jeu d'identificateurs d'entier valides */
|
||||||
|
private static final IdentificateurEntier[] ID_ENTIER = {
|
||||||
|
new IdentificateurEntier("a"),
|
||||||
|
new IdentificateurEntier("A"),
|
||||||
|
new IdentificateurEntier("alpha"),
|
||||||
|
new IdentificateurEntier("Alpha"),
|
||||||
|
new IdentificateurEntier("Alpha5"),
|
||||||
|
new IdentificateurEntier("jeSuisUnTresLongIdentifi"),
|
||||||
|
new IdentificateurEntier("R2D2"),
|
||||||
|
new IdentificateurEntier("MichelSardou"),
|
||||||
|
new IdentificateurEntier("PhilippePoutou2022")
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Jeu de chaînes valides */
|
||||||
|
private static final Chaine[] VALEURS_CHAINE = {
|
||||||
|
new Chaine(),
|
||||||
|
new Chaine("\"arztyehjklmpoijhghnbghjklmpoiuytrf"
|
||||||
|
+ "ghjnklmpoiuytrezaqsdfghnjklmpjbfrtyu\""),
|
||||||
|
new Chaine("\"\""),
|
||||||
|
new Chaine("\"coucou \""),
|
||||||
|
new Chaine("\"" + Integer.toString(42) + "\""),
|
||||||
|
new Chaine("\"Bidon\""),
|
||||||
|
new Chaine("\"toto\""),
|
||||||
|
new Chaine("\"tata\t\""),
|
||||||
|
new Chaine("\"titi\n\"")
|
||||||
|
};
|
||||||
|
|
||||||
|
// /** Jeu d'entiers valides */
|
||||||
|
// private static final Entier[] VALEUR_ENTIER = {
|
||||||
|
// // TODO: jeu d'entiers valide
|
||||||
|
// };
|
||||||
|
|
||||||
|
/** Jeu de variables chaîne valides*/
|
||||||
|
private static Variable[] fixtureChaine = new Variable[ID_CHAINE.length];
|
||||||
|
|
||||||
|
/* Jeu de variables entières valides*/
|
||||||
|
//private static Variable[] fixtureEntier= new Variable[ID_ENTIER.length];
|
||||||
|
|
||||||
|
private static void fixtureReload() {
|
||||||
|
for (int i = 0; i < ID_CHAINE.length; i++) {
|
||||||
|
fixtureChaine[i] = new Variable(ID_CHAINE[i], VALEURS_CHAINE[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO reload fixtureEntier
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test unitaire du constructeur Variable(Identificateur, Littéral)
|
||||||
|
*/
|
||||||
|
public static void testVariableIdentificateurChaineLitteral() {
|
||||||
|
|
||||||
|
for (int noJeu = 0; noJeu < VALEURS_CHAINE.length; noJeu++) {
|
||||||
|
try {
|
||||||
|
//new Variable(ID_CHAINE[noJeu], VALEURS_CHAINE[noJeu]); // bouchon
|
||||||
|
new Variable(ID_ENTIER[noJeu], VALEURS_CHAINE[noJeu]);
|
||||||
|
// TODO tester avec la classe Entier
|
||||||
|
// new Variable(ID_CHAINE[noJeu], VALEURS_ENTIER[noJeu]);
|
||||||
|
echec();
|
||||||
|
} catch (InterpreteurException lancee) {
|
||||||
|
// test OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test unitaire de getIdentificateur() d'une variable chaîne
|
||||||
|
*/
|
||||||
|
public static void testGetIdentificateurChaine() {
|
||||||
|
fixtureReload();
|
||||||
|
|
||||||
|
for (int i = 0; i < VALEURS_CHAINE.length; i++ ) {
|
||||||
|
assertTrue(ID_CHAINE[i].compareTo(fixtureChaine[i]
|
||||||
|
.getIdentificateur()) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test unitaire de getIdentificateur() d'une variable entière
|
||||||
|
*/
|
||||||
|
public static void testGetIdentificateurEntier() {
|
||||||
|
// fixtureReload();
|
||||||
|
//
|
||||||
|
// for (int i = 0; i < VALEURS_Entier.length; i++ ) {
|
||||||
|
// assertTrue(ID_ENTIER[i].compareTo(fixtureEntier[i]
|
||||||
|
// .getIdentificateur()) == 0);
|
||||||
|
// }
|
||||||
|
|
||||||
|
echec();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test unitaire de getValeur() d'une variable chaîne
|
||||||
|
*/
|
||||||
|
public static void testGetValeurChaine() {
|
||||||
|
fixtureReload();
|
||||||
|
|
||||||
|
for (int i = 0; i < VALEURS_CHAINE.length; i++ ) {
|
||||||
|
assertTrue(VALEURS_CHAINE[i]
|
||||||
|
.compareTo(fixtureChaine[i].getValeur()) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test unitaire de setValeur() d'une chaîne
|
||||||
|
*/
|
||||||
|
public static void testSetValeurChaine() {
|
||||||
|
|
||||||
|
fixtureReload();
|
||||||
|
|
||||||
|
final Chaine[] NOUVELLE_CHAINE = {
|
||||||
|
new Chaine("\"titi\""),
|
||||||
|
new Chaine("\"Mathématiques\""),
|
||||||
|
new Chaine("\"!?9563Message\""),
|
||||||
|
new Chaine("\"test TESTS\""),
|
||||||
|
new Chaine("\"-5 + 962\"")
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < NOUVELLE_CHAINE.length; i++) {
|
||||||
|
fixtureChaine[i].setValeur(NOUVELLE_CHAINE[i]);
|
||||||
|
assertTrue(NOUVELLE_CHAINE[i]
|
||||||
|
.compareTo(fixtureChaine[i].getValeur()) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test unitaire de toString()
|
||||||
|
*/
|
||||||
|
public static void testToString() {
|
||||||
|
fixtureReload();
|
||||||
|
|
||||||
|
final String[] ATTENDUS = {
|
||||||
|
"$a = \"\"",
|
||||||
|
"$B = \"arztyehjklmpoijhghnbghjklmpoiuytrf"
|
||||||
|
+ "ghjnklmpoiuytrezaqsdfghnjklmpjbfrtyu\"",
|
||||||
|
"$alpha = \"\"",
|
||||||
|
"$Alpha = \"coucou \"",
|
||||||
|
"$Alpha5 = \"42\"",
|
||||||
|
"$jeSuisUnTresLongIdentifi = \"Bidon\"",
|
||||||
|
"$R2D2 = \"toto\"",
|
||||||
|
"$MichelSardou = \"tata\t\"",
|
||||||
|
"$PhilippePoutou2022 = \"titi\n\""
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int noJeu = 0; noJeu < fixtureChaine.length; noJeu++ ) {
|
||||||
|
assertEquivalence(fixtureChaine[noJeu].toString(),
|
||||||
|
ATTENDUS[noJeu]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test unitaire de compareTo()
|
||||||
|
*/
|
||||||
|
public static void testCompareTo() {
|
||||||
|
fixtureReload();
|
||||||
|
|
||||||
|
final Variable REF_MIN
|
||||||
|
= new Variable(new IdentificateurChaine("$A"),
|
||||||
|
new Chaine("\"Min\""));
|
||||||
|
|
||||||
|
final Variable REF_MAX
|
||||||
|
= new Variable(new IdentificateurChaine("$z"),
|
||||||
|
new Chaine("\"Max\""));
|
||||||
|
|
||||||
|
for(int noJeu = 0; noJeu < fixtureChaine.length; noJeu++) {
|
||||||
|
assertTrue(fixtureChaine[noJeu].compareTo(REF_MIN) > 0);
|
||||||
|
assertTrue(fixtureChaine[noJeu].compareTo(REF_MAX) < 0);
|
||||||
|
assertTrue(fixtureChaine[noJeu].compareTo(fixtureChaine[noJeu]) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Faire le même test pour les variables contenant des entiers
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ package interpreteurlir.expressions;
|
|||||||
|
|
||||||
import interpreteurlir.Contexte;
|
import interpreteurlir.Contexte;
|
||||||
import interpreteurlir.InterpreteurException;
|
import interpreteurlir.InterpreteurException;
|
||||||
|
import interpreteurlir.donnees.Identificateur;
|
||||||
import interpreteurlir.donnees.litteraux.Litteral;
|
import interpreteurlir.donnees.litteraux.Litteral;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,10 +21,23 @@ import interpreteurlir.donnees.litteraux.Litteral;
|
|||||||
*/
|
*/
|
||||||
public class Expression {
|
public class Expression {
|
||||||
|
|
||||||
/** Contexte global pour accéder aux données. */
|
/** Index de l'operande gauche */
|
||||||
private static Contexte contexteGlobal;
|
protected static final int INDEX_OPERANDE_G = 0;
|
||||||
|
|
||||||
// TODO stocker opérandes (identificateur ou Litteral)
|
/** Index de l'operande droite */
|
||||||
|
protected static final int INDEX_OPERANDE_D = 1;
|
||||||
|
|
||||||
|
/** Index de de l'identificateur pour l'affectation */
|
||||||
|
protected static final int INDEX_AFFECTATION = 2;
|
||||||
|
|
||||||
|
/** Contexte global pour accéder aux données. */
|
||||||
|
protected static Contexte contexteGlobal;
|
||||||
|
|
||||||
|
/** Identificateurs opérandes de cette l'expression */
|
||||||
|
protected Identificateur[] identificateursOperandes;
|
||||||
|
|
||||||
|
/** Littéraux opérandes de cette expression */
|
||||||
|
protected Litteral[] litterauxOperandes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise une expression par défaut avec les liens nécessaires à
|
* Initialise une expression par défaut avec les liens nécessaires à
|
||||||
@@ -31,16 +45,26 @@ public class Expression {
|
|||||||
*/
|
*/
|
||||||
protected Expression() {
|
protected Expression() {
|
||||||
super();
|
super();
|
||||||
|
final int NB_IDENTIFICATEUR = 3;
|
||||||
|
final int NB_LITTERAL = 2;
|
||||||
|
|
||||||
|
identificateursOperandes = new Identificateur[NB_IDENTIFICATEUR];
|
||||||
|
litterauxOperandes = new Litteral[NB_LITTERAL];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculer la valeur de cette expression à ce moment précis.
|
* Calculer la valeur de cette expression à ce moment précis.
|
||||||
* Peut accéder au contexte.
|
* Peut accéder au contexte.
|
||||||
* @return un Litteral de valeur du résultat de l'expression
|
* @return un Litteral de valeur du résultat de l'expression
|
||||||
|
* @throws RuntimeException si le contexte n'est pas référencer
|
||||||
|
* dans la classe Expression
|
||||||
*/
|
*/
|
||||||
public Litteral calculer() {
|
public Litteral calculer() {
|
||||||
|
if (contexteGlobal == null) {
|
||||||
|
throw new RuntimeException("Le contexte doit être référencé "
|
||||||
|
+ "dans la classe Expression");
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* non javadoc
|
/* non javadoc
|
||||||
@@ -48,7 +72,25 @@ public class Expression {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Expression#toString() BOUCHON";
|
StringBuilder resultat = new StringBuilder("");
|
||||||
|
|
||||||
|
Identificateur affect = identificateursOperandes[INDEX_AFFECTATION];
|
||||||
|
resultat.append(affect == null ? "" : (affect.toString() + " = "));
|
||||||
|
|
||||||
|
Identificateur gaucheId = identificateursOperandes[INDEX_OPERANDE_G];
|
||||||
|
Litteral gaucheLitteral = litterauxOperandes[INDEX_OPERANDE_G];
|
||||||
|
resultat.append(gaucheId != null ? gaucheId.toString()
|
||||||
|
: gaucheLitteral.toString());
|
||||||
|
|
||||||
|
Identificateur droiteId = identificateursOperandes[INDEX_OPERANDE_D];
|
||||||
|
Litteral droiteLitteral = litterauxOperandes[INDEX_OPERANDE_D];
|
||||||
|
if (droiteId != null || droiteLitteral != null) {
|
||||||
|
resultat.append(" + ");
|
||||||
|
resultat.append(droiteId != null ? droiteId.toString()
|
||||||
|
: droiteLitteral.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultat.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,22 +99,34 @@ public class Expression {
|
|||||||
* et est possible une unique fois.
|
* et est possible une unique fois.
|
||||||
* @param aReferencer référence du contexte global
|
* @param aReferencer référence du contexte global
|
||||||
* @return <ul><li>true si le contexte a pu être référencé</li>
|
* @return <ul><li>true si le contexte a pu être référencé</li>
|
||||||
|
* <li>true si aReferencer == contexte déjà référencer</li>
|
||||||
* <li>false si aReferencer est null</li>
|
* <li>false si aReferencer est null</li>
|
||||||
* <li>false si un contexte est déjà référencer</li>
|
* <li>false si un contexte est déjà référencer</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public static boolean referencerContexte(Contexte aReferencer) {
|
public static boolean referencerContexte(Contexte aReferencer) {
|
||||||
|
if (aReferencer != null
|
||||||
|
&& (contexteGlobal == null || aReferencer == contexteGlobal)) {
|
||||||
|
contexteGlobal = aReferencer;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Détermine et créé une expression du bon type selon texteExpression.
|
* Détermine et créé une expression du bon type selon texteExpression.
|
||||||
|
* Les types possibles sont ExpressionChaine ou ExpressionEntier.
|
||||||
* @param texteExpression texte suivant la syntaxe d'une expression
|
* @param texteExpression texte suivant la syntaxe d'une expression
|
||||||
* @return l'expression du bon type correspondant à texteExpression
|
* @return l'expression du bon type correspondant à texteExpression
|
||||||
* @throws InterpreteurException si texteExpression n'est pas valide
|
* @throws InterpreteurException si texteExpression n'est pas valide
|
||||||
* ou amène à une incohérence de type
|
* ou amène à une incohérence de type
|
||||||
*/
|
*/
|
||||||
public static Expression determinerType(String texteExpression) {
|
public static Expression determinerTypeExpression(String texteExpression) {
|
||||||
return null;
|
String aTraiter = texteExpression.trim();
|
||||||
|
if (aTraiter.startsWith("$") || aTraiter.startsWith("\"")) {
|
||||||
|
return new ExpressionChaine(aTraiter);
|
||||||
|
} else {
|
||||||
|
return new ExpressionEntier(aTraiter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
package interpreteurlir.expressions;
|
package interpreteurlir.expressions;
|
||||||
|
|
||||||
import interpreteurlir.InterpreteurException;
|
import interpreteurlir.InterpreteurException;
|
||||||
|
import interpreteurlir.donnees.Identificateur;
|
||||||
|
import interpreteurlir.donnees.IdentificateurChaine;
|
||||||
import interpreteurlir.donnees.litteraux.Chaine;
|
import interpreteurlir.donnees.litteraux.Chaine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,15 +20,96 @@ import interpreteurlir.donnees.litteraux.Chaine;
|
|||||||
public class ExpressionChaine extends Expression {
|
public class ExpressionChaine extends Expression {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initalise une expression de type Chaine avec les liens nécessaires à son
|
* Initalise une expression de type Chaine
|
||||||
* calcule.
|
* avec les liens nécessaires à son calcul.
|
||||||
* @param texteExpression texte suivant la syntaxe d'une expression
|
* @param texteExpression texte suivant la syntaxe d'une expression
|
||||||
* @throws InterpreteurException si texteExpression n'est pas valide
|
* @throws InterpreteurException si texteExpression n'est pas valide
|
||||||
* ou amène à une incohérence de type
|
* ou amène à une incohérence de type
|
||||||
*/
|
*/
|
||||||
public ExpressionChaine(String texteExpression) {
|
public ExpressionChaine(String texteExpression) {
|
||||||
super();
|
super();
|
||||||
// TODO
|
final String MESSAGE_ERREUR = "une expression ne peut être vide";
|
||||||
|
|
||||||
|
String gauche;
|
||||||
|
String droite;
|
||||||
|
String aTraiter = texteExpression;
|
||||||
|
|
||||||
|
/* chaîne null ou blanche */
|
||||||
|
if (aTraiter == null || aTraiter.isBlank()) {
|
||||||
|
throw new InterpreteurException(MESSAGE_ERREUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
aTraiter = aTraiter.trim();
|
||||||
|
|
||||||
|
/* Traitement de la possible affectation */
|
||||||
|
int indexEgal = aTraiter.startsWith("$") ? aTraiter.indexOf('=') : -1;
|
||||||
|
if (indexEgal > -1) {
|
||||||
|
identificateursOperandes[INDEX_AFFECTATION] =
|
||||||
|
new IdentificateurChaine(aTraiter.substring(0, indexEgal));
|
||||||
|
aTraiter = aTraiter.substring(indexEgal + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Traitement du nombre d'opérande */
|
||||||
|
int indexPlus = indexOperateur(aTraiter, '+');
|
||||||
|
gauche = aTraiter;
|
||||||
|
if (indexPlus > -1) {
|
||||||
|
gauche = aTraiter.substring(0, indexPlus);
|
||||||
|
droite = aTraiter.substring(indexPlus + 1, aTraiter.length());
|
||||||
|
initialiserOperande(droite, INDEX_OPERANDE_D);
|
||||||
|
}
|
||||||
|
|
||||||
|
initialiserOperande(gauche, INDEX_OPERANDE_G);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Détermine l'index de l'opérateur en dehors des constantes littérales
|
||||||
|
* @param aTraiter chaîne à traiter
|
||||||
|
* @param operateur opérateur à chercher hors guillemet
|
||||||
|
* @return index dans à traiter du plus sinon -1 si aucun plus
|
||||||
|
*/
|
||||||
|
public static int indexOperateur(String aTraiter, char operateur) {
|
||||||
|
char[] aTester = aTraiter.toCharArray();
|
||||||
|
int indexPlus;
|
||||||
|
int nbGuillemet = 0;
|
||||||
|
for (indexPlus = 0 ;
|
||||||
|
indexPlus < aTester.length
|
||||||
|
&& (aTester[indexPlus] != operateur || nbGuillemet % 2 != 0) ;
|
||||||
|
indexPlus++) {
|
||||||
|
|
||||||
|
if (aTester[indexPlus] == '"') {
|
||||||
|
nbGuillemet++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return indexPlus >= aTester.length ? -1 : indexPlus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise l'opérande à sa place dans l'expression.
|
||||||
|
* @param operande représentation texte de l'opérande
|
||||||
|
* @param index index de l'operande parmi INDEX_OPERANDE_G
|
||||||
|
* et INDEX_OPERANDE_D
|
||||||
|
* @throws IllegalArgumentException si index non valide
|
||||||
|
*/
|
||||||
|
private void initialiserOperande(String operande, int index) {
|
||||||
|
if (INDEX_OPERANDE_G != index && INDEX_OPERANDE_D != index) {
|
||||||
|
throw new IllegalArgumentException("index invalide");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operandeEstLitteral(operande)) {
|
||||||
|
litterauxOperandes[index] = new Chaine(operande);
|
||||||
|
} else {
|
||||||
|
identificateursOperandes[index] =
|
||||||
|
new IdentificateurChaine(operande);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Détermine le genre de l'opérande (Chaine ou IdentificateurChaine).
|
||||||
|
* @param operande représentation texte de l'opérande
|
||||||
|
* @return true si operande est du genre Litteral sinon false
|
||||||
|
*/
|
||||||
|
private static boolean operandeEstLitteral(String operande) {
|
||||||
|
return operande.trim().startsWith("\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* non javadoc
|
/* non javadoc
|
||||||
@@ -34,17 +117,38 @@ public class ExpressionChaine extends Expression {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Chaine calculer() {
|
public Chaine calculer() {
|
||||||
// TODO Auto-generated method stub
|
Chaine valeur;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* non javadoc
|
super.calculer(); // exception levée si pas de contexte
|
||||||
* @see interpreteurlir.expressions.Expression#toString()
|
|
||||||
*/
|
/* Détermine opérandeGauche */
|
||||||
@Override
|
Identificateur idGauche =
|
||||||
public String toString() {
|
identificateursOperandes[INDEX_OPERANDE_G];
|
||||||
// TODO Auto-generated method stub
|
Chaine operandeG = (Chaine)(idGauche == null
|
||||||
return "ExpressionChaine#toString() BOUCHON";
|
? litterauxOperandes[INDEX_OPERANDE_G]
|
||||||
|
: contexteGlobal.lireValeurVariable(idGauche));
|
||||||
|
|
||||||
|
/* Détermine possible operandeDroite */
|
||||||
|
Identificateur idDroite =
|
||||||
|
identificateursOperandes[INDEX_OPERANDE_D];
|
||||||
|
Chaine operandeD = null;
|
||||||
|
if (idDroite != null || litterauxOperandes[INDEX_OPERANDE_D] != null) {
|
||||||
|
operandeD = (Chaine)(idDroite == null
|
||||||
|
? litterauxOperandes[INDEX_OPERANDE_D]
|
||||||
|
: contexteGlobal.lireValeurVariable(idDroite));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calcul de la valeur */
|
||||||
|
valeur = operandeD == null ? operandeG
|
||||||
|
: Chaine.concatener(operandeG, operandeD);
|
||||||
|
|
||||||
|
/* Affectation si nécessaire */
|
||||||
|
if (identificateursOperandes[INDEX_AFFECTATION] != null) {
|
||||||
|
contexteGlobal.ajouterVariable(
|
||||||
|
identificateursOperandes[INDEX_AFFECTATION], valeur);
|
||||||
|
}
|
||||||
|
|
||||||
|
return valeur;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,12 @@
|
|||||||
*/
|
*/
|
||||||
package interpreteurlir.expressions.tests;
|
package interpreteurlir.expressions.tests;
|
||||||
|
|
||||||
|
import static info1.outils.glg.Assertions.*;
|
||||||
|
|
||||||
import interpreteurlir.expressions.Expression;
|
import interpreteurlir.expressions.Expression;
|
||||||
|
import interpreteurlir.expressions.ExpressionChaine;
|
||||||
|
import interpreteurlir.expressions.ExpressionEntier;
|
||||||
|
import interpreteurlir.Contexte;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests unitaires de {@link Expression}
|
* Tests unitaires de {@link Expression}
|
||||||
@@ -16,4 +21,115 @@ import interpreteurlir.expressions.Expression;
|
|||||||
*/
|
*/
|
||||||
public class TestExpression {
|
public class TestExpression {
|
||||||
|
|
||||||
|
/** Jeu d'essai d'expression typée */
|
||||||
|
private Expression[] fixture = {
|
||||||
|
new ExpressionChaine("$chaine = \"texte\""),
|
||||||
|
new ExpressionChaine("$chaine=\"tata\""),
|
||||||
|
new ExpressionChaine(" $tata \t "),
|
||||||
|
new ExpressionChaine("\"une chaine de texte\""),
|
||||||
|
new ExpressionChaine("$chaine= \"toto\"+\"titi\""),
|
||||||
|
new ExpressionChaine("$chaine= $toto +\"titi\""),
|
||||||
|
new ExpressionChaine("$chaine= \"toto\"+ $titi"),
|
||||||
|
new ExpressionChaine("$chaine=$toto +$titi"),
|
||||||
|
new ExpressionChaine(" \"toto\"+\"titi\""),
|
||||||
|
new ExpressionChaine("$toto +\"titi\""),
|
||||||
|
new ExpressionChaine("\"toto\"+ $titi"),
|
||||||
|
new ExpressionChaine("$toto + $titi"),
|
||||||
|
// TODO expression entière
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests unitaires de {@link Expression#referencerContexte(Contexte)}
|
||||||
|
*/
|
||||||
|
public void testReferencerContexte() {
|
||||||
|
|
||||||
|
Contexte reference = new Contexte();
|
||||||
|
Contexte[] contextes = {
|
||||||
|
null, reference, reference, new Contexte()
|
||||||
|
};
|
||||||
|
|
||||||
|
boolean[] resultatAttendu = { false, true, true, false };
|
||||||
|
|
||||||
|
System.out.println("\tExécution du test de "
|
||||||
|
+ "Expression#referencerContexte(Contexte)");
|
||||||
|
for (int numTest = 0 ; numTest < contextes.length ; numTest++) {
|
||||||
|
assertTrue( Expression.referencerContexte(contextes[numTest])
|
||||||
|
== resultatAttendu[numTest]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests unitaires de {@link Expression#toString()}
|
||||||
|
*/
|
||||||
|
public void testToString() {
|
||||||
|
final String[] chaineAttendue = {
|
||||||
|
"$chaine = \"texte\"",
|
||||||
|
"$chaine = \"tata\"",
|
||||||
|
"$tata",
|
||||||
|
"\"une chaine de texte\"",
|
||||||
|
"$chaine = \"toto\" + \"titi\"",
|
||||||
|
"$chaine = $toto + \"titi\"",
|
||||||
|
"$chaine = \"toto\" + $titi",
|
||||||
|
"$chaine = $toto + $titi",
|
||||||
|
"\"toto\" + \"titi\"",
|
||||||
|
"$toto + \"titi\"",
|
||||||
|
"\"toto\" + $titi",
|
||||||
|
"$toto + $titi"
|
||||||
|
};
|
||||||
|
|
||||||
|
System.out.println("\tExécution du test de Expression#toString()");
|
||||||
|
for (int numTest = 0 ; numTest < chaineAttendue.length ; numTest++) {
|
||||||
|
assertEquivalence(chaineAttendue[numTest],
|
||||||
|
fixture[numTest].toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests unitaires de {@link Expression#determinerTypeExpression(String)}
|
||||||
|
*/
|
||||||
|
public void testDeterminerTypeExpression() {
|
||||||
|
final String[] TEXTE_EXPRESSION = {
|
||||||
|
/* Expression de type chaine */
|
||||||
|
"$chaine = \"texte\"",
|
||||||
|
"$chaine=\"tata\"",
|
||||||
|
" $tata \t ",
|
||||||
|
" \"une chaine de texte\"",
|
||||||
|
"$chaine= \"toto\"+\"titi\"",
|
||||||
|
" $chaine= $toto +\"titi\"",
|
||||||
|
"$chaine= \"toto\"+ $titi",
|
||||||
|
"$chaine=$toto +$titi",
|
||||||
|
" \"toto\"+\"titi\"",
|
||||||
|
"\t$toto +\"titi\"",
|
||||||
|
"\"toto\"+ $titi",
|
||||||
|
"$toto + $titi",
|
||||||
|
|
||||||
|
/* Expression de type Entier */
|
||||||
|
"78",
|
||||||
|
" entier",
|
||||||
|
"78 %89",
|
||||||
|
" entier- nombre",
|
||||||
|
"\t entier/78",
|
||||||
|
"entier = 78 ",
|
||||||
|
" nombre= nombre + 78",
|
||||||
|
" entier =78 *2"
|
||||||
|
// TODO expressionEntier
|
||||||
|
};
|
||||||
|
|
||||||
|
final int INDEX_DEBUT_ENTIER = 12;
|
||||||
|
|
||||||
|
System.out.println("\tExécution du test de "
|
||||||
|
+ "Expression#determinerTypeExpression(String)");
|
||||||
|
|
||||||
|
for (int numTest = 0; numTest < TEXTE_EXPRESSION.length ; numTest++) {
|
||||||
|
if (numTest < INDEX_DEBUT_ENTIER) {
|
||||||
|
assertTrue(Expression.determinerTypeExpression(
|
||||||
|
TEXTE_EXPRESSION[numTest]) instanceof ExpressionChaine);
|
||||||
|
} else {
|
||||||
|
assertTrue(Expression.determinerTypeExpression(
|
||||||
|
TEXTE_EXPRESSION[numTest]) instanceof ExpressionEntier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,17 @@
|
|||||||
*/
|
*/
|
||||||
package interpreteurlir.expressions.tests;
|
package interpreteurlir.expressions.tests;
|
||||||
|
|
||||||
|
import static info1.outils.glg.Assertions.*;
|
||||||
|
|
||||||
|
import interpreteurlir.Contexte;
|
||||||
|
import interpreteurlir.InterpreteurException;
|
||||||
|
import interpreteurlir.donnees.IdentificateurChaine;
|
||||||
|
import interpreteurlir.donnees.litteraux.Chaine;
|
||||||
import interpreteurlir.expressions.Expression;
|
import interpreteurlir.expressions.Expression;
|
||||||
|
import interpreteurlir.expressions.ExpressionChaine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests unitaires de {@link Expression}
|
* Tests unitaires de {@link ExpressionChaine}
|
||||||
* @author Nicolas Caminade
|
* @author Nicolas Caminade
|
||||||
* @author Sylvan Courtiol
|
* @author Sylvan Courtiol
|
||||||
* @author Pierre Debas
|
* @author Pierre Debas
|
||||||
@@ -16,4 +23,122 @@ import interpreteurlir.expressions.Expression;
|
|||||||
*/
|
*/
|
||||||
public class TestExpressionChaine {
|
public class TestExpressionChaine {
|
||||||
|
|
||||||
|
/** Jeu de tests d'expression chaîne valides*/
|
||||||
|
private ExpressionChaine[] fixture = {
|
||||||
|
new ExpressionChaine("$chaine = \"texte\""),
|
||||||
|
new ExpressionChaine("$chaine=\"tata\""),
|
||||||
|
new ExpressionChaine(" $tata \t "),
|
||||||
|
new ExpressionChaine("\"une chaine de texte\""),
|
||||||
|
new ExpressionChaine("$chaine= \"toto\"+\"titi\""),
|
||||||
|
new ExpressionChaine("$chaine= $toto +\"titi\""),
|
||||||
|
new ExpressionChaine("$chaine= \"toto\"+ $titi"),
|
||||||
|
new ExpressionChaine("$chaine=$toto +$titi"),
|
||||||
|
new ExpressionChaine(" \"toto\"+\"titi\""),
|
||||||
|
new ExpressionChaine("$toto +\"titi\""),
|
||||||
|
new ExpressionChaine("\"toto\"+ $titi"),
|
||||||
|
new ExpressionChaine("$toto + $titi"),
|
||||||
|
new ExpressionChaine("\"ab=bc\""),
|
||||||
|
new ExpressionChaine("$chaine = \"ab+cd\"+$toto")
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests unitaires de {@link ExpressionChaine#ExpressionChaine(String)}
|
||||||
|
*/
|
||||||
|
public void testExpressionChaineString() {
|
||||||
|
|
||||||
|
final String[] INVALIDES = {
|
||||||
|
null,
|
||||||
|
"",
|
||||||
|
"3,1415", "3.1415", "1.7976931348623157E308",
|
||||||
|
"45", "-89",
|
||||||
|
"tata + $toto",
|
||||||
|
"\"chaine\" = $vie",
|
||||||
|
"$chaine / \"tata\"",
|
||||||
|
"£", "$"
|
||||||
|
};
|
||||||
|
|
||||||
|
final String[] VALIDES = {
|
||||||
|
"$chaine = \"texte\"",
|
||||||
|
"$chaine=\"tata\"",
|
||||||
|
" $tata \t ",
|
||||||
|
"\"une chaine de texte\"",
|
||||||
|
"$chaine= \"toto\"+\"titi\"",
|
||||||
|
"$chaine= $toto +\"titi\"",
|
||||||
|
"$chaine= \"toto\"+ $titi",
|
||||||
|
"$chaine=$toto +$titi",
|
||||||
|
" \"toto\"+\"titi\"",
|
||||||
|
"$toto +\"titi\"",
|
||||||
|
"\"toto\"+ $titi",
|
||||||
|
"$toto + $titi",
|
||||||
|
"\"ab=bc\"",
|
||||||
|
"$chaine = \"ab+cd\"+$toto"
|
||||||
|
};
|
||||||
|
|
||||||
|
System.out.println("\tExécution du test de "
|
||||||
|
+ "ExpressionChaine#ExpressionChaine(String)");
|
||||||
|
for (String texteArgs : INVALIDES) {
|
||||||
|
try {
|
||||||
|
new ExpressionChaine(texteArgs);
|
||||||
|
echec();
|
||||||
|
} catch (InterpreteurException lancee) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String texteArgs : VALIDES) {
|
||||||
|
try {
|
||||||
|
new ExpressionChaine(texteArgs);
|
||||||
|
} catch (InterpreteurException lancee) {
|
||||||
|
echec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests unitaires de {@link ExpressionChaine#calculer()}
|
||||||
|
*/
|
||||||
|
public void testCalculer() {
|
||||||
|
final Chaine[] RESULTAT_ATTENDU = {
|
||||||
|
new Chaine("\"texte\""),
|
||||||
|
new Chaine("\"tata\""),
|
||||||
|
new Chaine("\"\""),
|
||||||
|
new Chaine("\"une chaine de texte\""),
|
||||||
|
new Chaine("\"tototiti\""),
|
||||||
|
new Chaine("\"valTototiti\""),
|
||||||
|
new Chaine("\"toto\""),
|
||||||
|
new Chaine("\"valToto\""),
|
||||||
|
new Chaine("\"tototiti\""),
|
||||||
|
new Chaine("\"valTototiti\""),
|
||||||
|
new Chaine("\"toto\""),
|
||||||
|
new Chaine("\"valToto\""),
|
||||||
|
new Chaine("\"ab=bc\""),
|
||||||
|
new Chaine("\"ab+cdvalToto\"")
|
||||||
|
};
|
||||||
|
|
||||||
|
System.out.println("\tExécution du test de "
|
||||||
|
+ "ExpressionChaine#calculer()");
|
||||||
|
|
||||||
|
/* Exception levée si contexte non référencé */
|
||||||
|
try {
|
||||||
|
fixture[0].calculer();
|
||||||
|
echec();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// vide
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Création contexte (avec $toto = "valToto") et référencement */
|
||||||
|
Contexte contexteGlobal = new Contexte();
|
||||||
|
contexteGlobal.ajouterVariable(new IdentificateurChaine("$toto"),
|
||||||
|
new Chaine("\"valToto\""));
|
||||||
|
Expression.referencerContexte(contexteGlobal);
|
||||||
|
System.out.print("\tContexte initial : \n" + contexteGlobal);
|
||||||
|
|
||||||
|
for (int numTest = 0; numTest < RESULTAT_ATTENDU.length ; numTest++) {
|
||||||
|
System.out.println("\nCalcul de : " + fixture[numTest]);
|
||||||
|
assertEquivalence(fixture[numTest].calculer()
|
||||||
|
.compareTo(RESULTAT_ATTENDU[numTest]), 0);
|
||||||
|
System.out.println("\tContexte : \n" + contexteGlobal);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/**
|
||||||
|
* Instruction.java 9 mai 2021
|
||||||
|
* IUT info1 2020-2021, pas de copyright, aucun droit
|
||||||
|
*/
|
||||||
|
package interpreteurlir.motscles.instructions;
|
||||||
|
|
||||||
|
import interpreteurlir.Contexte;
|
||||||
|
import interpreteurlir.expressions.Expression;
|
||||||
|
import interpreteurlir.motscles.Commande;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instruction du langage LIR. Chaque instruction se caractérise par une
|
||||||
|
* expression et un contexte d'exécution
|
||||||
|
* @author Nicolas Caminade
|
||||||
|
* @author Sylvan Courtiol
|
||||||
|
* @author Pierre Debas
|
||||||
|
* @author Heïa Dexter
|
||||||
|
* @author Lucas Vabre
|
||||||
|
*/
|
||||||
|
public class Instruction extends Commande {
|
||||||
|
|
||||||
|
/** Contexte d'exécution de cette instruction */
|
||||||
|
protected Contexte contexteGlobal;
|
||||||
|
|
||||||
|
/** Expression qui sera exécutée par la commande */
|
||||||
|
protected Expression aExecuter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise une instruction à partir du contexte d'éxécution et de
|
||||||
|
* l'expression à exécuter
|
||||||
|
* @param arguments expression qui sera exécutée
|
||||||
|
* @param contexte global de l'application
|
||||||
|
*/
|
||||||
|
public Instruction(String arguments, Contexte contexte) {
|
||||||
|
super(arguments,contexte);
|
||||||
|
// arguments non utilisés pour Instruction générale
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Non - javadoc
|
||||||
|
* @see interpreteurlir.motscles.Commande#executer()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean executer() {
|
||||||
|
return super.executer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Non - javadoc
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getSimpleName() + " " + aExecuter;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* InstructionVar.java 9 mai 2021
|
||||||
|
* IUT info1 2020-2021, pas de copyright, aucun droit
|
||||||
|
*/
|
||||||
|
package interpreteurlir.motscles.instructions;
|
||||||
|
|
||||||
|
import interpreteurlir.Contexte;
|
||||||
|
import interpreteurlir.InterpreteurException;
|
||||||
|
import interpreteurlir.expressions.Expression;
|
||||||
|
import interpreteurlir.expressions.ExpressionChaine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instruction de déclaration et d'affectation de variables. La syntaxe de
|
||||||
|
* cette expression est de la forme var identificateur = expression. Si
|
||||||
|
* expression non renseignée, l'interpréteur affichera un message d'erreur ;
|
||||||
|
* l'instruction doit effectuer systématiquement une affectation.
|
||||||
|
* @author Nicolas Caminade
|
||||||
|
* @author Sylvan Courtiol
|
||||||
|
* @author Pierre Debas
|
||||||
|
* @author Heïa Dexter
|
||||||
|
* @author Lucas Vabre
|
||||||
|
*/
|
||||||
|
public class InstructionVar extends Instruction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO comment initial state of the object
|
||||||
|
* @param arguments expression à exécuter
|
||||||
|
* @param contexte global de l'interpréteur
|
||||||
|
*/
|
||||||
|
public InstructionVar(String arguments, Contexte contexte) {
|
||||||
|
super(arguments, contexte);
|
||||||
|
|
||||||
|
if (arguments == null || arguments.isBlank()
|
||||||
|
|| ExpressionChaine.indexOperateur(arguments, '=') <= 0)
|
||||||
|
throw new InterpreteurException("erreur de syntaxe");
|
||||||
|
|
||||||
|
aExecuter = Expression.determinerTypeExpression(arguments.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Non - javadoc
|
||||||
|
* @see interpreteurlir.motscles.instructions.Instruction#executer()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean executer() {
|
||||||
|
aExecuter.calculer();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Non - javadoc
|
||||||
|
* @see interpreteurlir.motscles.instructions.Instruction#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "var " + aExecuter;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* TestInstruction.java 9 mai 2021
|
||||||
|
* IUT info1 2020-2021, pas de copyright, aucun droit
|
||||||
|
*/
|
||||||
|
package interpreteurlir.motscles.instructions.tests;
|
||||||
|
|
||||||
|
import interpreteurlir.Contexte;
|
||||||
|
import interpreteurlir.motscles.instructions.Instruction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests unitaires des instructions
|
||||||
|
* @author Nicolas Caminade
|
||||||
|
* @author Sylvan Courtiol
|
||||||
|
* @author Pierre Debas
|
||||||
|
* @author Heïa Dexter
|
||||||
|
* @author Lucas Vabre
|
||||||
|
*/
|
||||||
|
public class TestInstruction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test du constructeur
|
||||||
|
*/
|
||||||
|
public static void testInstruction() {
|
||||||
|
System.out.println("Test du constructeur");
|
||||||
|
Instruction aTester = new Instruction("Bonjour", new Contexte());
|
||||||
|
System.out.println("==> OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test de toString()
|
||||||
|
*/
|
||||||
|
public static void testToString() {
|
||||||
|
System.out.println("Test de toString()");
|
||||||
|
Instruction aTester = new Instruction("Bonjour", new Contexte());
|
||||||
|
|
||||||
|
if (!aTester.toString().equals("Instruction null"))
|
||||||
|
System.err.println("Echec du test");
|
||||||
|
else
|
||||||
|
System.out.println("==> OK\n");
|
||||||
|
|
||||||
|
System.out.println(aTester);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lancement des tests
|
||||||
|
* @param args non utilisé
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
testInstruction();
|
||||||
|
testToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* TestInstructionVar.java 9 mai 2021
|
||||||
|
* IUT info1 2020-2021, pas de copyright, aucun droit
|
||||||
|
*/
|
||||||
|
package interpreteurlir.motscles.instructions.tests;
|
||||||
|
|
||||||
|
import interpreteurlir.Contexte;
|
||||||
|
import interpreteurlir.InterpreteurException;
|
||||||
|
import interpreteurlir.motscles.instructions.InstructionVar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests unitaires de l'instruction var
|
||||||
|
* @author Nicolas Caminade
|
||||||
|
* @author Sylvan Courtiol
|
||||||
|
* @author Pierre Debas
|
||||||
|
* @author Heïa Dexter
|
||||||
|
* @author Lucas Vabre
|
||||||
|
*/
|
||||||
|
public class TestInstructionVar {
|
||||||
|
|
||||||
|
/** jeu de données pour tests */
|
||||||
|
public static final String[] VALIDES = {
|
||||||
|
"$toto = $tata", "entier=2+2", "$coucou = $toto + \"titi\"",
|
||||||
|
"anneeNaissance = 1898"
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test du constructeur InstructionVar
|
||||||
|
*/
|
||||||
|
public static void testInstructionVar() {
|
||||||
|
final String[] EXPRESSIONS_INVALIDES = {
|
||||||
|
"bonjour", "", null, "$toto $tata",
|
||||||
|
};
|
||||||
|
|
||||||
|
System.out.println("Test du constructeur\navec expressions invalides");
|
||||||
|
for (String aTester : EXPRESSIONS_INVALIDES) {
|
||||||
|
try {
|
||||||
|
new InstructionVar(aTester, new Contexte());
|
||||||
|
throw new RuntimeException("Echec du test");
|
||||||
|
} catch (InterpreteurException lancee) {
|
||||||
|
System.out.println(aTester + " ==> OK");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Avec expressions valides");
|
||||||
|
for (String aTester : VALIDES)
|
||||||
|
new InstructionVar(aTester, new Contexte());
|
||||||
|
|
||||||
|
System.out.println("Fin du test\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test de toString
|
||||||
|
*/
|
||||||
|
public static void testToString() {
|
||||||
|
final String[] CHAINES_ATTENDUES = {
|
||||||
|
"var $toto = $tata", "var entier=2+2",
|
||||||
|
"var $coucou = $toto + \\\"titi\\\"",
|
||||||
|
"var anneeNaissance = 1898"
|
||||||
|
};
|
||||||
|
|
||||||
|
System.out.println("Test de toString()");
|
||||||
|
for (int i = 0 ; i < VALIDES.length ; i++) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
assert VALIDES[i].toString().equals(CHAINES_ATTENDUES[i]);
|
||||||
|
} catch (AssertionError lancee) {
|
||||||
|
System.err.println("Echec du test à l'indice " + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("Fin du test\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO comment method responsibilities
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
testInstructionVar();
|
||||||
|
testToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user