Nested OR clauses can be simplified to a just a simple set of options. For example,
{@code "(a|b|(c|d|(e|f))|g)" => "a|b|c|d|e|f|g"}.
512275
static Matcher flattenNestedOr(Matcher matcher) {
    if (matcher instanceof OrMatcher) {
      List<Matcher> matchers = matcher.<OrMatcher>as().matchers();
      List<Matcher> ms = new ArrayList<>();
      for (Matcher m : matchers) {
        if (m instanceof OrMatcher) {
          ms.addAll(m.<OrMatcher>as().matchers());
        } else {
          ms.add(m);
        }
      }
      return OrMatcher.create(ms);
    }
    return matcher;
  }
632151
public static Boolean or(Object left, Object right) {
        return (Boolean) InfixOpNode.or(left, right, null);
    }
1360735
static List<String> parseOptionString(String s) {
    List<String> opts = new ArrayList<>();
    StringBuilder opt = new StringBuilder();
    boolean inOpt = false;
    boolean inSingleQuote = false;
    boolean inDoubleQuote = false;
    boolean escapeNext = false;

    // This is needed to detect when a quoted empty string is used as an argument ("" or '').
    boolean hasData = false;

    for (int i = 0; i < s.length(); i++) {
      int c = s.codePointAt(i);
      if (escapeNext) {
        opt.appendCodePoint(c);
        escapeNext = false;
      } else if (inOpt) {
        switch (c) {
        case '\\':
          if (inSingleQuote) {
            opt.appendCodePoint(c);
          } else {
            escapeNext = true;
          }
          break;
        case '\'':
          if (inDoubleQuote) {
            opt.appendCodePoint(c);
          } else {
            inSingleQuote = !inSingleQuote;
          }
          break;
        case '"':
          if (inSingleQuote) {
            opt.appendCodePoint(c);
          } else {
            inDoubleQuote = !inDoubleQuote;
          }
          break;
        default:
          if (!Character.isWhitespace(c) || inSingleQuote || inDoubleQuote) {
            opt.appendCodePoint(c);
          } else {
            opts.add(opt.toString());
            opt.setLength(0);
            inOpt = false;
            hasData = false;
          }
        }
      } else {
        switch (c) {
        case '\'':
          inSingleQuote = true;
          inOpt = true;
          hasData = true;
          break;
        case '"':
          inDoubleQuote = true;
          inOpt = true;
          hasData = true;
          break;
        case '\\':
          escapeNext = true;
          inOpt = true;
          hasData = true;
          break;
        default:
          if (!Character.isWhitespace(c)) {
            inOpt = true;
            hasData = true;
            opt.appendCodePoint(c);
          }
        }
      }
    }

    checkArgument(!inSingleQuote && !inDoubleQuote && !escapeNext, "Invalid option string: %s", s);
    if (hasData) {
      opts.add(opt.toString());
    }
    return opts;
  }
483819
@SafeVarargs
    public static <T, U, R> BiFunction<T, U, Optional<R>> maybeFirstMatch(BinaryClause<T, U, R>... clauses) {
        final List<Clause<Pair<T, U>, R>> unaryClauses = Sequences.of(clauses).map(BinaryClause::tupled).toList();
        return Pairs.untupled(new MaybeFirstMatchStrategy<>(unaryClauses));
    }
792056
private static Selector simplifyNOT(Selector tree) {
    if (tree instanceof Literal)
      return new LiteralImpl( EvaluatorImpl.not((Boolean) ((Literal) tree).getValue())); // was BooleanValue
    if (!(tree instanceof Operator))
      return new OperatorImpl(Selector.NOT, tree);
    Operator oper = (Operator) tree;
    switch(oper.getOp()) {
    case Selector.NOT:
      return simplifyTree(oper.getOperands()[0]);
    case Selector.AND:
      return makeOR(simplifyNOT(oper.getOperands()[0]),
                    simplifyNOT(oper.getOperands()[1]));
    case Selector.OR:
      return makeAND(simplifyNOT(oper.getOperands()[0]),
                     simplifyNOT(oper.getOperands()[1]));
    case Selector.EQ:
      return simplifyNE(oper.getOperands()[0], oper.getOperands()[1]);
    case Selector.NE:
      return simplifyEQ(oper.getOperands()[0], oper.getOperands()[1]);
    case Selector.GT:
      return new OperatorImpl(Selector.LE, oper.getOperands()[0], oper.getOperands()[1]);
    case Selector.LT:
      return new OperatorImpl(Selector.GE, oper.getOperands()[0], oper.getOperands()[1]);
    case Selector.GE:
      return new OperatorImpl(Selector.LT, oper.getOperands()[0], oper.getOperands()[1]);
    case Selector.LE:
      return new OperatorImpl(Selector.GT, oper.getOperands()[0], oper.getOperands()[1]);
    default:
      return new OperatorImpl(Selector.NOT, tree);
    }
  }
