Added finite state machines.

This commit is contained in:
Andrew Lalis 2021-05-06 11:06:07 +02:00
parent 48a69e4bb3
commit 6d0ef8c6d2
4 changed files with 132 additions and 2 deletions

View File

@ -17,9 +17,8 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.18</version>
<version>1.18.20</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,63 @@
package nl.andrewlalis.grammar_tool.machine;
import nl.andrewlalis.grammar_tool.grammar.Symbol;
import java.util.Objects;
import java.util.Set;
public class FiniteStateMachine {
private final Set<Symbol> alphabet;
private final Set<State> states;
private final Set<State> finalStates;
private final State startState;
private final Set<Transition> transitions;
public FiniteStateMachine(Set<Symbol> alphabet, Set<State> states, Set<State> finalStates, State startState, Set<Transition> transitions) {
this.alphabet = alphabet;
this.states = states;
this.finalStates = finalStates;
this.startState = startState;
this.transitions = transitions;
this.ensureValidElements();
}
private void ensureValidElements() {
if (!this.states.contains(this.startState)) {
throw new IllegalArgumentException("Start state is not an element of the whole set of states.");
}
if (!this.states.containsAll(this.finalStates)) {
throw new IllegalArgumentException("Not all final states belong to the whole set of states.");
}
if (this.finalStates.isEmpty()) {
throw new IllegalArgumentException("No final states. There must be at least one final state.");
}
for (Transition t : this.transitions) {
if (!this.states.contains(t.getStartState())) {
throw new IllegalArgumentException("Start state of transition does not belong to the whole set of states: " + t);
}
if (!this.states.contains(t.getEndState())) {
throw new IllegalArgumentException("End state of transition does not belong to the whole set of states: " + t);
}
if (!this.alphabet.contains(t.getAcceptingSymbol())) {
throw new IllegalArgumentException("Accepting symbol of transition is not in the alphabet: " + t);
}
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FiniteStateMachine that = (FiniteStateMachine) o;
return alphabet.equals(that.alphabet) &&
states.equals(that.states) &&
finalStates.equals(that.finalStates) &&
startState.equals(that.startState) &&
transitions.equals(that.transitions);
}
@Override
public int hashCode() {
return Objects.hash(alphabet, states, finalStates, startState, transitions);
}
}

View File

@ -0,0 +1,29 @@
package nl.andrewlalis.grammar_tool.machine;
import java.util.Objects;
public class State {
private final String name;
public State(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
State state = (State) o;
return name.equals(state.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
@Override
public String toString() {
return this.name;
}
}

View File

@ -0,0 +1,39 @@
package nl.andrewlalis.grammar_tool.machine;
import lombok.Getter;
import nl.andrewlalis.grammar_tool.grammar.Symbol;
import java.util.Objects;
@Getter
public class Transition {
private final State startState;
private final Symbol acceptingSymbol;
private final State endState;
public Transition(State startState, Symbol acceptingSymbol, State endState) {
this.startState = startState;
this.acceptingSymbol = acceptingSymbol;
this.endState = endState;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Transition that = (Transition) o;
return startState.equals(that.startState) &&
acceptingSymbol.equals(that.acceptingSymbol) &&
endState.equals(that.endState);
}
@Override
public int hashCode() {
return Objects.hash(startState, acceptingSymbol, endState);
}
@Override
public String toString() {
return String.format("%s (%s) -> %s", this.startState, this.acceptingSymbol, this.endState);
}
}