private void end(State start, State end, UTF8Sequence utf8, int upto, boolean doAll) {
   if (upto == utf8.len - 1) {
     // Done recursing
     start.addTransition(
         new Transition(
             utf8.byteAt(upto) & (~MASKS[utf8.numBits(upto) - 1]),
             utf8.byteAt(upto),
             end)); // type=end
   } else {
     final int startCode;
     if (utf8.numBits(upto) == 5) {
       // special case -- avoid created unused edges (utf8
       // doesn't accept certain byte sequences) -- there
       // are other cases we could optimize too:
       startCode = 194;
     } else {
       startCode = utf8.byteAt(upto) & (~MASKS[utf8.numBits(upto) - 1]);
     }
     if (doAll && utf8.byteAt(upto) != startCode) {
       all(start, end, startCode, utf8.byteAt(upto) - 1, utf8.len - upto - 1);
     }
     State n = newUTF8State();
     start.addTransition(new Transition(utf8.byteAt(upto), n)); // type=end
     end(n, end, utf8, 1 + upto, true);
   }
 }
  private void build(
      State start, State end, UTF8Sequence startUTF8, UTF8Sequence endUTF8, int upto) {

    // Break into start, middle, end:
    if (startUTF8.byteAt(upto) == endUTF8.byteAt(upto)) {
      // Degen case: lead with the same byte:
      if (upto == startUTF8.len - 1 && upto == endUTF8.len - 1) {
        // Super degen: just single edge, one UTF8 byte:
        start.addTransition(new Transition(startUTF8.byteAt(upto), endUTF8.byteAt(upto), end));
        return;
      } else {
        assert startUTF8.len > upto + 1;
        assert endUTF8.len > upto + 1;
        State n = newUTF8State();

        // Single value leading edge
        start.addTransition(new Transition(startUTF8.byteAt(upto), n)); // type=single

        // Recurse for the rest
        build(n, end, startUTF8, endUTF8, 1 + upto);
      }
    } else if (startUTF8.len == endUTF8.len) {
      if (upto == startUTF8.len - 1) {
        start.addTransition(
            new Transition(startUTF8.byteAt(upto), endUTF8.byteAt(upto), end)); // type=startend
      } else {
        start(start, end, startUTF8, upto, false);
        if (endUTF8.byteAt(upto) - startUTF8.byteAt(upto) > 1) {
          // There is a middle
          all(
              start,
              end,
              startUTF8.byteAt(upto) + 1,
              endUTF8.byteAt(upto) - 1,
              startUTF8.len - upto - 1);
        }
        end(start, end, endUTF8, upto, false);
      }
    } else {

      // start
      start(start, end, startUTF8, upto, true);

      // possibly middle, spanning multiple num bytes
      int byteCount = 1 + startUTF8.len - upto;
      final int limit = endUTF8.len - upto;
      while (byteCount < limit) {
        // wasteful: we only need first byte, and, we should
        // statically encode this first byte:
        tmpUTF8a.set(startCodes[byteCount - 1]);
        tmpUTF8b.set(endCodes[byteCount - 1]);
        all(start, end, tmpUTF8a.byteAt(0), tmpUTF8b.byteAt(0), tmpUTF8a.len - 1);
        byteCount++;
      }

      // end
      end(start, end, endUTF8, upto, true);
    }
  }
示例#3
0
 /**
  * Constructs sub-automaton corresponding to decimal numbers of value at most x.substring(n) and
  * length x.substring(n).length().
  */
 private static State atMost(String x, int n) {
   State s = new State();
   if (x.length() == n) s.setAccept(true);
   else {
     char c = x.charAt(n);
     s.addTransition(new Transition(c, atMost(x, (char) n + 1)));
     if (c > '0') s.addTransition(new Transition('0', (char) (c - 1), anyOfRightLength(x, n + 1)));
   }
   return s;
 }
示例#4
0
  @Test
  public void testBreakAndContinue() throws Exception {
    State s1 = new State("s1");
    s1.addTransition(new BreakAndContinueTransition("foo"));
    s1.addTransition(new SuccessTransition("foo"));

    StateContext context = new DefaultStateContext();
    StateMachine sm = new StateMachine(new State[] {s1}, "s1");
    sm.handle(new Event("foo", context));
    assertEquals(true, context.getAttribute("success"));
  }
