mirror of
https://github.com/LucasVbr/interpreteur-lir.git
synced 2026-05-14 01:31:53 +00:00
265 lines
9.4 KiB
Java
265 lines
9.4 KiB
Java
/**
|
||
* 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;
|
||
import interpreteurlir.motscles.instructions.Instruction;
|
||
import interpreteurlir.programmes.*;
|
||
|
||
/**
|
||
* 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;
|
||
|
||
/** programme de cet analyseur */
|
||
private Programme programme;
|
||
|
||
/**
|
||
* Initialise un analyseur ayant son propre contexte.
|
||
*/
|
||
public Analyseur() {
|
||
super();
|
||
entree = new Scanner(System.in);
|
||
contexteGlobal = new Contexte();
|
||
Expression.referencerContexte(contexteGlobal);
|
||
programme = new Programme();
|
||
Commande.referencerProgramme(programme);
|
||
}
|
||
|
||
/**
|
||
* Lance la boucle qui demande puis exécute des commandes ou instructions
|
||
* saisies par l'utilisateur.
|
||
*/
|
||
public void mainLoop() {
|
||
String ligneSaisie;
|
||
String[] decoupage;
|
||
String motCle;
|
||
String arguments;
|
||
String texteEtiquette;
|
||
for (;;) {
|
||
texteEtiquette = null;
|
||
|
||
System.out.print(INVITE);
|
||
ligneSaisie = entree.nextLine().trim();
|
||
|
||
/* Instruction avec étiquette */
|
||
if (!ligneSaisie.isBlank()
|
||
&& Character.isDigit(ligneSaisie.charAt(0))) {
|
||
decoupage = ligneSaisie.split(" ", 2);
|
||
texteEtiquette = decoupage.length >= 1 ? decoupage[0] : "";
|
||
ligneSaisie = decoupage.length >= 2 ? decoupage[1] : "";
|
||
}
|
||
|
||
decoupage = ligneSaisie.split(" ", 2);
|
||
motCle = decoupage.length >= 1 ? decoupage[0] : "";
|
||
arguments = decoupage.length >= 2 ? decoupage[1] : "";
|
||
|
||
if (texteEtiquette == null) {
|
||
executerCommande(motCle, arguments.trim());
|
||
} else {
|
||
editerProgramme(texteEtiquette, motCle, arguments.trim());
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Ajoute une ligne de code (étiquette associée à une instruction)
|
||
* au programme chargé.
|
||
* @param texteEtiquette représentation texte de l'étiquette
|
||
* @param motCle mot clé de l'instruction
|
||
* @param arguments reste de la ligne saisie après le mot clé
|
||
*/
|
||
private void editerProgramme(String texteEtiquette, String motCle,
|
||
String arguments) {
|
||
Class<?> aAjouter;
|
||
try {
|
||
aAjouter = rechercheInstruction(motCle);
|
||
|
||
Class<?> classeArg = String.class;
|
||
Class<?> classeContexte = Contexte.class;
|
||
Instruction inst = (Instruction)aAjouter
|
||
.getConstructor(classeArg, classeContexte)
|
||
.newInstance(arguments, contexteGlobal);
|
||
|
||
Etiquette etiquette = new Etiquette(texteEtiquette);
|
||
|
||
programme.ajouterLigne(etiquette, inst);
|
||
feedback(false);
|
||
|
||
} catch ( InvocationTargetException | IllegalAccessException
|
||
| InstantiationException | NoSuchMethodException
|
||
| InterpreteurException | ExecutionException lancee) {
|
||
|
||
System.err.println(NOK_FEEDBACK
|
||
+ (lancee.getMessage() != null
|
||
? lancee.getMessage()
|
||
: lancee.getCause().getMessage()));
|
||
}
|
||
|
||
}
|
||
|
||
/**
|
||
* 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 | ExecutionException 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);
|
||
} else if (!motCle.equals(motCle.toLowerCase())) {
|
||
throw new InterpreteurException(ERREUR_INCONNU);
|
||
}
|
||
|
||
motCle = (Character.toUpperCase(motCle.charAt(0)))
|
||
+ (motCle.length() > 1 ? motCle.substring(1) : "");
|
||
|
||
Class<?> aChercher;
|
||
try {
|
||
aChercher = Class.forName(CLASS_PATH_CMD + motCle);
|
||
} catch(ClassNotFoundException | NoClassDefFoundError nonCmd) {
|
||
try {
|
||
aChercher = Class.forName(CLASS_PATH_INST + motCle);
|
||
} catch(ClassNotFoundException nonInst) {
|
||
throw new InterpreteurException(ERREUR_INCONNU);
|
||
}
|
||
}
|
||
|
||
return aChercher;
|
||
}
|
||
|
||
/**
|
||
* Recherche l'instruction correspondant au mot clé.
|
||
* <ul><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 l'instruction
|
||
* @return Classe de cette instruction.
|
||
* @throws InterpreteurException si motCle est vide, null ou non reconnue
|
||
*/
|
||
private static Class<?> rechercheInstruction(String motCle) {
|
||
final String ERREUR_VIDE = "ligne vide";
|
||
final String ERREUR_INCONNU = "mot clé inconnu";
|
||
final String CLASS_PATH_INST =
|
||
"interpreteurlir.motscles.instructions.Instruction";
|
||
|
||
if (motCle == null || motCle.isBlank()) {
|
||
throw new InterpreteurException(ERREUR_VIDE);
|
||
} else if (!motCle.equals(motCle.toLowerCase())) {
|
||
throw new InterpreteurException(ERREUR_INCONNU);
|
||
}
|
||
|
||
motCle = (Character.toUpperCase(motCle.charAt(0)))
|
||
+ (motCle.length() > 1 ? motCle.substring(1) : "");
|
||
|
||
Class<?> aChercher;
|
||
try {
|
||
aChercher = Class.forName(CLASS_PATH_INST + motCle);
|
||
} catch(ClassNotFoundException | NoClassDefFoundError nonCmd) {
|
||
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();
|
||
}
|
||
|
||
|
||
}
|