/** * 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()); if (motCle.equals("lance") || (motCle.equals("affiche") && !arguments.isBlank())) { System.out.println(); } } 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é. *