import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.RandomAccessFile; import java.io.Reader; import java.io.StreamTokenizer; import java.io.StringReader; import java.util.HashMap; import java.util.Map; public class Calculette { private final Map operateurs = new HashMap(); public Calculette(String repertoireOperateurs) { try { new ChargeurOperateur().chargerOperateurs(repertoireOperateurs); } catch (Exception e) { throw new Error("Chargement opérateurs impossibles, " + e.getMessage()); } } private double expression(StreamTokenizer st) throws IOException, SyntaxErrorException { switch (st.ttype) { case StreamTokenizer.TT_NUMBER: return st.nval; case StreamTokenizer.TT_WORD: Operateur op = (Operateur) operateurs.get(st.sval); if (op == null) { throw new SyntaxErrorException(st, "Opérateur inconnu"); } double[] operandes = new double[op.arite()]; for (int i = 0; i < op.arite(); ++i) { st.nextToken(); operandes[i] = expression(st); } return op.evaluer(operandes); default: throw new SyntaxErrorException(st); } } public void evaluer(Reader entree, PrintWriter sortie, boolean finDeLigne) throws SyntaxErrorException, IOException { StreamTokenizer st = new StreamTokenizer(entree); st.wordChars('!', '~'); st.ordinaryChar('-'); st.eolIsSignificant(finDeLigne); st.nextToken(); while (st.ttype != StreamTokenizer.TT_EOF) { double valeur = expression(st); st.nextToken(); if (st.ttype != (finDeLigne ? StreamTokenizer.TT_EOL : StreamTokenizer.TT_EOF)) { throw new SyntaxErrorException(st); } sortie.println(valeur); if (finDeLigne) { st.nextToken(); } } } private static void usage() { System.err .println("java Calculette "); System.exit(1); } public void ajouter(Operateur op) { operateurs.put(op.symbole(), op); } class ChargeurOperateur extends ClassLoader { void chargerOperateurs(String repertoire) throws ClassNotFoundException, InstantiationException, IllegalAccessException { String[] fichiers = new File(repertoire).list(); String suffixe = ".class"; if (fichiers != null) { for (String f : fichiers) { if (f.endsWith(suffixe)) { String prefixe = f.substring(0, f.length() - suffixe.length()); Class c = findClass(repertoire, prefixe); ajouter(c.newInstance()); } } } } protected Class findClass(String rep, String nom) throws ClassNotFoundException { File f = new File(rep + File.separator + nom + ".class"); long size = f.length(); if (size > Integer.MAX_VALUE) { throw new ClassFormatError("Fichier " + nom + " trop long"); } byte[] buffer = new byte[(int) size]; try { RandomAccessFile randomAccessFile = new RandomAccessFile(f, "r"); randomAccessFile.readFully(buffer, 0, buffer.length); randomAccessFile.close(); } catch (IOException e) { throw new ClassNotFoundException(e.toString()); } Class c = defineClass(nom, buffer, 0, buffer.length); return c.asSubclass(Operateur.class); } } public static void main(String[] args) throws FileNotFoundException, IOException, SyntaxErrorException { if (args.length > 2) usage(); Calculette c = new Calculette("plugins"); PrintWriter sortie = (args.length == 2 ? new PrintWriter( new FileWriter(args[1])) : new PrintWriter(System.out, true)); // autoflush if (args.length >= 1) { c .evaluer(new BufferedReader(new FileReader(args[0])), sortie, true); } else { BufferedReader entree = new BufferedReader(new InputStreamReader( System.in)); for (String s = entree.readLine(); s != null; s = entree.readLine()) { c.evaluer(new StringReader(s), sortie, false); } } sortie.close(); } }