protected PatternExpr copy() {
   List<PatternExpr> newPatterns = new ArrayList<PatternExpr>(patterns.size());
   for (PatternExpr p : patterns) {
     newPatterns.add(p.copy());
   }
   return new AndPatternExpr(newPatterns);
 }
 protected int assignGroupIds(int start) {
   int nextId = start;
   for (PatternExpr pattern : patterns) {
     nextId = pattern.assignGroupIds(nextId);
   }
   return nextId;
 }
 protected int assignGroupIds(int start) {
   int nextId = start;
   // assign group ids of child expressions
   for (PatternExpr pattern : patterns) {
     nextId = pattern.assignGroupIds(nextId);
   }
   return nextId;
 }
 public void toPrecedenceFreeEPL(StringWriter writer, EPStatementFormatter formatter) {
   if ((this.getChildren() == null) || (this.getChildren().size() == 0)) {
     return;
   }
   PatternExpr patternExpr = getChildren().get(0);
   if (patternExpr != null) {
     patternExpr.toEPL(writer, getPrecedence(), formatter);
   }
 }
    protected Frag build() {
      Frag f = pattern.build();
      if (minMatch == 1 && maxMatch == 1) {
        return f;
      } else if (minMatch <= 10 && maxMatch <= 10 && greedyMatch) {
        // Make copies if number of matches is low
        // Doesn't handle nongreedy matches yet
        // For non greedy match need to move curOut before the recursive connect

        // Create NFA fragment that
        // have child pattern repeating for minMatch times
        if (minMatch > 0) {
          //  frag.start -> pattern NFA -> pattern NFA ->
          for (int i = 0; i < minMatch - 1; i++) {
            Frag f2 = pattern.build();
            f.connect(f2);
          }
        } else {
          // minMatch is 0
          // frag.start ->
          f = new Frag(new State());
        }
        if (maxMatch < 0) {
          // Unlimited (loop back to self)
          //        --------
          //       \|/     |
          // ---> pattern NFA --->
          Set<State> curOut = f.out;
          Frag f2 = pattern.build();
          f2.connect(f2);
          f.connect(f2);
          f.add(curOut);
        } else {
          // Limited number of times this pattern repeat,
          // just keep add pattern (with option of being done) until maxMatch reached
          // ----> pattern NFA ----> pattern NFA --->
          //   |                |
          //   -->              --->
          for (int i = minMatch; i < maxMatch; i++) {
            Set<State> curOut = f.out;
            Frag f2 = pattern.build();
            f.connect(f2);
            f.add(curOut);
          }
        }
        return f;
      } else {
        // More general but more expensive matching (when branching, need to keep state explicitly)
        State s = new RepeatState(f.start, minMatch, maxMatch, greedyMatch);
        f.connect(s);
        return new Frag(s);
      }
    }
 protected Frag build() {
   Frag frag = null;
   if (patterns.size() > 0) {
     PatternExpr first = patterns.get(0);
     frag = first.build();
     for (int i = 1; i < patterns.size(); i++) {
       PatternExpr pattern = patterns.get(i);
       Frag f = pattern.build();
       frag.connect(f);
     }
   }
   return frag;
 }
 protected int assignGroupIds(int start) {
   int nextId = start;
   if (capture) {
     captureGroupId = nextId;
     nextId++;
   }
   return pattern.assignGroupIds(nextId);
 }
 protected Frag build() {
   Frag frag = new Frag();
   frag.start = new State();
   // Create NFA fragment that
   // have one starting state that branches out to NFAs created by the children expressions
   //  ---> pattern 1 --->
   //   |
   //   ---> pattern 2 --->
   //   ...
   for (PatternExpr pattern : patterns) {
     // Build child NFA
     Frag f = pattern.build();
     // Add child NFA to next states of fragment start
     frag.start.add(f.start);
     // Add child NFA out (unlinked) states to out (unlinked) states of this fragment
     frag.add(f.out);
   }
   return frag;
 }
 protected PatternExpr getSequencePatternExpr(String name, boolean copy) {
   Object obj = variables.get(name);
   if (obj != null) {
     if (obj instanceof PatternExpr) {
       PatternExpr pe = (PatternExpr) obj;
       return (copy) ? pe.copy() : pe;
     } else if (obj instanceof NodePattern) {
       return new NodePatternExpr((NodePattern) obj);
     } else if (obj instanceof String) {
       try {
         return parser.parseSequence(this, (String) obj);
       } catch (Exception pex) {
         throw new RuntimeException("Error parsing " + obj + " to sequence pattern", pex);
       }
     } else {
       throw new Error("Invalid sequence pattern variable class: " + obj.getClass());
     }
   }
   return null;
 }
    protected Frag build() {
      ConjStartState conjStart = new ConjStartState(patterns.size());
      Frag frag = new Frag();
      frag.start = conjStart;
      // Create NFA fragment that
      // have one starting state that branches out to NFAs created by the children expressions
      // AND START ---> pattern 1 --->  AND END (0/n)
      //            |
      //             ---> pattern 2 ---> AND END (1/n)
      //             ...
      for (int i = 0; i < patterns.size(); i++) {
        PatternExpr pattern = patterns.get(i);
        // Build child NFA
        Frag f = pattern.build();
        // Add child NFA to next states of fragment start
        frag.start.add(f.start);

        f.connect(new ConjEndState(conjStart, i));
        // Add child NFA out (unlinked) states to out (unlinked) states of this fragment
        frag.add(f.out);
      }
      return frag;
    }
 protected int assignGroupIds(int start) {
   return pattern.assignGroupIds(start);
 }
 protected void updateBindings(VarGroupBindings bindings) {
   for (PatternExpr pattern : patterns) {
     pattern.updateBindings(bindings);
   }
 }
 protected void updateBindings(VarGroupBindings bindings) {
   // update bindings of child expressions
   for (PatternExpr pattern : patterns) {
     pattern.updateBindings(bindings);
   }
 }
 protected Frag build() {
   Frag f = pattern.build();
   Frag frag = new Frag(new GroupStartState(captureGroupId, f.start), f.out);
   frag.connect(new GroupEndState(captureGroupId));
   return frag;
 }
 protected void updateBindings(VarGroupBindings bindings) {
   if (varname != null) {
     bindings.set(captureGroupId, varname);
   }
   pattern.updateBindings(bindings);
 }
 protected PatternExpr copy() {
   return new RepeatPatternExpr(pattern.copy(), minMatch, maxMatch, greedyMatch);
 }
 protected void updateBindings(VarGroupBindings bindings) {
   pattern.updateBindings(bindings);
 }
 protected PatternExpr copy() {
   return new GroupPatternExpr(pattern.copy(), capture);
 }