示例#5
0
 /**
  * Constructs sub-automaton corresponding to decimal numbers of value at least x.substring(n) and
  * length x.substring(n).length().
  */
 private static State atLeast(String x, int n, Collection<State> initials, boolean zeros) {
   State s = new State();
   if (x.length() == n) s.setAccept(true);
   else {
     if (zeros) initials.add(s);
     char c = x.charAt(n);
     s.addTransition(new Transition(c, atLeast(x, n + 1, initials, zeros && c == '0')));
     if (c < '9') s.addTransition(new Transition((char) (c + 1), '9', anyOfRightLength(x, n + 1)));
   }
   return s;
 }
示例#6
0
  @Test
  public void testBreakAndGotoNext() throws Exception {
    State s1 = new State("s1");
    State s2 = new State("s2");
    s1.addTransition(new BreakAndGotoNextTransition("foo", "s2"));
    s2.addTransition(new SuccessTransition("foo"));

    StateContext context = new DefaultStateContext();
    StateMachine sm = new StateMachine(new State[] {s1, s2}, "s1");
    sm.handle(new Event("foo", context));
    assertSame(s2, context.getCurrentState());
    sm.handle(new Event("foo", context));
    assertEquals(true, context.getAttribute("success"));
  }
 private void all(State start, State end, int startCode, int endCode, int left) {
   if (left == 0) {
     start.addTransition(new Transition(startCode, endCode, end)); // type=all
   } else {
     State lastN = newUTF8State();
     start.addTransition(new Transition(startCode, endCode, lastN)); // type=all
     while (left > 1) {
       State n = newUTF8State();
       lastN.addTransition(new Transition(128, 191, n)); // type=all*
       left--;
       lastN = n;
     }
     lastN.addTransition(new Transition(128, 191, end)); // type = all*
   }
 }
 private void start(State start, State end, UTF8Sequence utf8, int upto, boolean doAll) {
   if (upto == utf8.len - 1) {
     // Done recursing
     start.addTransition(
         new Transition(
             utf8.byteAt(upto),
             utf8.byteAt(upto) | MASKS[utf8.numBits(upto) - 1],
             end)); // type=start
   } else {
     State n = newUTF8State();
     start.addTransition(new Transition(utf8.byteAt(upto), n)); // type=start
     start(n, end, utf8, 1 + upto, true);
     int endCode = utf8.byteAt(upto) | MASKS[utf8.numBits(upto) - 1];
     if (doAll && utf8.byteAt(upto) != endCode) {
       all(start, end, utf8.byteAt(upto) + 1, endCode, utf8.len - upto - 1);
     }
   }
 }
示例#9
0
 /**
  * Constructs sub-automaton corresponding to decimal numbers of value between x.substring(n) and
  * y.substring(n) and of length x.substring(n).length() (which must be equal to
  * y.substring(n).length()).
  */
 private static State between(
     String x, String y, int n, Collection<State> initials, boolean zeros) {
   State s = new State();
   if (x.length() == n) s.setAccept(true);
   else {
     if (zeros) initials.add(s);
     char cx = x.charAt(n);
     char cy = y.charAt(n);
     if (cx == cy)
       s.addTransition(new Transition(cx, between(x, y, n + 1, initials, zeros && cx == '0')));
     else { // cx<cy
       s.addTransition(new Transition(cx, atLeast(x, n + 1, initials, zeros && cx == '0')));
       s.addTransition(new Transition(cy, atMost(y, n + 1)));
       if (cx + 1 < cy)
         s.addTransition(
             new Transition((char) (cx + 1), (char) (cy - 1), anyOfRightLength(x, n + 1)));
     }
   }
   return s;
 }
  @Test
  public void
      shouldCheckTransitionToNextStateWithOneTransitionInMapAndEmptyElseTransitionAndReturnCorrectNextState()
          throws Exception {
    char transitionChar = 'a';
    State expectedState = new State("StateTo");
    state.addTransition(transitionChar, expectedState);

    State actualState = state.next(transitionChar);

    assertEquals(expectedState, actualState);
  }
  @Test
  public void shouldAddStringTransitionsAndReturnCorrectState() throws Exception {
    String transitions = "abc";

    State stateTo = new State("stateTo");

    state.addTransition(transitions, stateTo);

    assertEquals(stateTo, state.next(transitions.charAt(0)));
    assertEquals(stateTo, state.next(transitions.charAt(1)));
    assertEquals(stateTo, state.next(transitions.charAt(2)));
  }
  /**
   * uy.edu.fing.mina.omega.tffst.test 5, is the very example of the policy's paper. it works well
   * but A <-> B and B <-> A must be unified
   *
   * @param args
   */
  public static void main(String[] args) {

    Tffst.setMinimizeAlways(false);

    Tffst tffst1 = new Tffst();

    State s0 = new State();
    tffst1.setInitialState(s0);

    State s4 = new State();
    s4.setAccept(true);

    SimpleTf tf1 = new SimpleTf();
    tf1.setSLabel("A");

    SimpleTf tf2 = new SimpleTf();
    tf2.setSLabel("C");

    SimpleTf tf7 = new SimpleTf();
    tf7.setSLabel("I");

    SimpleTf tf8 = new SimpleTf();
    tf8.setSLabel("J");

    Transition trans1 = new Transition(tf1, tf2, s4);
    Transition trans5 = new Transition(tf7, tf8, s4);

    s0.addTransition(trans1);
    s4.addTransition(trans5);

    Utils.showDot(tffst1.toDot(""));

    tffst1.setDeterministic(false);
    tffst1.determinize();

    Utils.showDot(tffst1.toDot(""));

    Utils.showDot(tffst1.toSimpleTransitions().toDot(""));
  }
