6
\$\begingroup\$

I'm actually doing my own Prolog compiler just like SWISH one with Java. Prolog is a logic language that is particularly suited to programs that involve symbolic or non-numeric computation. Prolog consists of a series of rules and facts. A program is run by presenting some query and seeing if this can be proved against these known rules and facts.

It works with resolving, thanks to the Horn's clauses method, the last line which is called the goal with the first one which have the same litteral.

mag(paris,mag_a).
mag(paris,mag_b).
mag(lyon,mag_c).
mag(lyon,mag_d).
listeM(M):-mag(V,M),write(M),write( located_in ),write(V),nl.
listeM(X).

would give the goal listeM(X).:

mag_a located_in paris

Another example with the constant predicate fail

mag(paris,mag_a).
mag(paris,mag_b).
mag(lyon,mag_c).
mag(lyon,mag_d).
listeM(M):-mag(V,M),write(M),write( located_in ),write(V),nl,fail.
listeM(M):-write(end_list).
listeM(X).

would give the goal listeM(X).:

   mag_a located_in paris
   mag_b located_in paris
   mag_c located_in lyon
   mag_d located_in lyon
   fin liste
   true.

Another example with some arithmetical operations managed by the constant predicate plus and multi

multi(X,1,X).
multi(X,Y,R):-plus(Y1,1,Y),multi(X,Y1,R1),plus(R1,X,R).
multi(2,3,R),write(R).

would give with the goal multi(2,3,R),write(R)., that is to say searching to multiply 2 and 3

  6

Or even with the factorial calculation

fact(1,1).
fact(N,R):-plus(N1,1,N),fact(N1,R1),multi(N,R1,R).
multi(X,1,X).
multi(X,Y,R):-plus(Y1,1,Y),multi(X,Y1,R1),plus(R1,X,R).
go(N):-fact(N,R),write(N),write( has_the_following_factorial ),write(R).
go(6).

It would give with the goal go(6).

   6 has_the_following_factorial 720
   true 

In our program we load the file in the variable static String fichier ="yourFile.pl"; which has to be at the root of your workspace.

Our program actually works, but if you have any idea to make it simpler, I would be glad to hear it.

If you are able to know its perforamnce in the examples above in front of true, commercial tools such as SWISH, I would be glad too!

package projetMichel;
// file.txt has to be in the root of the project
// IMPORTANT: last line of the file has to be empty
// IR counts clauses and is used as the indice of resolution 
import java.io.*;
import java.util.*;

import projetMichel.ProjetMichel.Clause.Litteral.Symbole;

public class ProjetMichel {
    static String fichier ="exercice5.pl";
    static String[] Clauses= new String[120];
    static int cptVar = 0;
    static int maxVar = 200;
    static String[] VarAffich;
    static Object[] VarVal;
    static int[] VarSubst;
    static Clause Resolvante;
    static int IR=-1;
    static int ICF;
    static List listeCode;
    static List listeSymbole;
    static List listeAff;
    static int code;
    static boolean display = false;
    static boolean result = false;

    static int varExiste(String n){
        for(int i=0;i<listeAff.size();i++){
            if( ((String)listeAff.get(i)).equals(n)) return i;
        }
        return -1;
    }

    public static void main(String[] args) {


        String chaine="";
        VarAffich = new String[maxVar];
        VarVal = new Object[maxVar];
        VarSubst = new int[maxVar];String ligne="";
        //file reading  
        try{
            InputStream ips=new FileInputStream(fichier); 
            InputStreamReader ipsr=new InputStreamReader(ips);
            BufferedReader br=new BufferedReader(ipsr);

            Clauses = new String[100];
            for(int i=0;i<100;i++)Clauses[i]="";
            boolean suite;
            int i=0;
            while ((ligne=br.readLine())!=null){
                suite = false;
                System.out.println(ligne);
                Clauses[i]+=ligne;
                if(ligne.charAt(ligne.length()-1)!='.') {Clauses[i]+=" ";continue;}
                i++;
                chaine+=ligne+"\n";
            }
            br.close(); 
        }       
        catch (Exception e){
            //System.out.println("Erreur "+ligne.charAt(ligne.length()-1)+e.toString());
        }

        // Clause transformation and IR calculation
        int k = 0;
        while(!Clauses[k].equals("")){;ri(k);k++;}

        if(display){
            System.out.println("SUITE IR "+IR);

            for(int i=0;i<=IR;i++)System.out.println("LISTE "+Clause.ListeClauses[i]);
            System.out.println("Debut RESOLUTION IR "+IR);
        }

        resolution(Clause.ListeClauses);
        if(display){
            for(int i=0;i<=IR;i++)System.out.println("Liste "+Clause.ListeClauses[i]);
        }

    }

