Răsfoiți Sursa

Fusion LispImpl et LispEval

Arthur Brandao 6 ani în urmă
părinte
comite
099f4fe420
2 a modificat fișierele cu 172 adăugiri și 165 ștergeri
  1. 0 164
      src/migl/lisp/LispEval.java
  2. 172 1
      src/migl/lisp/LispImpl.java

+ 0 - 164
src/migl/lisp/LispEval.java

@@ -1,164 +0,0 @@
-package migl.lisp;
-
-import java.util.Map;
-import java.math.BigInteger;
-import java.util.HashMap;
-
-import migl.util.ConsList;
-import migl.util.ConsListFactory;
-
-@SuppressWarnings("unchecked")
-public class LispEval {
-	
-	/*
-	 * Utilisé LispElement.generate pour tous ce qui est retour ou quand la valeur doit être un element précis
-	 * Sinon utiliser getElement pour pour voir gerer les souslistes et les variables
-	 */
-	
-	private static Map<String, LispOperator> operators = new HashMap<>();
-	static {
-		operators.put("not", (lisp) -> {
-			if(lisp.size() != 1) {
-				throw new LispError("Incorrect number of argument");
-			}
-			boolean result = !getElement(lisp.car()).toBoolean();
-			return LispElement.generate(result);
-		});
-		operators.put("and", (lisp) -> {
-			if(lisp.size() != 2) {
-				throw new LispError("Incorrect number of argument");
-			}
-			boolean result = getElement(lisp.car()).toBoolean() && getElement(lisp.cdr().car()).toBoolean();
-			return LispElement.generate(result);
-		});
-		operators.put("or", (lisp) -> {
-			if(lisp.size() != 2) {
-				throw new LispError("Incorrect number of argument");
-			}
-			boolean result = getElement(lisp.car()).toBoolean() || getElement(lisp.cdr().car()).toBoolean();
-			return LispElement.generate(result);
-		});
-		operators.put(">", (lisp) -> {
-			if(lisp.size() != 2) {
-				throw new LispError("Incorrect number of argument");
-			}
-			boolean result = getElement(lisp.car()).toNumber() > getElement(lisp.cdr().car()).toNumber();
-			return LispElement.generate(result);
-		});
-		operators.put(">=", (lisp) -> {
-			if(lisp.size() != 2) {
-				throw new LispError("Incorrect number of argument");
-			}
-			boolean result = getElement(lisp.car()).toNumber() >= getElement(lisp.cdr().car()).toNumber();
-			return LispElement.generate(result);
-		});
-		operators.put("<", (lisp) -> {
-			if(lisp.size() != 2) {
-				throw new LispError("Incorrect number of argument");
-			}
-			boolean result = getElement(lisp.car()).toNumber() < getElement(lisp.cdr().car()).toNumber();
-			return LispElement.generate(result);
-		});
-		operators.put("<=", (lisp) -> {
-			if(lisp.size() != 2) {
-				throw new LispError("Incorrect number of argument");
-			}
-			boolean result = getElement(lisp.car()).toNumber() <= getElement(lisp.cdr().car()).toNumber();
-			return LispElement.generate(result);
-		});
-		operators.put("=", (lisp) -> {
-			if(lisp.size() != 2) {
-				throw new LispError("Incorrect number of argument");
-			}
-			boolean result = getElement(lisp.car()).toNumber() == getElement(lisp.cdr().car()).toNumber();
-			return LispElement.generate(result);
-		});
-		operators.put("+", (lisp) -> {
-			boolean isInt = true;
-			double result = 0;
-			while(!lisp.isEmpty()) {
-				LispElement<?> elt = getElement(lisp.car());
-				result += elt.toNumber();
-				isInt = isInt && elt.value.getClass() == BigInteger.class;
-				lisp = lisp.cdr();
-			}
-			if(isInt) {
-				return LispElement.generate((int) result);
-			}
-			return LispElement.generate(result);
-		});
-		operators.put("*", (lisp) -> {
-			boolean isInt = true;
-			double result = 1;
-			while(!lisp.isEmpty()) {
-				LispElement<?> elt = getElement(lisp.car());
-				result *= elt.toNumber();
-				isInt = isInt && elt.value.getClass() == BigInteger.class;
-				lisp = lisp.cdr();
-			}
-			if(isInt) {
-				return LispElement.generate((int) result);
-			}
-			return LispElement.generate(result);
-		});
-		operators.put("-", (lisp) -> {
-			switch(lisp.size()) {				
-				case 1:
-					LispElement<?> elt = getElement(lisp.car());
-					if(elt.value.getClass() == Double.class) {
-						return LispElement.generate(elt.toNumber() * -1);
-					}
-					return LispElement.generate(elt.toInt().multiply(new BigInteger("-1")));
-				case 2:
-					LispElement<?> elt1 = getElement(lisp.car());
-					LispElement<?> elt2 = getElement(lisp.cdr().car());
-					if(elt1.value.getClass() == Double.class || elt2.value.getClass() == Double.class) {
-						return LispElement.generate(elt1.toNumber() - elt2.toNumber());
-					}
-					return LispElement.generate(elt1.toInt().subtract(elt2.toInt()));
-				default:
-					throw new LispError("Incorrect number of argument");
-			}
-		});
-		operators.put("/", (lisp) -> {
-			if(lisp.size() != 2) {
-				throw new LispError("Incorrect number of argument");
-			}
-			LispElement<?> elt1 = getElement(lisp.car());
-			LispElement<?> elt2 = getElement(lisp.cdr().car());
-			if(elt1.value.getClass() == Double.class || elt2.value.getClass() == Double.class) {
-				return LispElement.generate(elt1.toNumber() / elt2.toNumber());
-			}
-			return LispElement.generate(elt1.toInt().divide(elt2.toInt()));
-		});
-	}
-	
-	public static LispElement<?> evaluate(Object elt) throws LispError {
-		if(elt instanceof ConsList) {
-			return evaluate((ConsList<Object>) elt);
-		}
-		return evaluate(ConsListFactory.singleton(elt));
-	}
-
-	public static LispElement<?> evaluate(ConsList<Object> lisp) throws LispError {
-		LispOperator op = operators.get(LispElement.generate(lisp.car()).toStr());
-		if(op == null) {
-			throw new LispError(new UnsupportedOperationException("Unknow expression"));
-		}
-		try {
-			return op.apply(lisp.cdr());
-		} catch (IllegalStateException ex) {
-			throw new LispError(ex.getMessage(), ex);
-		}
-	}
-	
-	/* --- Recuperation des elements --- */
-	
-	private static LispElement<?> getElement(Object elt) throws LispError {
-		if(elt instanceof ConsList) {
-			return evaluate((ConsList<Object>) elt);
-		}
-		return LispElement.generate(elt);
-	}
-
-}

