|
@@ -2,18 +2,13 @@ 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;
|
|
|
|
|
|
import migl.lisp.operator.ComparatorOperator;
|
|
|
import migl.lisp.operator.ConsOperator;
|
|
|
import migl.lisp.operator.DefineOperator;
|
|
|
import migl.lisp.operator.MinMaxOperator;
|
|
|
import migl.util.ConsList;
|
|
|
-import migl.util.ConsListFactory;
|
|
|
|
|
|
public class LispImpl implements Lisp {
|
|
|
|
|
@@ -152,25 +147,11 @@ public class LispImpl implements Lisp {
|
|
|
|
|
|
@Override
|
|
|
public Object parse(String expr) throws LispError {
|
|
|
- //Analyse l'expression
|
|
|
- if(!this.verify(expr)) {
|
|
|
+ LispParser lp = new LispParser(expr);
|
|
|
+ if(!lp.verify()) {
|
|
|
throw new LispError("Invalid Format");
|
|
|
}
|
|
|
- //Remplace les nil par ()
|
|
|
- expr = expr.replaceAll(" nil ", " () ").replaceAll("\\(nil ", "(() ").replaceAll(" nil\\)", " ())");
|
|
|
- //Explose l'expression
|
|
|
- Queue<String> explode = this.explode(expr);
|
|
|
- //Analyse le type d'expression
|
|
|
- String val = explode.poll();
|
|
|
- if("(".equals(val)){
|
|
|
- return this.parseList(explode);
|
|
|
- } else {
|
|
|
- //Element seul
|
|
|
- if(explode.size() > 0) {
|
|
|
- throw new LispError("Invalid Format");
|
|
|
- }
|
|
|
- return LispElement.valueOf(val).value;
|
|
|
- }
|
|
|
+ return lp.parse();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -189,130 +170,6 @@ public class LispImpl implements Lisp {
|
|
|
|
|
|
}
|
|
|
|
|
|
- /* --- Verification --- */
|
|
|
-
|
|
|
- /**
|
|
|
- * Verifie que le format d'un String correspond bien à une expression Lisp
|
|
|
- *
|
|
|
- * @param expr Le String à examiner
|
|
|
- * @return
|
|
|
- */
|
|
|
- private boolean verify(String expr) {
|
|
|
- expr = expr.trim();
|
|
|
- //Pas vide
|
|
|
- if(expr.length() == 0) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- //Liste ou element
|
|
|
- if(expr.charAt(0) == '(') {
|
|
|
- return this.verifyList(expr);
|
|
|
- }
|
|
|
- return this.verifyElement(expr);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Verifie que le format d'un String correspond bien à une liste Lisp
|
|
|
- *
|
|
|
- * @param expr Le String à examiner
|
|
|
- * @return
|
|
|
- */
|
|
|
- private boolean verifyList(String expr) {
|
|
|
- Pattern p = Pattern.compile("\\(([ |\t]*[A-Za-z0-9\\.\\+\\-\\/\\*<>=#!]+[ |\t]*)*\\)");
|
|
|
- Matcher m = p.matcher(expr);
|
|
|
- //Si pas de correspondance
|
|
|
- if(!m.find()) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- //Si toute la chaine
|
|
|
- else if(m.end() - m.start() == expr.length()) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- //Si commence au debut mais finit avant la fin il y a alors des elements hors de la liste
|
|
|
- else if(m.start() == 0) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- //Si il y a une liste dans la liste
|
|
|
- else {
|
|
|
- StringBuilder builder = new StringBuilder();
|
|
|
- builder.append(expr.substring(0, m.start())).append("list").append(expr.substring(m.end()));
|
|
|
- return this.verifyList(builder.toString());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Verifie que le format d'un String correspond bien à un element Lisp
|
|
|
- *
|
|
|
- * @param expr Le String à examiner
|
|
|
- * @return
|
|
|
- */
|
|
|
- private boolean verifyElement(String expr) {
|
|
|
- Pattern p = Pattern.compile("[ |\t]*[A-Za-z0-9\\.\\+\\-\\/\\*<>=#]+[ |\t]*");
|
|
|
- Matcher m = p.matcher(expr);
|
|
|
- return m.find();
|
|
|
- }
|
|
|
-
|
|
|
- /* --- Parser --- */
|
|
|
-
|
|
|
- /**
|
|
|
- * Découpe un string pour l'analyse Lisp
|
|
|
- *
|
|
|
- * @param expr L'expression à analyser
|
|
|
- * @return L'expression découpée
|
|
|
- */
|
|
|
- private Queue<String> explode(String expr) {
|
|
|
- String[] tmp = expr.trim().split("[ |\t]");
|
|
|
- Queue<String> result = new LinkedList<>();
|
|
|
- for(String str : tmp) {
|
|
|
- char[] charArray = str.toCharArray();
|
|
|
- StringBuilder builder = new StringBuilder();
|
|
|
- for(char c : charArray) {
|
|
|
- if(c == '(') {
|
|
|
- //Si il y a une chaine dans le builder à mettre avant
|
|
|
- if(builder.length() != 0) {
|
|
|
- result.add(builder.toString());
|
|
|
- builder = new StringBuilder();
|
|
|
- }
|
|
|
- result.add("" + c);
|
|
|
- } else if(c == ')') {
|
|
|
- //Si il y a une chaine dans le builder à mettre avant
|
|
|
- if(builder.length() != 0) {
|
|
|
- result.add(builder.toString());
|
|
|
- builder = new StringBuilder();
|
|
|
- }
|
|
|
- result.add("" + c);
|
|
|
- } else {
|
|
|
- builder.append(c);
|
|
|
- }
|
|
|
- }
|
|
|
- //Si il reste une chaine dans le builder à la fin
|
|
|
- if(builder.length() != 0) {
|
|
|
- result.add(builder.toString());
|
|
|
- }
|
|
|
- }
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Parse une file d'element en Lisp
|
|
|
- *
|
|
|
- * @param queue La file avec les valeurs récupérées {@link #explode(String)}
|
|
|
- * @return Liste d'element
|
|
|
- * @throws LispError Format invalide
|
|
|
- */
|
|
|
- private Object parseList(Queue<String> queue) throws LispError {
|
|
|
- ConsList<Object> list = ConsListFactory.nil();
|
|
|
- String val = queue.poll();
|
|
|
- while(!")".equals(val)) {
|
|
|
- if("(".equals(val)) {
|
|
|
- list = list.append(this.parseList(queue));
|
|
|
- } else {
|
|
|
- list = list.append(LispElement.valueOf(val).value);
|
|
|
- }
|
|
|
- val = queue.poll();
|
|
|
- }
|
|
|
- return list;
|
|
|
- }
|
|
|
-
|
|
|
/* --- Evaluation --- */
|
|
|
|
|
|
/**
|