private static List<TokenSpan> getSpans(final List<Token> tokens) {
        TokenIndex start = null;
        int dollarStart = -1;
        final List<TokenSpan> tokenSpans = new ArrayList<>();

        for (int i = 0; i < tokens.size(); i++) {
            final Token token = tokens.get(i);
            if (TokenType.UNKNOWN.equals(token.getTokenType())) {
                for (int j = token.getStart(); j <= token.getEnd(); j++) {
                    final char c = token.getChars()[j];
                    if (c == '$') {
                        start = null;
                        dollarStart = j;
                    } else if (c == '{') {
                        if (dollarStart >= 0 && dollarStart == j - 1) {
                            start = new TokenIndex(i, dollarStart);
                        } else {
                            start = null;
                            dollarStart = -1;
                        }
                    } else if (c == '}' && start != null) {
                        final TokenIndex end = new TokenIndex(i, j);
                        tokenSpans.add(new TokenSpan(start, end));
                        start = null;
                        dollarStart = -1;
                    }
                }
            }
        }

        return tokenSpans;
    }
This code is left here in case we decide we want to allow quoted param names.

@param tokens
@return
stroom-query/stroom-query-api/src/main/java/stroom/query/api/token/BasicTokeniser.java