1356987
function parseOptions(type, options) {
    const ret = {
        indentChar: " ",
        indentSize: 2,
        startIndent: 1,
        switchCase: 0,
    }

    if (Number.isSafeInteger(type)) {
        ret.indentSize = type
    } else if (type === "tab") {
        ret.indentChar = "\t"
        ret.indentSize = 1
    }
    if (Number.isSafeInteger(options.switchCase)) {
        ret.switchCase = options.switchCase
    }
    if (Number.isSafeInteger(options.startIndent)) {
        ret.startIndent = options.startIndent
    }

    return ret
}
286725
def _or(ctx, *logical):
    
    for arg in logical:
        if conversions.to_boolean(arg, ctx):
            return True
    return False
80098
function mix (r, s, or, cl) {
  if (!s || !r) {
    return r;
  }

  var i = 0,
    c, len;

  or = or || arguments.length === 2;

  if (cl && (len = cl.length)) {
    for (; i < len; i++) {
      c = cl[i];
      if ((c in s) && (or || !(c in r))) {
        r[c] = s[c];
      }
    }
  } else {
    for (c in s) {
      if (or || !(c in r)) {
        r[c] = s[c];
      }
    }
  }
  return r;
}
8082
public static Boolean or(Boolean a,Boolean b) 
  {
  	return orTable[ttIndex(a)][ttIndex(b)];
  }
268420
def p_expression_Or(self, p):
        ''
        p[0] = Or(p[1], p[3], lineno=p.lineno(1))
        p.set_lineno(0, p.lineno(1))
765817
public static <T> Predicate<T> FULL_OR(final Predicate<T> a, final Predicate<T> b) {
	return new Predicate<T>() {
	    public boolean check(T obj) {
		return a.check(obj) | b.check(obj);
	    }
	};
    }
616425
private static void flattenDNF(LogicClause top)
  {
    if(top.getOp() == LogicClause.Operator.LEAF || top.getOp() == LogicClause.Operator.AND)
    {
      List<LogicClause> children = new ArrayList<>();
      findAllChildrenForOp(top, children, LogicClause.Operator.AND);
      
      List<? extends Token> orginalAndContent = top.getContent();
      
      top.setOp(LogicClause.Operator.OR);
      top.clearChildren();
      // there is no original "|" in the token stream which we can refer to
      
      top.setContent(null);
      
      LogicClause andClause = new LogicClause(LogicClause.Operator.AND);
      andClause.setContent(orginalAndContent);
      top.addChild(andClause);
      
      andClause.addAllChildren(children);
      
    }
    else if(top.getOp() == LogicClause.Operator.OR)
    { 
      // first flatten the OR operator
      List<LogicClause> allOrNodes = new ArrayList<>();
      findAllChildrenForOp(top, allOrNodes, LogicClause.Operator.OR, true);
      
      top.clearChildren();
      top.addAllChildren(allOrNodes);
      
      // find sub and-clauses for all or-clauses
      for(LogicClause subclause : top.getChildren())
      {
        if(subclause.getOp() == LogicClause.Operator.LEAF)
        { 
          // add an artificial "and" node
          List<? extends Token> content = subclause.getContent();
          subclause.clearChildren();
          subclause.setOp(LogicClause.Operator.AND);
          // there is no original "&" in the token stream which we can refer to
          subclause.setContent(null);
          
          LogicClause newLeaf = new LogicClause(LogicClause.Operator.LEAF);
          newLeaf.setContent(content);
          subclause.addChild(newLeaf);
          
        }
        else if (subclause.getOp() == LogicClause.Operator.AND)
        {

          List<LogicClause> children = new ArrayList<>();
          findAllChildrenForOp(subclause, children, LogicClause.Operator.AND);

          subclause.clearChildren();

          for(LogicClause c : children)
          {
            subclause.addChild(c);
          }
        }
        else
        {
          Preconditions.checkArgument(false, "input is not in DNF");
        }
       
      }
    }
  }