    static Clause ri(int noClause){
        Clause c=new Clause();
        String mot = "";
        String mot_old = "";
        List liste = new LinkedList();
        Clause.Litteral lit = null;
        Clause.Litteral.Symbole s = null;
        boolean variables = false;
        boolean predicat = false;
        //AJOUT
        listeCode = new LinkedList();
        listeSymbole = new LinkedList();
        listeAff = new LinkedList();
        do{
            mot_old = mot;
            mot = parsingClause(noClause);
            if(mot.equals("(")||mot.equals("[")){
                variables = true;
                lit = c.new Litteral(mot_old);
                c.add(lit);
                continue;
            }
            if(mot.equals(",")){
                if(variables){
                    //System.out.println("symbole analyse "+mot_old);
                    if(varExiste(mot_old)==-1){
                        //System.out.println(mot_old+" n'existe pas "+listeAff);
                        code=Annuaire.Code++;//
                        Annuaire.AffSymbole.put(code, mot_old);
                        if(mot_old.charAt(0)>='A'&&mot_old.charAt(0)<='Z'){
                            Annuaire.ValSymbole.put(code, null);
                        }else Annuaire.ValSymbole.put(code, mot_old);
                        s = lit.new Symbole(mot_old);
                        s.code = code;
                        lit.add(s);
                        listeCode.add(code);
                        listeSymbole.add(s);
                        listeAff.add(mot_old);

                    }
                    else{
                        //System.out.println(mot_old+" existe"+varExiste(mot_old));
                        lit.add(listeSymbole.get(varExiste(mot_old)));          
                    }
                }
                if(predicat){
                    predicat = false;
                    c.add( c.new Litteral(mot_old));
                }
                continue;
            }
            if(mot.equals(")")||mot.equals("]")){
                variables = false;
                // verifying if a symbol does exist in the clause
                if(varExiste(mot_old)==-1){
                    //System.out.println(mot_old+" n'existe pas "+listeAff);
                    code=Annuaire.Code++;//
                    Annuaire.AffSymbole.put(code, mot_old);
                    if(mot_old.charAt(0)>='A'&&mot_old.charAt(0)<='Z'){
                        Annuaire.ValSymbole.put(code, null);
                    }else Annuaire.ValSymbole.put(code, mot_old);
                    s = lit.new Symbole(mot_old);
                    s.code = code;
                    lit.add(s);
                    listeCode.add(code);
                    listeSymbole.add(s);
                    listeAff.add(mot_old);
                }
                else{
                    //second cas: the bvariable has already been met
                    //System.out.println(mot_old+" existe"+varExiste(mot_old));
                    lit.add(listeSymbole.get(varExiste(mot_old)));

                }
                continue;
            }
            else{// c'est un mot

                if(predicatConstant(mot)){predicat = true;}
                continue;
            }

        }while (!mot.equals(""));
        // case of a constant predicat at the end of a Clause
        if(predicat){c.add(c.new Litteral(mot_old));}
        //we have to change the variables name adding the name (only var) didn't understood this type actually
        //il faut changer le nom des variables en y incorporant le nom (var uniquement)
        for(int i=0;i<listeCode.size();i++){
            if( Annuaire.val((Integer)listeCode.get(i))==null )
                Annuaire.AffSymbole.put((Integer)listeCode.get(i),listeAff.get(i)+listeCode.get(i).toString());
        }
        if(display){
            System.out.println("CLAUSE "+c);
        }

        Clause.ListeClauses[++IR] = c;
        return c;
    }
    static boolean delimiteur(char c){
        boolean b = false;
        if(c=='('||c==')'||c==','||c==':'||c=='['||c==']')b = true;
        return b;
    }
    static boolean predicatConstant(String p){
        boolean b = false;
        if(p.equals("nl")||p.equals("fail")||p.equals("!")||p.equals("cut")) b = true;
        return b;
    }
    static boolean variable(Object s){
        boolean b = false;
        String ch;
        if(s instanceof String){
            ch = (String)s;
            if(ch.charAt(0)>='A'&&ch.charAt(0)<='Z')b = true;
        }
        if(s instanceof Integer){
            return true;
        }

        return b;
    }
    static String parsingClause(int noClause){
        String mot="";
        //System.out.println("DEBUG "+Clauses[noClause].charAt(0));
        while(Clauses[noClause].charAt(0)==' ')Clauses[noClause]=Clauses[noClause].substring(1);
        if(Clauses[noClause].charAt(0)=='.'){Clauses[noClause]=Clauses[noClause].substring(1);return mot;}
        if(Clauses[noClause].charAt(0)==':' && Clauses[noClause].charAt(1)=='-'){
            Clauses[noClause]=Clauses[noClause].substring(2);
            return ":-";
        }
        if(delimiteur(Clauses[noClause].charAt(0))){
            String r= Character.toString(Clauses[noClause].charAt(0));
            Clauses[noClause]=Clauses[noClause].substring(1);
            return r;
        }
        // word began is being read

        while(!delimiteur(Clauses[noClause].charAt(0))&&Clauses[noClause].charAt(0)!='.'&&Clauses[noClause].charAt(0)!=' '){
            mot+=Character.toString(Clauses[noClause].charAt(0));
            Clauses[noClause]=Clauses[noClause].substring(1);
        }
        return mot;
    }
    static void resolution(Clause[] lc){
        if(display){
            for(int i=0;i<=IR;i++)System.out.print(lc[i]+" / ");
        }

        boolean unif;
        List res;
        Resolvante = lc[IR];//(Clause)lc.get(lc.size()-1);
        ICF=IR;
        int[] Index = new int[100];
        System.out.println("\nBEGINING !");
        while(IR >= ICF){           
            unif = false;
            Clause copieResolvante = Clause.copie(IR);
            int cptrLit= 0;
            for(int i=Index[IR];i<IR;i++){
                Clause courante = Clause.copie(i);
                Clause.Litteral l = (Clause.Litteral)copieResolvante.listeLitteraux.get(0);
                String enterChar = ((Clause.Litteral)copieResolvante.listeLitteraux.get(0)).predicat;
                if ( (enterChar.equals("write") || enterChar.equals("nl") || enterChar.equals("fail")||enterChar.equals("!")||enterChar.equals("plus")||enterChar.equals("multi")||enterChar.equals("fact")) && cptrLit <= copieResolvante.listeLitteraux.size()-1){

                    if(cptrLit > copieResolvante.listeLitteraux.size()- 1 ){ 
                        break;
                    }
                    while(((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).predicat.equals("write")){
                        Clause.Litteral.Symbole s = (Clause.Litteral.Symbole)l.get(0);
                        System.out.println(s);
                        cptrLit++;
                        //System (enterChar.equals("write") || enterChar.equals("nl") || enterChar.equals("fail")).out.println("copieResolvante : "+ copieResolvante.listeLitteraux.size());
                        if((cptrLit > copieResolvante.listeLitteraux.size()- 1 )||(copieResolvante.isEmpty())){     
                            break;
                        }

                        l = (Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit);// why?
                        //System.out.println(s);

                        copieResolvante.remove(0);
                        if(display){
                            System.out.println("\n\nCOPIE RESOLVANTE: " + copieResolvante);
                        }


                    }
                    if(cptrLit > copieResolvante.listeLitteraux.size()- 1 ){ 
                        break;
                    }
                    if(((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).predicat.equals("nl")){
                        System.out.println("\n");

                        if(copieResolvante.isEmpty()){ 
                            break;
                        }
                        copieResolvante.remove(0);
                    }

                    if(copieResolvante.toString().equals("fail")){
                        i++;
                        break;
                    }
                    if(copieResolvante.toString().equals("!")){
                        //IR++;
                    }

                    if(((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).predicat.equals("plus")){

                        if(display){
                            System.out.println("plus HAS BEEN DETECTED");
                        }

                            System.out.println("x : " + (projetMichel.ProjetMichel.Clause.Litteral.Symbole) ((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).get(0) + "\ny : " + (projetMichel.ProjetMichel.Clause.Litteral.Symbole) ((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).get(1) +"\nz : " + (projetMichel.ProjetMichel.Clause.Litteral.Symbole) ((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).get(2));
                            Clause.Litteral.Symbole x = (projetMichel.ProjetMichel.Clause.Litteral.Symbole) ((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).get(0);
                            Clause.Litteral.Symbole y = (projetMichel.ProjetMichel.Clause.Litteral.Symbole) ((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).get(1);
                            Clause.Litteral.Symbole z = (projetMichel.ProjetMichel.Clause.Litteral.Symbole) ((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).get(2);

                            plus(x,y,z);
                            copieResolvante.remove(0);
                            copieResolvante.listeLitteraux.remove(0);
                            if(display){
                                System.out.println("PLUS DONE\nGOAL:"+ copieResolvante +"\n****************************************\n");
                            }

                    }
                    if(((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).predicat.equals("multi")){
                            if(display){
                                System.out.println("multi HAS BEEN DETECTED");
                                System.out.println("x : " + (projetMichel.ProjetMichel.Clause.Litteral.Symbole) ((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).get(0) + "\ny : " + (projetMichel.ProjetMichel.Clause.Litteral.Symbole) ((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).get(1) +"\nz : " + (projetMichel.ProjetMichel.Clause.Litteral.Symbole) ((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).get(2));
                            }


                            Clause.Litteral.Symbole x = (projetMichel.ProjetMichel.Clause.Litteral.Symbole) ((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).get(0);
                            Clause.Litteral.Symbole y = (projetMichel.ProjetMichel.Clause.Litteral.Symbole) ((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).get(1);
                            Clause.Litteral.Symbole z = (projetMichel.ProjetMichel.Clause.Litteral.Symbole) ((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).get(2);

                            multi(x,y,z);
                            copieResolvante.remove(0);
                            copieResolvante.listeLitteraux.remove(0);
                            if(display){
                                System.out.println("MULTI DONE\nGOAL:"+ copieResolvante +"\n****************************************\n");
                            }

                    }

                    if(((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).predicat.equals("fact")){
                        if(display){
                            System.out.println("fact HAS BEEN DETECTED");
                            System.out.println("x : " + (projetMichel.ProjetMichel.Clause.Litteral.Symbole) ((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).get(0) + "\ny : " + (projetMichel.ProjetMichel.Clause.Litteral.Symbole) ((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).get(1)); 
                        }


                        Clause.Litteral.Symbole x = (projetMichel.ProjetMichel.Clause.Litteral.Symbole) ((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).get(0);
                        Clause.Litteral.Symbole y = (projetMichel.ProjetMichel.Clause.Litteral.Symbole) ((Clause.Litteral)copieResolvante.listeLitteraux.get(cptrLit)).get(1);

                        fact(x,y);
                        copieResolvante.remove(0);
                        copieResolvante.listeLitteraux.remove(0);
                        if(display){
                            System.out.println("FACR DONE\nGOAL:"+ copieResolvante +"\n****************************************\n");
                        }

                }

                }else{
                    if(display){
                        System.out.println("WE ARE TRYING TO UNIFY "+copieResolvante+" WITH "+courante+" IR: "+IR + ", i: "+i);
                    }

                    res = copieResolvante.unif(courante);
                    if(res==null){
                        if(display){
                            System.out.println("\n* * * NEW CLAUSE IS BEING TESTED * * *\n");
                        }
                        continue;
                    }
                    if (res.size()==0){
                        System.out.println("RESOLUTION ACHIEVED\n**************************************************************\n");
                        System.out.println("RESULT: here we want the result..........???" );
                        return;
                    }
                    if(res.size()>0){//succes unification
                        Index[IR-1]=i+1;
                        //IR++;
                        unif = true;
                        if(display){
                            System.out.println("RESOLUTION DONE\nGOAL:"+ res +"\n****************************************\n");
                        }
                        if(display){
                            for(int k=0;k<=IR;k++)System.out.print(Clause.ListeClauses[k]+" / ");
                        }
                        //for(int ii=0;ii<=Prolog.IR;i++)System.out.print(Clause.ListeClauses[ii]+" / ");
                        break;
                    }                   
                }
            }//fin for
            if(!unif)IR--;
        }
        if(result){
            System.out.println("FAILURE ON THE PROGRAM !");     
        }else{
            System.out.println("PROGRAM RESOLUTION DONE !");
        }


    }

    private static void fact(Symbole x, Symbole y) {
        // TODO Auto-generated method stub
        Integer variable= Integer.parseInt(x.toString());
        if(display){
            System.out.println("FACT FUNCTION");
        }
        if (isInt(x.toString())){
            if(display){
                System.out.println("\nx IS NOT NULL");
            }
            if (isInt(y.toString())){
                if(display){
                    System.out.println("\nNO CALCULATION IS BEING PROCESSED");
                    }
            }
            else {
                if(display){
                    System.out.println("\ny IS THE VARIABLE");
                    }
                int debut=Integer.parseInt(x.toString());
                for (int i=1;i<debut;i++){
                    variable=variable*i;

                }
                Annuaire.ValSymbole.put(y.code, variable);
                Annuaire.AffSymbole.put(y.code, variable.toString());
            }
        }
        else if(isInt(y.toString()) ){
            System.out.println("\nx IS THE VARIABLE,  WE HAVE TO DO THE DIVISION");
                Integer resultat = 0;
                int produit = 0;
                for (int i=1; i<Integer.parseInt(y.toString()); i++){
                    produit *= i;
                    if(produit==Integer.parseInt(y.toString())){
                        resultat=i;
                        return;     
                    }
                }
                System.out.println("No factorial has been found");


            Annuaire.ValSymbole.put(x.code, resultat);
            Annuaire.AffSymbole.put(x.code, resultat.toString());


        }
        else System.out.println("\nLACKS VARIABLES");
    }


    private static void multi(Symbole x, Symbole y, Symbole z) {
        // TODO Auto-generated method stub
        if(display){
            System.out.println("MULTI FUNCTION");
        }
        if (isInt(x.toString())){
            if(display){
                System.out.println("\nx IS NOT NULL");
            }
            if (isInt(y.toString())){
                if(display){
                    System.out.println("\ny IS NOT NULL");
                    }
                if (isInt(z.toString())){
                    if(display){
                        System.out.println("\nz IS NOT NULL, NO CALCULATION BEING PROCESSED");
                        }
                    System.out.println(Integer.parseInt(z.toString())==Integer.parseInt(x.toString())+Integer.parseInt(y.toString()));
                    }
                else{
                    if(display){
                        System.out.println("\nz IS THE VARIABLE");
                        }
                    Integer b=Integer.parseInt(x.toString())*Integer.parseInt(y.toString());
                    Annuaire.ValSymbole.put(z.code, b);
                    Annuaire.AffSymbole.put(z.code, b.toString());
                }
            }
            else if (isInt(z.toString())){
                if(display){
                    System.out.println("\ny IS THE VARIABLE, WE HAVE TO DO THE THE DIVISION");
                    }
                Integer b=Integer.parseInt(x.toString())+Integer.parseInt(y.toString());
                Annuaire.ValSymbole.put(y.code, b);
                Annuaire.AffSymbole.put(y.code, b.toString());
            }
        }
        else if(isInt(y.toString()) && isInt(z.toString())){
            System.out.println("\nx IS THE VARIABLE,  WE HAVE TO DO THE THE DIVISION");
            Integer variable= Integer.parseInt(x.toString());
            for (int i=Integer.parseInt(x.toString())-1;i==0;i--){
                variable=variable*i;
            }

            Annuaire.ValSymbole.put(x.code, variable);
            Annuaire.AffSymbole.put(x.code, variable.toString());


        }
        else System.out.println("\nLACKS VARIABLES");
    }

    private static void plus(Clause.Litteral.Symbole x, Clause.Litteral.Symbole y, Clause.Litteral.Symbole z) {
        // TODO Auto-generated method stub
        if(display){
            System.out.println("PLUS FUNCTION");
        }
        if (isInt(x.toString())){
            if(display){
                System.out.println("\nx IS NOT NULL");
            }
            if (isInt(y.toString())){
                if(display){
                    System.out.println("\ny IS NOT NULL");
                }
                if (isInt(z.toString())){
                    if(display){
                        System.out.println("\nz IS NOT NULL, NO CALCULATION BEING PROCESSED");
                    }
                    System.out.println(Integer.parseInt(z.toString())==Integer.parseInt(x.toString())+Integer.parseInt(y.toString()));
                    }
                else{
                    if(display){
                        System.out.println("\nz IS THE VARIABLE");
                    }
                    Integer b=Integer.parseInt(x.toString())+Integer.parseInt(y.toString());
                    Annuaire.ValSymbole.put(z.code, b);
                    Annuaire.AffSymbole.put(z.code, b.toString());
                }
            }
            else if (isInt(z.toString())){
                if(display){
                    System.out.println("\ny IS THE VARIABLE");
                }
                Integer b=Integer.parseInt(x.toString())+Integer.parseInt(y.toString());
                Annuaire.ValSymbole.put(y.code, b);
                Annuaire.AffSymbole.put(y.code, b.toString());
            }
        }
        else if(isInt(y.toString()) && isInt(z.toString())){
            if(display){
                System.out.println("\nx IS THE VARIABLE");
            }
            Integer b=Integer.parseInt(z.toString())-Integer.parseInt(y.toString());
            Annuaire.ValSymbole.put(x.code, b);
            Annuaire.AffSymbole.put(x.code, b.toString());

        }
        else System.out.println("\nLACKS VARIABLES");

    }

    private static boolean isInt(String affI) {
        // TODO Auto-generated method stub
        try {
            Integer.parseInt(affI);
            return true;
        } catch (NumberFormatException e) {
            return false;
        } catch (java.lang.NullPointerException e){
            return false;
        }

    }
    static  class Annuaire{
        static Map<Integer,Object> ValSymbole = new HashMap<Integer,Object>();
        static Map<Integer,String> AffSymbole = new HashMap<Integer,String>();
        static String aff(int c){return AffSymbole.get(c);}
        static Object val(int c){return ValSymbole.get(c);}
        static int Code=1;
    }


    static  class Clause extends LinkedList{
        boolean caseDisplay =false;// Why can't I declare it above? as a static argument?
        static Clause[] ListeClauses = new Clause[100];
        List listeVar;
        List listeLitteraux;
        List listeCode;
        int varExiste(String n){
            for(int i=0;i<listeVar.size();i++){
                if( ((String)listeVar.get(i)).equals(n)) return i;
            }
            return 0;
        }
        Clause(){
            super();
            listeVar = new LinkedList();
            listeCode = new LinkedList();
            //System.out.println("creation clause");
            listeLitteraux = new LinkedList();/*ListeClauses[IC++]=this;*/}
        public String toString(){String r=  super.toString();return r.substring(1, r.length()-1);}

        boolean isDouble(String str) {
            try {
                Double.parseDouble(str);
                return true;
            } catch (NumberFormatException e) {
                return false;
            }
        }

        class Litteral extends LinkedList{
            String predicat;
            List listeVar;
            @SuppressWarnings("rawtypes")
            Litteral(String p){
                super();
                predicat = p;listeVar = new LinkedList();listeLitteraux.add(this);
                //System.out.println("creation litteral "+predicat);
            }
            //public String toString(){return super.toString();}
            class Symbole{
                int code;
                String aff;
                String affI;
                Object val;
                Symbole(String s){
                }

                public String toString(){return Annuaire.aff(code);}
                Object getVal(){return null;}
                String getAff(){return affI;}
                boolean libre(){return true;}
            }

            public String toString(){
                if(ProjetMichel.predicatConstant(predicat))return predicat;
                return predicat+super.toString();
            }

        }
        static Clause copie(int i){
            ProjetMichel.Clauses[99]=Clause.ListeClauses[i].toString()+".";
            Clause c = ProjetMichel.ri(99);
            //we have to suppress the variable added to listeClause[]
            //il faut retirer la clause ajouté à listeClauses[]
            ProjetMichel.IR--;
            return c;
        }
        List unif(Clause c){
            Clause res = new Clause();
            Clause.Litteral l1 = (Clause.Litteral)get(0);
            Clause.Litteral l2 =(Clause.Litteral)c.get(0);

            if(!l1.predicat.equals(l2.predicat))return null;



            for(int i=0;i<l1.size();i++){
                Clause.Litteral.Symbole s1 = (Clause.Litteral.Symbole)l1.get(i);
                Clause.Litteral.Symbole s2 = (Clause.Litteral.Symbole)l2.get(i);


                if(caseDisplay){
                    System.out.println("CASE "+s1+" "+s2);
                }



                //case cst/cst 
                if((Annuaire.val(s1.code)!=null && Annuaire.val(s2.code)!=null)&&(!(s1.toString().equals(s2.toString())))){

                    if(caseDisplay){
                        System.out.println("s1: "+ s1);
                        System.out.println("s2: "+ s2);
                        System.out.println("Constant - Constant with s1 != s2 " + s1 + " " + s2+"\nCAN'T BE UNIFIED");
                    }

                    //should we write false? it would end the array decomposition
                    return null;
                }

                //case var/cste
                if(Annuaire.val(s1.code)==null && Annuaire.val(s2.code)!=null){
                    if(caseDisplay){
                        System.out.println("var/cste");
                        System.out.println("UNIFICATION BETWEEN "+this+" AND "+c);
                    }

                    Annuaire.ValSymbole.put(s1.code, Annuaire.val(s2.code));
                    Annuaire.AffSymbole.put(s1.code, Annuaire.aff(s2.code));

                    continue;
                }
                //case cste/var
                if(Annuaire.val(s2.code)==null && Annuaire.val(s1.code)!=null){
                    if(caseDisplay){
                        System.out.println("cste/var");
                        System.out.println("variable 1: "+Annuaire.aff(s2.code)+ " ,variable 2: "+ Annuaire.val(s1.code));
                        System.out.println("UNIFICATION BETWEEN "+this+" AND "+c);
                    }

                    Annuaire.ValSymbole.put(s2.code, Annuaire.val(s1.code));
                    Annuaire.AffSymbole.put(s2.code, Annuaire.aff(s1.code));
                    continue;
                }
                //case cste/cste
                if((Annuaire.val(s1.code)!=null && Annuaire.val(s2.code)!=null)&&(s1.toString().equals(s2.toString()))){
                    if(caseDisplay){
                        System.out.println("Constant - Constant with s1 == s2 " + s1 + " " + s2);
                    }

                    //should we write false? it would end the array decomposition
                }





                //case var/var
                if(Annuaire.val(s1.code)==null && Annuaire.val(s2.code)==null){
                    if(caseDisplay){
                        System.out.println("Variable - Variable");

                        System.out.println("VERIF "+s2.code+" "+s1.toString()+ " "+Annuaire.val(s1.code));
                        System.out.println("UNIFICATION BETWEEN "+this+" AND "+c);// traiter le null. 
                    }
                    Annuaire.AffSymbole.put(s2.code, s1.toString());
                    //Annuaire.ValSymbole.put(s2.code, Annuaire.val(s1.code).toString());// Doesn't change??? //java.lang.NullPointerException

                }



            }

            Clause nc = new Clause();
            for(int i=1;i<c.size();i++)nc.add(c.get(i));
            for(int i=1;i<size();i++)nc.add(get(i));
            ListeClauses[++ProjetMichel.IR] = nc;
            return nc;


        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ Just one minor comment: SWISH is freely available. It is based on SWI-Prolog, and the whole source of SWISH is available from: https://github.com/SWI-Prolog/swish. You can also download SWI-Prolog for free, all repositories are available from: https://github.com/SWI-Prolog. \$\endgroup\$ – mat May 4 '16 at 9:04
  • \$\begingroup\$ @mat Thank you very much, I didn't knew the code were freely available... In what language was it coded? Nonetheless, I'm not yet able to perfectly understand GitHub. \$\endgroup\$ – IggyPass May 4 '16 at 9:53
  • \$\begingroup\$ SWISH is written mostly in Prolog and JavaScript, and SWI-Prolog itself is written in C (the kernel) and Prolog (very many libraries). Both are available for free, and also in source form. You can see these statistics also in the Github repositories, by clicking on the colourful bar near the top of the repositories. \$\endgroup\$ – mat May 4 '16 at 11:05
  • \$\begingroup\$ Is this review still relevant? \$\endgroup\$ – oopexpert Jul 6 '16 at 21:02
  • \$\begingroup\$ @oopexpert The deadline has been crossed , yet, i would look at you review carefully if you do \$\endgroup\$ – IggyPass Jul 6 '16 at 21:35
2
\$\begingroup\$

Parsing is always a bit complicated/ugly in terms of code—a library like ANTLR can do some of the heavy lifting for you. But let's assume some level of for practice/exercise.

Recommendations

What follows are fairly broad recommendations based on the question: "If I were responsible for maintaining this code, what would I do?"

  1. Use lists (expandable) instead of arrays (fixed-length). A number of arrays have sizes that appear arbitrary, such as Clauses[120] (later redefined to length 100). Unless these lengths represent agreed-upon limits, in which case it would be best to name them through constants (e.g. MAX_CLAUSES), consider using an ArrayList instead. ArrayList has comparable performance to arrays, will grow as needed, and will relieve you of having to store or guess the number of elements.

  2. Add documentation or help code self-document. There are useful comments in the code, but not enough to get a view on what happens where, when, and why. They probably would be enough if the functions and variables could be renamed to signal use or purpose ( ICF? ri(int noClause)? ).

  3. Reduce the number of static, reachable, mutable references. The abundance of statics greatly widens the conceptual scope of named references, making it harder for human beings to read and reason about the code. Reduce this scope by making them instance references—this will also reduce the number of arrays you need—and by restricting access through private where possible.

    This will be tedious, make no mistake. It will require you to rethink and remodel some parts. But it will greatly improve the ability for people (including yourself!) to reason about the impact of a change to the code.

  4. Consider a Map<String, Symbol> symbols instead of List listeAff and List listeSymbole. Maps tend to be very fast in lookups, so it will save you processing time. It will also free you from keeping the two lists in sync.

  5. Add isInt() to specific classes where needed. All calls to isInt(String) appear to follow the pattern of isInt(Symbole.toString()). Consider adding an instance method isInt() to class Symbole, so that you can change isInt(x.toString()) into x.isInt().

  6. Aim for 1 statement per line, and prefer using braces for code blocks. This is not an unbreakable rule: there are cases where 'packing' statements or blocks is defensible for visual or conceptual reasons. But I'd err on the side of caution.

  7. Prefer generics over raw collections. Generics help keep your collections type-safe (reducing bugs) and reduce the number of casts you need.

  8. Prefer logging over System.out.print. Java comes with a logging utility (java.util.logging); you can also use one like log4j or slf4j-logback. If this feels like overkill, consider moving if (...) System.out.println(...) to methods like debug(String) to reduce clutter.

  9. Consider switch-case instead of if-else chains comparing to constants. ri(int) is an example where switch-case would probably both be faster and clearer.

  10. Scrutinize extends LinkedList. You'll probably need only two or three of its methods, so you might get away with adding the methods explicitly, and then delegating to a private field. If these classes do need to be list-like, consider adding the List interface instead, and then delegate, or add a method List asList() that provides a view of what you need.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.