private void processGroupBy(final KeywordGroup keywordGroup,
                                    final Map<String, Integer> groupMap,
                                    final int groupDepth) {
            String fieldName = null;
            final List<AbstractToken> children = keywordGroup.getChildren();
            boolean first = true;
            for (final AbstractToken t : children) {
                // Ignore BY
                if (!(first && TokenType.BY.equals(t.getTokenType()))) {
                    if (TokenType.isString(t)) {
                        if (fieldName == null) {
                            fieldName = t.getUnescapedText();
                        } else {
                            throw new TokenException(t, "Syntax exception, expected comma");
                        }
                    } else if (TokenType.COMMA.equals(t.getTokenType())) {
                        if (fieldName == null) {
                            throw new TokenException(t, "Syntax exception, expected field name");
                        }
                        groupMap.put(fieldName, groupDepth);
                        fieldName = null;
                    } else {
                        throw new TokenException(t, "Syntax exception, expected field name");
                    }
                }

                first = false;
            }
            if (fieldName != null) {
                groupMap.put(fieldName, groupDepth);
            }
        }
@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