protected static Path parsePathExpression()

in scripts/src/main/java/com/gu/typesafe/config/impl/PathParser.java [90:180]


    protected static Path parsePathExpression(Iterator<Token> expression,
                                              ConfigOrigin origin, String originalText,
                                              ArrayList<Token> pathTokens,
                                              com.gu.typesafe.config.ConfigSyntax flavor) {
        // each builder in "buf" is an element in the path.
        List<Element> buf = new ArrayList<Element>();
        buf.add(new Element("", false));

        if (!expression.hasNext()) {
            throw new com.gu.typesafe.config.ConfigException.BadPath(origin, originalText,
                    "Expecting a field name or path here, but got nothing");
        }

        while (expression.hasNext()) {
            Token t = expression.next();

            if (pathTokens != null)
                pathTokens.add(t);

            // Ignore all IgnoredWhitespace tokens
            if (Tokens.isIgnoredWhitespace(t))
                continue;

            if (Tokens.isValueWithType(t, ConfigValueType.STRING)) {
                com.gu.typesafe.config.impl.AbstractConfigValue v = Tokens.getValue(t);
                // this is a quoted string; so any periods
                // in here don't count as path separators
                String s = v.transformToString();

                addPathText(buf, true, s);
            } else if (t == Tokens.END) {
                // ignore this; when parsing a file, it should not happen
                // since we're parsing a token list rather than the main
                // token iterator, and when parsing a path expression from the
                // API, it's expected to have an END.
            } else {
                // any periods outside of a quoted string count as
                // separators
                String text;
                if (Tokens.isValue(t)) {
                    // appending a number here may add
                    // a period, but we _do_ count those as path
                    // separators, because we basically want
                    // "foo 3.0bar" to parse as a string even
                    // though there's a number in it. The fact that
                    // we tokenize non-string values is largely an
                    // implementation detail.
                    com.gu.typesafe.config.impl.AbstractConfigValue v = Tokens.getValue(t);

                    // We need to split the tokens on a . so that we can get sub-paths but still preserve
                    // the original path text when doing an insertion
                    if (pathTokens != null) {
                        pathTokens.remove(pathTokens.size() - 1);
                        pathTokens.addAll(splitTokenOnPeriod(t, flavor));
                    }
                    text = v.transformToString();
                } else if (Tokens.isUnquotedText(t)) {
                    // We need to split the tokens on a . so that we can get sub-paths but still preserve
                    // the original path text when doing an insertion on ConfigNodeObjects
                    if (pathTokens != null) {
                        pathTokens.remove(pathTokens.size() - 1);
                        pathTokens.addAll(splitTokenOnPeriod(t, flavor));
                    }
                    text = Tokens.getUnquotedText(t);
                } else {
                    throw new com.gu.typesafe.config.ConfigException.BadPath(
                            origin,
                            originalText,
                            "Token not allowed in path expression: "
                                    + t
                                    + " (you can double-quote this token if you really want it here)");
                }

                addPathText(buf, false, text);
            }
        }

        com.gu.typesafe.config.impl.PathBuilder pb = new com.gu.typesafe.config.impl.PathBuilder();
        for (Element e : buf) {
            if (e.sb.length() == 0 && !e.canBeEmpty) {
                throw new ConfigException.BadPath(
                        origin,
                        originalText,
                        "path has a leading, trailing, or two adjacent period '.' (use quoted \"\" empty string if you want an empty element)");
            } else {
                pb.appendKey(e.sb.toString());
            }
        }

        return pb.result();
    }