+ 172 - 1
src/migl/lisp/LispImpl.java

@@ -1,6 +1,9 @@
 package migl.lisp;
 
+import java.math.BigInteger;
+import java.util.HashMap;
 import java.util.LinkedList;
+import java.util.Map;
 import java.util.Queue;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -10,6 +13,128 @@ import migl.util.ConsListFactory;
 
 public class LispImpl implements Lisp {
 	
+	/**
+	 * Les operateurs gérés par l'interpréteur
+	 */
+	private static Map<String, LispOperator> operators = new HashMap<>();
+	static {
+		//Définition des opérateurs
+		operators.put("not", (lisp) -> {
+			if(lisp.size() != 1) {
+				throw new LispError("Incorrect number of argument");
+			}
+			boolean result = !getElement(lisp.car()).toBoolean();
+			return LispElement.generate(result);
+		});
+		operators.put("and", (lisp) -> {
+			if(lisp.size() != 2) {
+				throw new LispError("Incorrect number of argument");
+			}
+			boolean result = getElement(lisp.car()).toBoolean() && getElement(lisp.cdr().car()).toBoolean();
+			return LispElement.generate(result);
+		});
+		operators.put("or", (lisp) -> {
+			if(lisp.size() != 2) {
+				throw new LispError("Incorrect number of argument");
+			}
+			boolean result = getElement(lisp.car()).toBoolean() || getElement(lisp.cdr().car()).toBoolean();
+			return LispElement.generate(result);
+		});
+		operators.put(">", (lisp) -> {
+			if(lisp.size() != 2) {
+				throw new LispError("Incorrect number of argument");
+			}
+			boolean result = getElement(lisp.car()).toNumber() > getElement(lisp.cdr().car()).toNumber();
+			return LispElement.generate(result);
+		});
+		operators.put(">=", (lisp) -> {
+			if(lisp.size() != 2) {
+				throw new LispError("Incorrect number of argument");
+			}
+			boolean result = getElement(lisp.car()).toNumber() >= getElement(lisp.cdr().car()).toNumber();
+			return LispElement.generate(result);
+		});
+		operators.put("<", (lisp) -> {
+			if(lisp.size() != 2) {
+				throw new LispError("Incorrect number of argument");
+			}
+			boolean result = getElement(lisp.car()).toNumber() < getElement(lisp.cdr().car()).toNumber();
+			return LispElement.generate(result);
+		});
+		operators.put("<=", (lisp) -> {
+			if(lisp.size() != 2) {
+				throw new LispError("Incorrect number of argument");
+			}
+			boolean result = getElement(lisp.car()).toNumber() <= getElement(lisp.cdr().car()).toNumber();
+			return LispElement.generate(result);
+		});
+		operators.put("=", (lisp) -> {
+			if(lisp.size() != 2) {
+				throw new LispError("Incorrect number of argument");
+			}
+			boolean result = getElement(lisp.car()).toNumber() == getElement(lisp.cdr().car()).toNumber();
+			return LispElement.generate(result);
+		});
+		operators.put("+", (lisp) -> {
+			boolean isInt = true;
+			double result = 0;
+			while(!lisp.isEmpty()) {
+				LispElement<?> elt = getElement(lisp.car());
+				result += elt.toNumber();
+				isInt = isInt && elt.value.getClass() == BigInteger.class;
+				lisp = lisp.cdr();
+			}
+			if(isInt) {
+				return LispElement.generate((int) result);
+			}
+			return LispElement.generate(result);
+		});
+		operators.put("*", (lisp) -> {
+			boolean isInt = true;
+			double result = 1;
+			while(!lisp.isEmpty()) {
+				LispElement<?> elt = getElement(lisp.car());
+				result *= elt.toNumber();
+				isInt = isInt && elt.value.getClass() == BigInteger.class;
+				lisp = lisp.cdr();
+			}
+			if(isInt) {
+				return LispElement.generate((int) result);
+			}
+			return LispElement.generate(result);
+		});
+		operators.put("-", (lisp) -> {
+			switch(lisp.size()) {				
+				case 1:
+					LispElement<?> elt = getElement(lisp.car());
+					if(elt.value.getClass() == Double.class) {
+						return LispElement.generate(elt.toNumber() * -1);
+					}
+					return LispElement.generate(elt.toInt().multiply(new BigInteger("-1")));
+				case 2:
+					LispElement<?> elt1 = getElement(lisp.car());
+					LispElement<?> elt2 = getElement(lisp.cdr().car());
+					if(elt1.value.getClass() == Double.class || elt2.value.getClass() == Double.class) {
+						return LispElement.generate(elt1.toNumber() - elt2.toNumber());
+					}
+					return LispElement.generate(elt1.toInt().subtract(elt2.toInt()));
+				default:
+					throw new LispError("Incorrect number of argument");
+			}
+		});
+		operators.put("/", (lisp) -> {
+			if(lisp.size() != 2) {
+				throw new LispError("Incorrect number of argument");
+			}
+			LispElement<?> elt1 = getElement(lisp.car());
+			LispElement<?> elt2 = getElement(lisp.cdr().car());
+			if(elt1.value.getClass() == Double.class || elt2.value.getClass() == Double.class) {
+				return LispElement.generate(elt1.toNumber() / elt2.toNumber());
+			}
+			return LispElement.generate(elt1.toInt().divide(elt2.toInt()));
+		});
+	}
+	
 	@Override
 	public Object parse(String expr) throws LispError {
 		//Analyse l'expression
@@ -32,14 +157,19 @@ public class LispImpl implements Lisp {
 	}
 
 	@Override
+	@SuppressWarnings("unchecked")
 	public Object evaluate(Object ex) throws LispError {
-		return LispEval.evaluate(ex).value;
+		if(ex instanceof ConsList) {
+			return evaluate((ConsList<Object>) ex);
+		}
+		return evaluate(ConsListFactory.singleton(ex));
 	}
 	
 	/* --- Verification --- */
 	
 	/**
 	 * Verifie que le format d'un String correspond bien à une expression Lisp
+	 * 
 	 * @param expr Le String à examiner
 	 * @return
 	 */
@@ -58,6 +188,7 @@ public class LispImpl implements Lisp {
 	
 	/**
 	 * Verifie que le format d'un String correspond bien à une liste Lisp
+	 * 
 	 * @param expr Le String à examiner
 	 * @return
 	 */
@@ -86,6 +217,7 @@ public class LispImpl implements Lisp {
 	
 	/**
 	 * Verifie que le format d'un String correspond bien à un element Lisp
+	 * 
 	 * @param expr Le String à examiner
 	 * @return
 	 */
@@ -99,6 +231,7 @@ public class LispImpl implements Lisp {
 	
 	/**
 	 * Découpe un string pour l'analyse Lisp
+	 * 
 	 * @param expr L'expression à analyser
 	 * @return L'expression découpée
 	 */
@@ -137,6 +270,7 @@ public class LispImpl implements Lisp {
 	
 	/**
 	 * Parse une file d'element en Lisp
+	 * 
 	 * @param queue La file avec les valeurs parser par explode
 	 * @return Liste d'element
 	 * @throws LispError Format invalide
@@ -154,5 +288,42 @@ public class LispImpl implements Lisp {
 		}
 		return list;
 	}
+	
+	/* --- Evaluation --- */
+	
+	/**
+	 * Evalue un liste d'élément lisp parser dans un ConsList
+	 * 
+	 * @param lisp La liste parser {@link #parse(String)}
+	 * @return Valeur évaluer
+	 * @throws LispError
+	 */
+	private static LispElement<?> evaluate(ConsList<Object> lisp) throws LispError {
+		LispOperator op = operators.get(LispElement.generate(lisp.car()).toStr());
+		if(op == null) {
+			throw new LispError(new UnsupportedOperationException("Unknow expression"));
+		}
+		try {
+			return op.apply(lisp.cdr());
+		} catch (IllegalStateException ex) {
+			throw new LispError(ex.getMessage(), ex);
+		}
+	}
+	
+	/**
+	 * Récupère un élément dans la liste lisp
+	 * Si l'element est une liste elle seras alors analyser
+	 * 
+	 * @param elt L'element à récupérer
+	 * @return L'element ou le resultat de l'analyse si l'element est une liste
+	 * @throws LispError
+	 */
+	@SuppressWarnings("unchecked")
+	private static LispElement<?> getElement(Object elt) throws LispError {
+		if(elt instanceof ConsList) {
+			return evaluate((ConsList<Object>) elt);
+		}
+		return LispElement.generate(elt);
+	}
 
 }