commit 90a36dc18c0a6175becc1c73ef6bd7b04dbce48f Author: pfaure Date: Tue Mar 16 20:15:32 2021 +0100 Générateur de parseur diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1d07119 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +out/ +out/* +out/*/* +src/*.class +generator.sh diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..be0e69b --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +generator: clean clean_generator + javac src/Main.java src/Grammaire.java src/Regle.java src/Symbole.java src/IO.java + @echo '#!/bin/bash\ncd src\njava Main ../grammaires/$$1 $$2\nif [ $$? -eq 0 ]\nthen\n\tcd ../out\n\tmkdir $$2\n\tcd ../src\n\tchmod u+x $$2.sh\n\tmv $$2.pl ../out/$$2/$$2.pl\n\tmv $$2.sh ../out/$$2/$$2.sh\n\tcd ..\nelse\n\tcd ..\nfi\n' > generator.sh + @chmod u+x generator.sh + +edit: + pluma src/Main.java src/Grammaire.java src/Regle.java src/Symbole.java & + +edit_grammaires: + pluma grammaires/* & + +clean: + rm -f src/*.class + +clean_generator: + rm -f generator.sh + +clean_parseurs: + rm -f out/*/* + rm -d -f out/* + +clean_all: clean_generator clean clean_parseurs diff --git a/grammaires/anbn b/grammaires/anbn new file mode 100644 index 0000000..16ef216 --- /dev/null +++ b/grammaires/anbn @@ -0,0 +1,2 @@ +S : a S b +S : a b diff --git a/grammaires/dictionnaire b/grammaires/dictionnaire new file mode 100644 index 0000000..9f87ee6 --- /dev/null +++ b/grammaires/dictionnaire @@ -0,0 +1,8 @@ +S : int +S : string +S : { Assoc } +Assoc : KeyVal AssocBis +Assoc : +AssocBis : , KeyVal AssocBis +AssocBis : +KeyVal : id = S diff --git a/grammaires/test b/grammaires/test new file mode 100644 index 0000000..3699799 --- /dev/null +++ b/grammaires/test @@ -0,0 +1,4 @@ +S : A a +A : b C d +A : b A +C : e diff --git a/src/Grammaire.java b/src/Grammaire.java new file mode 100644 index 0000000..e8a59f5 --- /dev/null +++ b/src/Grammaire.java @@ -0,0 +1,35 @@ +import java.util.ArrayList; +import java.util.Iterator; + +public class Grammaire { + Symbole axiome; + ArrayList regles; + + public Grammaire(String grammaire) throws Exception { + this.regles = new ArrayList<>(); + + System.out.println("Création des objets Regles"); + String[] regles = grammaire.split("\n"); + Regle regle; + int i; + for (i=0;i iter = this.regles.iterator(); + Regle regle; + while (iter.hasNext()) { + regle = iter.next(); + retour = retour + regle.writeRegle() + "\n"; + } + + return retour; + } +} diff --git a/src/IO.java b/src/IO.java new file mode 100644 index 0000000..78afad7 --- /dev/null +++ b/src/IO.java @@ -0,0 +1,28 @@ +import java.io.*; + +public class IO { + public static String loadFile(File f) throws IOException { + BufferedInputStream in = new BufferedInputStream(new FileInputStream(f)); + StringWriter out = new StringWriter(); + int b; + while ((b=in.read()) != -1) + out.write(b); + out.flush(); + out.close(); + in.close(); + return out.toString(); + } + + public static void writeFile(String string, String name) throws IOException { + File f = new File(name); + BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(f)); + StringReader in = new StringReader(string); + int b; + while ((b=in.read()) != -1) + out.write(b); + out.flush(); + out.close(); + in.close(); + f.createNewFile(); + } +} diff --git a/src/Main.java b/src/Main.java new file mode 100644 index 0000000..383be57 --- /dev/null +++ b/src/Main.java @@ -0,0 +1,54 @@ +import java.io.*; + +public class Main { + + public static void main(String[] args) { + if (args.length == 2) { + System.out.println("Ouverture du ficher " + args[0]); + File f = new File(args[0]); + System.out.println("Lecture du la grammaire"); + String chaine = null; + try { + chaine = IO.loadFile(f); + } catch (IOException e) { + System.out.println("FATAL : Erreur lors de la lecture du ficher"); + System.exit(1); + } + Grammaire grammaire = null; + System.out.println("Création de l'objet Grammaire"); + try { + grammaire = new Grammaire(chaine); + } catch (Exception e) { + System.out.println("FATAL : Erreur lors de l'analyse des règles (controlez la syntaxe)"); + System.exit(2); + } + System.out.println("Génération du code Prolog du parseur"); + String parseur = grammaire.writeGrammaire(); + System.out.println("Ecriture du parseur dans le fichier " + args[1] + ".pl"); + try { + IO.writeFile(parseur, args[1] + ".pl"); + } catch (IOException e) { + System.out.println("FATAL : Erreur lors de l'écriture du fichier prolog"); + System.exit(3); + } + System.out.println("Création du launcher " + args[1] + ".sh"); + String laucher ="#!/bin/bash\n" + + "swipl -s " + args[1] + ".pl -g \"parse('$1'),halt.\" 2> /dev/null\n" + "" + + "if [ $? -eq 0 ]\n" + + "then\n" + + "\techo \"OK\"\n" + + "else\n" + + "\techo \"KO\"\n" + + "fi\n"; + try { + IO.writeFile(laucher, args[1] + ".sh"); + } catch (IOException e) { + System.out.println("FATAL : Erreur lors de l'écriture du launcher"); + System.exit(4); + } + } else { + System.out.println("Deux arguments requis : fichier contenant la grammaire et nom du parseur"); + System.exit(5); + } + } +} diff --git a/src/Regle.java b/src/Regle.java new file mode 100644 index 0000000..145da1a --- /dev/null +++ b/src/Regle.java @@ -0,0 +1,77 @@ +import java.util.ArrayList; +import java.util.Iterator; + +public class Regle { + private Symbole partieGauche; + private ArrayList partieDroite; + + public Regle(String regle) throws Exception { + // Regle de la forme : "S : a A b" + regle = regle + " "; + String[] parties = regle.split(":"); + if (parties.length != 2) { + throw new Exception("Regle illisible"); + } + + this.partieGauche = new Symbole(parties[0].strip()); + if (this.partieGauche.isEpsilon() || this.partieGauche.isTerminal()) { + throw new Exception("Regle illisible"); + } + + String[] symboles = parties[1].strip().replaceAll("\\s{2,}", " ").split(" "); + this.partieDroite = new ArrayList<>(); + if (symboles.length == 0) { + this.partieDroite.add(new Symbole("")); + } else { + int i; + for (i=0; i"; + Iterator iter = this.partieDroite.iterator(); + Symbole symbole; + while (iter.hasNext()) { + symbole = iter.next(); + retour = retour + " " + symbole.getValue(); + } + + return retour; + } + + public String writeRegle() { + String retour = "regle_" + this.partieGauche.getValue() + "(" + this.partieGauche.getValue() + "0, Retour) :-\t\t% " + this.printRegle() + "\n"; + Iterator iter = this.partieDroite.iterator(); + Symbole symbole; + int i = 0; + while (iter.hasNext()) { + symbole = iter.next(); + if (symbole.isEpsilon()) { + retour = retour + "\t" + this.partieGauche.getValue() + i + " = " + this.partieGauche.getValue() + (i+1) + ",\n"; + } else if (symbole.isTerminal()) { + retour = retour + "\t" + this.partieGauche.getValue() + i + " = [\"" + symbole.getValue() + "\"|" + this.partieGauche.getValue() + (i+1) + "],\n"; + } else { + retour = retour + "\tregle_" + symbole.getValue() + "(" + this.partieGauche.getValue() + i + ", " + this.partieGauche.getValue() + (i+1) + "),\n"; + } + i = i+1; + } + retour = retour + "\t" + this.partieGauche.getValue() + i + " = Retour,!.\n"; + + return retour; + } + + @Override + public String toString() { + return "Regle{" + + "partieGauche=" + partieGauche + + ", partieDroite=" + partieDroite + + '}'; + } +} diff --git a/src/Symbole.java b/src/Symbole.java new file mode 100644 index 0000000..8c16755 --- /dev/null +++ b/src/Symbole.java @@ -0,0 +1,39 @@ +import static java.lang.Character.isUpperCase; + +public class Symbole { + private boolean terminal; + private boolean epsilon; + private String value; + + public Symbole(String value) { + this.value = value; + if (this.value.isEmpty()) { + this.terminal = false; + this.epsilon = true; + } else { + this.epsilon = false; + this.terminal = !isUpperCase(this.value.charAt(0)); + } + } + + public boolean isTerminal() { + return terminal; + } + + public boolean isEpsilon() { + return epsilon; + } + + public String getValue() { + return value; + } + + @Override + public String toString() { + return "Symbole{" + + "terminal=" + terminal + + ", epsilon=" + epsilon + + ", value='" + value + '\'' + + '}'; + } +}