Skip to content

Commit

Permalink
merging chartrans-generic to master
Browse files Browse the repository at this point in the history
  • Loading branch information
Harald Kirsch committed Feb 21, 2016
2 parents 8f23099 + 1ee89e2 commit 1f0c4e3
Show file tree
Hide file tree
Showing 21 changed files with 925 additions and 715 deletions.
272 changes: 106 additions & 166 deletions src/java/monq/jfa/AbstractFaState.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*+*********************************************************************
/*+*********************************************************************
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
Expand All @@ -25,20 +25,30 @@ of the License, or (at your option) any later version.
/**
* implements a prototype of an {@link FaState} to
* ease subclassing for specialized states of an automaton.
*
* @author © 2005 Harald Kirsch
*/
class AbstractFaState implements FaState<AbstractFaState>, Serializable {
// for use in addEps(STATE) only
private final AbstractFaState[] tmp = new AbstractFaState[1];
private AbstractFaState[] eps = null;
private CharTrans<AbstractFaState> trans = null;
private FaAction action = null;

abstract class AbstractFaState
implements FaState, Serializable
{
// A state can be part of several subgraphs. Subgraphs are
// identified by a pair (FaAction, FaSubinfo.id). The FaAction is
// used in this map as a key. The values will be of type
// FaSubinfo[], sorted according to FaSubinfo.id (see
// FaSubinfo.compareTo()).
private Map<FaAction,FaSubinfo[]> subinfos = null;

/*+******************************************************************/
public AbstractFaState() {
// empty
}
/*+******************************************************************/
public AbstractFaState(FaAction a) {
this.action = a;
}
/*+******************************************************************/
@Override
public Map<FaAction,FaSubinfo[]> getSubinfos() {
return subinfos;
}
Expand All @@ -54,35 +64,28 @@ public Map<FaAction,FaSubinfo[]> getSubinfos() {
* <code>null</code>. In this case the information is added.</li>
* </ol>
*/
void mergeSub(FaAction a, FaSubinfo sfi) {
private static Map<FaAction, FaSubinfo[]>
mergeSub(Map<FaAction, FaSubinfo[]> subinfos, FaAction a, FaSubinfo sfi) {
if( subinfos==null ) subinfos = new HashMap<FaAction,FaSubinfo[]>();
FaSubinfo[] ary;


// If there is nothing yet for a, simply enter what we have as a
// new entry.
Object o = subinfos.get(a);
if( o==null ) {
FaSubinfo[] ary = subinfos.get(a);
if( ary==null ) {
//System.err.println("merging null with "+sfi+" for "+this);
ary = new FaSubinfo[1];
ary[0] = new FaSubinfo(sfi);
subinfos.put(a, ary);
return;
return subinfos;
}

// Something is already there for a, amend it.
ary = (FaSubinfo[])o;

//System.err.println("merging "+sfi+" into "+this+":");
//for(int kk=0; kk<ary.length; kk++) System.err.print(" "+ary[kk]);
//System.err.println();

// see if the subgraph denoted by sfi is already present
int pos = java.util.Arrays.binarySearch(ary, sfi);

// If sfi already present, just merge sfi in
if( pos>=0 ) {
ary[pos].merge(sfi);
return;
return subinfos;
}

// Since sfi denotes a new subgraph, we have to enlarge ary.
Expand All @@ -93,9 +96,12 @@ void mergeSub(FaAction a, FaSubinfo sfi) {
ary = tmp;
ary[pos] = new FaSubinfo(sfi);
subinfos.put(a, ary);
return subinfos;
}

@Override
public void addUnassignedSub(FaSubinfo sfi) {
mergeSub(null, sfi);
subinfos = mergeSub(subinfos, null, sfi);
}

/**
Expand All @@ -104,6 +110,7 @@ public void addUnassignedSub(FaSubinfo sfi) {
* action. Under most circumstances <code>from==null</code> which
* means the subgraph was not yet really assigned.</p>
*/
@Override
public void reassignSub(FaAction from, FaAction to) {
if( subinfos==null ) return;
FaSubinfo[] o = subinfos.get(from);
Expand All @@ -126,11 +133,23 @@ public void reassignSub(FaAction from, FaAction to) {
* extreme case, this state may be a start/inner/stop node for a
* certain subgraph.
*/
public void mergeSubinfos(Set<FaState> nfaStates) {
@Override
public <X extends FaState<X>> void mergeSubinfos(Set<X> nfaStates) {
subinfos = mergeSubinfosInto(subinfos, nfaStates);
}

/**
* for the benefit of DfaState to reuse this code
*
* TODO: move to some other place, possibly make the first parameter into a
* separate class.
*/
public static <X extends FaState<X>> Map<FaAction, FaSubinfo[]>
mergeSubinfosInto(Map<FaAction,FaSubinfo[]> subinfos, Set<X> nfaStates) {
// loop over all given states
Iterator<FaState> states = nfaStates.iterator();
Iterator<X> states = nfaStates.iterator();
while( states.hasNext() ) {
FaState other = states.next();
FaState<X> other = states.next();
Map<FaAction,FaSubinfo[]> otherSubs = other.getSubinfos();
if( otherSubs==null ) continue;

Expand All @@ -141,198 +160,119 @@ public void mergeSubinfos(Set<FaState> nfaStates) {
FaSubinfo[] ary = otherSubs.get(a);

// loop over all subgraph markers and merge them in
for(int i=0; i<ary.length; i++) mergeSub(a, ary[i]);
for(int i=0; i<ary.length; i++) {
subinfos = mergeSub(subinfos, a, ary[i]);
}
}
}
return subinfos;
}
/**********************************************************************/

public CharTrans getTrans() {return null;}
public void setTrans(CharTrans trans) {
throw new UnsupportedOperationException(getClass().getName());
@Override
public CharTrans<AbstractFaState> getTrans() {
return trans;
}
public FaAction getAction() {return null;}
public void clearAction() {;}
public boolean isImportant() {
return getTrans()!=null || getAction()!=null || subinfos!=null;
public void setTrans(CharTrans<AbstractFaState> trans) {
this.trans = trans;
}

public FaState[] getEps() {return null;}

public void addEps(FaState other) {
throw new UnsupportedOperationException(getClass().getName());
@Override
public FaAction getAction() {
return action;
}
public void addEps(FaState[] others) {
throw new UnsupportedOperationException(getClass().getName());
@Override
public void clearAction() {
action = null;
}
public void setEps(FaState[] others) {
throw new UnsupportedOperationException(getClass().getName());
@Override
public boolean isImportant() {
return getTrans()!=null || getAction()!=null || subinfos!=null;
}
@Override
public AbstractFaState[] getEps() {
return eps;
}
@Override
public void setEps(AbstractFaState[] eps) {
this.eps = eps;
}

public FaState follow(char ch) {
CharTrans trans = getTrans();
if( trans==null ) return null;
FaState state = trans.get(ch);
return state;
}
@Override
public void addEps(AbstractFaState state) {
tmp[0] = state;
addEps(tmp);
}
@Override
public void addEps(AbstractFaState[] others) {
if( others==null ) return;
if( eps==null ) {
eps = new AbstractFaState[others.length];
System.arraycopy(others, 0, eps, 0, others.length);
return;
}
AbstractFaState[] tmp = new AbstractFaState[eps.length+others.length];
System.arraycopy(eps, 0, tmp, 0, eps.length);
System.arraycopy(others, 0, tmp, eps.length, others.length);
eps = tmp;
}

@Override
public AbstractFaState follow(char ch) {
CharTrans<AbstractFaState> trans = getTrans();
if( trans==null ) return null;
AbstractFaState state = trans.get(ch);
return state;
}
/**********************************************************************/
/**
* implements an {@link java.util.Iterator} over all states reachable
* from this state. It iterates first over the character transitions
* and then over the epsilon transitions.
* <p>The {@link java.util.Iterator#remove() remove()} operation is not
* implemented.</p>
* implemented.</p>
*
* <p>Use {@link FaState#getChildIterator() getChildIterator()} of
* an {@link FaState} object to create a <code>ChildIterator</code>
* for that state.</p>
* for that state.</p>a
*/
public class ChildIterator implements Iterator<FaState> {
public class ChildIterator implements Iterator<AbstractFaState> {
private int trans_i = 0;
private int trans_L = 0;
private int eps_i = 0;
private int eps_L = 0;

ChildIterator(IterType iType) {
if (iType==IterType.ALL || iType==IterType.EPSILON) {
FaState[] eps = getEps();
AbstractFaState[] eps = getEps();
if( eps!=null ) eps_L = eps.length;
}
if (iType==IterType.ALL || iType==IterType.CHAR) {
CharTrans t = getTrans();
CharTrans<AbstractFaState> t = getTrans();
if( t!=null ) trans_L = t.size();
}
}

@Override
public boolean hasNext() {
return (eps_i<eps_L) || (trans_i<trans_L);
}

public FaState next() {
@Override
public AbstractFaState next() {
if( trans_i<trans_L ) {
return getTrans().getAt(trans_i++);
}
if( eps_i<eps_L ) return getEps()[eps_i++];
throw new java.util.NoSuchElementException();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
/**********************************************************************/
@Override
public Iterator<FaState> getChildIterator(IterType iType) {
public Iterator<AbstractFaState> getChildIterator(IterType iType) {
return new ChildIterator(iType);
}
/********************************************************************/
public static FaState createDfaState(FaAction a, boolean needEps) {
if( a!=null ) {
// for stop states, there is anyway an epsilon
return new DfaStopState(a);
}
if( needEps ) {
return new NfaState();
}
return new DfaState();
}
/********************************************************************/
/**
* is an {@link FaState} which has only epsilon transitions. Other
* subclasses of <code>AbstractFaState</code> which need epsilon
* transitions inherit from this one.
*
* <p><b>FIX ME:</b>I don't really bother to check in the
* <code>addEps</code> methods whether I add a transition a 2nd
* time. Normally this does not happen in Thompson's
* construction. And if it does, it is no harm anyway.</p>
*/
static class EpsState extends AbstractFaState {
private FaState[] eps=null;

public FaState[] getEps() {return eps;}
public void setEps(FaState[] eps) {this.eps = eps;}

public void addEps(FaState other) {
if( eps==null ) {
eps = new FaState[1];
eps[0] = other;
return;
}
FaState[] tmp = new FaState[eps.length+1];
System.arraycopy(eps, 0, tmp, 0, eps.length);
eps = tmp;
eps[eps.length-1] = other;
}

public void addEps(FaState[] others) {
//throw new UnsupportedOperationException(getClass().getName());
if( others==null ) return;
if( eps==null ) {
eps = new FaState[others.length];
System.arraycopy(others, 0, eps, 0, others.length);
return;
}
FaState[] tmp = new FaState[eps.length+others.length];
System.arraycopy(eps, 0, tmp, 0, eps.length);
System.arraycopy(others, 0, tmp, eps.length, others.length);
eps = tmp;
}
}

/********************************************************************/
/**
* is an {@link FaState} which has only explicit character
* transitions.
*/
static class DfaState extends AbstractFaState {
CharTrans trans = null;

//public DfaState(CharTrans trans) { this.trans = trans; }
public CharTrans getTrans() {return trans;}
public void setTrans(CharTrans t) {this.trans = t;}
}
/********************************************************************/
/**
* implements a state which can store character transitions, an
* action and, a bit surprisingly, epsilon transitions. The reason
* for the latter is, that every FA shall always be usable in
* regexp-operations. Most of these operations are all implemented
* by means of epsilon transitions which are added in particular to
* stop states.
*/
static class DfaStopState extends EpsState {
CharTrans trans = null;
FaAction action = null;

public DfaStopState(FaAction action) {
this.trans = null;
this.action = action;
}
public CharTrans getTrans() {return trans;}
public void setTrans(CharTrans t) {this.trans = t;}
public void clearAction() {action = null;}
public FaAction getAction() {return action;}
}
/**
* is an {@link FaState} which has epsilon transitions and can store
* an action.
*/
static class EpsStopState extends EpsState {
FaAction action = null;
public EpsStopState(FaAction a) { action = a; }
public FaAction getAction() { return action; }
public void clearAction() { action = null; }
}
/********************************************************************/
/**
* is an {@link FaState} with epsilon as well as character
* transitions.
*/
static class NfaState extends EpsState {
CharTrans trans = null;
public CharTrans getTrans() {return trans;}
public void setTrans(CharTrans t) {this.trans = t;}
}
/********************************************************************/
}
Loading

0 comments on commit 1f0c4e3

Please sign in to comment.