示例#13
0
  @Test
  public void testOnEntry() throws Exception {
    State s1 = new State("s1");
    State s2 = new State("s2");

    s1.addTransition(new SuccessTransition("foo", s2));
    s1.addOnExitSelfTransaction(new SampleSelfTransition());
    s2.addOnEntrySelfTransaction(new SampleSelfTransition());

    StateContext context = new DefaultStateContext();
    StateMachine sm = new StateMachine(new State[] {s1, s2}, "s1");
    sm.handle(new Event("foo", context));
    assertEquals(true, context.getAttribute("success"));
    assertEquals(true, context.getAttribute("SelfSuccess" + s1.getId()));
    assertEquals(true, context.getAttribute("SelfSuccess" + s2.getId()));
  }
  @Test
  public void shouldAddTwoCharTransitionsAndReturnCorrectNextState() throws Exception {
    char transitionChar1 = 'a';
    char transitionChar2 = 'b';

    State stateTo1 = new State("stateTo1");
    State stateTo2 = new State("stateTo2");

    state.addTransition(transitionChar1, stateTo1);
    state.addTransition(transitionChar2, stateTo2);

    assertEquals(stateTo1, state.next(transitionChar1));
    assertNotEquals(stateTo1, state.next(transitionChar2));
    assertEquals(stateTo2, state.next(transitionChar2));
    assertNotEquals(stateTo2, state.next(transitionChar1));
  }
  @Test
  public void shouldAddTwoStringTransitionsAndReturnCorrectState() throws Exception {
    String transitions1 = "ab";
    String transitions2 = "cd";

    State stateTo1 = new State("stateTo1");
    State stateTo2 = new State("stateTo2");

    state.addTransition(transitions1, stateTo1);
    state.addTransition(transitions2, stateTo2);

    assertEquals(stateTo1, state.next(transitions1.charAt(0)));
    assertEquals(stateTo1, state.next(transitions1.charAt(1)));
    assertEquals(stateTo2, state.next(transitions2.charAt(0)));
    assertEquals(stateTo2, state.next(transitions2.charAt(1)));

    assertNotEquals(stateTo1, state.next(transitions2.charAt(0)));
    assertNotEquals(stateTo1, state.next(transitions2.charAt(1)));
    assertNotEquals(stateTo2, state.next(transitions1.charAt(0)));
    assertNotEquals(stateTo2, state.next(transitions1.charAt(1)));
  }
 /**
  * Simple, original brics implementation of determinize() Determinizes the given automaton using
  * the given set of initial states.
  */
 public static void determinizeSimple(Automaton a, Set<State> initialset) {
   int[] points = a.getStartPoints();
   // subset construction
   Map<Set<State>, Set<State>> sets = new HashMap<Set<State>, Set<State>>();
   LinkedList<Set<State>> worklist = new LinkedList<Set<State>>();
   Map<Set<State>, State> newstate = new HashMap<Set<State>, State>();
   sets.put(initialset, initialset);
   worklist.add(initialset);
   a.initial = new State();
   newstate.put(initialset, a.initial);
   while (worklist.size() > 0) {
     Set<State> s = worklist.removeFirst();
     State r = newstate.get(s);
     for (State q : s)
       if (q.accept) {
         r.accept = true;
         break;
       }
     for (int n = 0; n < points.length; n++) {
       Set<State> p = new HashSet<State>();
       for (State q : s)
         for (Transition t : q.getTransitions())
           if (t.min <= points[n] && points[n] <= t.max) p.add(t.to);
       if (!sets.containsKey(p)) {
         sets.put(p, p);
         worklist.add(p);
         newstate.put(p, new State());
       }
       State q = newstate.get(p);
       int min = points[n];
       int max;
       if (n + 1 < points.length) max = points[n + 1] - 1;
       else max = Character.MAX_CODE_POINT;
       r.addTransition(new Transition(min, max, q));
     }
   }
   a.deterministic = true;
   a.clearNumberedStates();
   a.removeDeadTransitions();
 }
  /**
   * Determinizes the given automaton.
   *
   * <p>Worst case complexity: exponential in number of states.
   */
  static void determinize(Automaton a) {
    if (a.deterministic || a.isSingleton()) {
      return;
    }

    final State[] allStates = a.getNumberedStates();

    // subset construction
    final boolean initAccept = a.initial.accept;
    final int initNumber = a.initial.number;
    a.initial = new State();
    SortedIntSet.FrozenIntSet initialset = new SortedIntSet.FrozenIntSet(initNumber, a.initial);

    LinkedList<SortedIntSet.FrozenIntSet> worklist = new LinkedList<SortedIntSet.FrozenIntSet>();
    Map<SortedIntSet.FrozenIntSet, State> newstate =
        new HashMap<SortedIntSet.FrozenIntSet, State>();

    worklist.add(initialset);

    a.initial.accept = initAccept;
    newstate.put(initialset, a.initial);

    int newStateUpto = 0;
    State[] newStatesArray = new State[5];
    newStatesArray[newStateUpto] = a.initial;
    a.initial.number = newStateUpto;
    newStateUpto++;

    // like Set<Integer,PointTransitions>
    final PointTransitionSet points = new PointTransitionSet();

    // like SortedMap<Integer,Integer>
    final SortedIntSet statesSet = new SortedIntSet(5);

    while (worklist.size() > 0) {
      SortedIntSet.FrozenIntSet s = worklist.removeFirst();

      // Collate all outgoing transitions by min/1+max:
      for (int i = 0; i < s.values.length; i++) {
        final State s0 = allStates[s.values[i]];
        for (int j = 0; j < s0.numTransitions; j++) {
          points.add(s0.transitionsArray[j]);
        }
      }

      if (points.count == 0) {
        // No outgoing transitions -- skip it
        continue;
      }

      points.sort();

      int lastPoint = -1;
      int accCount = 0;

      final State r = s.state;
      for (int i = 0; i < points.count; i++) {

        final int point = points.points[i].point;

        if (statesSet.upto > 0) {
          assert lastPoint != -1;

          statesSet.computeHash();

          State q = newstate.get(statesSet);
          if (q == null) {
            q = new State();
            final SortedIntSet.FrozenIntSet p = statesSet.freeze(q);
            worklist.add(p);
            if (newStateUpto == newStatesArray.length) {
              final State[] newArray =
                  new State
                      [ArrayUtil.oversize(1 + newStateUpto, RamUsageEstimator.NUM_BYTES_OBJ_REF)];
              System.arraycopy(newStatesArray, 0, newArray, 0, newStateUpto);
              newStatesArray = newArray;
            }
            newStatesArray[newStateUpto] = q;
            q.number = newStateUpto;
            newStateUpto++;
            q.accept = accCount > 0;
            newstate.put(p, q);
          } else {
            assert (accCount > 0 ? true : false) == q.accept
                : "accCount="
                    + accCount
                    + " vs existing accept="
                    + q.accept
                    + " states="
                    + statesSet;
          }

          r.addTransition(new Transition(lastPoint, point - 1, q));
        }

        // process transitions that end on this point
        // (closes an overlapping interval)
        Transition[] transitions = points.points[i].ends.transitions;
        int limit = points.points[i].ends.count;
        for (int j = 0; j < limit; j++) {
          final Transition t = transitions[j];
          final Integer num = t.to.number;
          statesSet.decr(num);
          accCount -= t.to.accept ? 1 : 0;
        }
        points.points[i].ends.count = 0;

        // process transitions that start on this point
        // (opens a new interval)
        transitions = points.points[i].starts.transitions;
        limit = points.points[i].starts.count;
        for (int j = 0; j < limit; j++) {
          final Transition t = transitions[j];
          final Integer num = t.to.number;
          statesSet.incr(num);
          accCount += t.to.accept ? 1 : 0;
        }
        lastPoint = point;
        points.points[i].starts.count = 0;
      }
      points.reset();
      assert statesSet.upto == 0 : "upto=" + statesSet.upto;
    }
    a.deterministic = true;
    a.setNumberedStates(newStatesArray, newStateUpto);
  }
示例#18
0
 /**
  * Constructs sub-automaton corresponding to decimal numbers of length x.substring(n).length().
  */
 private static State anyOfRightLength(String x, int n) {
   State s = new State();
   if (x.length() == n) s.setAccept(true);
   else s.addTransition(new Transition('0', '9', anyOfRightLength(x, n + 1)));
   return s;
 }