private List<Object> gatherTerms(final List<AbstractToken> tokens) {
            final List<Object> out = new ArrayList<>(tokens.size());

            // Gather terms.
            final List<AbstractToken> termTokens = new ArrayList<>();
            for (final AbstractToken token : tokens) {
                if (termTokens.isEmpty() && token instanceof final KeywordGroup keywordGroup) {
                    out.add(processLogic(keywordGroup.getChildren()));
                } else if (termTokens.isEmpty() && token instanceof final TokenGroup tokenGroup) {
                    out.add(processLogic(tokenGroup.getChildren()));
                } else if (TokenType.AND.equals(token.getTokenType()) ||
                           TokenType.OR.equals(token.getTokenType()) ||
                           TokenType.NOT.equals(token.getTokenType())) {
                    if (!termTokens.isEmpty()) {
                        out.add(createTerm(termTokens));
                        termTokens.clear();
                    }
                    out.add(token);
                } else {
                    termTokens.add(token);
                }
            }
            if (!termTokens.isEmpty()) {
                out.add(createTerm(termTokens));
            }

            return out;
        }
@param isLenient Ignores any additional child tokens found. This is to support getting just
                 the data source from a partially written query, which is likely to not be
                 a valid query. For example, you may type
                 <pre>{@code from View sel}</pre> and at this point do code completion on 'sel'
                 so if this method is called it will treat 'sel as an extra child.
stroom-query/stroom-query-common/src/main/java/stroom/query/language/SearchRequestFactory.java