| Index: source/i18n/nfrs.cpp
 | 
| diff --git a/source/i18n/nfrs.cpp b/source/i18n/nfrs.cpp
 | 
| index 1a4bf493f3eb7ef83cd1ab8a601884a69c890044..85ebb06fabd4ed9ac7b6d91956d24d93bb7b85e9 100644
 | 
| --- a/source/i18n/nfrs.cpp
 | 
| +++ b/source/i18n/nfrs.cpp
 | 
| @@ -1,6 +1,6 @@
 | 
|  /*
 | 
|  ******************************************************************************
 | 
| -*   Copyright (C) 1997-2014, International Business Machines
 | 
| +*   Copyright (C) 1997-2015, International Business Machines
 | 
|  *   Corporation and others.  All Rights Reserved.
 | 
|  ******************************************************************************
 | 
|  *   file name:  nfrs.cpp
 | 
| @@ -26,6 +26,22 @@
 | 
|  #include "cmemory.h"
 | 
|  #endif
 | 
|  
 | 
| +enum {
 | 
| +    /** -x */
 | 
| +    NEGATIVE_RULE_INDEX = 0,
 | 
| +    /** x.x */
 | 
| +    IMPROPER_FRACTION_RULE_INDEX = 1,
 | 
| +    /** 0.x */
 | 
| +    PROPER_FRACTION_RULE_INDEX = 2,
 | 
| +    /** x.0 */
 | 
| +    MASTER_RULE_INDEX = 3,
 | 
| +    /** Inf */
 | 
| +    INFINITY_RULE_INDEX = 4,
 | 
| +    /** NaN */
 | 
| +    NAN_RULE_INDEX = 5,
 | 
| +    NON_NUMERICAL_RULE_LENGTH = 6
 | 
| +};
 | 
| +
 | 
|  U_NAMESPACE_BEGIN
 | 
|  
 | 
|  #if 0
 | 
| @@ -104,10 +120,6 @@ static const UChar gColon = 0x003a;
 | 
|  static const UChar gSemicolon = 0x003b;
 | 
|  static const UChar gLineFeed = 0x000a;
 | 
|  
 | 
| -static const UChar gFourSpaces[] =
 | 
| -{
 | 
| -    0x20, 0x20, 0x20, 0x20, 0
 | 
| -}; /* "    " */
 | 
|  static const UChar gPercentPercent[] =
 | 
|  {
 | 
|      0x25, 0x25, 0
 | 
| @@ -118,17 +130,17 @@ static const UChar gNoparse[] =
 | 
|      0x40, 0x6E, 0x6F, 0x70, 0x61, 0x72, 0x73, 0x65, 0
 | 
|  }; /* "@noparse" */
 | 
|  
 | 
| -NFRuleSet::NFRuleSet(UnicodeString* descriptions, int32_t index, UErrorCode& status)
 | 
| +NFRuleSet::NFRuleSet(RuleBasedNumberFormat *_owner, UnicodeString* descriptions, int32_t index, UErrorCode& status)
 | 
|    : name()
 | 
|    , rules(0)
 | 
| -  , negativeNumberRule(NULL)
 | 
| +  , owner(_owner)
 | 
| +  , fractionRules()
 | 
|    , fIsFractionRuleSet(FALSE)
 | 
|    , fIsPublic(FALSE)
 | 
|    , fIsParseable(TRUE)
 | 
| -  , fRecursionCount(0)
 | 
