// // Copyright (C) 2011 United States Government as represented by the // Administrator of the National Aeronautics and Space Administration // (NASA). All Rights Reserved. // // This software is distributed under the NASA Open Source Agreement // (NOSA), version 1.3. The NOSA has been approved by the Open Source // Initiative. See the file NOSA-1.3-JPF at the top of the distribution // directory tree for the complete NOSA document. // // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. // package gov.nasa.jpf.util.automaton; import java.io.PrintStream; /** * generic class for modeling automatons * * Since this is used in so many extensions from both model and native code, * it seems appropriate to add a basis implementation to util. * * To make it more amenable to modeling (e.g. for native peer implementation), * we avoid using standard Java containers at the expense of efficiency for * large numbers of states and transitions */ public class Automaton <S extends State> { static final int STATE_INC = 16; static final int INPUT_INC = 16; protected String label; protected int nStates; protected State[] states; protected int nInputs; protected String[] alphabet; protected int current; public Automaton (String label, int numberOfStates, int numberOfInputs){ this.label = label; states = new State[numberOfStates]; alphabet = new String[numberOfInputs]; } public Automaton (String label, int numberOfStates){ this( label, numberOfStates, INPUT_INC); } public Automaton(String label){ this(label, STATE_INC, INPUT_INC); } public void addState (State newState){ if (nStates == states.length){ State[] a = new State[nStates + STATE_INC]; System.arraycopy(states, 0, a, 0, nStates); states = a; } states[nStates] = newState; newState.setId(nStates); nStates++; } public void addStates (State ... newStates){ int n = nStates + newStates.length; if (n >= states.length){ State[] a = new State[n]; System.arraycopy(states, 0, a, 0, nStates); states = a; } for (int i=0; i<newStates.length; i++){ State s = newStates[i]; states[nStates] = s; s.setId(nStates); nStates++; } } public String getLabel(){ return label; } public int getNumberOfStates(){ return nStates; } @SuppressWarnings("unchecked") public S getCurrentState(){ return (S)states[current]; } public String[] computeAlphabet(){ for (int i = 0; i < nStates; i++) { State s = states[i]; int nTrans = s.getNumberOfTransitions(); nextTransition: for (int j = 0; j < nTrans; j++) { Transition t = s.getTransition(j); String label = t.getLabel(); for (int k = 0; k < nInputs; k++) { if (alphabet[k].equals(label)) { break nextTransition; } } if (nInputs == alphabet.length) { String[] a = new String[nInputs + INPUT_INC]; System.arraycopy(alphabet, 0, a, 0, nInputs); alphabet = a; } alphabet[nInputs] = label; nInputs++; } } return alphabet; } public String[] getAlphabet(){ if (nInputs == 0){ return computeAlphabet(); } else { return alphabet; } } public void printOn (PrintStream ps){ ps.printf("Automaton '%s'\n", label); for (int i=0; i<nStates; i++){ states[i].printOn(ps); } } }