1188641
function Matcher(options) {

        options = options || {};

        /**
         * ### Matcher.x
         *
         * The row-index of the last returned match by Matcher.getMatch
         *
         * @see Matcher.getMatch
         */
        this.x = null;

        /**
         * ### Matcher.y
         *
         * The column-index of the last returned match by Matcher.getMatch
         *
         * @see Matcher.getMatch
         */
        this.y = null;

        /**
         * ### Matcher.matches
         *
         * Nested array of matches (with position-numbers)
         *
         * Nests a new array for each round, and within each round
         * individual matches are also array. For example:
         *
         * ```javascript
         *
         * // Matching array.
         * [
         *
         *   // First round.
         *   [ [ p1, p2 ], [ p3, p4 ], ... ],
         *
         *   // Second round.
         *   [ [ p2, p3 ], [ p4, p1 ], ... ],
         *
         *   // Further rounds.
         * ];
         * ```
         *
         * @see Matcher.setMatches
         */
        this.matches = null;

        /**
         * ### Matcher.resolvedMatches
         *
         * Nested array of matches (with id-strings)
         *
         * Exactly Matcher.matches, but with with ids instead of numbers
         *
         * This method is used both by getMatch and getMatchObject (if
         * a single match is requested).
         *
         * @see Matcher.matches
         * @see Matcher.resolvedMatchesObj
         * @see Matcher.resolvedMatchesById
         * @see Matcher.setIds
         * @see Matcher.setAssignerCb
         * @see Matcher.match
         */
        this.resolvedMatches = null;

        /**
         * ### Matcher.resolvedMatchesObj
         *
         * Array of maps id to partner, one map per round
         *
         * ```javascript
         *
         * // Matching array.
         * [
         *
         *   // First round.
         *   { p1: 'p2', p2: 'p1', p3: 'p4', p4: 'p3',  ... },
         *
         *   // Second round.
         *   { p2: 'p3', p3: 'p2', p4: 'p1', p1: 'p4',  ... },
         *
         *   // Further rounds.
         * ];
         * ```
         *
         * @see Matcher.resolvedMatches
         * @see Matcher.resolvedMatchesById
         * @see Matcher.setIds
         * @see Matcher.match
         */
        this.resolvedMatchesObj = null;

        /**
         * ### Matcher.resolvedMatchesById
         *
         * Maps ids to a sequence of matches
         *
         * ```javascript
         *
         * // Matching object.
         * {
         *
         *   // All rounds.
         *   p1: [ 'p2', 'p4', ... ],
         *   p2: [ 'p1', 'p3', ... ],
         *   p3: [ 'p4', 'p2', ... ],
         *   p4: [ 'p3', 'p1', ... ]
         *   ...
         *
         * };
         * ```
         *
         * @see Matcher.resolvedMatches
         * @see Matcher.resolvedMatchesObj
         * @see Matcher.setIds
         * @see Matcher.match
         */
        this.resolvedMatchesById = null;

        /**
         * ### Matcher.ids
         *
         * Array ids to match
         *
         * @see Matcher.setIds
         */
        this.ids = null;

        /**
         * ### Matcher.ids
         *
         * Array mapping each ordinal position to an id
         *
         * @see Matcher.ids
         * @see Matcher.assignerCb
         */
        this.assignedIds = null;

        /**
         * ### Matcher.idsMap
         *
         * Map ids to match
         *
         * @see Matcher.setIds
         */
        this.idsMap = null;

        /**
         * ### Matcher.assignedIdsMap
         *
         * Map ids to ordinal position in matches
         *
         * @see Matcher.idsMap
         * @see Matcher.assignedIds
         */
        this.assignedIdsMap = null;

        /**
         * ### Matcher.assignerCb
         *
         * Callback that assigns ids to positions
         *
         * An assigner callback must take as input an array of ids,
         * reorder them according to some criteria, and return it.
         * The order of the items in the returned array will be used to
         * match the numbers in the `matches` array.
         *
         * @see Matcher.ids
         * @see Matcher.matches
         * @see Matcher.assignedIds
         */
        this.assignerCb = Matcher.randomAssigner;

        /**
         * ## Matcher.missingId
         *
         * An id used to replace missing players ids
         */
        this.missingId = Matcher.missingId;

        /**
         * ## Matcher.missingId
         *
         * An id used by matching algorithms to complete unfinished matches
         */
        this.bye = Matcher.bye;

        /**
         * ## Matcher.doObjLists
         *
         * Flag that obj lists should be created when `match` is invoked
         *
         * @see Matcher.resolvedMatchesObj
         * @see Matcher.matcher
         */
        this.doObjLists = true;

        /**
         * ## Matcher.doIdLists
         *
         * Flag that id lists should be created when `match` is invoked
         *
         * @see Matcher.resolvedMatchesById
         * @see Matcher.matcher
         */
        this.doIdLists = true;

        /**
         * ## Matcher.doRoles
         *
         * Flag that roles should be assigned when `match` is invoked
         *
         * Requires roles to be set, otherwise an error is thrown
         *
         * @see Matcher.roles
         * @see Matcher.roler
         * @see Matcher.matcher
         */
        this.doRoles = false;

        /**
         * ## Matcher.roler
         *
         * Handles assigning roles to matches
         *
         * If null here, is initialized by `init` if doRoles is TRUE.
         *
         * @see Matcher.doRoles
         * @see Matcher.init
         */
        this.roler = options.roler || null;

        /**
         * ## Matcher.roles
         *
         * Roles map created if `doRoles` is TRUE
         *
         * @see Matcher.doRoles
         * @see Matcher.roler
         * @see Matcher.matcher
         */
        this.roler = options.roler || null;

        // Init.
        this.init(options);
    }