|  {
 | 
| -    for (int i = 0; i < 3; ++i) {
 | 
| -        fractionRules[i] = NULL;
 | 
| +    for (int32_t i = 0; i < NON_NUMERICAL_RULE_LENGTH; ++i) {
 | 
| +        nonNumericalRules[i] = NULL;
 | 
|      }
 | 
|  
 | 
|      if (U_FAILURE(status)) {
 | 
| @@ -179,7 +191,7 @@ NFRuleSet::NFRuleSet(UnicodeString* descriptions, int32_t index, UErrorCode& sta
 | 
|  }
 | 
|  
 | 
|  void
 | 
| -NFRuleSet::parseRules(UnicodeString& description, const RuleBasedNumberFormat* owner, UErrorCode& status)
 | 
| +NFRuleSet::parseRules(UnicodeString& description, UErrorCode& status)
 | 
|  {
 | 
|      // start by creating a Vector whose elements are Strings containing
 | 
|      // the descriptions of the rules (one rule per element).  The rules
 | 
| @@ -217,85 +229,103 @@ NFRuleSet::parseRules(UnicodeString& description, const RuleBasedNumberFormat* o
 | 
|      // (this isn't a for loop because we might be deleting items from
 | 
|      // the vector-- we want to make sure we only increment i when
 | 
|      // we _didn't_ delete aything from the vector)
 | 
| -    uint32_t i = 0;
 | 
| -    while (i < rules.size()) {
 | 
| +    int32_t rulesSize = rules.size();
 | 
| +    for (int32_t i = 0; i < rulesSize; i++) {
 | 
|          NFRule* rule = rules[i];
 | 
| +        int64_t baseValue = rule->getBaseValue();
 | 
|  
 | 
| -        switch (rule->getType()) {
 | 
| +        if (baseValue == 0) {
 | 
|              // if the rule's base value is 0, fill in a default
 | 
|              // base value (this will be 1 plus the preceding
 | 
|              // rule's base value for regular rule sets, and the
 | 
|              // same as the preceding rule's base value in fraction
 | 
|              // rule sets)
 | 
| -        case NFRule::kNoBase:
 | 
|              rule->setBaseValue(defaultBaseValue, status);
 | 
| -            if (!isFractionRuleSet()) {
 | 
| -                ++defaultBaseValue;
 | 
| -            }
 | 
| -            ++i;
 | 
| -            break;
 | 
| -
 | 
| -            // if it's the negative-number rule, copy it into its own
 | 
| -            // data member and delete it from the list
 | 
| -        case NFRule::kNegativeNumberRule:
 | 
| -            if (negativeNumberRule) {
 | 
| -                delete negativeNumberRule;
 | 
| -            }
 | 
| -            negativeNumberRule = rules.remove(i);
 | 
| -            break;
 | 
| -
 | 
| -            // if it's the improper fraction rule, copy it into the
 | 
| -            // correct element of fractionRules
 | 
| -        case NFRule::kImproperFractionRule:
 | 
| -            if (fractionRules[0]) {
 | 
| -                delete fractionRules[0];
 | 
| -            }
 | 
| -            fractionRules[0] = rules.remove(i);
 | 
| -            break;
 | 
| -
 | 
| -            // if it's the proper fraction rule, copy it into the
 | 
| -            // correct element of fractionRules
 | 
| -        case NFRule::kProperFractionRule:
 | 
| -            if (fractionRules[1]) {
 | 
| -                delete fractionRules[1];
 | 
| -            }
 | 
| -            fractionRules[1] = rules.remove(i);
 | 
| -            break;
 | 
| -
 | 
| -            // if it's the master rule, copy it into the
 | 
| -            // correct element of fractionRules
 | 
| -        case NFRule::kMasterRule:
 | 
| -            if (fractionRules[2]) {
 | 
| -                delete fractionRules[2];
 | 
| -            }
 | 
| -            fractionRules[2] = rules.remove(i);
 | 
| -            break;
 | 
| -
 | 
| +        }
 | 
| +        else {
 | 
|              // if it's a regular rule that already knows its base value,
 | 
|              // check to make sure the rules are in order, and update
 | 
|              // the default base value for the next rule
 | 
| -        default:
 | 
| -            if (rule->getBaseValue() < defaultBaseValue) {
 | 
| +            if (baseValue < defaultBaseValue) {
 | 
|                  // throw new IllegalArgumentException("Rules are not in order");
 | 
|                  status = U_PARSE_ERROR;
 | 
|                  return;
 | 
|              }
 | 
| -            defaultBaseValue = rule->getBaseValue();
 | 
| -            if (!isFractionRuleSet()) {
 | 
| -                ++defaultBaseValue;
 | 
| -            }
 | 
| -            ++i;
 | 
| -            break;
 | 
| +            defaultBaseValue = baseValue;
 | 
| +        }
 | 
| +        if (!fIsFractionRuleSet) {
 | 
| +            ++defaultBaseValue;
 | 
|          }
 | 
|      }
 | 
|  }
 | 
|  
 | 
| +/**
 | 
| + * Set one of the non-numerical rules.
 | 
| + * @param rule The rule to set.
 | 
| + */
 | 
| +void NFRuleSet::setNonNumericalRule(NFRule *rule) {
 | 
| +    int64_t baseValue = rule->getBaseValue();
 | 
| +    if (baseValue == NFRule::kNegativeNumberRule) {
 | 
| +        delete nonNumericalRules[NEGATIVE_RULE_INDEX];
 | 
| +        nonNumericalRules[NEGATIVE_RULE_INDEX] = rule;
 | 
| +    }
 | 
| +    else if (baseValue == NFRule::kImproperFractionRule) {
 | 
| +        setBestFractionRule(IMPROPER_FRACTION_RULE_INDEX, rule, TRUE);
 | 
| +    }
 | 
| +    else if (baseValue == NFRule::kProperFractionRule) {
 | 
| +        setBestFractionRule(PROPER_FRACTION_RULE_INDEX, rule, TRUE);
 | 
| +    }
 | 
| +    else if (baseValue == NFRule::kMasterRule) {
 | 
| +        setBestFractionRule(MASTER_RULE_INDEX, rule, TRUE);
 | 
| +    }
 | 
| +    else if (baseValue == NFRule::kInfinityRule) {
 | 
| +        delete nonNumericalRules[INFINITY_RULE_INDEX];
 | 
| +        nonNumericalRules[INFINITY_RULE_INDEX] = rule;
 | 
| +    }
 | 
| +    else if (baseValue == NFRule::kNaNRule) {
 | 
| +        delete nonNumericalRules[NAN_RULE_INDEX];
 | 
| +        nonNumericalRules[NAN_RULE_INDEX] = rule;
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +/**
 | 
| + * Determine the best fraction rule to use. Rules matching the decimal point from
 | 
| + * DecimalFormatSymbols become the main set of rules to use.
 | 
| + * @param originalIndex The index into nonNumericalRules
 | 
| + * @param newRule The new rule to consider
 | 
| + * @param rememberRule Should the new rule be added to fractionRules.
 | 
| + */
 | 
| +void NFRuleSet::setBestFractionRule(int32_t originalIndex, NFRule *newRule, UBool rememberRule) {
 | 
| +    if (rememberRule) {
 | 
| +        fractionRules.add(newRule);
 | 
| +    }
 | 
| +    NFRule *bestResult = nonNumericalRules[originalIndex];
 | 
| +    if (bestResult == NULL) {
 | 
| +        nonNumericalRules[originalIndex] = newRule;
 | 
| +    }
 | 
| +    else {
 | 
| +        // We have more than one. Which one is better?
 | 
| +        const DecimalFormatSymbols *decimalFormatSymbols = owner->getDecimalFormatSymbols();
 | 
| +        if (decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol).charAt(0)
 | 
| +            == newRule->getDecimalPoint())
 | 
| +        {
 | 
| +            nonNumericalRules[originalIndex] = newRule;
 | 
| +        }
 | 
| +        // else leave it alone
 | 
| +    }
 | 
| +}
 | 
| +
 | 
|  NFRuleSet::~NFRuleSet()
 | 
|  {
 | 
| -    delete negativeNumberRule;
 | 
| -    delete fractionRules[0];
 | 
| -    delete fractionRules[1];
 | 
| -    delete fractionRules[2];
 | 
| +    for (int i = 0; i < NON_NUMERICAL_RULE_LENGTH; i++) {
 | 
| +        if (i != IMPROPER_FRACTION_RULE_INDEX
 | 
| +            && i != PROPER_FRACTION_RULE_INDEX
 | 
| +            && i != MASTER_RULE_INDEX)
 | 
| +        {
 | 
| +            delete nonNumericalRules[i];
 | 
| +        }
 | 
| +        // else it will be deleted via NFRuleList fractionRules
 | 
| +    }
 | 
|  }
 | 
|  
 | 
|  static UBool
 | 
| @@ -316,12 +346,16 @@ NFRuleSet::operator==(const NFRuleSet& rhs) const
 | 
|  {
 | 
|      if (rules.size() == rhs.rules.size() &&
 | 
|          fIsFractionRuleSet == rhs.fIsFractionRuleSet &&
 | 
| -        name == rhs.name &&
 | 
| -        util_equalRules(negativeNumberRule, rhs.negativeNumberRule) &&
 | 
| -        util_equalRules(fractionRules[0], rhs.fractionRules[0]) &&
 | 
| -        util_equalRules(fractionRules[1], rhs.fractionRules[1]) &&
 | 
| -        util_equalRules(fractionRules[2], rhs.fractionRules[2])) {
 | 
| +        name == rhs.name) {
 | 
|  
 | 
| +        // ...then compare the non-numerical rule lists...
 | 
| +        for (int i = 0; i < NON_NUMERICAL_RULE_LENGTH; i++) {
 | 
| +            if (!util_equalRules(nonNumericalRules[i], rhs.nonNumericalRules[i])) {
 | 
| +                return FALSE;
 | 
| +            }
 | 
| +        }
 | 
| +
 | 
| +        // ...then compare the rule lists...
 | 
|          for (uint32_t i = 0; i < rules.size(); ++i) {
 | 
|              if (*rules[i] != *rhs.rules[i]) {
 | 
|                  return FALSE;
 | 
| @@ -332,41 +366,62 @@ NFRuleSet::operator==(const NFRuleSet& rhs) const
 | 
|      return FALSE;
 | 
|  }
 | 
|  
 | 
| -#define RECURSION_LIMIT 50
 | 
| +void
 | 
| +NFRuleSet::setDecimalFormatSymbols(const DecimalFormatSymbols &newSymbols, UErrorCode& status) {
 | 
| +    for (uint32_t i = 0; i < rules.size(); ++i) {
 | 
| +        rules[i]->setDecimalFormatSymbols(newSymbols, status);
 | 
| +    }
 | 
| +    // Switch the fraction rules to mirror the DecimalFormatSymbols.
 | 
| +    for (int32_t nonNumericalIdx = IMPROPER_FRACTION_RULE_INDEX; nonNumericalIdx <= MASTER_RULE_INDEX; nonNumericalIdx++) {
 | 
| +        if (nonNumericalRules[nonNumericalIdx]) {
 | 
| +            for (uint32_t fIdx = 0; fIdx < fractionRules.size(); fIdx++) {
 | 
| +                NFRule *fractionRule = fractionRules[fIdx];
 | 
| +                if (nonNumericalRules[nonNumericalIdx]->getBaseValue() == fractionRule->getBaseValue()) {
 | 
| +                    setBestFractionRule(nonNumericalIdx, fractionRule, FALSE);
 | 
| +                }
 | 
| +            }
 | 
| +        }
 | 
| +    }
 | 
| +
 | 
| +    for (uint32_t nnrIdx = 0; nnrIdx < NON_NUMERICAL_RULE_LENGTH; nnrIdx++) {
 | 
| +        NFRule *rule = nonNumericalRules[nnrIdx];
 | 
| +        if (rule) {
 | 
| +            rule->setDecimalFormatSymbols(newSymbols, status);
 | 
| +        }
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +#define RECURSION_LIMIT 64
 | 
|  
 | 
|  void
 | 
| -NFRuleSet::format(int64_t number, UnicodeString& toAppendTo, int32_t pos, UErrorCode& status) const
 | 
| +NFRuleSet::format(int64_t number, UnicodeString& toAppendTo, int32_t pos, int32_t recursionCount, UErrorCode& status) const
 | 
|  {
 | 
| -    NFRule *rule = findNormalRule(number);
 | 
| +    if (recursionCount >= RECURSION_LIMIT) {
 | 
| +        // stop recursion
 | 
| +        status = U_INVALID_STATE_ERROR;
 | 
| +        return;
 | 
| +    }
 | 
| +    const NFRule *rule = findNormalRule(number);
 | 
|      if (rule) { // else error, but can't report it
 | 
| -        NFRuleSet* ncThis = (NFRuleSet*)this;
 | 
| -        if (ncThis->fRecursionCount++ >= RECURSION_LIMIT) {
 | 
| -            // stop recursion
 | 
| -            ncThis->fRecursionCount = 0;
 | 
| -        } else {
 | 
| -            rule->doFormat(number, toAppendTo, pos, status);
 | 
| -            ncThis->fRecursionCount--;
 | 
| -        }
 | 
| +        rule->doFormat(number, toAppendTo, pos, ++recursionCount, status);
 | 
|      }
 | 
|  }
 | 
|  
 | 
|  void
 | 
| -NFRuleSet::format(double number, UnicodeString& toAppendTo, int32_t pos, UErrorCode& status) const
 | 
| +NFRuleSet::format(double number, UnicodeString& toAppendTo, int32_t pos, int32_t recursionCount, UErrorCode& status) const
 | 
|  {
 | 
| -    NFRule *rule = findDoubleRule(number);
 | 
| +    if (recursionCount >= RECURSION_LIMIT) {
 | 
| +        // stop recursion
 | 
| +        status = U_INVALID_STATE_ERROR;
 | 
| +        return;
 | 
| +    }
 | 
| +    const NFRule *rule = findDoubleRule(number);
 | 
|      if (rule) { // else error, but can't report it
 | 
| -        NFRuleSet* ncThis = (NFRuleSet*)this;
 | 
| -        if (ncThis->fRecursionCount++ >= RECURSION_LIMIT) {
 | 
| -            // stop recursion
 | 
| -            ncThis->fRecursionCount = 0;
 | 
| -        } else {
 | 
| -            rule->doFormat(number, toAppendTo, pos, status);
 | 
| -            ncThis->fRecursionCount--;
 | 
| -        }
 | 
| +        rule->doFormat(number, toAppendTo, pos, ++recursionCount, status);
 | 
|      }
 | 
|  }
 | 
|  
 | 
| -NFRule*
 | 
| +const NFRule*
 | 
|  NFRuleSet::findDoubleRule(double number) const
 | 
|  {
 | 
|      // if this is a fraction rule set, use findFractionRuleSetRule()
 | 
| @@ -374,33 +429,49 @@ NFRuleSet::findDoubleRule(double number) const
 | 
|          return findFractionRuleSetRule(number);
 | 
|      }
 | 
|  
 | 
| +    if (uprv_isNaN(number)) {
 | 
| +        const NFRule *rule = nonNumericalRules[NAN_RULE_INDEX];
 | 
| +        if (!rule) {
 | 
| +            rule = owner->getDefaultNaNRule();
 | 
| +        }
 | 
| +        return rule;
 | 
| +    }
 | 
| +
 | 
|      // if the number is negative, return the negative number rule
 | 
|      // (if there isn't a negative-number rule, we pretend it's a
 | 
|      // positive number)
 | 
|      if (number < 0) {
 | 
| -        if (negativeNumberRule) {
 | 
| -            return  negativeNumberRule;
 | 
| +        if (nonNumericalRules[NEGATIVE_RULE_INDEX]) {
 | 
| +            return  nonNumericalRules[NEGATIVE_RULE_INDEX];
 | 
|          } else {
 | 
|              number = -number;
 | 
|          }
 | 
|      }
 | 
|  
 | 
| +    if (uprv_isInfinite(number)) {
 | 
| +        const NFRule *rule = nonNumericalRules[INFINITY_RULE_INDEX];
 | 
| +        if (!rule) {
 | 
| +            rule = owner->getDefaultInfinityRule();
 | 
| +        }
 | 
| +        return rule;
 | 
| +    }
 | 
| +
 | 
|      // if the number isn't an integer, we use one of the fraction rules...
 | 
|      if (number != uprv_floor(number)) {
 | 
|          // if the number is between 0 and 1, return the proper
 | 
|          // fraction rule
 | 
| -        if (number < 1 && fractionRules[1]) {
 | 
| -            return fractionRules[1];
 | 
| +        if (number < 1 && nonNumericalRules[PROPER_FRACTION_RULE_INDEX]) {
 | 
| +            return nonNumericalRules[PROPER_FRACTION_RULE_INDEX];
 | 
|          }
 | 
|          // otherwise, return the improper fraction rule
 | 
| -        else if (fractionRules[0]) {
 | 
| -            return fractionRules[0];
 | 
| +        else if (nonNumericalRules[IMPROPER_FRACTION_RULE_INDEX]) {
 | 
| +            return nonNumericalRules[IMPROPER_FRACTION_RULE_INDEX];
 | 
|          }
 | 
|      }
 | 
|  
 | 
|      // if there's a master rule, use it to format the number
 | 
| -    if (fractionRules[2]) {
 | 
| -        return fractionRules[2];
 | 
| +    if (nonNumericalRules[MASTER_RULE_INDEX]) {
 | 
| +        return nonNumericalRules[MASTER_RULE_INDEX];
 | 
|      }
 | 
|  
 | 
|      // and if we haven't yet returned a rule, use findNormalRule()
 | 
| @@ -409,7 +480,7 @@ NFRuleSet::findDoubleRule(double number) const
 | 
|      return findNormalRule(r);
 | 
|  }
 | 
|  
 | 
| -NFRule *
 | 
| +const NFRule *
 | 
|  NFRuleSet::findNormalRule(int64_t number) const
 | 
|  {
 | 
|      // if this is a fraction rule set, use findFractionRuleSetRule()
 | 
| @@ -422,8 +493,8 @@ NFRuleSet::findNormalRule(int64_t number) const
 | 
|      // if the number is negative, return the negative-number rule
 | 
|      // (if there isn't one, pretend the number is positive)
 | 
|      if (number < 0) {
 | 
| -        if (negativeNumberRule) {
 | 
| -            return negativeNumberRule;
 | 
| +        if (nonNumericalRules[NEGATIVE_RULE_INDEX]) {
 | 
| +            return nonNumericalRules[NEGATIVE_RULE_INDEX];
 | 
|          } else {
 | 
|              number = -number;
 | 
|          }
 | 
| @@ -480,7 +551,7 @@ NFRuleSet::findNormalRule(int64_t number) const
 | 
|          return result;
 | 
|      }
 | 
|      // else use the master rule
 | 
| -    return fractionRules[2];
 | 
| +    return nonNumericalRules[MASTER_RULE_INDEX];
 | 
|  }
 | 
|  
 | 
|  /**
 | 
| @@ -498,7 +569,7 @@ NFRuleSet::findNormalRule(int64_t number) const
 | 
|   * a number between 0 and 1)
 | 
|   * @return The rule to use to format this number
 | 
|   */
 | 
| -NFRule*
 | 
| +const NFRule*
 | 
|  NFRuleSet::findFractionRuleSetRule(double number) const
 | 
|  {
 | 
|      // the obvious way to do this (multiply the value being formatted
 | 
| @@ -631,40 +702,16 @@ NFRuleSet::parse(const UnicodeString& text, ParsePosition& pos, double upperBoun
 | 
|      fprintf(stderr, "'\n");
 | 
|      fprintf(stderr, "  parse negative: %d\n", this, negativeNumberRule != 0);
 | 
|  #endif
 | 
| -
 | 
| -    // start by trying the negative number rule (if there is one)
 | 
| -    if (negativeNumberRule) {
 | 
| -        Formattable tempResult;
 | 
| -#ifdef RBNF_DEBUG
 | 
| -        fprintf(stderr, "  <nfrs before negative> %x ub: %g\n", negativeNumberRule, upperBound);
 | 
| -#endif
 | 
| -        UBool success = negativeNumberRule->doParse(text, workingPos, 0, upperBound, tempResult);
 | 
| -#ifdef RBNF_DEBUG
 | 
| -        fprintf(stderr, "  <nfrs after negative> success: %d wpi: %d\n", success, workingPos.getIndex());
 | 
| -#endif
 | 
| -        if (success && workingPos.getIndex() > highWaterMark.getIndex()) {
 | 
| -            result = tempResult;
 | 
| -            highWaterMark = workingPos;
 | 
| -        }
 | 
| -        workingPos = pos;
 | 
| -    }
 | 
| -#ifdef RBNF_DEBUG
 | 
| -    fprintf(stderr, "<nfrs> continue fractional with text '");
 | 
| -    dumpUS(stderr, text);
 | 
| -    fprintf(stderr, "' hwm: %d\n", highWaterMark.getIndex());
 | 
| -#endif
 | 
| -    // then try each of the fraction rules
 | 
| -    {
 | 
| -        for (int i = 0; i < 3; i++) {
 | 
| -            if (fractionRules[i]) {
 | 
| -                Formattable tempResult;
 | 
| -                UBool success = fractionRules[i]->doParse(text, workingPos, 0, upperBound, tempResult);
 | 
| -                if (success && (workingPos.getIndex() > highWaterMark.getIndex())) {
 | 
| -                    result = tempResult;
 | 
| -                    highWaterMark = workingPos;
 | 
| -                }
 | 
| -                workingPos = pos;
 | 
| +    // Try each of the negative rules, fraction rules, infinity rules and NaN rules
 | 
| +    for (int i = 0; i < NON_NUMERICAL_RULE_LENGTH; i++) {
 | 
| +        if (nonNumericalRules[i]) {
 | 
| +            Formattable tempResult;
 | 
| +            UBool success = nonNumericalRules[i]->doParse(text, workingPos, 0, upperBound, tempResult);
 | 
| +            if (success && (workingPos.getIndex() > highWaterMark.getIndex())) {
 | 
| +                result = tempResult;
 | 
| +                highWaterMark = workingPos;
 | 
|              }
 | 
| +            workingPos = pos;
 | 
|          }
 | 
|      }
 | 
|  #ifdef RBNF_DEBUG
 | 
| @@ -720,30 +767,37 @@ NFRuleSet::parse(const UnicodeString& text, ParsePosition& pos, double upperBoun
 | 
|  void
 | 
|  NFRuleSet::appendRules(UnicodeString& result) const
 | 
|  {
 | 
| +    uint32_t i;
 | 
| +
 | 
|      // the rule set name goes first...
 | 
|      result.append(name);
 | 
|      result.append(gColon);
 | 
|      result.append(gLineFeed);
 | 
|  
 | 
|      // followed by the regular rules...
 | 
| -    for (uint32_t i = 0; i < rules.size(); i++) {
 | 
| -        result.append(gFourSpaces, 4);
 | 
| +    for (i = 0; i < rules.size(); i++) {
 | 
|          rules[i]->_appendRuleText(result);
 | 
|          result.append(gLineFeed);
 | 
|      }
 | 
|  
 | 
|      // followed by the special rules (if they exist)
 | 
| -    if (negativeNumberRule) {
 | 
| -        result.append(gFourSpaces, 4);
 | 
| -        negativeNumberRule->_appendRuleText(result);
 | 
| -        result.append(gLineFeed);
 | 
| -    }
 | 
| -
 | 
| -    {
 | 
| -        for (uint32_t i = 0; i < 3; ++i) {
 | 
| -            if (fractionRules[i]) {
 | 
| -                result.append(gFourSpaces, 4);
 | 
| -                fractionRules[i]->_appendRuleText(result);
 | 
| +    for (i = 0; i < NON_NUMERICAL_RULE_LENGTH; ++i) {
 | 
| +        NFRule *rule = nonNumericalRules[i];
 | 
| +        if (nonNumericalRules[i]) {
 | 
| +            if (rule->getBaseValue() == NFRule::kImproperFractionRule
 | 
| +                || rule->getBaseValue() == NFRule::kProperFractionRule
 | 
| +                || rule->getBaseValue() == NFRule::kMasterRule)
 | 
| +            {
 | 
| +                for (uint32_t fIdx = 0; fIdx < fractionRules.size(); fIdx++) {
 | 
| +                    NFRule *fractionRule = fractionRules[fIdx];
 | 
| +                    if (fractionRule->getBaseValue() == rule->getBaseValue()) {
 | 
| +                        fractionRule->_appendRuleText(result);
 | 
| +                        result.append(gLineFeed);
 | 
| +                    }
 | 
| +                }
 | 
| +            }
 | 
| +            else {
 | 
| +                rule->_appendRuleText(result);
 | 
|                  result.append(gLineFeed);
 | 
|              }
 | 
|          }
 | 
| 
 |