protected <T> boolean match(
     int bid, SequenceMatcher.MatchedStates<T> matchedStates, boolean consume) {
   if (consume) {
     Interval<Integer> matchedInterval =
         matchedStates.getBranchStates().getMatchedInterval(bid, this);
     int cur = matchedStates.curPosition;
     if (matchedInterval == null) {
       // Haven't tried to match this node before, try now
       // Get element and return if it matched or not
       List<? extends T> nodes = matchedStates.elements();
       // TODO: Fix type checking
       Collection<Interval<Integer>> matched = pattern.match(nodes, cur);
       // TODO: Check intervals are valid?   Start at cur and ends after?
       if (matched != null && matched.size() > 0) {
         int nBranches = matched.size();
         int i = 0;
         for (Interval<Integer> interval : matched) {
           i++;
           int bid2 = matchedStates.getBranchStates().getBranchId(bid, i, nBranches);
           matchedStates.getBranchStates().setMatchedInterval(bid2, this, interval);
           // If matched, need to add next states to the queue of states to be processed
           // keep in current state until end node reached
           if (interval.getEnd() - 1 <= cur) {
             matchedStates.addStates(bid2, next);
           } else {
             matchedStates.addState(bid2, this);
           }
         }
         return true;
       } else {
         return false;
       }
     } else {
       // Previously matched this state - just need to step through until we get to end of
       // matched interval
       if (matchedInterval.getEnd() - 1 <= cur) {
         matchedStates.addStates(bid, next);
       } else {
         matchedStates.addState(bid, this);
       }
       return true;
     }
   } else {
     // Not consuming element - add this state back to queue of states to be processed
     // This state was not successfully matched
     matchedStates.addState(bid, this);
     return false;
   }
 }
 protected <T> boolean match(
     int bid,
     SequenceMatcher.MatchedStates<T> matchedStates,
     SequenceMatcher.MatchedGroup matchedGroup,
     int matchedNodes) {
   T node = matchedStates.get();
   if (matcher.matches(
       node, matchedStates.elements().get(matchedGroup.matchBegin + matchedNodes))) {
     matchedNodes++;
     matchedStates
         .getBranchStates()
         .setMatchStateInfo(
             bid,
             this,
             new Pair<SequenceMatcher.MatchedGroup, Integer>(matchedGroup, matchedNodes));
     int len = matchedGroup.matchEnd - matchedGroup.matchBegin;
     if (len == matchedNodes) {
       matchedStates.addStates(bid, next);
     } else {
       matchedStates.addState(bid, this);
     }
     return true;
   }
   return false;
 }
 protected <T> boolean match(
     int bid, SequenceMatcher.MatchedStates<T> matchedStates, boolean consume) {
   if (consume) {
     // Get element and return if it matched or not
     T node = matchedStates.get();
     // TODO: Fix type checking
     if (pattern.match(node)) {
       // If matched, need to add next states to the queue of states to be processed
       matchedStates.addStates(bid, next);
       return true;
     } else {
       return false;
     }
   } else {
     // Not consuming element - add this state back to queue of states to be processed
     // This state was not successfully matched
     matchedStates.addState(bid, this);
     return false;
   }
 }