private static Path parsePathExpression ( Iterator < Token > expression , ConfigOrigin origin , String originalText ) { // 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 ConfigException . BadPath ( origin , originalText , "Expecting a field name or path here, but got nothing" ) ; } while ( expression . hasNext ( ) ) { Token t = expression . next ( ) ; if ( Tokens . isValueWithType ( t , ConfigValueType . STRING ) ) { 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. AbstractConfigValue v = Tokens . getValue ( t ) ; text = v . transformToString ( ) ; } else if ( Tokens . isUnquotedText ( t ) ) { text = Tokens . getUnquotedText ( t ) ; } else { throw new 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 ) ; } } PathBuilder pb = new 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 ( ) ; }
originalText may be null if not available