diff --git a/FormeleMethoden.iml b/FormeleMethoden.iml new file mode 100644 index 0000000..4e83dc3 --- /dev/null +++ b/FormeleMethoden.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/images/1048780942.png b/images/1048780942.png new file mode 100644 index 0000000..27f446a Binary files /dev/null and b/images/1048780942.png differ diff --git a/images/1068821280.png b/images/1068821280.png new file mode 100644 index 0000000..86e5b53 Binary files /dev/null and b/images/1068821280.png differ diff --git a/images/1105752207.png b/images/1105752207.png new file mode 100644 index 0000000..ace387d Binary files /dev/null and b/images/1105752207.png differ diff --git a/images/1136662765.png b/images/1136662765.png new file mode 100644 index 0000000..0ec401f Binary files /dev/null and b/images/1136662765.png differ diff --git a/images/1220868996.png b/images/1220868996.png new file mode 100644 index 0000000..60a4cbf Binary files /dev/null and b/images/1220868996.png differ diff --git a/images/1261661665.png b/images/1261661665.png new file mode 100644 index 0000000..86e5b53 Binary files /dev/null and b/images/1261661665.png differ diff --git a/images/1288384970.png b/images/1288384970.png new file mode 100644 index 0000000..aea5fa4 Binary files /dev/null and b/images/1288384970.png differ diff --git a/images/1289763598.png b/images/1289763598.png new file mode 100644 index 0000000..186f168 Binary files /dev/null and b/images/1289763598.png differ diff --git a/images/1462205525.png b/images/1462205525.png new file mode 100644 index 0000000..5691ef9 Binary files /dev/null and b/images/1462205525.png differ diff --git a/images/1494429597.png b/images/1494429597.png new file mode 100644 index 0000000..aea5fa4 Binary files /dev/null and b/images/1494429597.png differ diff --git a/images/1509687272.png b/images/1509687272.png new file mode 100644 index 0000000..9e7c1a7 Binary files /dev/null and b/images/1509687272.png differ diff --git a/images/156596164.png b/images/156596164.png new file mode 100644 index 0000000..915844e Binary files /dev/null and b/images/156596164.png differ diff --git a/images/157529001.png b/images/157529001.png new file mode 100644 index 0000000..d28d2f7 Binary files /dev/null and b/images/157529001.png differ diff --git a/images/1653777739.png b/images/1653777739.png new file mode 100644 index 0000000..ba9e5ba Binary files /dev/null and b/images/1653777739.png differ diff --git a/images/1740047789.png b/images/1740047789.png new file mode 100644 index 0000000..8387455 Binary files /dev/null and b/images/1740047789.png differ diff --git a/images/1862002344.png b/images/1862002344.png new file mode 100644 index 0000000..40b6a36 Binary files /dev/null and b/images/1862002344.png differ diff --git a/images/1954850820.png b/images/1954850820.png new file mode 100644 index 0000000..8d7d0bf Binary files /dev/null and b/images/1954850820.png differ diff --git a/images/1963223277.png b/images/1963223277.png new file mode 100644 index 0000000..e85de4a Binary files /dev/null and b/images/1963223277.png differ diff --git a/images/203837073.png b/images/203837073.png new file mode 100644 index 0000000..d170308 Binary files /dev/null and b/images/203837073.png differ diff --git a/images/207639314.png b/images/207639314.png new file mode 100644 index 0000000..5691ef9 Binary files /dev/null and b/images/207639314.png differ diff --git a/images/2087861873.png b/images/2087861873.png new file mode 100644 index 0000000..3ba01b3 Binary files /dev/null and b/images/2087861873.png differ diff --git a/images/2112867385.png b/images/2112867385.png new file mode 100644 index 0000000..1dcd20f Binary files /dev/null and b/images/2112867385.png differ diff --git a/images/302729159.png b/images/302729159.png new file mode 100644 index 0000000..42d8984 Binary files /dev/null and b/images/302729159.png differ diff --git a/images/312365023.png b/images/312365023.png new file mode 100644 index 0000000..5bd41f0 Binary files /dev/null and b/images/312365023.png differ diff --git a/images/318078938.png b/images/318078938.png new file mode 100644 index 0000000..b01ae97 Binary files /dev/null and b/images/318078938.png differ diff --git a/images/336201256.png b/images/336201256.png new file mode 100644 index 0000000..dd7a5f5 Binary files /dev/null and b/images/336201256.png differ diff --git a/images/383269663.png b/images/383269663.png new file mode 100644 index 0000000..a1c29ad Binary files /dev/null and b/images/383269663.png differ diff --git a/images/389888761.png b/images/389888761.png new file mode 100644 index 0000000..d571a96 Binary files /dev/null and b/images/389888761.png differ diff --git a/images/459301452.png b/images/459301452.png new file mode 100644 index 0000000..ba9e5ba Binary files /dev/null and b/images/459301452.png differ diff --git a/images/495694988.png b/images/495694988.png new file mode 100644 index 0000000..21b3767 Binary files /dev/null and b/images/495694988.png differ diff --git a/images/509460607.png b/images/509460607.png new file mode 100644 index 0000000..44aab15 Binary files /dev/null and b/images/509460607.png differ diff --git a/images/603413993.png b/images/603413993.png new file mode 100644 index 0000000..fdf2387 Binary files /dev/null and b/images/603413993.png differ diff --git a/images/634333128.png b/images/634333128.png new file mode 100644 index 0000000..153ccf5 Binary files /dev/null and b/images/634333128.png differ diff --git a/images/654648053.png b/images/654648053.png new file mode 100644 index 0000000..dfa332c Binary files /dev/null and b/images/654648053.png differ diff --git a/images/655304795.png b/images/655304795.png new file mode 100644 index 0000000..42d8984 Binary files /dev/null and b/images/655304795.png differ diff --git a/images/664788275.png b/images/664788275.png new file mode 100644 index 0000000..ba49623 Binary files /dev/null and b/images/664788275.png differ diff --git a/images/703135839.png b/images/703135839.png new file mode 100644 index 0000000..5bd41f0 Binary files /dev/null and b/images/703135839.png differ diff --git a/images/723574364.png b/images/723574364.png new file mode 100644 index 0000000..aea5fa4 Binary files /dev/null and b/images/723574364.png differ diff --git a/images/754924751.png b/images/754924751.png new file mode 100644 index 0000000..bf80bd0 Binary files /dev/null and b/images/754924751.png differ diff --git a/images/765439555.png b/images/765439555.png new file mode 100644 index 0000000..8563547 Binary files /dev/null and b/images/765439555.png differ diff --git a/images/792217629.png b/images/792217629.png new file mode 100644 index 0000000..86b5331 Binary files /dev/null and b/images/792217629.png differ diff --git a/images/821989711.png b/images/821989711.png new file mode 100644 index 0000000..28bb4dc Binary files /dev/null and b/images/821989711.png differ diff --git a/images/851412221.png b/images/851412221.png new file mode 100644 index 0000000..86dff9a Binary files /dev/null and b/images/851412221.png differ diff --git a/images/982413416.png b/images/982413416.png new file mode 100644 index 0000000..5d03914 Binary files /dev/null and b/images/982413416.png differ diff --git a/images/cdfa.png b/images/cdfa.png new file mode 100644 index 0000000..5befd75 Binary files /dev/null and b/images/cdfa.png differ diff --git a/images/dfa.png b/images/dfa.png new file mode 100644 index 0000000..5bd41f0 Binary files /dev/null and b/images/dfa.png differ diff --git a/images/dfa1.png b/images/dfa1.png new file mode 100644 index 0000000..5bd41f0 Binary files /dev/null and b/images/dfa1.png differ diff --git a/images/dfa2.png b/images/dfa2.png new file mode 100644 index 0000000..5691ef9 Binary files /dev/null and b/images/dfa2.png differ diff --git a/images/dfa4.png b/images/dfa4.png new file mode 100644 index 0000000..a49e57b Binary files /dev/null and b/images/dfa4.png differ diff --git a/images/mcdfa.png b/images/mcdfa.png new file mode 100644 index 0000000..ce91539 Binary files /dev/null and b/images/mcdfa.png differ diff --git a/images/ndfa1.png b/images/ndfa1.png new file mode 100644 index 0000000..5e9c4b5 Binary files /dev/null and b/images/ndfa1.png differ diff --git a/images/ndfa2.png b/images/ndfa2.png new file mode 100644 index 0000000..e85de4a Binary files /dev/null and b/images/ndfa2.png differ diff --git a/images/ndfa3.png b/images/ndfa3.png new file mode 100644 index 0000000..aea5fa4 Binary files /dev/null and b/images/ndfa3.png differ diff --git a/images/regex1.png b/images/regex1.png new file mode 100644 index 0000000..cc90c66 Binary files /dev/null and b/images/regex1.png differ diff --git a/images/regex3.png b/images/regex3.png new file mode 100644 index 0000000..27bc191 Binary files /dev/null and b/images/regex3.png differ diff --git a/images/test.png b/images/test.png new file mode 100644 index 0000000..50f7c34 Binary files /dev/null and b/images/test.png differ diff --git a/input/dfa1.dot b/input/dfa1.dot new file mode 100644 index 0000000..cbc32cc --- /dev/null +++ b/input/dfa1.dot @@ -0,0 +1,7 @@ +DFA +B0 +E1 +0>a>1 +0>b>1 +1>a>0 +1>b>1 \ No newline at end of file diff --git a/input/dfa2.dot b/input/dfa2.dot new file mode 100644 index 0000000..4e2b9d3 --- /dev/null +++ b/input/dfa2.dot @@ -0,0 +1,13 @@ +DFA +B0 +E4,2 +0>a>1 +0>b>2 +1>a>0 +1>b>2 +2>a>3 +2>b>4 +3>a>0 +3>b>2 +4>a>1 +4>b>0 \ No newline at end of file diff --git a/input/dfa3.dot b/input/dfa3.dot new file mode 100644 index 0000000..4473d15 --- /dev/null +++ b/input/dfa3.dot @@ -0,0 +1,11 @@ +DFA +B1 +E3 +0>a>0 +0>b>1 +1>a>2 +1>b>1 +2>a>0 +2>b>3 +3>a>2 +3>b>1 \ No newline at end of file diff --git a/input/dfa4.dot b/input/dfa4.dot new file mode 100644 index 0000000..fced27f --- /dev/null +++ b/input/dfa4.dot @@ -0,0 +1,15 @@ +DFA +B0 +E2,4 +0>a>0 +0>b>1 +1>a>2 +1>b>1 +2>a>0 +2>b>3 +3>a>4 +3>b>1 +4>a>5 +4>b>3 +5>a>0 +5>b>3 diff --git a/input/ndfa1.dot b/input/ndfa1.dot new file mode 100644 index 0000000..2942a7b --- /dev/null +++ b/input/ndfa1.dot @@ -0,0 +1,11 @@ +NDFA +B0 +E1,2 +0>a>1 +0>b>1 +0>$>2 +1>a>0 +1>b>1 +2>a>1 +2>b>0 +2>b>2 \ No newline at end of file diff --git a/input/ndfa2.dot b/input/ndfa2.dot new file mode 100644 index 0000000..2146846 --- /dev/null +++ b/input/ndfa2.dot @@ -0,0 +1,12 @@ +NDFA +B0 +E4 +0>a>0 +0>b>0 +0>a>1 +0>b>3 +1>b>2 +2>b>4 +3>a>4 +4>a>4 +4>b>4 \ No newline at end of file diff --git a/input/ndfa3.dot b/input/ndfa3.dot new file mode 100644 index 0000000..d71989a --- /dev/null +++ b/input/ndfa3.dot @@ -0,0 +1,13 @@ +NDFA +B0 +E2 +0>a>1 +0>b>1 +0>b>2 +1>b>3 +1>$>3 +1>a>2 +2>a>1 +3>a>4 +4>b>4 +4>$>2 \ No newline at end of file diff --git a/input/regex1.dot b/input/regex1.dot new file mode 100644 index 0000000..773f066 --- /dev/null +++ b/input/regex1.dot @@ -0,0 +1,2 @@ +REGEX +(a|b)* \ No newline at end of file diff --git a/input/regex2.dot b/input/regex2.dot new file mode 100644 index 0000000..af98a82 --- /dev/null +++ b/input/regex2.dot @@ -0,0 +1,2 @@ +REGEX +(aa)+(bba)*(a|b)*(c|d) \ No newline at end of file diff --git a/input/regex3.dot b/input/regex3.dot new file mode 100644 index 0000000..9f6778b --- /dev/null +++ b/input/regex3.dot @@ -0,0 +1,2 @@ +REGEX +(n+o+)|(ye+s+)!* \ No newline at end of file diff --git a/src/com/imegumii/Automata.java b/src/com/imegumii/Automata.java new file mode 100644 index 0000000..faf1ad3 --- /dev/null +++ b/src/com/imegumii/Automata.java @@ -0,0 +1,150 @@ +package com.imegumii; + +import java.util.*; + +/** + * Created by imegumii on 18/04/2017. + */ +public class Automata extends Importable { + + protected Set> transistions; + + protected SortedSet states; + protected SortedSet beginStates; + protected SortedSet eindStates; + + protected SortedSet symbols; + + public Automata() { + super(Type.ERROR); + states = new TreeSet(); + beginStates = new TreeSet(); + eindStates = new TreeSet(); + + transistions = new TreeSet<>(); + + this.symbols = new TreeSet<>(); + } + + public void addTransition (Transition t) { + if(t.symbol != Transition.EPSILON) + symbols.add(t.symbol); + + transistions.add(t); + states.add(t.vanState); + states.add(t.naarState); + } + + public void defineAsStartState(T t) { + states.add(t); + beginStates.add(t); + } + + public void defineAsEndState(T t) { + states.add(t); + eindStates.add(t); + } + + public void printTransitions () { + transistions.forEach(System.out::println); + } + + public String getTransitions() + { + StringBuilder s = new StringBuilder(); + s.append(type).append("\n"); + s.append('B'); + boolean first = true; + for (T beginState : this.beginStates) { + if (first) { + first = false; + } else { + s.append(','); + } + s.append(beginState.toString()); + } + s.append('\n'); + first = true; + s.append('E'); + for (T eindState : this.eindStates) { + if (first) { + first = false; + } else { + s.append(','); + } + s.append(eindState.toString()); + } + s.append('\n'); + + for(Transition t : transistions) + { + s.append(t.toString()).append("\n"); + } + + return s.toString(); + } + + public void print() { + System.out.println("Transitions"); + this.printTransitions(); + System.out.println("Beginstates"); + System.out.println(beginStates); + System.out.println("Eindstates"); + System.out.println(eindStates); + } + + public void clearEindStates() + { + eindStates.clear(); + } + + public void clearBeginStates() + { + beginStates.clear(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (T state : this.states) { + sb.append(state); + } + return "Automata" + sb.toString(); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof Automata)) + return false; + + Automata other = (Automata) obj; + + DFA dfa1; + DFA dfa2; + + if(this.type == Type.NDFA) + { + dfa1 = ((NDFA)this).toDFA().minimaliseerHopcroft(); + } + else + { + dfa1 = ((DFA)this).minimaliseerHopcroft(); + } + + if(other.type == Type.NDFA) + { + dfa2 = ((NDFA) obj).toDFA().minimaliseerHopcroft(); + } + else + { + dfa2 = ((DFA) obj).minimaliseerHopcroft(); + } + + DFA result = dfa2.ontkenning().en(dfa1).minimaliseerHopcroft(); + + if(result.states.size() <= 1) + return true; + + return false; + } +} diff --git a/src/com/imegumii/BackgroundWorker.java b/src/com/imegumii/BackgroundWorker.java new file mode 100644 index 0000000..a2ec1ab --- /dev/null +++ b/src/com/imegumii/BackgroundWorker.java @@ -0,0 +1,74 @@ +package com.imegumii; + +import com.sun.jmx.remote.internal.ArrayQueue; + +import java.util.ArrayDeque; +import java.util.Queue; + +/** + * Created by kenny on 12-6-2017. + */ +public class BackgroundWorker implements Runnable{ + + public interface Worker { + void execute(); + }; + + private Thread t; + private boolean running; + private Queue workers; + + private static BackgroundWorker worker; + + public static BackgroundWorker instance() + { + if(worker == null) + worker = new BackgroundWorker(); + + return worker; + } + + private BackgroundWorker() + { + running = true; + workers = new ArrayDeque(); + + t = new Thread(this); + t.start(); + } + + public void addWorker(Worker w) + { + workers.add(w); + } + + public void kill() + { + running = false; + } + + public void cancel() { + this.t.interrupt(); + } + + @Override + public void run() { + + while(running) + { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + System.out.println("Canceled thread"); + } + + if(workers.isEmpty()) + continue; + + Worker current = workers.poll(); + + current.execute(); + } + + } +} diff --git a/src/com/imegumii/DFA.java b/src/com/imegumii/DFA.java new file mode 100644 index 0000000..c6e9c7b --- /dev/null +++ b/src/com/imegumii/DFA.java @@ -0,0 +1,211 @@ +package com.imegumii; + +import java.util.Iterator; +import java.util.SortedSet; +import java.util.TreeSet; +import javafx.util.Pair; + +/** + * Created by imegumii on 01/05/2017. + */ +public class DFA extends Automata { + + public DFA() { + super(); + this.type = Type.DFA; + } + + public boolean accepteer(String s) { + // bij een DFA is er maar een beginstate, dus gebruiken we first. + T beginState = this.beginStates.first(); + T currentState = beginState; + + + for (int i = 0; i < s.length(); i++) { + if (!this.symbols.contains(s.charAt(i))) { + // reject, because we don't contain this symbol + return false; + } + for (Transition t : this.transistions) { +// System.out.println("State is " + t.vanState); +// System.out.println("CurrentState is " + currentState); + if (t.vanState.equals(currentState)) { +// System.out.println("Char is " + s.charAt(i) + " and state is " + t); + // if states match, parse using symbols. + if (t.symbol == s.charAt(i)) { + // symbols match +// System.out.println("Symbols match for " + t + " and " + s.charAt(i) + " with currentState " + currentState); + currentState = t.naarState; + break; + } + } + } + } +// System.out.println("Ended on state " + currentState); + return this.eindStates.contains(currentState); + } + + private TreeSet addSymbols(int n, TreeSet tempSet) { + TreeSet tempGenerated = new TreeSet<>(tempSet); + if (n == 0) { + return tempGenerated; + } + + for(String s : tempSet) { + for(Character c : this.symbols) { + tempGenerated.add(s + c); + } + } + + tempGenerated.addAll(addSymbols(n - 1, tempGenerated)); + + return tempGenerated; + } + + public Taal geefTaalTotLengte(int n) { + TreeSet taal = new TreeSet<>(); + for (Character c : this.symbols) { + taal.add("" + c); + } + return new Taal(addSymbols(n - 1, taal)); + } + + public NDFA reverse() + { + NDFA reversed = new NDFA(); + + for(Transition t : transistions) + { + reversed.addTransition(new Transition(t.naarState.toString(), t.symbol, t.vanState.toString())); + } + + for(T state : eindStates) { + reversed.defineAsStartState(state.toString()); + } + + for(T state : beginStates) { + reversed.defineAsEndState(state.toString()); + } + + return reversed; + } + + public DFA minimaliseer() { + return this.reverse().toDFA().reverse().toDFA(); + } + + public DFA minimaliseerHopcroft() { + HopcroftConverter converter = new HopcroftConverter((DFA) this); + return converter.minimize(); + } + + public DFA ontkenning() { + + DFA result = new DFA(); + + for(Transition t : this.transistions) + { + result.addTransition(t); + } + + for(T s : this.eindStates) + { + result.defineAsStartState(s); + } + + for(T s : this.beginStates) + { + result.defineAsEndState(s); + } + + return result; + /* + DFA returnDFA = new DFA(); + + SortedSet newEndStates = new TreeSet<>(); + + for (T state : this.states) { + if (!this.eindStates.contains(state)) { + newEndStates.add(state); + } + } + + for (T newEndState : newEndStates) { + returnDFA.defineAsEndState(newEndState); + } + + for (T beginState : this.beginStates) { + returnDFA.defineAsStartState(beginState); + } + + for (Transition transistion : this.transistions) { + returnDFA.addTransition(transistion); + } + + return returnDFA;*/ + } + + public DFA en(DFA other) + { + return maakTupleDFA((DFA)this, (DFA)other, false); + } + + public DFA of(DFA other) + { + return maakTupleDFA((DFA)this, (DFA)other, true); + } + + private DFA maakTupleDFA(DFA dfa1, DFA dfa2, boolean of) + { + DFA merged = new DFA(); + + //Create all transitions and states + for(Transition t1 : dfa1.transistions) + { + for(Transition t2 : dfa2.transistions) + { + if(t1.symbol == t2.symbol) { + Transition t3 = new Transition(t1.vanState + "-" + t2.vanState, t1.symbol, t1.naarState + "-" + t2.naarState); + + if(dfa1.beginStates.contains(t1.vanState) && dfa2.beginStates.contains(t2.vanState)) + merged.defineAsStartState((String)t3.vanState); + + if(of) + { + if(dfa1.eindStates.contains(t1.vanState) || dfa2.eindStates.contains(t2.vanState)) + merged.defineAsEndState((String)t3.vanState); + } + else + { + if(dfa1.eindStates.contains(t1.vanState) && dfa2.eindStates.contains(t2.vanState)) + merged.defineAsEndState((String)t3.vanState); + } + + merged.addTransition(t3); + } + } + } + + //Delete wrong states + SortedSet usedStates = new TreeSet(); + for(Transition t : merged.transistions) + { + usedStates.add((String)t.naarState); + } + + Iterator> it = merged.transistions.iterator(); + + while(it.hasNext()) + { + Transition t = it.next(); + + if(!usedStates.contains(t.vanState) && !merged.beginStates.contains(t.vanState)) + { + it.remove(); + merged.eindStates.remove(t.vanState); + } + } + + return merged; + } +} diff --git a/src/com/imegumii/FileParser.java b/src/com/imegumii/FileParser.java new file mode 100644 index 0000000..a6bdfea --- /dev/null +++ b/src/com/imegumii/FileParser.java @@ -0,0 +1,108 @@ +package com.imegumii; + +import java.io.*; +import java.nio.Buffer; + +/** + * Created by kenny on 8-6-2017. + */ +public class FileParser { + + public static Importable read(String filename) + { + File f = new File("input/" + filename); + + Importable imp = null; + + try (BufferedReader br = new BufferedReader(new FileReader(f))) { + + String type = br.readLine(); + + switch (type) + { + case "DFA": + imp = readDFA(br); + break; + case "NDFA": + imp = readNDFA(br); + break; + case "REGEX": + imp = readRegex(br); + break; + default: + break; + } + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return imp; + } + + public static DFA readDFA(BufferedReader br) throws IOException { + + DFA dfa = new DFA(); + + String line; + while ((line = br.readLine()) != null) { + if(line.startsWith("B")) { + String[] states = line.substring(1,line.length()).split(","); + for(String s : states) { dfa.defineAsStartState(s); } + } + + else if(line.startsWith("E")) { + String[] states = line.substring(1,line.length()).split(","); + for(String s : states) { dfa.defineAsEndState(s); } + } + + else { + String[] trans = line.split(">"); + dfa.addTransition(new Transition(trans[0], trans[1].toCharArray()[0], trans[2])); + } + } + + return dfa; + } + + public static NDFA readNDFA(BufferedReader br) throws IOException { + + NDFA ndfa = new NDFA(); + String line; + while ((line = br.readLine()) != null) { + if(line.startsWith("B")) { + String[] states = line.substring(1,line.length()).split(","); + for(String s : states) { ndfa.defineAsStartState(s); } + } + + else if(line.startsWith("E")) { + String[] states = line.substring(1,line.length()).split(","); + for(String s : states) { ndfa.defineAsEndState(s); } + } + + else { + String[] trans = line.split(">"); + + if(trans[1].equals("$")) { + ndfa.addTransition(new Transition(trans[0], Transition.EPSILON, trans[2])); + } + else + ndfa.addTransition(new Transition(trans[0], trans[1].toCharArray()[0], trans[2])); + } + } + + return ndfa; + } + + public static RegExp readRegex(BufferedReader br) throws IOException { + String line = "Error"; + line = br.readLine(); + + RegExp regex = new RegExp(); + regex = regex.naarRegExp(line); + + return regex; + } +} diff --git a/src/com/imegumii/GrammarConverter.java b/src/com/imegumii/GrammarConverter.java new file mode 100644 index 0000000..d067e35 --- /dev/null +++ b/src/com/imegumii/GrammarConverter.java @@ -0,0 +1,104 @@ +package com.imegumii; + +import java.util.ArrayList; +import java.util.SortedSet; +import java.util.TreeSet; + +/** + * Created by imegumii on 12/06/2017. + */ +public class GrammarConverter { + + private SortedSet getGrammar (NDFA automata, String state) { + SortedSet canGoTo = new TreeSet<>(); + for (Character symbol : automata.symbols) { + SortedSet bereikbaarVanafViaEpsilonBereikbareState = automata.statesBereikbaarVanaf(state, symbol); + for (String s1 : bereikbaarVanafViaEpsilonBereikbareState) { + canGoTo.add("" + symbol + s1); + } + } + return canGoTo; + } + + public Grammar toGrammar(NDFA automata) { + ArrayList grammar = new ArrayList<>(); + Grammar retval = null; + for (String state : automata.states) { + SortedSet canGoTo = new TreeSet<>(); + // Check where we can go from here + for (Character symbol : automata.symbols) { +// canGoTo.add("" + symbol + state); + // follow epsilon + canGoTo.addAll(getGrammar(automata, state)); + + SortedSet bereikbaarVanafEpsilon = automata.statesBereikbaarVanaf(state, Transition.EPSILON); + for (String s : bereikbaarVanafEpsilon) { + canGoTo.add("" + Transition.EPSILON + s); + SortedSet bereikbaarVanafEpsilonViaSymbool = automata.statesBereikbaarVanaf(s, symbol); + for (String s1 : bereikbaarVanafEpsilonViaSymbool) { + canGoTo.add("" + symbol + s1); + } + } +// for (String s : bereikbaarVanafEpsilon) { +// canGoTo.addAll(getGrammar(automata, s)); +// } + + } + grammar.add(new Grammar(state, canGoTo, null)); + } +// System.out.println(grammar); +// grammar.forEach(System.out::println); + for (Grammar grammar1 : grammar) { + if (grammar.size() > 1) { + if (retval == null) { + retval = grammar1; + continue; + } else { + retval = retval.link(grammar1); + } + } else { + retval = grammar1; + } + } + return grammar.get(0); + } + + public class Grammar { + Grammar below; + String state; + SortedSet options; + + public Grammar(String state, SortedSet options, Grammar below) { + this.state = state; + this.options = options; + this.below = below; + } + + @Override + public String toString() { + return state + " -> " + options; + } + + public Grammar link(Grammar other) { + this.below = other; + return other; + } + + public String printToString() { + StringBuilder sb = new StringBuilder(); + sb.append(toString()); + sb.append("\n"); + if (below != null) { + sb.append(below.printToString()); + } + return sb.toString(); + } + + public void print() { + System.out.println(state + " -> " + options); + if (below != null) { + below.print(); + } + } + } +} diff --git a/src/com/imegumii/Graph.java b/src/com/imegumii/Graph.java new file mode 100644 index 0000000..a87e424 --- /dev/null +++ b/src/com/imegumii/Graph.java @@ -0,0 +1,118 @@ +package com.imegumii; + +import guru.nidi.graphviz.engine.Format; +import guru.nidi.graphviz.engine.Graphviz; +import guru.nidi.graphviz.model.Label; +import guru.nidi.graphviz.model.MutableGraph; +import guru.nidi.graphviz.model.Node; +import guru.nidi.graphviz.parse.Parser; + +import java.io.*; + +import static guru.nidi.graphviz.model.Factory.graph; +import static guru.nidi.graphviz.model.Factory.node; + +/** + * Created by kenny on 18-5-2017. + */ +public class Graph { + + public static String generateGraphString(Automata a) + { + String text = "digraph finite_state_machine {\nrankdir=LR;\nsize=\"8,5\";\n"; + + + if(a.eindStates.size() > 0) { + text += "node [shape=cirlce, peripheries=2];"; + + for (String s : a.eindStates) { + text += "\"" + s + "\" "; + } + + text += ";"; + } + + if(a.beginStates.size() > 0) { + text += "\nnode [shape = point];\n"; + + for (String s : a.beginStates) { + text += "\" \" -> \"" + s + "\" [label = \" \"];"; + } + } + + text += "\nnode [shape = circle];\n"; + + for(Transition t : a.transistions) + { + String s = ""; + if(t.symbol == Transition.EPSILON) + s = "$"; + else + s = t.symbol + ""; + + text += "\"" + t.vanState + "\" -> \"" + t.naarState + "\" [ label = \"" + s + "\"];\n"; + } + + text += "}"; + + return text; + } + + public static String generateImageString(Automata a) + { + String text = "digraph {\nrankdir=LR;\n"; + + if(a.eindStates.size() > 0) { + for (String s : a.eindStates) { + text += "\"" + s + "\" [peripheries=2]\n"; + } + } + + if(a.beginStates.size() > 0) { + text += "\nstart [shape = point];\n"; + + for (String s : a.beginStates) { + text += "\"start\" -> \"" + s + "\" [label = \" \", color=aquamarine4];"; + } + } + + for(Transition t : a.transistions) + { + String s = ""; + if(t.symbol == Transition.EPSILON) + s = "$"; + else + s = t.symbol + ""; + + text += "\"" + t.vanState + "\" -> \"" + t.naarState + "\" [ label = \"" + s + "\"];\n"; + } + + text += "}"; + + return text; + } + + public static synchronized File generateImage(Automata a) + { + return generateImage(a, null); + } + + public static synchronized File generateImage(Automata a, String fileName) { + + File f; + if (fileName != null) { + f = new File("images/" + fileName + ".png"); + } else { + f = new File("images/" + a.hashCode() + ".png"); + } + + try { + MutableGraph g = Parser.read(Graph.generateImageString(a)); + Graphviz.fromGraph(g).width(Math.min(15000, Math.max(a.states.size() * 150, 750))).render(Format.PNG).toFile(f); + } catch (IOException e) { + e.printStackTrace(); + } + + return f; + } +} diff --git a/src/com/imegumii/HopcroftConverter.java b/src/com/imegumii/HopcroftConverter.java new file mode 100644 index 0000000..19f3d1e --- /dev/null +++ b/src/com/imegumii/HopcroftConverter.java @@ -0,0 +1,239 @@ +package com.imegumii; + +import javafx.geometry.HPos; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.SortedSet; +import java.util.TreeSet; + +/** + * Created by kenny on 30-5-2017. + */ +public class HopcroftConverter { + + private DFA automata; + private SortedSet sets; + + public HopcroftConverter(DFA automata) + { + this.automata = automata; + this.sets = new TreeSet(); + + DFAtoHopcroft(); + updateGroupReferences(); + + System.out.println("\nFound " + sets.size() + " sets."); + } + + public DFA minimize() + { + int lastround = 0; + int newround = 2; + + int count = 0; + + while(lastround != newround) { + + count++; + System.out.println("Minimize round " + count + " (" + lastround + "/" + newround + ")"); + + lastround = newround; + newround = splitGroups(lastround); + + updateGroupReferences(); + } + + return HopcrofttoDFA(); + } + + private void DFAtoHopcroft() + { + String beginGroup = getGroupName(); + String endGroup = getGroupName(); + + for(Transition t : automata.transistions) + { + boolean found = false; + HopcroftSet currentSet = null; + + for(HopcroftSet s : sets) { + if (t.vanState.equals(s.state)) { + found = true; + currentSet = s; + break; + } + } + + if(!found) { + String groupName = beginGroup; + boolean endState = false; + if(automata.eindStates.contains((String)t.vanState)) { + groupName = endGroup; + endState = true; + } + currentSet = new HopcroftSet(groupName, (String)t.vanState, endState); + sets.add(currentSet); + } + + currentSet.addColum(new HopcroftColumn(t.symbol, (String)t.naarState, "-")); + } + } + + private DFA HopcrofttoDFA() + { + DFA result = new DFA(); + + ArrayList groups = new ArrayList(); + + for(HopcroftSet s : sets) + { + if(!groups.contains(s.group)) + { + for(HopcroftColumn c : s.columns) + result.addTransition(new Transition(s.group, c.symbol, c.group)); + + if(s.isEndState) + result.defineAsEndState(s.group); + + groups.add(s.group); + } + + if(automata.beginStates.contains(s.state)) + result.defineAsStartState(s.group); + } + + return result; + } + + private void updateGroupReferences() + { + for(HopcroftSet s : sets) + { + for(HopcroftColumn c : s.columns) + { + for(HopcroftSet h : sets) + { + if(c.state.equals(h.state)) + c.group = h.group; + } + } + } + } + + private int splitGroups(int oldsize) + { + HashMap> groups = new HashMap>(); + + for(HopcroftSet s : sets) + { + String key = s.group; + + for(HopcroftColumn c : s.columns) + key += c.symbol + c.group; + + if(!groups.containsKey(key)) + { + groups.put(key, new ArrayList()); + } + + groups.get(key).add(s); + } + + if(oldsize == groups.size()) + return oldsize; + + sets.clear(); + + for(ArrayList arr : groups.values()) + { + String newGroupName = getGroupName(); + + for(HopcroftSet ns : arr) + { + ns.group = newGroupName; + sets.add(ns); + } + } + + return groups.size(); + } + + + private int count = -1; + private int suffix = 0; + private String[] alphabet = {"A", "B", "C", "D", "E", "F", "G","H","I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}; + + private String getGroupName() + { + count++; + if(count >= alphabet.length) { + count = 0; + suffix++; + } + + return alphabet[count] + suffix; + } + +} + +class HopcroftSet implements Comparable{ + + public String group; + public String state; + + public ArrayList columns; + + public boolean isEndState = false; + + public HopcroftSet(String group, String state, boolean isEndState) + { + this.group = group; + this.state = state; + this.isEndState = isEndState; + + columns = new ArrayList<>(); + } + + public void addColum(HopcroftColumn c) + { + this.columns.add(c); + } + + public void clearColumns() + { + this.columns.clear(); + } + + @Override + public int compareTo(HopcroftSet o) { + return (this.group + this.state).compareTo(o.group + o.state); + } + + @Override + public String toString() + { + String s = group + " " + state + " | "; + + for(HopcroftColumn c : columns) + s += "(" + c.symbol + ") " + c.state + " " + c.group + " | "; + + s+= " " + (isEndState?"*":""); + + return s; + } +} + +class HopcroftColumn { + + public char symbol; + public String state; + public String group; + + public HopcroftColumn(char s, String state, String group) + { + this.symbol = s; + this.state = state; + this.group = group; + } +} \ No newline at end of file diff --git a/src/com/imegumii/Importable.java b/src/com/imegumii/Importable.java new file mode 100644 index 0000000..0c71155 --- /dev/null +++ b/src/com/imegumii/Importable.java @@ -0,0 +1,15 @@ +package com.imegumii; + +/** + * Created by kenny on 9-6-2017. + */ +public class Importable { + public static enum Type {DFA, NDFA, REGEX, ERROR}; + + public Type type; + + public Importable(Type t) + { + this.type = t; + } +} diff --git a/src/com/imegumii/Main.java b/src/com/imegumii/Main.java new file mode 100644 index 0000000..cbde22c --- /dev/null +++ b/src/com/imegumii/Main.java @@ -0,0 +1,34 @@ +package com.imegumii; + +import com.imegumii.ui.Frame; +import com.imegumii.ui.PopupFrame; + +import java.util.TreeSet; + +public class Main { + + + public static void main(String[] args) { +// String s = "a*(aa+ |ba*b ) * (abba|baab|bbbb)+"; +// +// String s2 = "a(a+ | b*((a|b)+))"; +// String s3 = "(a|b)+a"; +// +// String s4 = "a+((ab)*b|ab|(b)*bb)+(abba|baab)+"; +// String s5 = "a(ab)*b(a|b)|ab|(b)*bb"; +// String s6 = "(fuck)+"; +// String s7 = "a((a|b)+(baab|abba))"; +// String s8 = "(( (a|b)*(baab))+)banaan"; +// +//// NDFA ndfa = (NDFA) FileParser.read("ndfa1.dot"); +//// ndfa.print(); +//// new GrammarConverter().toGrammar(ndfa).print(); +// +// RegExp r = new RegExp(); +// String todo = s8; +// System.out.println(todo); +// System.out.println(r.naarRegExp(todo).getTaal(6, 10)); + + new Frame(); + } +} diff --git a/src/com/imegumii/NDFA.java b/src/com/imegumii/NDFA.java new file mode 100644 index 0000000..784aebb --- /dev/null +++ b/src/com/imegumii/NDFA.java @@ -0,0 +1,135 @@ +package com.imegumii; + +import java.util.*; + +/** + * Created by imegumii on 01/05/2017. + */ +public class NDFA extends Automata { + + public NDFA() { + super(); + this.type = Type.NDFA; + } + + public SortedSet statesBereikbaarVanaf(T vanaf, char s) { + SortedSet bereikbaar = new TreeSet(); + Iterator> it = this.transistions.iterator(); + + while(it.hasNext()) { + Transition t = it.next(); + +// System.out.println(t); + if (vanaf.equals(t.vanState)) { +// System.out.println("Dit is onze staat"); + boolean isGelijk = false; + isGelijk = s == t.symbol; +// System.out.println("Zijn symbolen gelijk? " + isGelijk); + + if (isGelijk && !bereikbaar.contains(t.naarState)) { + bereikbaar.add(t.naarState); + bereikbaar.addAll(statesBereikbaarVanaf(t.naarState, Transition.EPSILON)); + } + } + + } + + return bereikbaar; + } + + public DFA toDFA () { + DFA eindDFA = new DFA<>(); + + SortedSet startSet = new TreeSet(); + //er kunnen meer start states zijn, + // een NDFA kan namelijk meerdere start states hebben (die met epsilon overgangen dan toch naar 1 state gewerkt kunnen worden) + for (T t : this.beginStates) { + startSet.add(t); + startSet.addAll(statesBereikbaarVanaf(t, Transition.EPSILON)); + } +// System.out.println("Begin states zijn: "); +// startSet.forEach(System.out::println); + + HashMap, Integer> totaalEindStates = new HashMap<>(); + + totaalEindStates.put(startSet, 0); + + Queue> kue = new LinkedList<>(); + kue.offer(startSet); // add beginstate(s) + +// System.out.println("Start ------------"); + + int stateCounter = 1; + + SortedSet> trans = new TreeSet<>(); + + while (!kue.isEmpty()) { + SortedSet set = kue.poll(); + // we beginnen bij de begin states + + // kijk welke states je kunt bereiken vanaf deze state. + for (Character symbol : this.symbols) { + SortedSet totaalTeBereiken = new TreeSet<>(); + boolean isEindState = false; + boolean isBeginState = stateCounter == 1; + for (T t : set) { + // kijk wat er te bereiken is vanaf t +// System.out.println("Bereikbaar vanaf T "+ t + " en s " + symbol + " is"); + SortedSet bereikbareStates = statesBereikbaarVanaf(t, symbol); +// System.out.println("Vanaf " + t + " kan ik bij " + bereikbareStates + " komen via " + symbol); + totaalTeBereiken.addAll(bereikbareStates); + if (this.eindStates.contains(t)) { + isEindState = true; + } + } + + if (!totaalEindStates.containsKey(totaalTeBereiken)) { + kue.offer(totaalTeBereiken); + totaalEindStates.put(totaalTeBereiken, stateCounter); + stateCounter++; + } + + // add transitions +// System.out.println("Vanaf " + set + " kan ik dus bij " + totaalTeBereiken + " komen via " + symbol); + eindDFA.addTransition(new Transition<>(totaalEindStates.get(set).toString(), symbol, totaalEindStates.get(totaalTeBereiken).toString())); + if (isBeginState) { + // beginstate + eindDFA.defineAsStartState(totaalEindStates.get(set).toString()); + } + if (isEindState) { +// System.out.println("Eind state is "); + eindDFA.defineAsEndState(totaalEindStates.get(set).toString()); + } + + } + + } + +// System.out.println("----end"); + +// System.out.println("In totaal krijgen we " + totaalEindStates); +// eindDFA.transistions.forEach((t) -> { +//// System.out.println(t.vanState); +// System.out.println("(" + getByValue(totaalEindStates, t.vanState) + ", " + t.symbol + ")-->" + getByValue(totaalEindStates, t.naarState)); +// +// }); + + +// trans.forEach(System.out::println); +// for (Transition t : trans) { +// eindDFA.addTransition(t); +// } + return eindDFA; + } + +// public SortedSet getByValue (HashMap, Integer> map, String value) { +// for (Map.Entry, Integer> e : map.entrySet()) { +// if (value.equals(e.getValue().toString())) { +// return e.getKey(); +// } +// } +// +// return null; +// } + +} diff --git a/src/com/imegumii/RegExp.java b/src/com/imegumii/RegExp.java new file mode 100644 index 0000000..bae1d49 --- /dev/null +++ b/src/com/imegumii/RegExp.java @@ -0,0 +1,340 @@ +package com.imegumii; + +import sun.misc.Regexp; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Created by kenny on 2-5-2017. + */ +public class RegExp extends Importable{ + + public enum Operator { PLUS, STER, OF, PUNT, EEN} + + Operator operator; + String characters; + + RegExp links; + RegExp rechts; + + static final Comparator vergelijkDmvLengte = (s1, s2) -> { + if (s1.length() == s2.length()) + {return s1.compareTo(s2);} + else + {return s1.length() - s2.length();} + }; + + public RegExp() + { + super(Type.REGEX); + operator = Operator.EEN; + characters = ""; + links = null; + rechts = null; + } + + public RegExp(String chars){ + super(Type.REGEX); + operator = Operator.EEN; + characters = chars; + links = null; + rechts = null; + } + + public RegExp loopRecursiefDoorString(String startString, RegExp r) { + int count = 0; + boolean moetRecursief = false; + + for (int i = 0; i < startString.length(); i++) { + char c = startString.charAt(i); + + if (c == '(') { + count++; + } + if (c == ')') { + count--; + } + if (count > 1) { + moetRecursief = true; + } + } + + Queue queue = new LinkedList<>(); + queue.add(startString); + + Deque processedParantheses = new ArrayDeque<>(); + + RegExp retval = new RegExp(); + + while (!queue.isEmpty()) { + String s = queue.poll(); +// System.out.println("Working on " + s); + Deque start = new ArrayDeque<>(); + Deque end = new ArrayDeque<>(); + + String toProcessAfter = s; + + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + + if (c == '(') { + start.addLast(i); + } + + if (c == ')') { + end.addFirst(i); + } + + if (!start.isEmpty() && !end.isEmpty()) { + int startPos = start.pollLast(); + int endPos = end.pollFirst(); + + String sub = s.substring(startPos + 1, endPos); +// System.out.println("Sub is " + sub); + + StringBuilder toReplace = new StringBuilder(s.substring(startPos, endPos + 1)); + StringBuilder replaceWith = new StringBuilder("" + Transition.ENDCHAR); +// System.out.println("Toreplace is " + toReplace.toString()); + toProcessAfter = toProcessAfter.replace(toReplace, replaceWith); +// System.out.println("Next string is " + toProcessAfter); + queue.add(toProcessAfter); + if (sub.contains("" + Transition.ENDCHAR)) { + // We have simplified the parantheses here, therefore before we continue we must first turn this into a regexp + RegExp reg = stringNaarRegExp(sub, r, processedParantheses); + processedParantheses.add(reg); +// System.out.println(reg.getTaal(10, 100)); + } else { + processedParantheses.add(stringNaarRegExp(sub, r, null)); + } +// System.out.println("----"); + break; + } + } + if (!s.contains("(")) { + retval = stringNaarRegExp(toProcessAfter, r, processedParantheses); + } + } +// System.out.println(retval.getTaal(10, 100)); +// System.out.println("----------"); + return retval; + } + + public RegExp naarRegExp(String s) { + + StringBuilder noSpacesString = new StringBuilder(); + + for (char c : s.toCharArray()) { + if (c != ' ') { + noSpacesString.append(c); + } + } +// RegExp retval = new RegExp(); + // Als eerste moet de string in groupen gedeeld worden op basis van haakjes. + // bijv. "a+((ab)*b|ab|(b)*bb)+(abba|baab)+" naar ["a+", [ [["ab"], "*b"], ["ab"], [["b"], "*bb"], "+" ], [ ["abba", "baab"], "+"] ] + // Dit moet dan naar dit worden omgezet: + // a.plus().punt( (ab.ster().punt(b).of(ab).of(b.ster().punt(bb)).plus()) ).punt( abba.punt().baab.plus() ) + // Niet gelukt. +// System.out.println("We lopen door " + s); + RegExp r = loopRecursiefDoorString(noSpacesString.toString(), new RegExp()); + return r; + } + + public RegExp stringNaarRegExp(String start, RegExp initieel, Deque alreadyParsed) { + ArrayList toOf = new ArrayList<>(); + + ArrayList strings = new ArrayList<>(); + StringBuilder currentString = new StringBuilder(); + for (int i = 0; i < start.length(); i++) { + char current = start.charAt(i); + + if (current == '|') { + // flush currentString to strings array + strings.add(currentString.toString()); + currentString = new StringBuilder(); + continue; + } + + currentString.append(current); + } + + strings.add(currentString.toString()); + +// System.out.println("OfStrings: " + strings); + + RegExp retval = new RegExp(); +// toDot.add(initieel); + + for (String s : strings) { + RegExp total = new RegExp(); + ArrayList toDot = new ArrayList<>(); + for (int i = 0; i < s.length(); i++) { + char current = s.charAt(i); + RegExp prev; + switch(current) { + case '*': + prev = toDot.get(toDot.size() -1); + toDot.add(prev.ster()); + toDot.remove(prev); +// System.out.println("STER"); + break; + case '+': + prev = toDot.get(toDot.size() -1); + toDot.add(prev.plus()); + toDot.remove(prev); +// System.out.println("PLUS"); + break; + case Transition.ENDCHAR: + toDot.add(alreadyParsed.pollFirst()); + break; + default: + toDot.add(new RegExp("" + current)); +// System.out.println("NEW CHAR"); + break; + } + } + + for (RegExp regExp : toDot) { + total = total.punt(regExp); + } + + toOf.add(total); + } + RegExp prev = null; + for (RegExp regExp : toOf) { + if (toOf.size() > 1) { + if (prev == null) { + prev = regExp; + continue; + } + retval = prev.of(regExp); + prev = retval; + } else { + retval = retval.punt(regExp); + } + + } + + + return retval; + } + + + public RegExp plus() + { + RegExp res = new RegExp(); + res.operator = Operator.PLUS; + res.links = this; + return res; + } + + public RegExp ster() + { + RegExp res = new RegExp(); + res.operator = Operator.STER; + res.links = this; + return res; + } + + public RegExp of(RegExp other) + { + RegExp res = new RegExp(); + res.operator = Operator.OF; + res.links = this; + res.rechts = other; + return res; + } + + public RegExp punt(RegExp other) + { + RegExp res = new RegExp(); + res.operator = Operator.PUNT; + res.links = this; + res.rechts = other; + return res; + } + + public Taal getTaal(int maxOperaties, int maxLength) + { + SortedSet leeg = new TreeSet<>(vergelijkDmvLengte); + SortedSet resultaat = new TreeSet<>(vergelijkDmvLengte); + + SortedSet resLinks, resRechts; + + if(maxOperaties < 1) return new Taal(leeg); + + switch(operator) + { + case EEN: + resultaat.add(characters); + break; + + case OF: + resLinks = links == null ? leeg : links.getTaal(maxOperaties - 1, maxLength).getSymbols(); + resRechts = rechts == null ? leeg : rechts.getTaal(maxOperaties - 1, maxLength).getSymbols(); + resultaat.addAll (resLinks); + resultaat.addAll (resRechts); + break; + + case PUNT: + resLinks = links == null ? leeg : links.getTaal(maxOperaties, maxLength).getSymbols(); + resRechts = rechts == null ? leeg : rechts.getTaal(maxOperaties, maxLength).getSymbols(); + for (String s1 : resLinks) { + for (String s2 : resRechts) { + resultaat.add(s1 + s2); + } + } + break; + + case STER: + case PLUS: + resLinks = links == null ? leeg : links.getTaal(maxOperaties - 1, maxLength).getSymbols(); + resultaat.addAll(resLinks); + for (int i = 1; i < maxOperaties; i++) + { + HashSet tempTaal = new HashSet(resultaat); + for (String s1 : resLinks) + { + for (String s2 : tempTaal) + { + resultaat.add (s1+s2); + } + } + } + if (this.operator == Operator.STER) + { + resultaat.add(""); + } + break; + + + default: + System.out.println ("getTaal is nog niet gedefinieerd voor de operator: " + this.operator); + break; + + } + SortedSet ret = new TreeSet<>(); + resultaat.stream().filter(r -> r.length() <= maxLength).forEach(ret::add); + return new Taal(ret); + } + + public class Tuple { + public final X left; + public final Y right; + public Tuple(X left, Y right) { + this.left = left; + this.right = right; + } + + @Override + public String toString() { + return "(" + left + "," + right + ")"; + } + + } + + @Override + public String toString() { + return "Chars: " + this.characters + " en operator: " + this.operator; + } +} diff --git a/src/com/imegumii/Taal.java b/src/com/imegumii/Taal.java new file mode 100644 index 0000000..3c26d68 --- /dev/null +++ b/src/com/imegumii/Taal.java @@ -0,0 +1,23 @@ +package com.imegumii; + +import java.util.SortedSet; + +/** + * Created by imegumii on 02/05/2017. + */ +public class Taal { + private SortedSet symbols; + + public Taal(SortedSet sortedSet) { + this.symbols = sortedSet; + } + + public SortedSet getSymbols() { + return symbols; + } + + @Override + public String toString() { + return symbols.toString(); + } +} diff --git a/src/com/imegumii/Test.java b/src/com/imegumii/Test.java new file mode 100644 index 0000000..159aac1 --- /dev/null +++ b/src/com/imegumii/Test.java @@ -0,0 +1,495 @@ +package com.imegumii; + +import java.util.TreeSet; + +/** + * Created by kenny on 8-6-2017. + */ +public class Test { + public static void test() + { + // Practicum1(); + +// Practicum2(); + +// Practicum4(); + +// Practicum5(); + +// ReverseAutomata(); + +// Hopcroft(); + +// TupleConstructie(); + +// FileReadTest(); + + // Hopcroft(); +// TestUitOpdrachtBeschrijving(); + + String s = "a*(aa+ |ba*b ) * (abba|baab|bbbb)+"; + + + String s2 = "a(a+ | b*((a|b)+))"; + String s3 = "(a|b)+a"; + + String s4 = "a+((ab)*b|ab|(b)*bb)+(abba|baab)+"; + String s5 = "((ab)*b(a|b)|ab|(b)*bb)+"; + + RegExp reg = new RegExp(); +// System.out.println(reg.toRegExp("a*|b+").getTaal(5)); + +// RegExp r1 = new RegExp("a"); +// RegExp r2 = new RegExp("b"); +// +// RegExp r3 = r1.punt(r2); +// +// RegExp r4 = new RegExp(); +// +// RegExp r5 = r3.punt(r4); +// +// traverseRegExp(r5); +// System.out.println(aantalOperators(r5, 1)); +// System.out.println(r5.getTaal(5)); + +// RegExp all = bSter.punt(aPlus); +// RegExp all = r1.punt(r2.ster()).punt(r3.plus()); +// +// System.out.println(all.getTaal(5)); +// reg.parseString(s); +// reg.parseString(s2); +// System.out.println(reg.parseString(s4).getTaal(3)); +// System.out.println(aantalOperators(reg.parseString(s2),1)); +// System.out.println(aantalOperators(reg.parseString(s4), 1)); +// System.out.println(aantalOperators(reg.parseString(s5), 1)); +// System.out.println(reg.parseString(s3).getTaal(100)); // werkte! + } + + public static void P1Opdracht1(TreeSet stringsToParse) { + Character [] characters = {'a', 'b'}; + DFA myAutomata = new DFA(); + + // AAB + myAutomata.addTransition(new Transition("q0", 'a', "q1")); + + myAutomata.addTransition(new Transition("q1", 'b', "q2")); + myAutomata.addTransition(new Transition("q1", 'a', "q0")); + + myAutomata.addTransition(new Transition("q2", 'b', "q3")); + myAutomata.addTransition(new Transition("q2", 'a', "q5")); + + myAutomata.addTransition(new Transition("q3", "q0")); + + // BAAB + myAutomata.addTransition(new Transition("q0", 'b', "q4")); + + myAutomata.addTransition(new Transition("q4", 'a', "q5")); + myAutomata.addTransition(new Transition("q4", 'b', "q4")); + + myAutomata.addTransition(new Transition("q5", 'a', "q6")); + myAutomata.addTransition(new Transition("q5", 'b', "q4")); + + myAutomata.addTransition(new Transition("q6", 'a', "q4")); + myAutomata.addTransition(new Transition("q6", 'b', "q7")); + + myAutomata.addTransition(new Transition("q7", 'a', "q4")); + myAutomata.addTransition(new Transition("q7", 'b', "q4")); + + myAutomata.defineAsStartState("q0"); + myAutomata.defineAsEndState("q3"); + myAutomata.defineAsEndState("q7"); + + myAutomata.printTransitions(); + + final long[] startTime = {System.currentTimeMillis()}; + myAutomata.geefTaalTotLengte(10).getSymbols().forEach((s) -> { + long before = System.currentTimeMillis(); + boolean result = myAutomata.accepteer(s); + long after = System.currentTimeMillis(); + long delta = (after-before); + System.out.println("string " + s + " fully parsed, result: " + result + " , it took " + delta + " ms"); + startTime[0] += delta; + }); + System.out.println((System.currentTimeMillis() - startTime[0])); + } + + public static void Practicum1() { + TreeSet stringsToParse = new TreeSet<>(); + stringsToParse.add("abbaa"); + stringsToParse.add("babaa"); + stringsToParse.add("abbaaabaab"); + stringsToParse.add("abaab"); + stringsToParse.add("aaaabba"); + stringsToParse.add("baab"); + stringsToParse.add("baaba"); + stringsToParse.add("baabaabba"); + stringsToParse.add("aaaaabb"); // this is wrong, something is wrong + + + P1Opdracht1(stringsToParse); + } + + public static void Practicum2() + { + RegExp a = new RegExp("a"); + RegExp b = new RegExp("b"); + + // expr1: "baa" + RegExp expr1 = new RegExp("baa"); + // expr2: "bb" + RegExp expr2 = new RegExp("bb"); + // expr3: "baa | baa" + RegExp expr3 = expr1.of(expr2); + + // all: "(a|b)*" + RegExp all = (a.of(b)).ster(); + + // expr4: "(baa | baa)+" + RegExp expr4 = expr3.plus(); + // expr5: "(baa | baa)+ (a|b)*" + RegExp expr5 = expr4.punt(all); + +// System.out.println("taal van (baa):\n" + expr1.getTaal(5)); +// System.out.println("taal van (bb):\n" + expr2.getTaal(5)); +// System.out.println("taal van (baa | bb):\n" + expr3.getTaal(5)); +// +// System.out.println("taal van (a|b)*:\n" + all.getTaal(5)); +// System.out.println("taal van (baa | bb)+:\n" + expr4.getTaal(5)); +// System.out.println("taal van (baa | bb)+ (a|b)*:\n" + expr5.getTaal(6)); + + } + + public static void Thompson() { + RegExp expr1 = new RegExp(); + expr1 = expr1.naarRegExp("a(abba|baab)*b+"); + + NDFA test = ThompsonConverter.convert(expr1); + + Graph.generateImage(test, "thompson"); + } + + public static void Hopcroft() + { + DFA automata = new DFA(); + + + automata.addTransition(new Transition("q0", 'a', "q2")); + automata.addTransition(new Transition("q0", 'b', "q3")); + automata.addTransition(new Transition("q1", 'a', "q3")); + automata.addTransition(new Transition("q1", 'b', "q2")); + automata.addTransition(new Transition("q2", 'a', "q0")); + automata.addTransition(new Transition("q2", 'b', "q4")); + automata.addTransition(new Transition("q3", 'a', "q1")); + automata.addTransition(new Transition("q3", 'b', "q5")); + automata.addTransition(new Transition("q4", 'a', "q6")); + automata.addTransition(new Transition("q4", 'b', "q5")); + automata.addTransition(new Transition("q5", 'a', "q2")); + automata.addTransition(new Transition("q5", 'b', "q0")); + automata.addTransition(new Transition("q6", 'a', "q4")); + automata.addTransition(new Transition("q6", 'b', "q0")); + + automata.defineAsStartState("q0"); + + automata.defineAsEndState("q1"); + automata.defineAsEndState("q3"); + automata.defineAsEndState("q4"); + automata.defineAsEndState("q6"); + + + /* + automata.addTransition(new Transition("0", 'a', "0")); + automata.addTransition(new Transition("0", 'b', "1")); + + automata.addTransition(new Transition("1", 'a', "2")); + automata.addTransition(new Transition("1", 'b', "1")); + + automata.addTransition(new Transition("2", 'a', "0")); + automata.addTransition(new Transition("2", 'b', "3")); + + automata.addTransition(new Transition("3", 'a', "4")); + automata.addTransition(new Transition("3", 'b', "1")); + + automata.addTransition(new Transition("4", 'a', "5")); + automata.addTransition(new Transition("4", 'b', "3")); + + automata.addTransition(new Transition("5", 'a', "0")); + automata.addTransition(new Transition("5", 'b', "3")); + + automata.defineAsStartState("0"); + automata.defineAsEndState("2"); + automata.defineAsEndState("4"); + */ + + System.out.println("\nNormal automata.."); + System.out.println(Graph.generateGraphString(automata)); + + HopcroftConverter convert = new HopcroftConverter(automata); + DFA minimized = convert.minimize(); + + System.out.println("\nMinimized automata.."); + Graph.generateImage(minimized, null); + } + + public static void ReverseAutomata() + { + DFA myAutomata = new DFA(); + + // AAB + myAutomata.addTransition(new Transition("0", 'a', "0")); + myAutomata.addTransition(new Transition("0", 'b', "1")); + + myAutomata.addTransition(new Transition("1", 'a', "0")); + myAutomata.addTransition(new Transition("1", 'b', "2")); + + myAutomata.addTransition(new Transition("2", 'a', "0")); + myAutomata.addTransition(new Transition("2", 'b', "2")); + + myAutomata.defineAsStartState("0"); + myAutomata.defineAsEndState("2"); + +// System.out.println(Graph.generateGraphString(myAutomata)); + +// System.out.println("\nREVERSE:"); + + NDFA reverseAutomata = myAutomata.reverse(); + +// System.out.println(Graph.generateGraphString(reverseAutomata)); + + System.out.println("ORIGINEEL"); + myAutomata.printTransitions(); + System.out.println("MET BEGIN EN EIND"); + System.out.println(myAutomata.beginStates); + System.out.println(myAutomata.eindStates); + System.out.println("REVERSE"); + reverseAutomata.printTransitions(); + System.out.println("MET BEGIN EN EIND"); + System.out.println(reverseAutomata.beginStates); + System.out.println(reverseAutomata.eindStates); + } + + public static void Practicum4() { + NDFA myAutomata = new NDFA(); + +// myAutomata.addTransition(new Transition("0", 'a', "1")); +// myAutomata.addTransition(new Transition("0", 'a', "2")); +// myAutomata.addTransition(new Transition("1", 'a', "1")); +// myAutomata.addTransition(new Transition("1", 'a', "2")); +// myAutomata.addTransition(new Transition("2", 'b', "1")); +// myAutomata.addTransition(new Transition("2", 'b', "3")); +// myAutomata.addTransition(new Transition("3", 'a', "2")); +// myAutomata.addTransition(new Transition("3", 'a', "1")); +// myAutomata.defineAsStartState("0"); +// myAutomata.defineAsEndState("0"); +// myAutomata.defineAsEndState("1"); + + // Test 2 +// myAutomata.addTransition(new Transition("0", 'a', "1")); +// +// myAutomata.addTransition(new Transition("0", 'a', "3")); +// myAutomata.addTransition(new Transition("0", 'b', "3")); +// +// myAutomata.addTransition(new Transition("0", 'a', "2")); +// myAutomata.addTransition(new Transition("0", 'b', "2")); +// +// myAutomata.addTransition(new Transition("1", 'a', "1")); +// myAutomata.addTransition(new Transition("1", 'b', "3")); +// +// myAutomata.addTransition(new Transition("1", 'a', "2")); +// myAutomata.addTransition(new Transition("1", 'b', "2")); +// +// myAutomata.addTransition(new Transition("2", 'b', "2")); +// myAutomata.addTransition(new Transition("2", 'b', "4")); +// +// myAutomata.addTransition(new Transition("2", 'b', "3")); //ja? Ja. +// myAutomata.addTransition(new Transition("3", 'b', "2")); +// +// myAutomata.addTransition(new Transition("3", 'b', "3")); +// +// myAutomata.addTransition(new Transition("3", 'a', "4")); +// myAutomata.addTransition(new Transition("3", 'b', "4")); +// +// myAutomata.defineAsStartState("0"); +// myAutomata.defineAsEndState("1"); + + // Test 3 + +// myAutomata.addTransition(new Transition("1", 'a', "2")); +// myAutomata.addTransition(new Transition("1", 'b', "1")); +// +// myAutomata.addTransition(new Transition("2", 'a', "3")); +// myAutomata.addTransition(new Transition("2", 'b', "2")); +// myAutomata.addTransition(new Transition("2", Transition.EPSILON, "1")); +// +// myAutomata.addTransition(new Transition("3", 'a', "4")); +// myAutomata.addTransition(new Transition("3", 'b', "3")); +// myAutomata.addTransition(new Transition("3", Transition.EPSILON, "2")); +// +// myAutomata.addTransition(new Transition("4", 'a', "1")); +// myAutomata.addTransition(new Transition("4", 'b', "4")); +// myAutomata.addTransition(new Transition("4", Transition.EPSILON, "3")); +// +// myAutomata.defineAsStartState("1"); +// myAutomata.defineAsEndState("2"); +// myAutomata.defineAsEndState("3"); + + System.out.println("De NDFA is "); + myAutomata.printTransitions(); + System.out.println("Met als begin en eind states"); + System.out.println(myAutomata.beginStates); + System.out.println(myAutomata.eindStates); + + System.out.println("DFA is dan "); + DFA myDfa = myAutomata.toDFA(); + myDfa.printTransitions(); + System.out.println("Met als begin en eind states"); + System.out.println(myDfa.beginStates); + System.out.println(myDfa.eindStates); + + } + + public static void Practicum5 () { + + DFA myAutomata = new DFA(); + // Test 4 minimalisatie + + myAutomata.addTransition(new Transition("0", 'a', "0")); + myAutomata.addTransition(new Transition("0", 'b', "1")); + + myAutomata.addTransition(new Transition("1", 'a', "2")); + myAutomata.addTransition(new Transition("1", 'b', "1")); + + myAutomata.addTransition(new Transition("2", 'a', "0")); + myAutomata.addTransition(new Transition("2", 'b', "3")); + + myAutomata.addTransition(new Transition("3", 'a', "4")); + myAutomata.addTransition(new Transition("3", 'b', "1")); + + myAutomata.addTransition(new Transition("4", 'a', "5")); + myAutomata.addTransition(new Transition("4", 'b', "3")); + + myAutomata.addTransition(new Transition("5", 'a', "0")); + myAutomata.addTransition(new Transition("5", 'b', "3")); + + myAutomata.defineAsStartState("0"); + myAutomata.defineAsEndState("2"); + myAutomata.defineAsEndState("4"); + + System.out.println("Ongeminimaliseerd krijgen we:"); + myAutomata.print(); + System.out.println("-------"); + Graph.generateImage(myAutomata, null); + + DFA geminimaliseerd = myAutomata.minimaliseer(); + System.out.println("Geminimaliseerd krijgen we:"); + geminimaliseerd.print(); + System.out.println("------"); + Graph.generateImage(geminimaliseerd, null); + geminimaliseerd.ontkenning(); + } + + public static void TupleConstructie() + { + DFA aut1 = new DFA(); + + aut1.addTransition(new Transition("1", 'a', "2")); + aut1.addTransition(new Transition("1", 'b', "1")); + + aut1.addTransition(new Transition("2", 'a', "1")); + aut1.addTransition(new Transition("2", 'b', "2")); + + + aut1.defineAsStartState("1"); + aut1.defineAsEndState("1"); + + System.out.println("\n\nA1\n--------"); + System.out.println(Graph.generateImageString(aut1)); + Graph.generateImage(aut1, "automaat1"); + + + DFA aut2 = new DFA(); + + aut2.addTransition(new Transition("1", 'a', "1")); + aut2.addTransition(new Transition("1", 'b', "2")); + + aut2.addTransition(new Transition("2", 'a', "1")); + aut2.addTransition(new Transition("2", 'b', "3")); + + aut2.addTransition(new Transition("3", 'a', "1")); + aut2.addTransition(new Transition("3", 'b', "4")); + + aut2.addTransition(new Transition("4", 'a', "4")); + aut2.addTransition(new Transition("4", 'b', "4")); + + aut2.defineAsStartState("1"); + aut2.defineAsEndState("1"); + aut2.defineAsEndState("2"); + + System.out.println("\n\nA2\n--------"); + System.out.println(Graph.generateImageString(aut2)); + Graph.generateImage(aut2, "automaat2"); + + DFA en = aut1.en(aut2); + + System.out.println("\n\nEN\n--------"); + System.out.println(Graph.generateImageString(en)); + Graph.generateImage(en, "en"); + + DFA of = aut1.of(aut2); + + System.out.println("\n\nOF\n--------"); + System.out.println(Graph.generateImageString(of)); + Graph.generateImage(of, "of"); + } + + public static void TestUitOpdrachtBeschrijving() { + NDFA ndfa = new NDFA(); + + ndfa.addTransition(new Transition("q0", 'a', "q1")); + + ndfa.addTransition(new Transition("q1", 'b', "q2")); + ndfa.addTransition(new Transition("q1", 'b', "q0")); + + ndfa.addTransition(new Transition("q2", 'a', "q0")); + ndfa.addTransition(new Transition("q2", 'a', "q3")); + + ndfa.addTransition(new Transition("q3", 'a', "q4")); + + ndfa.defineAsStartState("q0"); + + ndfa.defineAsEndState("q0"); + ndfa.defineAsEndState("q4"); + + Graph.generateImage(ndfa, "Ndfa"); + + DFA dfa = ndfa.toDFA(); + + Graph.generateImage(dfa, "Dfa"); + } + + public static void traverseRegExp(RegExp r) { + if (r == null) { + return; + } + System.out.println(r); + System.out.println("Printing left "); + traverseRegExp(r.links); + System.out.println("Printing right"); + traverseRegExp(r.rechts); + System.out.println("----"); + } + + public static int aantalOperators(RegExp r, int i) { + if (r != null) { + if (r.links != null) { + i++; + i = aantalOperators(r.links, i); + } + if (r.rechts != null) { + i++; + i = aantalOperators(r.rechts, i); + } + } + + return i; + } +} diff --git a/src/com/imegumii/ThompsonConverter.java b/src/com/imegumii/ThompsonConverter.java new file mode 100644 index 0000000..eba7f39 --- /dev/null +++ b/src/com/imegumii/ThompsonConverter.java @@ -0,0 +1,169 @@ +package com.imegumii; + +/** + * Created by kenny on 17-5-2017. + */ +public class ThompsonConverter { + + private static int count = 0; + + public static NDFA convert(RegExp regex) + { + NDFA generated = new NDFA(); + + convertStatement(regex, generated); + + return generated; + } + + private static void convertStatement(RegExp regex, NDFA automata) + { + switch(regex.operator) + { + case PLUS: + + //Links + convertStatement(regex.links, automata); + String endLink1 = automata.eindStates.first(); + String beginLink1 = automata.beginStates.first(); + + String newstart = getState(); + String newEnd = getState(); + + //Repeat + automata.addTransition(new Transition(newstart, Transition.EPSILON, beginLink1)); + automata.addTransition(new Transition(endLink1, Transition.EPSILON, newEnd)); + automata.addTransition(new Transition(endLink1, Transition.EPSILON, beginLink1)); + + automata.clearEindStates(); + automata.clearBeginStates(); + + automata.defineAsStartState(newstart); + automata.defineAsEndState(newEnd); + + break; + case STER: + + //Links + convertStatement(regex.links, automata); + String endLink2 = automata.eindStates.first(); + String beginLink2 = automata.beginStates.first(); + + //New states + String start2 = getState(); + String end2 = getState(); + + //Repeat and skip + automata.addTransition(new Transition(start2, Transition.EPSILON, end2)); + automata.addTransition(new Transition(endLink2, Transition.EPSILON, beginLink2)); + automata.addTransition(new Transition(start2, Transition.EPSILON, beginLink2)); + automata.addTransition(new Transition(endLink2, Transition.EPSILON, end2)); + + automata.clearEindStates(); + automata.clearBeginStates(); + + automata.defineAsStartState(start2); + automata.defineAsEndState(end2); + + break; + case OF: + + //Links + convertStatement(regex.links, automata); + String topEnd = automata.eindStates.first(); + String topBegin = automata.beginStates.first(); + + //Rechts + convertStatement(regex.rechts, automata); + String bottomBegin = automata.beginStates.first(); + String bottomEnd = automata.eindStates.first(); + + //New states + String start3 = getState(); + String end3 = getState(); + + //Link both + automata.addTransition(new Transition(start3, Transition.EPSILON, topBegin)); + automata.addTransition(new Transition(start3, Transition.EPSILON, bottomBegin)); + automata.addTransition(new Transition(topEnd, Transition.EPSILON, end3)); + automata.addTransition(new Transition(bottomEnd, Transition.EPSILON, end3)); + + automata.clearEindStates(); + automata.clearBeginStates(); + + automata.defineAsStartState(start3); + automata.defineAsEndState(end3); + + + break; + case PUNT: + + //Links + convertStatement(regex.links, automata); + String endLink = automata.eindStates.first(); + String newBeginLink = automata.beginStates.first(); + + //Rechts + convertStatement(regex.rechts, automata); + String beginLink = automata.beginStates.first(); + String newEndLink = automata.eindStates.first(); + + //Link both + automata.addTransition(new Transition(endLink, Transition.EPSILON, beginLink)); + + automata.clearEindStates(); + automata.clearBeginStates(); + + automata.defineAsStartState(newBeginLink); + automata.defineAsEndState(newEndLink); + + break; + case EEN: + + char[] s = regex.characters.toCharArray(); + + automata.clearBeginStates(); + automata.clearEindStates(); + + if(regex.characters.length() <= 0) + { + String state1 = getState(); + String state2 = getState(); + + Transition t = new Transition(state1, Transition.EPSILON, state2); + + automata.addTransition(t); + automata.defineAsStartState(state1); + automata.defineAsEndState(state2); + + break; + } + + String prevState = getState(); + String newState = ""; + automata.defineAsStartState(prevState); + + for(char c : s) + { + newState = getState(); + Transition t = new Transition(prevState, c, newState); + prevState = newState; + automata.addTransition(t); + } + + automata.defineAsEndState(newState); + + break; + default: + System.out.println("Error #8.1"); + break; + } + } + + private static String getState() + { + count++; + return "q" + count; + } + +} diff --git a/src/com/imegumii/Transition.java b/src/com/imegumii/Transition.java new file mode 100644 index 0000000..ffdd9c2 --- /dev/null +++ b/src/com/imegumii/Transition.java @@ -0,0 +1,50 @@ +package com.imegumii; + +/** + * Created by imegumii on 18/04/2017. + */ +public class Transition implements Comparable> { + public static final char ENDCHAR = '$'; + + public static final char EPSILON = 'ε'; + + public T vanState; + public char symbol; + public T naarState; + + public Transition(T from, T to) { + this(from, ENDCHAR, to); + } + + public Transition(T van, char s, T naar) { + this.vanState = van; + this.symbol = s; + this.naarState = naar; + } + + public boolean equals (Object other) { + if (other == null) { + return false; + } else if (other instanceof Transition) { + Transition otherTransition = (Transition) other; + return this.vanState.equals(otherTransition.vanState) && this.naarState.equals(otherTransition.naarState) && this.symbol == otherTransition.symbol; + } else { + return false; + } + } + + @Override + public int compareTo(Transition t) { + int vanCompare = vanState.compareTo(t.vanState); + int symbolCompare = new Character (symbol).compareTo(t.symbol); + int naarCompare = naarState.compareTo(t.naarState); + + return (vanCompare != 0 ? vanCompare : (symbolCompare != 0 ? symbolCompare : naarCompare)); + } + + @Override + public String toString() { + return "" + this.vanState + ">" + this.symbol + ">" + this.naarState; + + } +} diff --git a/src/com/imegumii/Util.java b/src/com/imegumii/Util.java new file mode 100644 index 0000000..89f3751 --- /dev/null +++ b/src/com/imegumii/Util.java @@ -0,0 +1,21 @@ +package com.imegumii; + +/** + * Created by kenny on 12-6-2017. + */ +public class Util { + + public static String randomString(int lenght) + { + String s = ""; + String all = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + + for(int i = 0; i < lenght; i++) + { + int rand = (int)(Math.random() * all.length()); + s += all.substring(rand, rand+1); + } + + return s; + } +} diff --git a/src/com/imegumii/ui/Frame.java b/src/com/imegumii/ui/Frame.java new file mode 100644 index 0000000..67896f8 --- /dev/null +++ b/src/com/imegumii/ui/Frame.java @@ -0,0 +1,28 @@ +package com.imegumii.ui; + +import javax.swing.*; +import java.awt.*; + +/** + * Created by kenny on 8-6-2017. + */ +public class Frame extends JFrame { + + public Frame() + { + super("Automata"); + + this.setSize(1000, 800); + //this.setResizable(false); + this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + + JPanel container = new JPanel(new BorderLayout()); + container.add(TabPanel.Instance(), BorderLayout.CENTER); + container.add(InputPanel.Instance(), BorderLayout.NORTH); + container.add(StatusPanel.Instance(), BorderLayout.SOUTH); + + this.setContentPane(container); + + this.setVisible(true); + } +} diff --git a/src/com/imegumii/ui/GraphImagePanel.java b/src/com/imegumii/ui/GraphImagePanel.java new file mode 100644 index 0000000..756a256 --- /dev/null +++ b/src/com/imegumii/ui/GraphImagePanel.java @@ -0,0 +1,130 @@ +package com.imegumii.ui; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; +import java.awt.geom.Point2D; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.*; + +/** + * Created by kenny on 9-6-2017. + */ +public class GraphImagePanel extends JPanel { + + private BufferedImage image; + + private float scale = 1f; + private float x = 0f, y = 0f; + private Point dragStartScreen; + private Point dragEndScreen; + + public GraphImagePanel(File f) + { + super(); + + this.setBackground(Color.WHITE); + + try { + image = ImageIO.read(f); +// x = image.getWidth() / 2; +// y = image.getHeight() / 2; + } catch (IOException e) { + e.printStackTrace(); + } + + addMouseWheelListener(new MouseAdapter() { + + @Override + public void mouseWheelMoved(MouseWheelEvent e) { +// System.out.println("Scrolled" + scale); + double delta = 0.05f * e.getPreciseWheelRotation(); + scale += delta; + revalidate(); + repaint(); + } + + }); + + addMouseMotionListener(new MouseMotionListener() { + @Override + public void mouseDragged(MouseEvent e) { + dragEndScreen = e.getPoint(); + double dx = dragEndScreen.getX() - dragStartScreen.getX(); + double dy = dragEndScreen.getY() - dragStartScreen.getY(); + x += dx; + y += dy; + dragStartScreen = dragEndScreen; + dragEndScreen = null; + repaint(); + } + + @Override + public void mouseMoved(MouseEvent e) { + } + }); + + addMouseListener(new MouseListener() { + @Override + public void mouseClicked(MouseEvent e) { + + } + + @Override + public void mousePressed(MouseEvent e) { + dragStartScreen = e.getPoint(); + dragEndScreen = null; + } + + @Override + public void mouseReleased(MouseEvent e) { + + } + + @Override + public void mouseEntered(MouseEvent e) { + + } + + @Override + public void mouseExited(MouseEvent e) { + + } + }); + + repaint(); + } + + public void paintComponent(Graphics g){ + super.paintComponent(g); + + Graphics2D g2d = (Graphics2D) g; + g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); + g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC)); + + if(image != null){ + +// int width = this.getWidth(); +// int height = this.getHeight(); +// +// if(image.getWidth() > image.getHeight()) { +// height = (int)((width * image.getHeight()) / image.getWidth()); +// } +// else { +// width = (int) ((height * image.getWidth()) / image.getHeight()); +// } + AffineTransform at = new AffineTransform(); + g.drawLine(-1000, 0, 1000, 0); + g.drawLine(0, -1000, 0, 1000); + at.scale(1, -1); + at.setToTranslation(x, y); + at.scale(scale, scale); + g2d.drawImage(image, at, this); +// g2d.drawImage(image, 0,0, width, height, this); + } + } +} diff --git a/src/com/imegumii/ui/GraphPanel.java b/src/com/imegumii/ui/GraphPanel.java new file mode 100644 index 0000000..784a2b8 --- /dev/null +++ b/src/com/imegumii/ui/GraphPanel.java @@ -0,0 +1,310 @@ +package com.imegumii.ui; + +import com.imegumii.*; +import org.apache.commons.io.FileUtils; +import org.apache.xpath.SourceTree; + +import javax.imageio.ImageIO; +import javax.swing.*; +import javax.swing.border.Border; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.geom.Point2D; +import java.io.*; +import java.awt.image.BufferedImage; + +/** + * Created by kenny on 8-6-2017. + */ +public class GraphPanel extends JPanel { + + private String name; + private File imageLocation; + private Automata automata; + + public String getName() + { + return name; + } + + public GraphPanel(String name, File f, Automata automata) + { + super(new BorderLayout()); + + this.name = name; + this.imageLocation = f; + this.automata = automata; + + this.add(new GraphImagePanel(imageLocation), BorderLayout.CENTER); + + JPanel buttonPanel = new JPanel(); + buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS)); + buttonPanel.setBackground(Color.WHITE); + buttonPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.BLACK), BorderFactory.createEmptyBorder(10, 10, 10, 10))); + + JButton closeTab = new JButton("Close"); + closeTab.setForeground(new Color(200, 100, 100)); + closeTab.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + TabPanel.Instance().remove(GraphPanel.this); + } + }); + + JButton exportData = new JButton("Export data"); + exportData.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + + BackgroundWorker.instance().addWorker(new BackgroundWorker.Worker() { + @Override + public void execute() { + String filename = "data." + Util.randomString(5) + ".dot"; + File file = new File("export/" + filename); + + if(file.exists()){ + int reply = JOptionPane.showConfirmDialog(null, "The file " + filename + "already exists. Do you want to overwrite it?", "File exists", JOptionPane.YES_NO_OPTION); + if (reply != JOptionPane.YES_OPTION) { + StatusPanel.Instance().setStatus("Cancelled export"); + return; + } + } + + PrintWriter w = null; + try { + w = new PrintWriter(file); + w.print(automata.getTransitions()); + w.flush(); + w.close(); + StatusPanel.Instance().setStatus("Success: " + filename); + } catch (FileNotFoundException e1) { + StatusPanel.Instance().setStatus("Something went wrong while exporting the file"); + } + } + }); + } + }); + + JButton exportImage = new JButton("Export image"); + exportImage.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + + BackgroundWorker.instance().addWorker(new BackgroundWorker.Worker() { + @Override + public void execute() { + String filename = "img." + Util.randomString(5) + ".png"; + File file = new File("export/" + filename); + + if(file.exists()){ + int reply = JOptionPane.showConfirmDialog(GraphPanel.this, "The file " + filename + "already exists. Do you want to overwrite it?", "File exists", JOptionPane.YES_NO_OPTION); + if (reply != JOptionPane.YES_OPTION) { + StatusPanel.Instance().setStatus("Cancelled export"); + return; + } + } + + try { + FileUtils.copyFile(f, file); + StatusPanel.Instance().setStatus("Success: " + filename); + } catch (IOException e1) { + StatusPanel.Instance().setStatus("Something went wrong while exporting the file"); + } + } + }); + } + }); + + JButton minimizeButton = new JButton("Hopcroft"); + minimizeButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + BackgroundWorker.instance().addWorker(new BackgroundWorker.Worker() { + @Override + public void execute() { + if(automata.type == Importable.Type.NDFA) + { + StatusPanel.Instance().setStatus("Converting to DFA ", 20); + DFA convert = ((NDFA) automata).toDFA(); + + StatusPanel.Instance().setStatus("Generating image for DFA", 30); + File img = Graph.generateImage(convert); + TabPanel.Instance().addGraph(name, img, convert); + + StatusPanel.Instance().setStatus("Minimizing DFA", 50); + DFA mini = convert.minimaliseerHopcroft(); + + StatusPanel.Instance().setStatus("Generating minimized image", 70); + File img2 = Graph.generateImage(mini); + TabPanel.Instance().addGraph(name, img2, mini); + + StatusPanel.Instance().setStatus("Done", 100); + } + else if(automata.type == Importable.Type.DFA) + { + StatusPanel.Instance().setStatus("Minimizing dfa." + name, 40); + DFA dfa = (DFA) automata; + DFA mini = dfa.minimaliseerHopcroft(); + + StatusPanel.Instance().setStatus("Generating minimized image", 60); + File img3 = Graph.generateImage(mini); + TabPanel.Instance().addGraph(name, img3, mini); + + StatusPanel.Instance().setStatus("Done", 100); + } + } + }); + } + }); + + JButton minimize2Button = new JButton("Bryzowski"); + minimize2Button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + BackgroundWorker.instance().addWorker(new BackgroundWorker.Worker() { + @Override + public void execute() { + if(automata.type == Importable.Type.NDFA) + { + StatusPanel.Instance().setStatus("Converting to DFA ", 20); + DFA convert = ((NDFA) automata).toDFA(); + + StatusPanel.Instance().setStatus("Generating image for DFA", 30); + File img = Graph.generateImage(convert); + TabPanel.Instance().addGraph(name, img, convert); + + StatusPanel.Instance().setStatus("Minimizing DFA", 50); + DFA mini = convert.minimaliseer(); + + StatusPanel.Instance().setStatus("Generating minimized image", 70); + File img2 = Graph.generateImage(mini); + TabPanel.Instance().addGraph(name, img2, mini); + + StatusPanel.Instance().setStatus("Done", 100); + } + else if(automata.type == Importable.Type.DFA) + { + StatusPanel.Instance().setStatus("Minimizing dfa." + name, 40); + DFA dfa = (DFA) automata; + DFA mini = dfa.minimaliseer(); + + StatusPanel.Instance().setStatus("Generating minimized image", 60); + File img3 = Graph.generateImage(mini); + TabPanel.Instance().addGraph(name, img3, mini); + + StatusPanel.Instance().setStatus("Done", 100); + } + } + }); + } + }); + + JButton toDfaButton = new JButton("to DFA"); + toDfaButton.addActionListener(e -> { + BackgroundWorker.instance().addWorker(() -> { + StatusPanel.Instance().setStatus("Converting to DFA ", 10); + DFA convert = ((NDFA) automata).toDFA(); + + StatusPanel.Instance().setStatus("Generating image for DFA", 50); + File img = Graph.generateImage(convert); + TabPanel.Instance().addGraph(name, img, convert); + + StatusPanel.Instance().setStatus("Done", 100); + }); + }); + + JButton reverseButton = new JButton("Reverse"); + reverseButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + BackgroundWorker.instance().addWorker(new BackgroundWorker.Worker() { + @Override + public void execute() { + + StatusPanel.Instance().setStatus("Reversing ", 20); + + NDFA reverse = ((DFA) automata).reverse(); + + StatusPanel.Instance().setStatus("Generating reversed image", 70); + + File img = Graph.generateImage(reverse); + + TabPanel.Instance().addGraph("Reverse " + name, img, reverse); + + StatusPanel.Instance().setStatus("Done", 100); + } + }); + } + }); + + JButton notButton = new JButton("Not"); + notButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + BackgroundWorker.instance().addWorker(new BackgroundWorker.Worker() { + @Override + public void execute() { + + StatusPanel.Instance().setStatus("Nothing ", 20); + + DFA not = ((DFA) automata).ontkenning(); + + StatusPanel.Instance().setStatus("Generating not image", 70); + + File img = Graph.generateImage(not); + + TabPanel.Instance().addGraph("Not " + name, img, not); + + StatusPanel.Instance().setStatus("Done", 100); + } + }); + } + }); + + JButton showPopup = new JButton("Show popup"); + showPopup.addActionListener(e -> { + new PopupFrame(name, automata); + }); + + JButton showGrammar = new JButton("Show grammar"); + showGrammar.addActionListener(e -> { + BackgroundWorker.instance().addWorker(() -> { + GrammarConverter c = new GrammarConverter(); + new TextPanel("Grammar", c.toGrammar((NDFA) automata).printToString()); + }); + }); + + buttonPanel.add(Box.createHorizontalGlue()); + + if(automata.type == Importable.Type.DFA) { + buttonPanel.add(notButton); + buttonPanel.add(Box.createRigidArea(new Dimension(10, 0))); + buttonPanel.add(reverseButton); + buttonPanel.add(Box.createRigidArea(new Dimension(10, 0))); + } + + buttonPanel.add(showPopup); + buttonPanel.add(Box.createRigidArea(new Dimension(10, 0))); + + if (automata.type == Importable.Type.NDFA) { + buttonPanel.add(showGrammar); + buttonPanel.add(Box.createRigidArea(new Dimension(10, 0))); + + buttonPanel.add(toDfaButton); + buttonPanel.add(Box.createRigidArea(new Dimension(10, 0))); + } + + buttonPanel.add(minimize2Button); + buttonPanel.add(Box.createRigidArea(new Dimension(10, 0))); + buttonPanel.add(minimizeButton); + buttonPanel.add(Box.createRigidArea(new Dimension(10, 0))); + buttonPanel.add(exportImage); + buttonPanel.add(Box.createRigidArea(new Dimension(10,0))); + buttonPanel.add(exportData); + buttonPanel.add(Box.createRigidArea(new Dimension(10,0))); + buttonPanel.add(closeTab); + + this.add(buttonPanel, BorderLayout.SOUTH); + } +} diff --git a/src/com/imegumii/ui/InputPanel.java b/src/com/imegumii/ui/InputPanel.java new file mode 100644 index 0000000..a92affd --- /dev/null +++ b/src/com/imegumii/ui/InputPanel.java @@ -0,0 +1,422 @@ +package com.imegumii.ui; + +import com.imegumii.*; +import jdk.nashorn.internal.runtime.regexp.joni.Regex; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.util.ArrayList; + +/** + * Created by kenny on 8-6-2017. + */ +public class InputPanel extends JPanel { + + private static InputPanel panel; + + public static InputPanel Instance() + { + if(panel == null) + panel = new InputPanel(); + + return panel; + } + + private InputPanel() + { + super(); + this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); + + JPanel topPanel = new JPanel(); + topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.LINE_AXIS)); + topPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + + topPanel.add(new JLabel("Regular expression")); + topPanel.add(Box.createRigidArea(new Dimension(10,0))); + + JTextField text = new JTextField(); + + topPanel.add(text); + + topPanel.add(Box.createRigidArea(new Dimension(10, 0))); + + JButton button = new JButton("Generate"); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + + BackgroundWorker.instance().addWorker(new BackgroundWorker.Worker() { + @Override + public void execute() { + String regS = text.getText().trim(); + String name = regS; + + StatusPanel.Instance().setStatus("Parsing REGEX", 20); + + RegExp regex = new RegExp(); + regex = regex.naarRegExp(regS); + + StatusPanel.Instance().setStatus("Converting REGEX to NDFA", 40); + + NDFA ndfa = ThompsonConverter.convert(regex); + + StatusPanel.Instance().setStatus("Generating image for NDFA", 70); + + File img = Graph.generateImage(ndfa); + + TabPanel.Instance().addGraph(name, img, ndfa); + +// StatusPanel.Instance().setStatus("Generating taal", 90); + +// new PopupFrame(name, regex); + + StatusPanel.Instance().setStatus("Done", 100); + } + }); + } + }); + + topPanel.add(button); + + topPanel.add(Box.createHorizontalGlue()); + this.add(topPanel); + + + //------------ + //BOTTOM PANEL + //----------- + + JPanel bottomPanel = new JPanel(); + bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.LINE_AXIS)); + bottomPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + + bottomPanel.add(new JLabel("File")); + bottomPanel.add(Box.createRigidArea(new Dimension(10,0))); + + JComboBox fileCombo = new JComboBox(findFiles()); + + bottomPanel.add(fileCombo); + + bottomPanel.add(Box.createRigidArea(new Dimension(10, 0))); + + JButton fileButton = new JButton("Generate"); + fileButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + + BackgroundWorker.instance().addWorker(new BackgroundWorker.Worker() { + @Override + public void execute() { +; + StatusPanel.Instance().setStatus("Parsing file", 10); + + String file = (String)fileCombo.getSelectedItem(); + String name = file.replaceAll(".dot", ""); + + Importable p = FileParser.read(file); + + if(p.type == Importable.Type.NDFA) + { + StatusPanel.Instance().setStatus("Generating image for NDFA", 60); + NDFA ndfa = (NDFA)p; + + File f = Graph.generateImage(ndfa); + + TabPanel.Instance().addGraph(name, f, ndfa); + } + + if(p.type == Importable.Type.DFA) + { + StatusPanel.Instance().setStatus("Generating image for DFA", 60); + DFA dfa = (DFA)p; + + File f = Graph.generateImage(dfa); + + TabPanel.Instance().addGraph(name, f, dfa); + } + + if(p.type == Importable.Type.REGEX) + { + StatusPanel.Instance().setStatus("Converting REGEX to NDFA", 40); + RegExp regex = (RegExp) p; + + NDFA ndfa = ThompsonConverter.convert(regex); + + StatusPanel.Instance().setStatus("Generating image for NDFA", 70); + + File f = Graph.generateImage(ndfa); + + TabPanel.Instance().addGraph(name, f, ndfa); + } + + StatusPanel.Instance().setStatus("Done", 100); + + } + }); + } + }); + + bottomPanel.add(fileButton); + + this.add(bottomPanel); + + + + //------------ + //Advanced PANEL + //----------- + + JPanel advPanel = new JPanel(); + advPanel.setLayout(new BoxLayout(advPanel, BoxLayout.LINE_AXIS)); + advPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + + JComboBox f1Combo = new JComboBox(findFiles()); + JComboBox f2Combo = new JComboBox(findFiles()); + + JButton orButton = new JButton("or"); + orButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + + BackgroundWorker.instance().addWorker(new BackgroundWorker.Worker() { + @Override + public void execute() { + StatusPanel.Instance().setStatus("Parsing files", 10); + + String file1 = (String)f1Combo.getSelectedItem(); + String name1 = file1.replaceAll(".dot", ""); + String file2 = (String)f2Combo.getSelectedItem(); + String name2 = file2.replaceAll(".dot", ""); + + Importable p1 = FileParser.read(file1); + Importable p2 = FileParser.read(file1); + + DFA dfa1 = null; + + if(p1.type == Importable.Type.NDFA) + { + StatusPanel.Instance().setStatus("Converting NDFA to DFA", 30); + NDFA ndfa1 = (NDFA)p1; + dfa1 = ndfa1.toDFA().minimaliseerHopcroft(); + } + if(p1.type == Importable.Type.DFA) + { + dfa1 = (DFA)p1; + } + if(p1.type == Importable.Type.REGEX) + { + StatusPanel.Instance().setStatus("Converting REGEX to DFA", 30); + RegExp regex = (RegExp) p1; + NDFA ndfa1 = ThompsonConverter.convert(regex); + dfa1 = ndfa1.toDFA().minimaliseerHopcroft(); + } + + DFA dfa2 = null; + + if(p2.type == Importable.Type.NDFA) + { + StatusPanel.Instance().setStatus("Converting NDFA to DFA", 50); + NDFA ndfa2 = (NDFA)p2; + dfa2 = ndfa2.toDFA().minimaliseerHopcroft(); + } + if(p2.type == Importable.Type.DFA) + { + dfa2 = (DFA)p2; + } + if(p2.type == Importable.Type.REGEX) + { + StatusPanel.Instance().setStatus("Converting REGEX to DFA", 50); + RegExp regex2 = (RegExp) p2; + NDFA ndfa2 = ThompsonConverter.convert(regex2); + dfa2 = ndfa2.toDFA().minimaliseerHopcroft(); + } + + StatusPanel.Instance().setStatus("Executing or operation", 65); + DFA of = dfa1.of(dfa2); + + StatusPanel.Instance().setStatus("Generating image", 80); + + File f = Graph.generateImage(of); + TabPanel.Instance().addGraph(name1 + " or " + name2, f, of); + + StatusPanel.Instance().setStatus("Done", 100); + + } + }); + } + }); + + JButton andButton = new JButton("and"); + andButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + + BackgroundWorker.instance().addWorker(new BackgroundWorker.Worker() { + @Override + public void execute() { + StatusPanel.Instance().setStatus("Parsing files", 10); + + String file1 = (String)f1Combo.getSelectedItem(); + String name1 = file1.replaceAll(".dot", ""); + String file2 = (String)f2Combo.getSelectedItem(); + String name2 = file2.replaceAll(".dot", ""); + + Importable p1 = FileParser.read(file1); + Importable p2 = FileParser.read(file1); + + DFA dfa1 = null; + + if(p1.type == Importable.Type.NDFA) + { + StatusPanel.Instance().setStatus("Converting NDFA to DFA", 30); + NDFA ndfa1 = (NDFA)p1; + dfa1 = ndfa1.toDFA().minimaliseerHopcroft(); + } + if(p1.type == Importable.Type.DFA) + { + dfa1 = (DFA)p1; + } + if(p1.type == Importable.Type.REGEX) + { + StatusPanel.Instance().setStatus("Converting REGEX to DFA", 30); + RegExp regex = (RegExp) p1; + NDFA ndfa1 = ThompsonConverter.convert(regex); + dfa1 = ndfa1.toDFA().minimaliseerHopcroft(); + } + + DFA dfa2 = null; + + if(p2.type == Importable.Type.NDFA) + { + StatusPanel.Instance().setStatus("Converting NDFA to DFA", 50); + NDFA ndfa2 = (NDFA)p2; + dfa2 = ndfa2.toDFA().minimaliseerHopcroft(); + } + if(p2.type == Importable.Type.DFA) + { + dfa2 = (DFA)p2; + } + if(p2.type == Importable.Type.REGEX) + { + StatusPanel.Instance().setStatus("Converting REGEX to DFA", 50); + RegExp regex2 = (RegExp) p2; + NDFA ndfa2 = ThompsonConverter.convert(regex2); + dfa2 = ndfa2.toDFA().minimaliseerHopcroft(); + } + + StatusPanel.Instance().setStatus("Executing and operation", 65); + DFA en = dfa1.en(dfa2); + + StatusPanel.Instance().setStatus("Generating image", 80); + + File f = Graph.generateImage(en); + TabPanel.Instance().addGraph(name1 + " and " + name2, f, en); + + StatusPanel.Instance().setStatus("Done", 100); + } + }); + } + }); + + JButton equalsButton = new JButton("equals"); + equalsButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + + BackgroundWorker.instance().addWorker(new BackgroundWorker.Worker() { + @Override + public void execute() { + StatusPanel.Instance().setStatus("Parsing files", 10); + + String file1 = (String)f1Combo.getSelectedItem(); + String name1 = file1.replaceAll(".dot", ""); + String file2 = (String)f2Combo.getSelectedItem(); + String name2 = file2.replaceAll(".dot", ""); + + Importable p1 = FileParser.read(file1); + Importable p2 = FileParser.read(file1); + + Automata aut = null; + + if(p1.type == Importable.Type.NDFA ) + { + aut = (NDFA)p1; + } + if(p1.type == Importable.Type.DFA) + { + aut = (DFA)p1; + } + if(p1.type == Importable.Type.REGEX) + { + StatusPanel.Instance().setStatus("Converting REGEX to NDFA", 30); + RegExp regex = (RegExp) p1; + aut = (NDFA)ThompsonConverter.convert(regex); + } + + Automata aut2 = null; + + if(p2.type == Importable.Type.NDFA) + { + aut2 = (NDFA)p2; + } + if(p2.type == Importable.Type.DFA) + { + aut2 = (DFA)p2; + } + if(p2.type == Importable.Type.REGEX) + { + StatusPanel.Instance().setStatus("Converting REGEX to NDFA", 50); + RegExp regex2 = (RegExp) p2; + aut2 = (NDFA)ThompsonConverter.convert(regex2); + } + + StatusPanel.Instance().setStatus("Executing equals operation", 80); + + boolean equals = aut.equals(aut2); + + new TextPanel(name1 + " equals " + name2, (equals?"They are equal":"They are not equal")); + + StatusPanel.Instance().setStatus("Done", 100); + } + }); + } + }); + + advPanel.add(f1Combo); + advPanel.add(Box.createRigidArea(new Dimension(10, 0))); + + advPanel.add(equalsButton); + advPanel.add(Box.createRigidArea(new Dimension(10, 0))); + advPanel.add(andButton); + advPanel.add(Box.createRigidArea(new Dimension(10, 0))); + advPanel.add(orButton); + advPanel.add(Box.createRigidArea(new Dimension(10, 0))); + + advPanel.add(f2Combo); + advPanel.add(Box.createRigidArea(new Dimension(10, 0))); + + this.add(advPanel); + } + + private String[] findFiles() + { + File folder = new File("input"); + File[] listOfFiles = folder.listFiles(); + + ArrayList fileNames = new ArrayList(); + + for (int i = 0; i < listOfFiles.length; i++) { + if (listOfFiles[i].isFile() && listOfFiles[i].getName().endsWith(".dot")) { + fileNames.add(listOfFiles[i].getName()); + } + } + + String[] files = new String[fileNames.size()]; + files = fileNames.toArray(files); + + return files; + } +} diff --git a/src/com/imegumii/ui/PopupFrame.java b/src/com/imegumii/ui/PopupFrame.java new file mode 100644 index 0000000..f6a03ce --- /dev/null +++ b/src/com/imegumii/ui/PopupFrame.java @@ -0,0 +1,169 @@ +package com.imegumii.ui; + +import com.imegumii.*; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.text.BadLocationException; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.util.SortedSet; +import java.util.TreeSet; + +/** + * Created by kenny on 12-6-2017. + */ +public class PopupFrame extends JFrame { + + boolean selected = false; + + public PopupFrame(String name, Importable r) + { + super(name); + + this.setSize(600, 600); + //this.setResizable(false); + this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + + DFA tempDfa = null; + + if (r.type == Importable.Type.DFA) { + tempDfa = ((DFA) r).minimaliseer(); + } else if (r.type == Importable.Type.REGEX) { + tempDfa = ThompsonConverter.convert((RegExp) r).toDFA().minimaliseer(); + } else if (r.type == Importable.Type.NDFA) { + tempDfa = ((NDFA) r).toDFA().minimaliseer(); + } + + JPanel container = new JPanel(new BorderLayout()); + + JPanel topPanel = new JPanel(); + topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS)); + topPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + + JPanel acceptPanel = new JPanel(); + acceptPanel.setLayout(new BoxLayout(acceptPanel, BoxLayout.LINE_AXIS)); + acceptPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + + JPanel generatePanel = new JPanel(); + generatePanel.setLayout(new BoxLayout(generatePanel, BoxLayout.LINE_AXIS)); + generatePanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + + JPanel textPanel = new JPanel(); + textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.Y_AXIS)); + textPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + + JTextArea textArea = new JTextArea(); + JScrollPane scrollPane = new JScrollPane(textArea); + + JTextArea acceptArea = new JTextArea(); + JScrollPane acceptScrollPane = new JScrollPane(acceptArea); + + JTextField operaties = new JTextField(); + JTextField lengte = new JTextField(); + + JButton generateButton = new JButton("Generate language"); +// JButton cancelButton = new JButton("Cancel operation"); + JCheckBox checkBox = new JCheckBox("Negate"); + + JTextField acceptString = new JTextField(); + + JButton acceptButton = new JButton("Accept string"); + DFA minimizedDfa = tempDfa; + generateButton.addActionListener(e -> { + textArea.setText(""); // reset + BackgroundWorker.instance().addWorker(() -> { + long currentTime = System.currentTimeMillis(); +// Taal t = r.getTaal(Integer.parseInt(operaties.getText()), Integer.parseInt(lengte.getText())); + SortedSet symbols = minimizedDfa.geefTaalTotLengte(Integer.parseInt(lengte.getText())).getSymbols(); + SortedSet actuallyContains = new TreeSet<>(); + if (selected) { + for (String symbol : symbols) { + if (!minimizedDfa.accepteer(symbol)) { + actuallyContains.add(symbol); + } + } + textArea.append("The language does not contain " + actuallyContains.size() + " strings out of a max of " + symbols.size() + "\n"); + } else { + for (String symbol : symbols) { + if (minimizedDfa.accepteer(symbol)) { + actuallyContains.add(symbol); + } + } + textArea.append("The language contains " + actuallyContains.size() + " strings out of a max of " + symbols.size() + "\n"); + } + textArea.append("It took " + (System.currentTimeMillis() - currentTime) + " milliseconds to generate and filter them\n"); + actuallyContains.forEach(s -> textArea.append("String: " + s + "\n")); + }); + }); + + checkBox.addItemListener(e -> { + if (e.getStateChange() == ItemEvent.DESELECTED) { + selected = false; + } else { + selected = true; + } + }); + +// cancelButton.addActionListener(e -> { +// BackgroundWorker.instance().cancel(); +// }); + + acceptButton.addActionListener(e -> { + BackgroundWorker.instance().addWorker(() -> { + try { + acceptArea.getDocument().insertString(0, "Does the regex accept " + acceptString.getText() + " ? " + (minimizedDfa.accepteer(acceptString.getText()) ? "yes" : "no") + "\n", null); + } catch (BadLocationException e1) { + e1.printStackTrace(); + } + }); + }); + + operaties.setText("4"); + lengte.setText("5"); + + textPanel.add(scrollPane); + textPanel.add(acceptScrollPane); + container.add(textPanel, BorderLayout.CENTER); + + generatePanel.add(generateButton); + generatePanel.add(Box.createRigidArea(new Dimension(10,0))); + + generatePanel.add(checkBox); + generatePanel.add(Box.createRigidArea(new Dimension(10,0))); + +// generatePanel.add(cancelButton); +// generatePanel.add(Box.createRigidArea(new Dimension(10,0))); + + generatePanel.add(new JLabel("Max operations")); + generatePanel.add(Box.createRigidArea(new Dimension(10,0))); + + generatePanel.add(operaties); + generatePanel.add(Box.createRigidArea(new Dimension(10,0))); + + generatePanel.add(new JLabel("Max length")); + generatePanel.add(Box.createRigidArea(new Dimension(10,0))); + + generatePanel.add(lengte); + + acceptPanel.add(acceptButton); + acceptPanel.add(Box.createRigidArea(new Dimension(10,0))); + + acceptPanel.add(new JLabel("Input a string")); + acceptPanel.add(Box.createRigidArea(new Dimension(10,0))); + + acceptPanel.add(acceptString); + acceptPanel.add(Box.createRigidArea(new Dimension(10,0))); + + topPanel.add(generatePanel); + topPanel.add(acceptPanel); + + container.add(topPanel, BorderLayout.NORTH); + + this.setContentPane(container); + + this.setVisible(true); + } +} diff --git a/src/com/imegumii/ui/StatusPanel.java b/src/com/imegumii/ui/StatusPanel.java new file mode 100644 index 0000000..bcb4ae2 --- /dev/null +++ b/src/com/imegumii/ui/StatusPanel.java @@ -0,0 +1,61 @@ +package com.imegumii.ui; + +import javax.swing.*; +import java.awt.*; + +import java.util.Date; +import java.util.Timer; +import java.util.TimerTask; + +/** + * Created by kenny on 9-6-2017. + */ +public class StatusPanel extends JPanel { + + private static StatusPanel panel; + + private JLabel status; + private JProgressBar progress; + + public static StatusPanel Instance() + { + if(panel == null) + panel = new StatusPanel(); + + return panel; + } + + public StatusPanel() + { + super(); + this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); + this.setBackground(Color.LIGHT_GRAY); + this.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + + progress = new JProgressBar(); + progress.setValue(0); + progress.setPreferredSize(new Dimension(250, 0)); + + status = new JLabel("Application ready"); + + this.add(progress); + this.add(Box.createHorizontalGlue()); + this.add(status); + } + + public void setStatus(String text, int progress) + { + this.progress.setValue(progress); + this.status.setText(text); + } + + public void setStatus(int progress) + { + this.progress.setValue(progress); + } + + public void setStatus(String text) + { + this.status.setText(text); + } +} diff --git a/src/com/imegumii/ui/TabPanel.java b/src/com/imegumii/ui/TabPanel.java new file mode 100644 index 0000000..21609dc --- /dev/null +++ b/src/com/imegumii/ui/TabPanel.java @@ -0,0 +1,42 @@ +package com.imegumii.ui; + +import com.imegumii.Automata; + +import javax.swing.*; +import java.awt.*; +import java.io.*; + +/** + * Created by kenny on 9-6-2017. + */ +public class TabPanel extends JTabbedPane { + + private static TabPanel panel; + + public static TabPanel Instance() + { + if(panel == null) + panel = new TabPanel(); + + return panel; + } + + private TabPanel() + { + super(); + } + + public void addGraph(String name, File image, Automata a) + { + String n = a.type.toString() + ": " + name; + + this.addTab(n, new GraphPanel(name, image, a)); + this.setSelectedIndex(this.getTabCount() - 1); + } + + public void removeGraph(GraphPanel component) + { + this.remove(component); + } + +} diff --git a/src/com/imegumii/ui/TextPanel.java b/src/com/imegumii/ui/TextPanel.java new file mode 100644 index 0000000..057573c --- /dev/null +++ b/src/com/imegumii/ui/TextPanel.java @@ -0,0 +1,24 @@ +package com.imegumii.ui; + +import javax.swing.*; + +/** + * Created by imegumii on 13/06/2017. + */ +public class TextPanel extends JFrame { + public TextPanel (String name, String text) { + super(name); + this.setSize(600, 600); + //this.setResizable(false); + this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + + JTextArea textArea = new JTextArea(); + JScrollPane scrollPane = new JScrollPane(textArea); + + textArea.append(text); + + this.setContentPane(scrollPane); + + this.setVisible(true); + } +}