diff --git a/ChatGPTParsing/.classpath b/ChatGPTParsing/.classpath
new file mode 100644
index 0000000000000000000000000000000000000000..f00af9b48a8a4f64caeafed618292ba48d9511fd
--- /dev/null
+++ b/ChatGPTParsing/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
+		<attributes>
+			<attribute name="module" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/ChatGPTParsing/.gitignore b/ChatGPTParsing/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..ae3c1726048cd06b9a143e0376ed46dd9b9a8d53
--- /dev/null
+++ b/ChatGPTParsing/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/ChatGPTParsing/.project b/ChatGPTParsing/.project
new file mode 100644
index 0000000000000000000000000000000000000000..e4c374832de488d97e54889dc81cecc33269c5ec
--- /dev/null
+++ b/ChatGPTParsing/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>ChatGPTParsing</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/ChatGPTParsing/src/auxiliary/ListofListContains.java b/ChatGPTParsing/src/auxiliary/ListofListContains.java
new file mode 100644
index 0000000000000000000000000000000000000000..35c0b89628716abb6ea5e50a1836b6657edbdc0a
--- /dev/null
+++ b/ChatGPTParsing/src/auxiliary/ListofListContains.java
@@ -0,0 +1,15 @@
+package auxiliary;
+
+import java.util.List;
+
+public class ListofListContains {
+
+	public static boolean contains(List<List<String>> container, List<String> contained) {
+		for (List<String> c : container) {
+			if (c.equals(contained)) {
+				return true;
+			}
+		}
+		return false;
+	}
+}
diff --git a/ChatGPTParsing/src/co_reachable/CoReachability.java b/ChatGPTParsing/src/co_reachable/CoReachability.java
new file mode 100644
index 0000000000000000000000000000000000000000..f92e69d3bf8d10b352450b249c088a0cafc06a68
--- /dev/null
+++ b/ChatGPTParsing/src/co_reachable/CoReachability.java
@@ -0,0 +1,43 @@
+package co_reachable;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+public class CoReachability {
+
+	public static Set<String> coReachableSet(Map<String, List<List<String>>> rules) {
+		Set<String> coReachable = new HashSet<>();
+		int n = coReachable.size();
+		int m = Integer.MAX_VALUE;
+		while (n != m) {
+			m = n;
+			for (Entry<String, List<List<String>>> v : rules.entrySet()) {
+				if (!coReachable.contains(v.getKey())) {
+					for (List<String> conclusio : v.getValue()) {
+						boolean notCoReachable = false;
+						for (String c : conclusio) {
+							if (rules.keySet().contains(c) && !coReachable.contains(c)) {
+								notCoReachable = true;
+								break;
+							}
+						}
+						if (!notCoReachable) {
+							coReachable.add(v.getKey());
+							break;
+						}
+					}
+				}
+			}
+			n = coReachable.size();
+		}
+		return coReachable;
+	}
+
+	public static boolean emptyLanguage(Map<String, List<List<String>>> rules, String start) {
+		return !coReachableSet(rules).contains(start);
+	}
+
+}
\ No newline at end of file
diff --git a/ChatGPTParsing/src/module-info.java b/ChatGPTParsing/src/module-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..a60ffe8317c17729297fabc80e50aea215d40eb5
--- /dev/null
+++ b/ChatGPTParsing/src/module-info.java
@@ -0,0 +1,2 @@
+module GrammarGenerator {
+}
\ No newline at end of file
diff --git a/ChatGPTParsing/src/reachable/Reachability.java b/ChatGPTParsing/src/reachable/Reachability.java
new file mode 100644
index 0000000000000000000000000000000000000000..1166ba5963a8ccd4685864d9aff2ddff7d2ae529
--- /dev/null
+++ b/ChatGPTParsing/src/reachable/Reachability.java
@@ -0,0 +1,36 @@
+package reachable;
+
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+
+public class Reachability {
+
+	public static Set<String> reachableSet(Map<String, List<List<String>>> rules, String start) {
+		Queue<String> reachableQueue = new LinkedList<>();
+		Set<String> reachable = new HashSet<>();
+		reachable.add(start);
+		reachableQueue.add(start);
+		reachableSet(rules, reachableQueue, reachable);
+		return reachable;
+	}
+
+	private static void reachableSet(Map<String, List<List<String>>> rules, Queue<String> reachableQueue,
+			Set<String> reachable) {
+		String premise = reachableQueue.poll();
+		if (premise != null) {
+			for (List<String> conclusio : rules.get(premise)) {
+				for (String c : conclusio) {
+					if (rules.keySet().contains(c) && !reachable.contains(c)) {
+						reachableQueue.add(c);
+					}
+					reachable.add(c);
+				}
+			}
+			reachableSet(rules, reachableQueue, reachable);
+		}
+	}
+}
diff --git a/ChatGPTParsing/src/type2/Type2GrammarGenerator.java b/ChatGPTParsing/src/type2/Type2GrammarGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..866c62583a6f21df9f23400e09960be5092cc233
--- /dev/null
+++ b/ChatGPTParsing/src/type2/Type2GrammarGenerator.java
@@ -0,0 +1,138 @@
+package type2;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+import auxiliary.ListofListContains;
+import co_reachable.CoReachability;
+import reachable.Reachability;
+
+public class Type2GrammarGenerator {
+
+	Random random = new Random();
+
+	private Map<String, List<List<String>>> genType2GrammarRuleSet(String[] vars, int alphaSize, int maxConclusios,
+			int maxConclusioSize) {
+		Map<String, List<List<String>>> rules = new HashMap<>();
+		for (String v : vars) {
+			List<List<String>> conclusios = genConclusios(alphaSize, vars, maxConclusios, maxConclusioSize);
+			rules.put(v, conclusios);
+		}
+		return rules;
+	}
+
+	private List<List<String>> genConclusios(int alphaSize, String[] vars, int maxConclusios, int maxConclusioSize) {
+		List<List<String>> conclusios = new LinkedList<>();
+		int numOfConclusios = random.nextInt(maxConclusios) + 1;
+		while (conclusios.size() < numOfConclusios) {
+			List<String> conclusio = genConclusio(alphaSize, vars, maxConclusioSize);
+			if (!ListofListContains.contains(conclusios, conclusio)) {
+				conclusios.add(conclusio);
+			}
+		}
+		return conclusios;
+	}
+
+	private List<String> genConclusio(int alphaSize, String[] vars, int maxConclusioSize) {
+		return (Math.random() <= 0.1) ? new LinkedList<>() : genRandomString(alphaSize, vars, maxConclusioSize);
+
+	}
+
+	private List<String> genRandomString(int alphaSize, String[] vars, int maxConclusioSize) {
+		List<String> s = new LinkedList<>();
+		int conclusioSize = random.nextInt(maxConclusioSize) + 1;
+		while (s.size() < conclusioSize) {
+			int i = random.nextInt(vars.length + alphaSize);
+			if (i < vars.length) {
+				if (i == 0) {
+					i = 83;
+				} else if (i > 0 && i <= 18) {
+					i += 64;
+				} else {
+					i += 65;
+				}
+			} else {
+				i += 97 - vars.length;
+			}
+			char c = (char) i;
+			s.add(c + "");
+		}
+		return s;
+	}
+
+	public List<Map<String, List<List<String>>>> genType2GrammarRuleSets(String[] vars, int alphaSize,
+			int maxConclusios, int maxConclusioSize, int n) {
+		List<Map<String, List<List<String>>>> grammarRuleSets = new LinkedList<>();
+		while (grammarRuleSets.size() < n) {
+			grammarRuleSets.add(genType2GrammarRuleSet(vars, alphaSize, maxConclusios, maxConclusioSize));
+		}
+		return grammarRuleSets;
+	}
+
+	public List<Map<String, List<List<String>>>> genType2GrammarRuleSets1(String[] vars, int alphaSize,
+			int maxConclusios, int maxConclusioSize, String s, int n) {
+		List<Map<String, List<List<String>>>> grammarRuleSets = new LinkedList<>();
+		while (grammarRuleSets.size() < n) {
+			Map<String, List<List<String>>> rules = genType2GrammarRuleSet(vars, alphaSize, maxConclusios,
+					maxConclusioSize);
+			if (!CoReachability.emptyLanguage(rules, s)) {
+				grammarRuleSets.add(rules);
+			}
+		}
+		return grammarRuleSets;
+	}
+
+	public List<Map<String, List<List<String>>>> genType2GrammarRuleSets2(String[] vars, int alphaSize,
+			int maxConclusios, int maxConclusioSize, int n) {
+		List<Map<String, List<List<String>>>> grammarRuleSets = new LinkedList<>();
+		while (grammarRuleSets.size() < n) {
+			Map<String, List<List<String>>> rules = genType2GrammarRuleSet(vars, alphaSize, maxConclusios,
+					maxConclusioSize);
+			if (CoReachability.coReachableSet(rules).containsAll(rules.keySet())) {
+				grammarRuleSets.add(rules);
+			}
+		}
+		return grammarRuleSets;
+	}
+
+	public List<Map<String, List<List<String>>>> genType2GrammarRuleSets3(String[] vars, int alphaSize,
+			int maxConclusios, int maxConclusioSize, String s, int n) {
+		List<Map<String, List<List<String>>>> grammarRuleSets = new LinkedList<>();
+		Set<String> varSet = new HashSet<>();
+		Set<String> alphaSet = new HashSet<>();
+		for (String v : vars) {
+			varSet.add(v);
+		}
+		for (int i = 0; i < alphaSize; i++) {
+			alphaSet.add(((char) (i + 97)) + "");
+		}
+		while (grammarRuleSets.size() < n) {
+			Map<String, List<List<String>>> rules = genType2GrammarRuleSet(vars, alphaSize, maxConclusios,
+					maxConclusioSize);
+			boolean allCoReachable = CoReachability.coReachableSet(rules).containsAll(rules.keySet());
+			boolean allReachable = Reachability.reachableSet(rules, s).containsAll(rules.keySet())
+					&& Reachability.reachableSet(rules, s).containsAll(alphaSet);
+			if (allCoReachable && allReachable) {
+				grammarRuleSets.add(rules);
+			}
+		}
+		return grammarRuleSets;
+	}
+
+	public static void main(String[] args) {
+		Map<String, List<List<String>>> ruleSet = new HashMap<>();
+		List<List<String>> l1 = List.of(List.of("A", "S"));
+		ruleSet.put("S", l1);
+		List<List<String>> l2 = List.of(List.of("a"), List.of("b", "A"));
+		ruleSet.put("A", l2);
+		System.out.println(ruleSet);
+		Set<String> crs = CoReachability.coReachableSet(ruleSet);
+		System.out.println(crs);
+	}
+
+}
diff --git a/ChatGPTParsing/src/type2/Type2Parser.java b/ChatGPTParsing/src/type2/Type2Parser.java
new file mode 100644
index 0000000000000000000000000000000000000000..848f92c1cd6668574ae761313671c187d45cc35a
--- /dev/null
+++ b/ChatGPTParsing/src/type2/Type2Parser.java
@@ -0,0 +1,439 @@
+package type2;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import auxiliary.ListofListContains;
+import co_reachable.CoReachability;
+import reachable.Reachability;
+
+public class Type2Parser {
+
+	private static Map<String, List<List<String>>> createCNF(Map<String, List<List<String>>> rules, String start) {
+		Set<String> nullable = nullableSet(rules);
+		Map<String, List<List<String>>> newRules0 = new HashMap<>(rules);
+		if (nullable.contains(start)) {
+			List<List<String>> newStartRule = new LinkedList<>();
+			List<String> c0 = new LinkedList<>();
+			c0.add(start);
+			newStartRule.add(c0);
+			newStartRule.add(new LinkedList<>());
+			newRules0.put("S'", newStartRule);
+		}
+		Map<String, List<List<String>>> newRules1 = removeUselessSymbols(newRules0,
+				newRules0.keySet().contains("S'") ? "S'" : start);
+		List<List<String>> startRule = newRules1.remove("S'");
+		Map<String, List<List<String>>> newRules2 = removeEpsilonRules(newRules1, nullable);
+		if (startRule != null) {
+			newRules2.put("S'", startRule);
+		}
+		Map<String, List<List<String>>> newRules3 = normalize(newRules2);
+		Map<String, List<List<String>>> newRules4 = removeChainRules(newRules3);
+		Map<String, List<List<String>>> newRules5 = removeUselessSymbols(newRules4,
+				newRules4.keySet().contains("S'") ? "S'" : start);
+		return shortenConclusios(newRules5);
+	}
+
+	private static Set<String> nullableSet(Map<String, List<List<String>>> rules) {
+		Set<String> nullable = new HashSet<>();
+		int n = nullable.size();
+		int m = Integer.MAX_VALUE;
+		while (n != m) {
+			m = n;
+			for (Entry<String, List<List<String>>> rule : rules.entrySet()) {
+				if (!nullable.contains(rule.getKey())) {
+					for (List<String> conclusio : rule.getValue()) {
+						boolean notNullable = false;
+						for (String c : conclusio) {
+							if (!nullable.contains(c)) {
+								notNullable = true;
+								break;
+							}
+						}
+						if (!notNullable) {
+							nullable.add(rule.getKey());
+							break;
+						}
+					}
+				}
+			}
+			n = nullable.size();
+		}
+		return nullable;
+	}
+
+	private static Map<String, List<List<String>>> removeUselessSymbols(Map<String, List<List<String>>> rules,
+			String start) {
+		Map<String, List<List<String>>> rules1 = removeNonCoReachableVariables(rules, start);
+		if (rules1.isEmpty()) {
+			return rules1;
+		}
+		return removeNonReachableSymbols(rules1, start);
+	}
+
+	private static Map<String, List<List<String>>> removeNonCoReachableVariables(Map<String, List<List<String>>> rules,
+			String start) {
+		Set<String> coReachable = CoReachability.coReachableSet(rules);
+		if (!coReachable.contains(start)) {
+			return new HashMap<>();
+		}
+		Map<String, List<List<String>>> newRules = new HashMap<>();
+		for (Entry<String, List<List<String>>> rule : rules.entrySet()) {
+			if (coReachable.contains(rule.getKey())) {
+				List<List<String>> newConclusios = new LinkedList<>();
+				for (List<String> conclusio : rule.getValue()) {
+					boolean containsNonCoReachable = false;
+					for (String c : conclusio) {
+						if (rules.keySet().contains(c) && !coReachable.contains(c)) {
+							containsNonCoReachable = true;
+							break;
+						}
+					}
+					if (!containsNonCoReachable) {
+						newConclusios.add(conclusio);
+					}
+				}
+				newRules.put(rule.getKey(), newConclusios);
+			}
+		}
+		return newRules;
+	}
+
+	private static Map<String, List<List<String>>> removeNonReachableSymbols(Map<String, List<List<String>>> rules,
+			String start) {
+		Set<String> reachable = Reachability.reachableSet(rules, start);
+		Map<String, List<List<String>>> newRules = new HashMap<>();
+		for (Entry<String, List<List<String>>> rule : rules.entrySet()) {
+			if (reachable.contains(rule.getKey())) {
+				List<List<String>> newConclusios = new LinkedList<>();
+				for (List<String> conclusio : rule.getValue()) {
+					boolean containsNonReachable = false;
+					for (String c : conclusio) {
+						if (rules.keySet().contains(c) && !reachable.contains(c)) {
+							containsNonReachable = true;
+							break;
+						}
+					}
+					if (!containsNonReachable) {
+						newConclusios.add(conclusio);
+					}
+				}
+				newRules.put(rule.getKey(), newConclusios);
+			}
+		}
+		return newRules;
+	}
+
+	private static Map<String, List<List<String>>> removeEpsilonRules(Map<String, List<List<String>>> rules,
+			Set<String> nullable) {
+		Map<String, List<List<String>>> newRules = new HashMap<>();
+		for (Entry<String, List<List<String>>> rule : rules.entrySet()) {
+			List<List<String>> newConclusios = new LinkedList<>();
+			for (List<String> oldConclusio : rule.getValue()) {
+				List<List<String>> newCons = removeNullable(oldConclusio, nullable);
+				for (List<String> newCon : newCons) {
+					if ((!newCon.isEmpty() && !ListofListContains.contains(newConclusios, newCon))) {
+						newConclusios.add(newCon);
+					}
+				}
+
+			}
+			newRules.put(rule.getKey(), newConclusios);
+		}
+		return newRules;
+	}
+
+	private static List<List<String>> removeNullable(List<String> r, Set<String> nullable) {
+		List<String> lNull = new LinkedList<>();
+		List<Integer> posNull = new LinkedList<>();
+		Map<Integer, String> posNonNull = new HashMap<>();
+		for (int i = 0; i < r.size(); i++) {
+			if (nullable.contains(r.get(i))) {
+				lNull.add(r.get(i));
+				posNull.add(i);
+			} else {
+				posNonNull.put(i, r.get(i));
+			}
+		}
+		List<List<Integer>> ps = powerset(lNull.size() - 1);
+		List<Map<Integer, String>> newCons = new LinkedList<>();
+		for (List<Integer> s : ps) {
+			Map<Integer, String> newCon = new HashMap<>();
+			for (int i : s) {
+				newCon.put(posNull.get(i), lNull.get(i));
+			}
+			newCons.add(newCon);
+		}
+		List<List<String>> newConsAdded = new LinkedList<>();
+		for (Map<Integer, String> newCon : newCons) {
+			List<String> newConAdded = new LinkedList<>();
+			for (int i = 0; i < r.size(); i++) {
+				String s0 = newCon.get(i);
+				String s1 = posNonNull.get(i);
+				if (s0 != null) {
+					newConAdded.add(s0);
+				} else if (s1 != null) {
+					newConAdded.add(s1);
+				}
+			}
+			newConsAdded.add(newConAdded);
+		}
+		return newConsAdded;
+	}
+
+	private static List<List<Integer>> powerset(int n) {
+		List<List<Integer>> ps = new ArrayList<>();
+		if (n < 0) {
+			ps.add(new ArrayList<>());
+		} else {
+			for (List<Integer> s : powerset(n - 1)) {
+				ps.add(s);
+				List<Integer> s1 = new ArrayList<>(s);
+				s1.add(n);
+				ps.add(s1);
+			}
+		}
+		return ps;
+	}
+
+	private static Map<String, List<List<String>>> normalize(Map<String, List<List<String>>> rules) {
+		Map<String, List<List<String>>> newRules = new HashMap<>();
+		Map<String, String> vars = new HashMap<>();
+		for (Entry<String, List<List<String>>> rule : rules.entrySet()) {
+			List<List<String>> newConclusios = new LinkedList<>();
+			for (List<String> conclusio : rule.getValue()) {
+				if (conclusio.size() > 1) {
+					List<String> newConclusio = new LinkedList<>();
+					for (int i = 0; i < conclusio.size(); i++) {
+						String s = conclusio.get(i);
+						if (!rules.keySet().contains(s)) {
+							vars.computeIfAbsent(s, k -> "V" + k);
+							newConclusio.add(vars.get(s));
+						} else {
+							newConclusio.add(s);
+						}
+					}
+					newConclusios.add(newConclusio);
+				} else {
+					newConclusios.add(conclusio);
+				}
+			}
+			newRules.put(rule.getKey(), newConclusios);
+		}
+		for (Entry<String, String> entry : vars.entrySet()) {
+			List<List<String>> ll = new LinkedList<>();
+			List<String> l = new LinkedList<>();
+			l.add(entry.getKey());
+			ll.add(l);
+			newRules.put(entry.getValue(), ll);
+		}
+		return newRules;
+	}
+
+	private static Map<String, List<List<String>>> removeChainRules(Map<String, List<List<String>>> rules) {
+		Map<String, List<List<String>>> newRules = new HashMap<>();
+		Map<String, Set<String>> chainProdMap = findChainProductions(rules);
+		Map<String, List<List<String>>> chainRulesDeleted = deleteChainRules(rules);
+		for (String premise : rules.keySet()) {
+			List<List<String>> newConclusios = new LinkedList<>();
+			for (String s : chainProdMap.get(premise)) {
+				for (List<String> newConclusio : chainRulesDeleted.get(s)) {
+					if (!ListofListContains.contains(newConclusios, newConclusio)) {
+						newConclusios.add(newConclusio);
+					}
+				}
+
+			}
+			newRules.put(premise, newConclusios);
+		}
+		return newRules;
+	}
+
+	private static Map<String, List<List<String>>> deleteChainRules(Map<String, List<List<String>>> rules) {
+		Map<String, List<List<String>>> newRules = new HashMap<>();
+		for (Entry<String, List<List<String>>> rule : rules.entrySet()) {
+			List<List<String>> newConclusios = new LinkedList<>();
+			for (List<String> conclusio : rule.getValue()) {
+				if (conclusio.size() == 1 && rules.keySet().contains(conclusio.get(0))) {
+					continue;
+				}
+				newConclusios.add(conclusio);
+			}
+			newRules.put(rule.getKey(), newConclusios);
+		}
+		return newRules;
+	}
+
+	private static Map<String, Set<String>> findChainProductions(Map<String, List<List<String>>> rules) {
+		Map<String, Set<String>> chainProdMap = new HashMap<>();
+		for (Entry<String, List<List<String>>> rule : rules.entrySet()) {
+			Set<String> chainProds = new HashSet<>();
+			chainProds.add(rule.getKey());
+			findChainProductions(rules, rule.getKey(), chainProds);
+			chainProdMap.put(rule.getKey(), chainProds);
+		}
+		return chainProdMap;
+	}
+
+	private static void findChainProductions(Map<String, List<List<String>>> rules, String key,
+			Set<String> chainProds) {
+		for (List<String> conclusio : rules.get(key)) {
+			if (conclusio.size() == 1 && rules.keySet().contains(conclusio.get(0))
+					&& !chainProds.contains(conclusio.get(0))) {
+				chainProds.add(conclusio.get(0));
+				findChainProductions(rules, conclusio.get(0), chainProds);
+			}
+		}
+	}
+
+	private static Map<String, List<List<String>>> shortenConclusios(Map<String, List<List<String>>> rules) {
+		Map<String, List<List<String>>> newRules = new HashMap<>();
+		Map<String, List<List<String>>> addNewRules = new HashMap<>();
+		int i = 0;
+		for (Entry<String, List<List<String>>> rule : rules.entrySet()) {
+			List<List<String>> newConclusios = new LinkedList<>();
+			for (List<String> conclusio : rule.getValue()) {
+				if (conclusio.size() > 2) {
+					List<String> c0 = new LinkedList<>();
+					c0.add(conclusio.get(0));
+					c0.add("@" + i);
+					newConclusios.add(c0);
+					int k = conclusio.size() - 2;
+					for (int j = 1; j < k; j++) {
+						List<List<String>> csj = new LinkedList<>();
+						List<String> cj = new LinkedList<>();
+						cj.add(conclusio.get(j));
+						cj.add("@" + (i + 1));
+						csj.add(cj);
+						addNewRules.put("@" + i++, csj);
+					}
+					List<List<String>> csn = new LinkedList<>();
+					List<String> cn = new LinkedList<>();
+					cn.add(conclusio.get(k));
+					cn.add(conclusio.get(k + 1));
+					csn.add(cn);
+					addNewRules.put("@" + i++, csn);
+				} else {
+					newConclusios.add(conclusio);
+				}
+			}
+			newRules.put(rule.getKey(), newConclusios);
+		}
+		newRules.putAll(addNewRules);
+		return newRules;
+	}
+
+	private static boolean cyk(Map<String, List<List<String>>> rules, String word, String start) {
+		int n = word.length();
+		String[][][] table = new String[n][n][rules.keySet().size()];
+		Map<String, Integer> indexMap = indexMap(rules.keySet());
+		for (int i = 0; i < n; i++) {
+			Set<String> producesTerminal = producesTerminal(rules, word.charAt(i) + "");
+			for (String premise : producesTerminal) {
+				table[i][i][indexMap.get(premise)] = premise;
+			}
+		}
+		for (int j = 1; j < n; j++) {
+			for (int i = 0; i < n - j; i++) {
+				Set<String> s = new HashSet<>();
+				for (int k = i; k < i + j; k++) {
+					Set<String> s0 = producesVariable(table[i][k], table[k + 1][i + j], rules);
+					s.addAll(s0);
+				}
+				for (String v : s) {
+					table[i][i + j][indexMap.get(v)] = v;
+				}
+			}
+		}
+		return table[0][n - 1][indexMap.get(start)] != null;
+	}
+
+	private static Set<String> producesTerminal(Map<String, List<List<String>>> rules, String charAt) {
+		Set<String> pt = new HashSet<>();
+		for (Entry<String, List<List<String>>> rule : rules.entrySet()) {
+			for (List<String> conclusio : rule.getValue()) {
+				if (conclusio.size() == 1 && conclusio.get(0).equals(charAt)) {
+					pt.add(rule.getKey());
+				}
+			}
+		}
+		return pt;
+	}
+
+	private static Set<String> producesVariable(String[] v1, String[] v2, Map<String, List<List<String>>> rules) {
+		Set<String> pv = new HashSet<>();
+		for (String s1 : v1) {
+			if (s1 != null) {
+				for (String s2 : v2) {
+					if (s2 != null) {
+						pv.addAll(producesVariable(rules, s1, s2));
+					}
+				}
+			}
+
+		}
+		return pv;
+	}
+
+	private static Set<String> producesVariable(Map<String, List<List<String>>> rules, String v1, String v2) {
+		Set<String> pv = new HashSet<>();
+		List<String> varPair = new LinkedList<>();
+		varPair.add(v1);
+		varPair.add(v2);
+		for (Entry<String, List<List<String>>> rule : rules.entrySet()) {
+			for (List<String> conclusio : rule.getValue()) {
+				if (conclusio.equals(varPair)) {
+					pv.add(rule.getKey());
+				}
+			}
+		}
+		return pv;
+	}
+
+	private static Map<String, Integer> indexMap(Set<String> vars) {
+		Map<String, Integer> indexMap = new HashMap<>();
+		int i = 0;
+		for (String v : vars) {
+			indexMap.put(v, i);
+			i++;
+		}
+		return indexMap;
+	}
+
+	public static boolean isPartOfLanguage(Map<String, List<List<String>>> rules, String word, String start) {
+		Map<String, List<List<String>>> cnf = createCNF(rules, start);
+		if (word.isEmpty()) {
+			return ListofListContains.contains(cnf.get("S'"), new LinkedList<>());
+		}
+		return cyk(cnf, word, cnf.keySet().contains("S'") ? "S'" : start);
+	}
+
+	public static void main(String[] args) {
+		Map<String, List<List<String>>> rules = new HashMap<>();
+		List<List<String>> s = List.of(List.of("a", "A", "b", "B"), List.of("a", "A", "c"), List.of("B", "C"),
+				List.of("B", "D", "a"));
+		rules.put("S", s);
+		List<List<String>> a = List.of(List.of("c", "A", "a"), List.of("b"), List.of("D", "c", "F"),
+				List.of("B", "C", "a"));
+		rules.put("A", a);
+		List<List<String>> b = List.of(List.of("C", "B"), List.of("A"), List.of("C"), List.of("a"), List.of());
+		rules.put("B", b);
+		List<List<String>> c = List.of(List.of("c", "c", "c"), List.of("A", "B", "C"), List.of("B", "C", "F"),
+				List.of());
+		rules.put("C", c);
+		List<List<String>> d = List.of(List.of("a", "D", "b"), List.of("A", "F", "c"));
+		rules.put("D", d);
+		List<List<String>> e = List.of(List.of("A", "a", "C"), List.of("C", "E", "b"), List.of("a", "b"), List.of());
+		rules.put("E", e);
+		List<List<String>> f = List.of(List.of("B", "D", "c"), List.of("a", "F"), List.of("B", "C", "D"));
+		rules.put("F", f);
+		System.out.println(isPartOfLanguage(rules, "", "S"));
+	}
+
+}
diff --git a/ChatGPTParsing/src/type3/FiniteStateMachine.java b/ChatGPTParsing/src/type3/FiniteStateMachine.java
new file mode 100644
index 0000000000000000000000000000000000000000..e9b162fb8ee314e4f56f123d3fc8822c036a7393
--- /dev/null
+++ b/ChatGPTParsing/src/type3/FiniteStateMachine.java
@@ -0,0 +1,32 @@
+package type3;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class FiniteStateMachine {
+
+	private Set<State> current;
+
+	public FiniteStateMachine(State initial) {
+		this.current = Set.of(initial);
+	}
+
+	public FiniteStateMachine(Set<State> current) {
+		this.current = current;
+	}
+
+	public FiniteStateMachine switchStates(String c) {
+		return new FiniteStateMachine(
+				this.current.stream().map(s -> s.transit(c)).flatMap(Set::stream).collect(Collectors.toSet()));
+	}
+
+	public boolean canStop() {
+		return this.current.stream().anyMatch(State::isFinal);
+	}
+
+	@Override
+	public String toString() {
+		return this.current.toString();
+	}
+
+}
diff --git a/ChatGPTParsing/src/type3/State.java b/ChatGPTParsing/src/type3/State.java
new file mode 100644
index 0000000000000000000000000000000000000000..6b9b17f4ab7e23363e76d433d1a1cc2225376d7e
--- /dev/null
+++ b/ChatGPTParsing/src/type3/State.java
@@ -0,0 +1,42 @@
+package type3;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class State {
+
+	private String name;
+	private List<Transition> transitions;
+	private boolean isFinal;
+
+	public State(String name) {
+		this(name, false);
+	}
+
+	public State(String name, boolean isFinal) {
+		this.name = name;
+		this.transitions = new ArrayList<>();
+		this.isFinal = isFinal;
+	}
+
+	public State with(Transition tr) {
+		this.transitions.add(tr);
+		return this;
+	}
+
+	public Set<State> transit(String c) {
+		return transitions.stream().filter(t -> t.isPossible(c)).map(Transition::state).collect(Collectors.toSet());
+	}
+
+	public boolean isFinal() {
+		return this.isFinal;
+	}
+
+	@Override
+	public String toString() {
+		return this.name;
+	}
+
+}
diff --git a/ChatGPTParsing/src/type3/Transition.java b/ChatGPTParsing/src/type3/Transition.java
new file mode 100644
index 0000000000000000000000000000000000000000..74f8f2a2780610f6ef64a7ba8ffafc341bb42d14
--- /dev/null
+++ b/ChatGPTParsing/src/type3/Transition.java
@@ -0,0 +1,21 @@
+package type3;
+
+public class Transition {
+
+	private String rule;
+	private State next;
+
+	public Transition(String rule, State next) {
+		this.rule = rule;
+		this.next = next;
+	}
+
+	public boolean isPossible(CharSequence c) {
+		return this.rule.equals(c.toString());
+	}
+
+	public State state() {
+		return this.next;
+	}
+
+}
diff --git a/ChatGPTParsing/src/type3/Type3GrammarGenerator.java b/ChatGPTParsing/src/type3/Type3GrammarGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..832627448c70d9f5ad4cbe5a27b930edde8cbd48
--- /dev/null
+++ b/ChatGPTParsing/src/type3/Type3GrammarGenerator.java
@@ -0,0 +1,116 @@
+package type3;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+import auxiliary.ListofListContains;
+import co_reachable.CoReachability;
+import reachable.Reachability;
+
+public class Type3GrammarGenerator {
+
+	Random random = new Random();
+
+	public Map<String, List<List<String>>> genType3GrammarRuleSet(String[] vars, int alphaSize, int maxConclusios,
+			String s) {
+		Map<String, List<List<String>>> rules = new HashMap<>();
+		List<List<String>> conclusios0 = genConclusios(alphaSize, vars, maxConclusios, true);
+		rules.put(s, conclusios0);
+		for (int i = 1; i < vars.length; i++) {
+			List<List<String>> conclusios1 = genConclusios(alphaSize, vars, maxConclusios, false);
+			rules.put(vars[i], conclusios1);
+		}
+		return rules;
+	}
+
+	private List<List<String>> genConclusios(int alphaSize, String[] vars, int maxConclusios, boolean start) {
+		List<List<String>> conclusios = new LinkedList<>();
+		if (start && Math.random() <= 0.5) {
+			conclusios.add(new LinkedList<>());
+		}
+		int numOfConclusios = random.nextInt(maxConclusios) + 1;
+		while (conclusios.size() < numOfConclusios || ListofListContains.contains(conclusios, new LinkedList<>())
+				&& conclusios.size() < numOfConclusios + 1) {
+			List<String> conclusio = genConclusio(alphaSize, vars);
+			if (!ListofListContains.contains(conclusios, conclusio)) {
+				conclusios.add(conclusio);
+			}
+		}
+		return conclusios;
+	}
+
+	private List<String> genConclusio(int alphaSize, String[] vars) {
+		List<String> c = new LinkedList<>();
+		String s = ((char) (random.nextInt(alphaSize) + 97)) + "";
+		c.add(s);
+		if (Math.random() < 0.7) {
+			c.add(vars[random.nextInt(vars.length)]);
+		}
+		return c;
+	}
+
+	public List<Map<String, List<List<String>>>> genType3GrammarRuleSets0(String[] vars, int alphaSize,
+			int maxConclusios, String s, int n) {
+		List<Map<String, List<List<String>>>> grammarRuleSets = new LinkedList<>();
+		while (grammarRuleSets.size() < n) {
+			Map<String, List<List<String>>> rules = genType3GrammarRuleSet(vars, alphaSize, maxConclusios, s);
+			grammarRuleSets.add(rules);
+		}
+		return grammarRuleSets;
+	}
+
+	public List<Map<String, List<List<String>>>> genType3GrammarRuleSets1(String[] vars, int alphaSize,
+			int maxConclusios, String s, int n) {
+		List<Map<String, List<List<String>>>> grammarRuleSets = new LinkedList<>();
+		while (grammarRuleSets.size() < n) {
+			Map<String, List<List<String>>> rules = genType3GrammarRuleSet(vars, alphaSize, maxConclusios, s);
+			if (!CoReachability.emptyLanguage(rules, s)) {
+				grammarRuleSets.add(rules);
+			}
+		}
+		return grammarRuleSets;
+	}
+
+	public List<Map<String, List<List<String>>>> genType3GrammarRuleSets2(String[] vars, int alphaSize,
+			int maxConclusios, String s, int n) {
+		List<Map<String, List<List<String>>>> grammarRuleSets = new LinkedList<>();
+		while (grammarRuleSets.size() < n) {
+			Map<String, List<List<String>>> rules = genType3GrammarRuleSet(vars, alphaSize, maxConclusios, s);
+			if (CoReachability.coReachableSet(rules).containsAll(rules.keySet())) {
+				grammarRuleSets.add(rules);
+			}
+		}
+		return grammarRuleSets;
+	}
+
+	public List<Map<String, List<List<String>>>> genType3GrammarRuleSets3(String[] vars, int alphaSize,
+			int maxConclusios, String s, int n) {
+		List<Map<String, List<List<String>>>> grammarRuleSets = new LinkedList<>();
+		Set<String> alphaSet = new HashSet<>();
+		for (int i = 0; i < alphaSize; i++) {
+			alphaSet.add(((char) (i + 97)) + "");
+		}
+		while (grammarRuleSets.size() < n) {
+			Map<String, List<List<String>>> rules = genType3GrammarRuleSet(vars, alphaSize, maxConclusios, s);
+			boolean allCoReachable = CoReachability.coReachableSet(rules).containsAll(rules.keySet());
+			boolean allReachable = Reachability.reachableSet(rules, s).containsAll(rules.keySet())
+					&& Reachability.reachableSet(rules, s).containsAll(alphaSet);
+			if (allCoReachable && allReachable) {
+				grammarRuleSets.add(rules);
+			}
+		}
+		return grammarRuleSets;
+	}
+
+	public static void main(String[] args) {
+		Type3GrammarGenerator gen = new Type3GrammarGenerator();
+		String[] vars = { "S", "A", "B", "C", "D" };
+		List<Map<String, List<List<String>>>> ruleSets = gen.genType3GrammarRuleSets3(vars, 4, 3, "S", 10);
+		System.out.println(ruleSets);
+	}
+}
diff --git a/ChatGPTParsing/src/type3/Type3Parser.java b/ChatGPTParsing/src/type3/Type3Parser.java
new file mode 100644
index 0000000000000000000000000000000000000000..8d5dc9bc6fff07d0d45cfff03a4e3adc72e0d455
--- /dev/null
+++ b/ChatGPTParsing/src/type3/Type3Parser.java
@@ -0,0 +1,64 @@
+package type3;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import auxiliary.ListofListContains;
+
+public class Type3Parser {
+
+	private static FiniteStateMachine grammarToFSM(Map<String, List<List<String>>> rules, String start) {
+		Map<String, State> states = new HashMap<>();
+		for (Entry<String, List<List<String>>> entry : rules.entrySet()) {
+			if (entry.getKey().equals(start) && ListofListContains.contains(entry.getValue(), new LinkedList<>())) {
+				states.put(start, new State(start, true));
+			} else {
+				states.put(entry.getKey(), new State(entry.getKey()));
+			}
+		}
+		String stop = "qStop";
+		states.put(stop, new State(stop, true));
+		for (Entry<String, List<List<String>>> entry : rules.entrySet()) {
+			for (List<String> c : entry.getValue()) {
+				if (c.equals(new LinkedList<>())) {
+					continue;
+				}
+				if (c.size() == 2) {
+					states.get(entry.getKey()).with(new Transition(c.get(0), states.get(c.get(1))));
+				} else {
+					states.get(entry.getKey()).with(new Transition(c.get(0), states.get(stop)));
+				}
+
+			}
+		}
+		return new FiniteStateMachine(states.get(start + ""));
+	}
+
+	public static boolean isPartOfLanguage(Map<String, List<List<String>>> rules, String word, String start) {
+		FiniteStateMachine fsm = grammarToFSM(rules, start);
+		for (char c : word.toCharArray()) {
+			fsm = fsm.switchStates(c + "");
+		}
+		return fsm.canStop();
+	}
+
+	public static void main(String[] args) {
+		Map<String, List<List<String>>> rules = new HashMap<>();
+		List<List<String>> s = List.of(List.of(), List.of("a", "A"), List.of("b", "B"), List.of("a", "C"),
+				List.of("a"));
+		rules.put("S", s);
+		List<List<String>> a = List.of(List.of("b", "Q"));
+		rules.put("A", a);
+		List<List<String>> q = List.of(List.of("b", "B"));
+		rules.put("Q", q);
+		List<List<String>> b = List.of(List.of("a", "A"), List.of("b"), List.of("a"));
+		rules.put("B", b);
+		List<List<String>> c = List.of(List.of("b", "B"), List.of("c", "C"));
+		rules.put("C", c);
+		System.out.println(isPartOfLanguage(rules, "", "S"));
+	}
+
+}