134797
@Nullable
    public static Predicate anyOf(Collection<Predicate> exprs) {
        Predicate rv = null;
        for (Predicate b : exprs) {
            if (b != null) {
                rv = rv == null ? b : ExpressionUtils.or(rv,b);
            }
        }
        return rv;
    }
827718
public static Or or(Expression<Boolean> left, Expression<Boolean> right) {
        return new Or(left, right);
    }
650579
public Expr or(Expr expr) {
        if (type == Type.TRUE ||
            type == Type.FALSE ||
            type == NONE) {
            set(expr);
        } else if (expr.type != Type.TRUE &&
                   expr.type != Type.FALSE &&
                   expr.type != Type.NONE) {
            if (type.isLogical() && !expr.type.isLogical()) {
                if (type == OR)
                    right.or(expr);
                else if (type != NOT)
                    setLogical(Type.OR, expr, new Expr(this));
                else
                    setLogical(Type.OR, new Expr(this), expr);
            }
            else
                setLogical(Type.OR, new Expr(this), expr);
        }
        return this;
    }
214169
public void simplify() throws ParseException {
    if (!simplified) {
      simplified = true;
      boolean optionalParts = true;
      List<MtasCQLParserBasicSentencePartCondition> newPartList;
      MtasCQLParserBasicSentencePartCondition lastPart = null;
      newPartList = new ArrayList<MtasCQLParserBasicSentencePartCondition>();
      // try and merge equal basicSentencePart (word/group) conditions
      for (MtasCQLParserBasicSentencePartCondition part : partList) {
        if ((lastPart == null) || !lastPart.equals(part)) {
          lastPart = part;
          newPartList.add(part);
          if (!part.isOptional()) {
            optionalParts = false;
          }
        } else {
          int newMinimumOccurence;
          int newMaximumOccurence;
          if (!lastPart.isOptional() && !part.isOptional()) {
            newMinimumOccurence = lastPart.getMinimumOccurence()
                + part.getMinimumOccurence();
            newMaximumOccurence = lastPart.getMaximumOccurence()
                + part.getMaximumOccurence();
            lastPart.setOccurence(newMinimumOccurence, newMaximumOccurence);
          } else if (!lastPart.isOptional() && part.isOptional()) {
            if (part.getMinimumOccurence() == 1) {
              newMinimumOccurence = lastPart.getMinimumOccurence()
                  + part.getMinimumOccurence() - 1;
              newMaximumOccurence = lastPart.getMaximumOccurence()
                  + part.getMaximumOccurence();
              lastPart.setOccurence(newMinimumOccurence, newMaximumOccurence);
            } else {
              lastPart = part;
              newPartList.add(part);
              if (!part.isOptional()) {
                optionalParts = false;
              }
            }
          } else if (lastPart.isOptional() && !part.isOptional()) {
            if (lastPart.getMinimumOccurence() == 1) {
              newMinimumOccurence = lastPart.getMinimumOccurence()
                  + part.getMinimumOccurence() - 1;
              newMaximumOccurence = lastPart.getMaximumOccurence()
                  + part.getMaximumOccurence();
              lastPart.setOccurence(newMinimumOccurence, newMaximumOccurence);
              lastPart.setOptional(false);
              optionalParts = false;
            } else {
              lastPart = part;
              newPartList.add(part);
              optionalParts = false;
            }
          } else {
            if ((lastPart.getMinimumOccurence() == 1)
                && (part.getMinimumOccurence() == 1)) {
              newMinimumOccurence = 1;
              newMaximumOccurence = lastPart.getMaximumOccurence()
                  + part.getMaximumOccurence();
              lastPart.setOccurence(newMinimumOccurence, newMaximumOccurence);
              lastPart.setOptional(true);
            } else {
              lastPart = part;
              newPartList.add(part);
            }
          }
        }
      }
      partList = newPartList;
      if (optionalParts) {
        optional = true;
      }
    }
  }