Object parseArrayAccessFilter(boolean acceptBracket) {
            if (acceptBracket) {
                accept('[');
            }

            boolean predicateFlag = false;
            int lparanCount = 0;

            if (ch == '?') {
                next();
                accept('(');
                lparanCount++;
                while (ch == '(') {
                    next();
                    lparanCount++;
                }
                predicateFlag = true;
            }

            skipWhitespace();

            if (predicateFlag
                    || IOUtils.firstIdentifier(ch)
                    || Character.isJavaIdentifierStart(ch)
                    || ch == '\\'
                    || ch == '@') {
                boolean self = false;
                if (ch == '@') {
                    next();
                    accept('.');
                    self = true;
                }
                String propertyName = readName();

                skipWhitespace();

                if (predicateFlag && ch == ')') {
                    next();

                    Filter filter = new NotNullSegement(propertyName, false);
                    while (ch == ' ') {
                        next();
                    }

                    if (ch == '&' || ch == '|') {
                        filter = filterRest(filter);
                    }

                    if (acceptBracket) {
                        accept(']');
                    }
                    return filter;
                }

                if (acceptBracket && ch == ']') {
                    if (isEOF()) {
                        if (propertyName.equals("last")) {
                            return new MultiIndexSegment(new int[]{-1});
                        }
                    }

                    next();
                    Filter filter = new NotNullSegement(propertyName, false);
                    while (ch == ' ') {
                        next();
                    }

                    if (ch == '&' || ch == '|') {
                        filter = filterRest(filter);
                    }

                    accept(')');
                    if (predicateFlag) {
                        accept(')');
                    }

                    if (acceptBracket) {
                        accept(']');
                    }
                    return filter;
                }

                boolean function = false;
                skipWhitespace();
                if (ch == '(') {
                    next();
                    accept(')');
                    skipWhitespace();
                    function = true;
                }

                Operator op = readOp();

                skipWhitespace();

                if (op == Operator.BETWEEN || op == Operator.NOT_BETWEEN) {
                    final boolean not = (op == Operator.NOT_BETWEEN);

                    Object startValue = readValue();

                    String name = readName();

                    if (!"and".equalsIgnoreCase(name)) {
                        throw new JSONPathException(path);
                    }

                    Object endValue = readValue();

                    if (startValue == null || endValue == null) {
                        throw new JSONPathException(path);
                    }

                    if (isInt(startValue.getClass()) && isInt(endValue.getClass())) {
                        Filter filter = new IntBetweenSegement(propertyName
                                , function
                                , TypeUtils.longExtractValue((Number) startValue)
                                , TypeUtils.longExtractValue((Number) endValue)
                                , not);
                        return filter;
                    }

                    throw new JSONPathException(path);
                }

                if (op == Operator.IN || op == Operator.NOT_IN) {
                    final boolean not = (op == Operator.NOT_IN);
                    accept('(');

                    List<Object> valueList = new JSONArray();
                    {
                        Object value = readValue();
                        valueList.add(value);

                        for (;;) {
                            skipWhitespace();
                            if (ch != ',') {
                                break;
                            }
                            next();

                            value = readValue();
                            valueList.add(value);
                        }
                    }

                    boolean isInt = true;
                    boolean isIntObj = true;
                    boolean isString = true;
                    for (Object item : valueList) {
                        if (item == null) {
                            if (isInt) {
                                isInt = false;
                            }
                            continue;
                        }

                        Class<?> clazz = item.getClass();
                        if (isInt && !(clazz == Byte.class || clazz == Short.class || clazz == Integer.class
                                       || clazz == Long.class)) {
                            isInt = false;
                            isIntObj = false;
                        }

                        if (isString && clazz != String.class) {
                            isString = false;
                        }
                    }

                    if (valueList.size() == 1 && valueList.get(0) == null) {
                        Filter filter;
                        if (not) {
                            filter = new NotNullSegement(propertyName, function);
                        } else {
                            filter = new NullSegement(propertyName, function);
                        }

                        while (ch == ' ') {
                            next();
                        }

                        if (ch == '&' || ch == '|') {
                            filter = filterRest(filter);
                        }

                        accept(')');
                        if (predicateFlag) {
                            accept(')');
                        }

                        if (acceptBracket) {
                            accept(']');
                        }

                        return filter;
                    }

                    if (isInt) {
                        if (valueList.size() == 1) {
                            long value = TypeUtils.longExtractValue((Number) valueList.get(0));
                            Operator intOp = not ? Operator.NE : Operator.EQ;
                            Filter filter = new IntOpSegement(propertyName, function, value, intOp);
                            while (ch == ' ') {
                                next();
                            }

                            if (ch == '&' || ch == '|') {
                                filter = filterRest(filter);
                            }

                            accept(')');
                            if (predicateFlag) {
                                accept(')');
                            }

                            if (acceptBracket) {
                                accept(']');
                            }

                            return filter;
                        }

                        long[] values = new long[valueList.size()];
                        for (int i = 0; i < values.length; ++i) {
                            values[i] = TypeUtils.longExtractValue((Number) valueList.get(i));
                        }

                        Filter filter = new IntInSegement(propertyName, function, values, not);

                        while (ch == ' ') {
                            next();
                        }

                        if (ch == '&' || ch == '|') {
                            filter = filterRest(filter);
                        }

                        accept(')');
                        if (predicateFlag) {
                            accept(')');
                        }

                        if (acceptBracket) {
                            accept(']');
                        }

                        return filter;
                    }

                    if (isString) {
                        if (valueList.size() == 1) {
                            String value = (String) valueList.get(0);

                            Operator intOp = not ? Operator.NE : Operator.EQ;
                            Filter filter = new StringOpSegement(propertyName, function, value, intOp);

                            while (ch == ' ') {
                                next();
                            }

                            if (ch == '&' || ch == '|') {
                                filter = filterRest(filter);
                            }

                            accept(')');
                            if (predicateFlag) {
                                accept(')');
                            }

                            if (acceptBracket) {
                                accept(']');
                            }

                            return filter;
                        }

                        String[] values = new String[valueList.size()];
                        valueList.toArray(values);

                        Filter filter = new StringInSegement(propertyName, function, values, not);

                        while (ch == ' ') {
                            next();
                        }

                        if (ch == '&' || ch == '|') {
                            filter = filterRest(filter);
                        }

                        accept(')');
                        if (predicateFlag) {
                            accept(')');
                        }

                        if (acceptBracket) {
                            accept(']');
                        }

                        return filter;
                    }

                    if (isIntObj) {
                        Long[] values = new Long[valueList.size()];
                        for (int i = 0; i < values.length; ++i) {
                            Number item = (Number) valueList.get(i);
                            if (item != null) {
                                values[i] = TypeUtils.longExtractValue(item);
                            }
                        }

                        Filter filter = new IntObjInSegement(propertyName, function, values, not);

                        while (ch == ' ') {
                            next();
                        }

                        if (ch == '&' || ch == '|') {
                            filter = filterRest(filter);
                        }

                        accept(')');
                        if (predicateFlag) {
                            accept(')');
                        }

                        if (acceptBracket) {
                            accept(']');
                        }

                        return filter;
                    }

                    throw new UnsupportedOperationException();
                }

                if (ch == '\'' || ch == '"') {
                    String strValue = readString();

                    Filter filter = null;
                    if (op == Operator.RLIKE) {
                        filter = new RlikeSegement(propertyName, function, strValue, false);
                    } else if (op == Operator.NOT_RLIKE) {
                        filter = new RlikeSegement(propertyName, function, strValue, true);
                    } else  if (op == Operator.LIKE || op == Operator.NOT_LIKE) {
                        while (strValue.indexOf("%%") != -1) {
                            strValue = strValue.replaceAll("%%", "%");
                        }

                        final boolean not = (op == Operator.NOT_LIKE);

                        int p0 = strValue.indexOf('%');
                        if (p0 == -1) {
                            if (op == Operator.LIKE) {
                                op = Operator.EQ;
                            } else {
                                op = Operator.NE;
                            }
                            filter = new StringOpSegement(propertyName, function, strValue, op);
                        } else {
                            String[] items = strValue.split("%");

                            String startsWithValue = null;
                            String endsWithValue = null;
                            String[] containsValues = null;
                            if (p0 == 0) {
                                if (strValue.charAt(strValue.length() - 1) == '%') {
                                    containsValues = new String[items.length - 1];
                                    System.arraycopy(items, 1, containsValues, 0, containsValues.length);
                                } else {
                                    endsWithValue = items[items.length - 1];
                                    if (items.length > 2) {
                                        containsValues = new String[items.length - 2];
                                        System.arraycopy(items, 1, containsValues, 0, containsValues.length);
                                    }
                                }
                            } else if (strValue.charAt(strValue.length() - 1) == '%') {
                                if (items.length == 1) {
                                    startsWithValue = items[0];
                                } else {
                                    containsValues = items;
                                }
                            } else {
                                if (items.length == 1) {
                                    startsWithValue = items[0];
                                } else if (items.length == 2) {
                                    startsWithValue = items[0];
                                    endsWithValue = items[1];
                                } else {
                                    startsWithValue = items[0];
                                    endsWithValue = items[items.length - 1];
                                    containsValues = new String[items.length - 2];
                                    System.arraycopy(items, 1, containsValues, 0, containsValues.length);
                                }
                            }

                            filter = new MatchSegement(propertyName, function, startsWithValue, endsWithValue,
                                    containsValues, not);
                        }
                    } else {
                        filter = new StringOpSegement(propertyName, function, strValue, op);
                    }

                    while (ch == ' ') {
                        next();
                    }

                    if (ch == '&' || ch == '|') {
                        filter = filterRest(filter);
                    }

                    if (predicateFlag) {
                        accept(')');
                    }
                    
                    if (acceptBracket) {
                        accept(']');
                    }

                    return filter;
                }

                if (isDigitFirst(ch)) {
                    long value = readLongValue();
                    double doubleValue = 0D;
                    if (ch == '.') {
                        doubleValue = readDoubleValue(value);
                        
                    }

                    Filter filter;

                    if (doubleValue == 0) {
                        filter = new IntOpSegement(propertyName, function, value, op);
                    } else {
                        filter = new DoubleOpSegement(propertyName, function, doubleValue, op);
                    }

                    while (ch == ' ') {
                        next();
                    }

                    if (lparanCount > 1 && ch == ')') {
                        next();
                        lparanCount--;
                    }

                    if (ch == '&' || ch == '|') {
                        filter = filterRest(filter);
                    }

                    if (predicateFlag) {
                        lparanCount--;
                        accept(')');
                    }

                    if (acceptBracket) {
                        accept(']');
                    }

                    return filter;
                } else if (ch == '$') {
                    Segment segment = readSegement();
                    RefOpSegement filter = new RefOpSegement(propertyName, function, segment, op);
                    hasRefSegment = true;
                    while (ch == ' ') {
                        next();
                    }

                    if (predicateFlag) {
                        accept(')');
                    }

                    if (acceptBracket) {
                        accept(']');
                    }

                    return filter;
                } else if (ch == '/') {
                    int flags = 0;
                    StringBuilder regBuf = new StringBuilder();
                    for (;;) {
                        next();
                        if (ch == '/') {
                            next();
                            if (ch == 'i') {
                                next();
                                flags |= Pattern.CASE_INSENSITIVE;
                            }
                            break;
                        }

                        if (ch == '\\') {
                            next();
                            regBuf.append(ch);
                        } else {
                            regBuf.append(ch);
                        }
                    }

                    Pattern pattern = Pattern.compile(regBuf.toString(), flags);
                    RegMatchSegement filter = new RegMatchSegement(propertyName, function, pattern, op);

                    if (predicateFlag) {
                        accept(')');
                    }

                    if (acceptBracket) {
                        accept(']');
                    }

                    return filter;
                }

                if (ch == 'n') {
                    String name = readName();
                    if ("null".equals(name)) {
                        Filter filter = null;
                        if (op == Operator.EQ) {
                            filter = new NullSegement(propertyName, function);
                        } else if (op == Operator.NE) {
                            filter = new NotNullSegement(propertyName, function);
                        }

                        if (filter != null) {
                            while (ch == ' ') {
                                next();
                            }

                            if (ch == '&' || ch == '|') {
                                filter = filterRest(filter);
                            }
                        }

                        if (predicateFlag) {
                            accept(')');
                        }
                        accept(']');

                        if (filter != null) {
                            return filter;
                        }

                        throw new UnsupportedOperationException();
                    }
                } else if (ch == 't') {
                    String name = readName();
                    
                    if ("true".equals(name)) {
                        Filter filter = null;

                        if (op == Operator.EQ) {
                            filter = new ValueSegment(propertyName, function, Boolean.TRUE, true);
                        } else if (op == Operator.NE) {
                            filter = new ValueSegment(propertyName, function, Boolean.TRUE, false);
                        }

                        if (filter != null) {
                            while (ch == ' ') {
                                next();
                            }

                            if (ch == '&' || ch == '|') {
                                filter = filterRest(filter);
                            }
                        }

                        if (predicateFlag) {
                            accept(')');
                        }
                        accept(']');

                        if (filter != null) {
                            return filter;
                        }

                        throw new UnsupportedOperationException();
                    }
                } else if (ch == 'f') {
                    String name = readName();
                    
                    if ("false".equals(name)) {
                        Filter filter = null;

                        if (op == Operator.EQ) {
                            filter = new ValueSegment(propertyName, function, Boolean.FALSE, true);
                        } else if (op == Operator.NE) {
                            filter = new ValueSegment(propertyName, function, Boolean.FALSE, false);
                        }

                        if (filter != null) {
                            while (ch == ' ') {
                                next();
                            }

                            if (ch == '&' || ch == '|') {
                                filter = filterRest(filter);
                            }
                        }

                        if (predicateFlag) {
                            accept(')');
                        }
                        accept(']');

                        if (filter != null) {
                            return filter;
                        }

                        throw new UnsupportedOperationException();
                    }
                }

                throw new UnsupportedOperationException();
                // accept(')');
            }

            int start = pos - 1;
            char startCh = ch;
            while (ch != ']' && ch != '/' && !isEOF()) {
                if (ch == '.' //
                        && (!predicateFlag) // 
                        && !predicateFlag
                        && startCh != '\''
                ) {
                    break;
                }
                
                if (ch == '\\') {
                    next();
                }
                next();
            }
            
            int end;
            if (acceptBracket) {
                end = pos - 1;
            } else {
                if (ch == '/' || ch == '.') {
                    end = pos - 1;
                } else {
                    end = pos;
                }
            }
            
            String text = path.substring(start, end);

            if (text.indexOf('\\') != 0) {
                StringBuilder buf = new StringBuilder(text.length());
                for (int i = 0; i < text.length(); ++i) {
                    char ch = text.charAt(i);
                    if (ch == '\\' && i < text.length() - 1) {
                        char c2 = text.charAt(i + 1);
                        if (c2 == '@' || ch == '\\' || ch == '\"') {
                            buf.append(c2);
                            i++;
                            continue;
                        }
                    }

                    buf.append(ch);
                }
                text = buf.toString();
            }
            
            if (text.indexOf("\\.") != -1) {
                String propName;
                if (startCh == '\'' && text.length() > 2 && text.charAt(text.length() - 1) == startCh) {
                    propName = text.substring(1, text.length() - 1);
                } else {
                    propName = text.replaceAll("\\\\\\.", "\\.");
                    if (propName.indexOf("\\-") != -1) {
                        propName = propName.replaceAll("\\\\-", "-");
                    }
                }

                if (predicateFlag) {
                    accept(')');
                }

                return new PropertySegment(propName, false);
            }

            Segment segment = buildArraySegement(text);

            if (acceptBracket && !isEOF()) {
                accept(']');
            }

            return segment;
        }
@since 1.2.51
@param json
@param path
@return
src/main/java/com/alibaba/fastjson/JSONPath.java