-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCTLParser.java
More file actions
134 lines (109 loc) · 4.54 KB
/
CTLParser.java
File metadata and controls
134 lines (109 loc) · 4.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
* @author Alain Barbier alias "Metroidzeta"
*
* Pour compiler avec Windows, GNU/Linux et MacOS :
* > javac formules/unaires/*.java formules/binaires/*.java formules/*.java *.java
*
* Pour exécuter :
* > java CTLMain
*/
import formules.*;
import formules.unaires.*;
import formules.binaires.*;
import java.util.Set;
public class CTLParser {
private static final char[] OPERATEURS_BINAIRES = {'&', '|', '>', '?'};
private static final char[] OPERATEUR_UNTIL = {'U'};
private final Set<String> labelsReconnus;
public CTLParser(KripkeStructure kripke) {
labelsReconnus = kripke.getEnsembleLabels();
}
public Formule parse(String str) { // transforme un string en une formule CTL (null = mauvaise syntaxe)
if (str == null || str.isBlank()) return null;
if (str.equalsIgnoreCase("false")) return new FALSE(); // "false/FALSE"
if (str.equalsIgnoreCase("true")) return new TRUE(); // "true/TRUE"
if (labelsReconnus.contains(str)) return new PROPOSITION(str); // proposition
if (str.charAt(0) == '-') return parseNOT(str); // NOT
if (str.length() < 3) return null;
if (estUnaireAE(str)) return parseUnaireAE(str); // str = A/E:X/F/G..
if (estBinaireAE(str)) return parseBinaireAE(str); // str = A/E(..U..)
if (estParenthesesBinaireOp(str)) return parseParenthesesBinaireOp(str); // str = (..S..), S € '&,|,>,?'
return null;
}
private Formule parseNOT(String str) {
Formule droite = parse(str.substring(1)); // parse(strDroite)
return droite == null ? null : new NOT(droite); // null ou NOT(droite)
}
private Formule parseUnaireAE(String str) {
char first = str.charAt(0), second = str.charAt(1);
Formule droite = parse(str.substring(2)); // parse(strDroite)
if (droite == null) return null;
String op = "" + first + second;
return switch (op) {
case "AX" -> new AX(droite);
case "AF" -> new AF(droite);
case "AG" -> new AG(droite);
case "EX" -> new EX(droite);
case "EF" -> new EF(droite);
case "EG" -> new EG(droite);
default -> null;
};
}
private Formule parseBinaireAE(String str) {
int indexU = trouverIndex(str, OPERATEUR_UNTIL);
if (indexU <= 2 || indexU >= str.length() - 2) return null; // U mal placé
Formule gauche = parse(str.substring(2, indexU)); // parse(strGauche)
Formule droite = parse(str.substring(indexU + 1, str.length() - 1)); // parse(strDroite)
if (gauche == null || droite == null) return null;
return str.startsWith("A") ? new AU(gauche, droite) : new EU(gauche, droite);
}
private Formule parseParenthesesBinaireOp(String str) {
int indexOp = trouverIndex(str, OPERATEURS_BINAIRES);
if (indexOp <= 1 || indexOp >= str.length() - 2) return null; // opérande mal placé
Formule gauche = parse(str.substring(1, indexOp));
Formule droite = parse(str.substring(indexOp + 1, str.length() - 1));
if (gauche == null || droite == null) return null;
return switch (str.charAt(indexOp)) {
case '&' -> new AND(gauche, droite);
case '|' -> new OR(gauche, droite);
case '>' -> new IMPLIES(gauche, droite);
case '?' -> new EQUIV(gauche, droite);
default -> null;
};
}
private static boolean estUnaireAE(String str) {
char first = str.charAt(0), second = str.charAt(1);
return (first == 'A' || first == 'E') && (second == 'X' || second == 'F' || second == 'G');
}
private static boolean estBinaireAE(String str) {
char first = str.charAt(0), second = str.charAt(1);
return (first == 'A' || first == 'E') && second == '(' && str.endsWith(")")
&& parenthesesEquilibrees(str)
&& str.contains("U"); // contient UNTIL
}
private static boolean estParenthesesBinaireOp(String str) {
return str.startsWith("(") && str.endsWith(")")
&& parenthesesEquilibrees(str)
&& str.matches(".*[&|>?].*"); // contient AND/OR/IMPLIES/EQUIV
}
private static int nbOccurrences(String str, char targetChar) {
return (int) str.chars().filter(c -> c == targetChar).count();
}
private static boolean parenthesesEquilibrees(String strFormule) {
return nbOccurrences(strFormule, '(') == nbOccurrences(strFormule, ')');
}
private static int trouverIndex(String str, char[] caracteresRecherches) {
int nbParenthesesOuvertes = 0;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (c == '(') nbParenthesesOuvertes++;
else if (c == ')') nbParenthesesOuvertes--;
else if (nbParenthesesOuvertes == 1) {
for (char caractere : caracteresRecherches) {
if (c == caractere) return i;
}
}
}
return -1;
}
}