/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* This file is part of SableCC. *
* See the file "LICENSE" for copyright information and the *
* terms and conditions for copying, distribution and *
* modification of SableCC. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package org.sablecc.sablecc;
public class NFA implements Cloneable {
public State[] states;
private NFA(int size) {
System.out.print(".");
states = new State[size];
}
public NFA() {
this(2);
states[0] = new State();
states[0].transitions[0] = new Transition(null, 1);
states[1] = new State();
}
public NFA(CharSet chars) {
this(2);
states[0] = new State();
states[0].transitions[0] = new Transition(chars, 1);
states[1] = new State();
}
public NFA(String string) {
this(string.length() + 1);
for (int i = 0; i < string.length(); i++) {
states[i] = new State();
states[i].transitions[0] = new Transition(new CharSet(string.charAt(i)), i + 1);
}
states[string.length()] = new State();
}
private NFA(NFA nfa) {
this(nfa.states.length);
for (int i = 0; i < nfa.states.length; i++) {
states[i] = new State(nfa.states[i]);
}
}
public NFA zeroOrMore() {
NFA nfa = new NFA(states.length + 2);
nfa.states[0] = new State();
nfa.states[0].transitions[0] = new Transition(null, 1);
nfa.states[0].transitions[1] = new Transition(null, states.length + 1);
for (int i = 0; i < states.length; i++) {
nfa.states[i + 1] = new State(states[i]);
if (nfa.states[i + 1].transitions[0] != null) {
nfa.states[i + 1].transitions[0].destination += 1;
}
if (nfa.states[i + 1].transitions[1] != null) {
nfa.states[i + 1].transitions[1].destination += 1;
}
}
nfa.states[states.length].transitions[0] = new Transition(null, 1);
nfa.states[states.length].transitions[1] = new Transition(null, states.length + 1);
nfa.states[states.length + 1] = new State();
return nfa;
}
public NFA zeroOrOne() {
NFA nfa = new NFA(states.length + 2);
nfa.states[0] = new State();
nfa.states[0].transitions[0] = new Transition(null, 1);
nfa.states[0].transitions[1] = new Transition(null, states.length + 1);
for (int i = 0; i < states.length; i++) {
nfa.states[i + 1] = new State(states[i]);
if (nfa.states[i + 1].transitions[0] != null) {
nfa.states[i + 1].transitions[0].destination += 1;
}
if (nfa.states[i + 1].transitions[1] != null) {
nfa.states[i + 1].transitions[1].destination += 1;
}
}
nfa.states[states.length].transitions[1] = new Transition(null, states.length + 1);
nfa.states[states.length + 1] = new State();
return nfa;
}
public NFA oneOrMore() {
NFA nfa = new NFA(states.length + 2);
nfa.states[0] = new State();
nfa.states[0].transitions[0] = new Transition(null, 1);
for (int i = 0; i < states.length; i++) {
nfa.states[i + 1] = new State(states[i]);
if (nfa.states[i + 1].transitions[0] != null) {
nfa.states[i + 1].transitions[0].destination += 1;
}
if (nfa.states[i + 1].transitions[1] != null) {
nfa.states[i + 1].transitions[1].destination += 1;
}
}
nfa.states[states.length].transitions[0] = new Transition(null, 1);
nfa.states[states.length].transitions[1] = new Transition(null, states.length + 1);
nfa.states[states.length + 1] = new State();
return nfa;
}
public NFA concatenate(NFA next) {
NFA nfa = new NFA(states.length + next.states.length - 1);
for (int i = 0; i < states.length - 1; i++) {
nfa.states[i] = new State(states[i]);
}
for (int i = 0; i < next.states.length; i++) {
nfa.states[states.length + i - 1] = new State(next.states[i]);
if (nfa.states[states.length + i - 1].transitions[0] != null) {
nfa.states[states.length + i - 1].transitions[0].destination +=
states.length - 1;
}
if (nfa.states[states.length + i - 1].transitions[1] != null) {
nfa.states[states.length + i - 1].transitions[1].destination +=
states.length - 1;
}
}
return nfa;
}
public NFA alternate(NFA next) {
NFA nfa = new NFA(states.length + next.states.length + 2);
nfa.states[0] = new State();
nfa.states[0].transitions[0] = new Transition(null, 1);
nfa.states[0].transitions[1] = new Transition(null, states.length + 1);
for (int i = 0; i < states.length; i++) {
nfa.states[i + 1] = new State(states[i]);
if (nfa.states[i + 1].transitions[0] != null) {
nfa.states[i + 1].transitions[0].destination += 1;
}
if (nfa.states[i + 1].transitions[1] != null) {
nfa.states[i + 1].transitions[1].destination += 1;
}
}
nfa.states[states.length].transitions[0] =
new Transition(null, states.length + next.states.length + 1);
for (int i = 0; i < next.states.length; i++) {
nfa.states[states.length + i + 1] = new State(next.states[i]);
if (nfa.states[states.length + i + 1].transitions[0] != null) {
nfa.states[states.length + i + 1].transitions[0].destination +=
states.length + 1;
}
if (nfa.states[states.length + i + 1].transitions[1] != null) {
nfa.states[states.length + i + 1].transitions[1].destination +=
states.length + 1;
}
}
nfa.states[states.length + next.states.length].transitions[0] =
new Transition(null, states.length + next.states.length + 1);
nfa.states[states.length + next.states.length + 1] = new State();
return nfa;
}
public NFA merge(NFA next) {
NFA nfa = new NFA(states.length + next.states.length + 1);
nfa.states[0] = new State();
nfa.states[0].transitions[0] = new Transition(null, 1);
nfa.states[0].transitions[1] = new Transition(null, states.length + 1);
for (int i = 0; i < states.length; i++) {
nfa.states[i + 1] = new State(states[i]);
if (nfa.states[i + 1].transitions[0] != null) {
nfa.states[i + 1].transitions[0].destination += 1;
}
if (nfa.states[i + 1].transitions[1] != null) {
nfa.states[i + 1].transitions[1].destination += 1;
}
}
for (int i = 0; i < next.states.length; i++) {
nfa.states[states.length + i + 1] = new State(next.states[i]);
if (nfa.states[states.length + i + 1].transitions[0] != null) {
nfa.states[states.length + i + 1].transitions[0].destination +=
states.length + 1;
}
if (nfa.states[states.length + i + 1].transitions[1] != null) {
nfa.states[states.length + i + 1].transitions[1].destination +=
states.length + 1;
}
}
return nfa;
}
@Override
public Object clone() {
return new NFA(this);
}
@Override
public String toString() {
StringBuffer result = new StringBuffer();
for (int i = 0; i < states.length; i++) {
result.append(i + ":" + states[i] + System.getProperty("line.separator"));
}
return result.toString();
}
public static class State {
public String accept;
public Transition[] transitions = new Transition[2];
public State() {
}
public State(State state) {
if (state.accept != null) {
accept = state.accept;
}
if (state.transitions[0] != null) {
transitions[0] = new Transition(state.transitions[0]);
}
if (state.transitions[1] != null) {
transitions[1] = new Transition(state.transitions[1]);
}
}
@Override
public String toString() {
StringBuffer result = new StringBuffer();
if (accept != null) {
result.append("(" + accept + ") ");
}
if (transitions[0] != null) {
result.append(" " + transitions[0]);
}
if (transitions[1] != null) {
result.append(" " + transitions[1]);
}
return result.toString();
}
}
public static class Transition {
public CharSet chars;
public int destination;
public Transition(CharSet chars, int destination) {
this.chars = chars;
this.destination = destination;
}
public Transition(Transition transition) {
chars = transition.chars;
destination = transition.destination;
}
@Override
public String toString() {
return destination + ":{" + chars + "}";
}
}
}