Générateur de parseur

This commit is contained in:
Paul Faure 2021-03-16 20:15:32 +01:00
commit 90a36dc18c
10 changed files with 274 additions and 0 deletions

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
out/
out/*
out/*/*
src/*.class
generator.sh

22
Makefile Normal file
View file

@ -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

2
grammaires/anbn Normal file
View file

@ -0,0 +1,2 @@
S : a S b
S : a b

8
grammaires/dictionnaire Normal file
View file

@ -0,0 +1,8 @@
S : int
S : string
S : { Assoc }
Assoc : KeyVal AssocBis
Assoc :
AssocBis : , KeyVal AssocBis
AssocBis :
KeyVal : id = S

4
grammaires/test Normal file
View file

@ -0,0 +1,4 @@
S : A a
A : b C d
A : b A
C : e

35
src/Grammaire.java Normal file
View file

@ -0,0 +1,35 @@
import java.util.ArrayList;
import java.util.Iterator;
public class Grammaire {
Symbole axiome;
ArrayList<Regle> 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<regles.length;i++) {
regle = new Regle(regles[i]);
if (i == 0) {
this.axiome = regle.getPartieGauche();
}
this.regles.add(regle);
}
}
public String writeGrammaire() {
String retour = "parse(Mot) :-\n\tsplit_string(Mot, \" \", \" \", List),\n\tregle_" + this.axiome.getValue() + "(List, []).\n\n";
Iterator<Regle> iter = this.regles.iterator();
Regle regle;
while (iter.hasNext()) {
regle = iter.next();
retour = retour + regle.writeRegle() + "\n";
}
return retour;
}
}

28
src/IO.java Normal file
View file

@ -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();
}
}

54
src/Main.java Normal file
View file

@ -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);
}
}
}

77
src/Regle.java Normal file
View file

@ -0,0 +1,77 @@
import java.util.ArrayList;
import java.util.Iterator;
public class Regle {
private Symbole partieGauche;
private ArrayList<Symbole> 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<symboles.length; i++) {
this.partieDroite.add(new Symbole(symboles[i]));
}
}
}
public Symbole getPartieGauche() {
return partieGauche;
}
public String printRegle() {
String retour = this.partieGauche.getValue() + " ->";
Iterator<Symbole> 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<Symbole> 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 +
'}';
}
}

39
src/Symbole.java Normal file
View file

@ -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 + '\'' +
'}';
}
}