code: private void extractSubstitutions(NFRuleSet             owner,
                                        String                ruleText,
                                        NFRule                predecessor) {
          this.ruleText = ruleText;
          sub1 = extractSubstitution(owner, predecessor);
          if (sub1 == null) {
              // Small optimization. There is no need to create a redundant NullSubstitution.
              sub2 = null;
          }
          else {
              sub2 = extractSubstitution(owner, predecessor);
          }
          ruleText = this.ruleText;
          int pluralRuleStart = ruleText.indexOf("$(");
          int pluralRuleEnd = (pluralRuleStart >= 0 ? ruleText.indexOf(")$", pluralRuleStart) : -1);
          if (pluralRuleEnd >= 0) {
              int endType = ruleText.indexOf(',', pluralRuleStart);
              if (endType < 0) {
                  throw new IllegalArgumentException("Rule \"" + ruleText + "\" does not have a defined type");
              }
              String type = this.ruleText.substring(pluralRuleStart + 2, endType);
              PluralRules.PluralType pluralType;
              if ("cardinal".equals(type)) {
                  pluralType = PluralRules.PluralType.CARDINAL;
              }
              else if ("ordinal".equals(type)) {
                  pluralType = PluralRules.PluralType.ORDINAL;
              }
              else {
                  throw new IllegalArgumentException(type + " is an unknown type");
              }
              rulePatternFormat = formatter.createPluralFormat(pluralType,
                      ruleText.substring(endType + 1, pluralRuleEnd));
          }
      }
docs: Searches the rule's rule text for the substitution tokens,
  creates the substitutions, and removes the substitution tokens
  from the rule's rule text.
  @param owner The rule set containing this rule
  @param predecessor The rule preceding this one in "owners" rule list
  @param ruleText The rule text