code: private String resolve(String cdr, Function<String,String> map) {
          StringBuilder res = new StringBuilder(cdr.length()*2);
          int state = 0;
          String var = "";
          for (int i=0; i < cdr.length(); i++ ) {
              char c = cdr.charAt(i);
              if ( c == '$' ) {
                  state = 1;
              } else {
                  switch (state) {
                      case 0:
                          res.append(c); break;
                      case 1: {
                          if ( Character.isLetterOrDigit(c) ) {
                              var += c;
                          } else {
                              String apply = map.apply(var);
                              if ( apply != null )
                                  res.append(apply);
                              else
                                  res.append("$"+var);
                              state = 0; i--; var = "";
                          }
                          break;
                      }
                  }
              }
          }
          String expanded = res.toString();
          if ( ! expanded.equals(cdr) )
              return resolve(expanded,map);
          return expanded;
      }
docs: replace $variables by mapping function result