Commit 8006c97e authored by EdwinMindcraft's avatar EdwinMindcraft
Browse files

Rudimentary Regular Language support.

parent 5e3e3465
......@@ -20,6 +20,7 @@ If no input is specified, the program will try to read from `stdin`.
* ```complete``` Completes the given automaton by adding a "trash" state.
* ```minimize``` Minimizes the given automaton (This task runs ```complete``` first).
* ```cleanup``` Removes unreachable states.
* ```language``` Extracts a regular language from the given automaton.
### Options
* ```-g``` Outputs a string in the [dot](https://graphviz.org/doc/info/lang.html) format to be used with GraphViz
......
......@@ -29,7 +29,7 @@ public class Main {
}
}
if (ls.size() < 1) {
System.err.println("Usage: [-g] [-o output] <minimize|determine|complete|cleanup|pass> [file]");
System.err.println("Usage: [-g] [-o output] <minimize|determine|complete|cleanup|language|pass> [file]");
return;
}
String str = ls.size() >= 2 ? Files.asCharSource(new File(ls.get(1)), StandardCharsets.UTF_8).read() : CharStreams.toString(new InputStreamReader(System.in));
......@@ -48,6 +48,11 @@ public class Main {
case "cleanup":
automaton = automaton.removeUnreachableStates();
break;
case "language":
try (OutputStreamWriter writer = new OutputStreamWriter(stream, StandardCharsets.UTF_8)) {
writer.write(automaton.buildLanguage().getExpression());
}
return;
case "pass":
break;
default:
......
package org.insa.determination.struct;
import it.unimi.dsi.fastutil.chars.Char2ObjectMap;
import it.unimi.dsi.fastutil.chars.Char2ObjectMaps;
import it.unimi.dsi.fastutil.chars.CharOpenHashSet;
import it.unimi.dsi.fastutil.chars.CharSet;
import it.unimi.dsi.fastutil.chars.*;
import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.objects.ObjectCharImmutablePair;
import it.unimi.dsi.fastutil.objects.ObjectCharPair;
......@@ -135,6 +132,30 @@ public class Automaton {
return builder.build();
}
public RegularLanguage buildLanguage() {
List<State> terminal = this.nodes.values().stream().filter(State::isTerminal).collect(Collectors.toList());
List<State> initial = this.nodes.values().stream().filter(State::isInitial).collect(Collectors.toList());
Optional<RegularLanguage> reduce = terminal.stream().flatMap(term -> initial.stream().map(init -> IntIntPair.of(init.getId(), term.getId()))).map(x -> this.build(x, new IntOpenHashSet(this.nodes.keySet()))).reduce(RegularLanguage::union);
return reduce.orElse(null);
}
private RegularLanguage build(IntIntPair pair, IntSet remainingKeys) {
int initial = pair.leftInt();
int terminal = pair.rightInt();
OptionalInt max = remainingKeys.stream().mapToInt(Integer::intValue).max();
if (max.isEmpty()) {
return new RegularLanguage(this.getTransitionMap().getOrDefault(IntIntPair.of(initial, terminal), CharSets.EMPTY_SET).toArray(new char[0]));
} else {
int m = max.getAsInt();
IntSet copied = new IntOpenHashSet(remainingKeys);
copied.remove(m);
return this.build(pair, copied)
.union(this.build(IntIntPair.of(initial, m), copied)
.concat(this.build(IntIntPair.of(m, m), copied).zeroOrMore())
.concat(this.build(IntIntPair.of(m, terminal), copied)));
}
}
public Automaton removeUnreachableStates() {
IntSet terminalPrecursor = new IntOpenHashSet();
IntSet reachable = new IntOpenHashSet();
......
package org.insa.determination.struct;
import it.unimi.dsi.fastutil.chars.CharArrayList;
import java.util.stream.Collectors;
public class RegularLanguage {
private final String expression;
public RegularLanguage(char... recognized) {
this.expression = recognized.length == 0 ? "\u03B5" : recognized.length == 1 ? String.valueOf(recognized[0]) : "{" + new CharArrayList(recognized).stream().map(String::valueOf).collect(Collectors.joining(",")) + "}";
}
private RegularLanguage(String exp) {
this.expression = exp;
}
public String getExpression() {
return this.expression;
}
public RegularLanguage zeroOrMore() {
return new RegularLanguage("(" + this.getExpression() + ")*");
}
public RegularLanguage union(RegularLanguage other) {
return new RegularLanguage("(" + this.getExpression() + ") \u222A (" + other.getExpression() + ")");
}
public RegularLanguage concat(RegularLanguage other) {
return new RegularLanguage(this.getExpression() + other.getExpression());
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment