]> granicus.if.org Git - icu/commitdiff
ICU-13574 Trying to get std::move operator to work on AffixMatcherWarehouse. No...
authorShane Carr <shane@unicode.org>
Sat, 10 Feb 2018 15:49:02 +0000 (15:49 +0000)
committerShane Carr <shane@unicode.org>
Sat, 10 Feb 2018 15:49:02 +0000 (15:49 +0000)
X-SVN-Rev: 40895

icu4c/source/i18n/numparse_affixes.cpp
icu4c/source/i18n/numparse_affixes.h
icu4c/source/i18n/numparse_impl.cpp
icu4c/source/i18n/numparse_impl.h
icu4c/source/i18n/numparse_types.h
icu4c/source/test/intltest/numbertest_parse.cpp
icu4j/main/classes/core/src/com/ibm/icu/impl/number/parse/AffixMatcher.java

index a164f0b70e429e8529483451d181705b054e5b1d..b5d447f192f1ffb0a1bfa04e7987d2141055e310 100644 (file)
@@ -17,6 +17,42 @@ using namespace icu::number;
 using namespace icu::number::impl;
 
 
+namespace {
+
+/**
+ * Helper method to return whether the given AffixPatternMatcher equals the given pattern string.
+ * Either both arguments must be null or the pattern string inside the AffixPatternMatcher must equal
+ * the given pattern string.
+ */
+static bool matched(const AffixPatternMatcher* affix, const UnicodeString& patternString) {
+    return (affix == nullptr && patternString.isBogus()) ||
+           (affix != nullptr && affix->getPattern() == patternString);
+}
+
+/**
+ * Helper method to return the length of the given AffixPatternMatcher. Returns 0 for null.
+ */
+static int32_t length(const AffixPatternMatcher* matcher) {
+    return matcher == nullptr ? 0 : matcher->getPattern().length();
+}
+
+/**
+ * Helper method to return whether (1) both lhs and rhs are null/invalid, or (2) if they are both
+ * valid, whether they are equal according to operator==.  Similar to Java Objects.equals()
+ */
+static bool equals(const AffixPatternMatcher* lhs, const AffixPatternMatcher* rhs) {
+    if (lhs == nullptr && rhs == nullptr) {
+        return true;
+    }
+    if (lhs == nullptr || rhs == nullptr) {
+        return false;
+    }
+    return *lhs == *rhs;
+}
+
+}
+
+
 AffixPatternMatcherBuilder::AffixPatternMatcherBuilder(const UnicodeString& pattern,
                                                        AffixTokenMatcherWarehouse& warehouse,
                                                        IgnorablesMatcher* ignorables)
@@ -101,6 +137,9 @@ AffixTokenMatcherWarehouse::AffixTokenMatcherWarehouse(const UChar* currencyCode
     utils::copyCurrencyCode(this->currencyCode, currencyCode);
 }
 
+AffixTokenMatcherWarehouse::AffixTokenMatcherWarehouse(
+        AffixTokenMatcherWarehouse&& src) U_NOEXCEPT = default;
+
 AffixTokenMatcherWarehouse::~AffixTokenMatcherWarehouse() {
     // Delete the variable number of batches of code point matchers
     for (int32_t i = 0; i < codePointNumBatches; i++) {
@@ -204,16 +243,53 @@ bool AffixPatternMatcher::operator==(const AffixPatternMatcher& other) const {
 }
 
 
-AffixMatcherWarehouse::AffixMatcherWarehouse(const AffixPatternProvider& patternInfo,
-                                             NumberParserImpl& output,
-                                             AffixTokenMatcherWarehouse& warehouse,
-                                             const IgnorablesMatcher& ignorables, parse_flags_t parseFlags,
-                                             UErrorCode& status)
-        : fAffixTokenMatcherWarehouse(std::move(warehouse)) {
+AffixMatcherWarehouse::AffixMatcherWarehouse(AffixTokenMatcherWarehouse& warehouse)
+        : fAffixTokenMatcherWarehouse(std::move(warehouse)) {}
+
+AffixMatcherWarehouse& AffixMatcherWarehouse::operator=(AffixMatcherWarehouse&& src) = default;
+
+bool AffixMatcherWarehouse::isInteresting(const AffixPatternProvider& patternInfo,
+                                          const IgnorablesMatcher& ignorables, parse_flags_t parseFlags,
+                                          UErrorCode& status) {
+    UnicodeStringCharSequence posPrefixString(patternInfo.getString(AffixPatternProvider::AFFIX_POS_PREFIX));
+    UnicodeStringCharSequence posSuffixString(patternInfo.getString(AffixPatternProvider::AFFIX_POS_SUFFIX));
+    UnicodeStringCharSequence negPrefixString(UnicodeString(u""));
+    UnicodeStringCharSequence negSuffixString(UnicodeString(u""));
+    if (patternInfo.hasNegativeSubpattern()) {
+        negPrefixString = UnicodeStringCharSequence(patternInfo.getString(AffixPatternProvider::AFFIX_NEG_PREFIX));
+        negSuffixString = UnicodeStringCharSequence(patternInfo.getString(AffixPatternProvider::AFFIX_NEG_SUFFIX));
+    }
+
+    if (0 == (parseFlags & PARSE_FLAG_USE_FULL_AFFIXES) &&
+        AffixUtils::containsOnlySymbolsAndIgnorables(posPrefixString, *ignorables.getSet(), status) &&
+        AffixUtils::containsOnlySymbolsAndIgnorables(posSuffixString, *ignorables.getSet(), status) &&
+        AffixUtils::containsOnlySymbolsAndIgnorables(negPrefixString, *ignorables.getSet(), status) &&
+        AffixUtils::containsOnlySymbolsAndIgnorables(negSuffixString, *ignorables.getSet(), status)
+        // HACK: Plus and minus sign are a special case: we accept them trailing only if they are
+        // trailing in the pattern string.
+        && !AffixUtils::containsType(posSuffixString, TYPE_PLUS_SIGN, status) &&
+        !AffixUtils::containsType(posSuffixString, TYPE_MINUS_SIGN, status) &&
+        !AffixUtils::containsType(negSuffixString, TYPE_PLUS_SIGN, status) &&
+        !AffixUtils::containsType(negSuffixString, TYPE_MINUS_SIGN, status)) {
+        // The affixes contain only symbols and ignorables.
+        // No need to generate affix matchers.
+        return false;
+    }
+    return true;
+}
+
+AffixMatcherWarehouse AffixMatcherWarehouse::createAffixMatchers(const AffixPatternProvider& patternInfo,
+                                                                 MutableMatcherCollection& output,
+                                                                 AffixTokenMatcherWarehouse tokenWarehouse,
+                                                                 const IgnorablesMatcher& ignorables,
+                                                                 parse_flags_t parseFlags,
+                                                                 UErrorCode& status) {
     if (!isInteresting(patternInfo, ignorables, parseFlags, status)) {
-        return;
+        return {};
     }
 
+    AffixMatcherWarehouse warehouse(tokenWarehouse);
+
     // The affixes have interesting characters, or we are in strict mode.
     // Use initial capacity of 6, the highest possible number of AffixMatchers.
     UnicodeString sb;
@@ -233,19 +309,21 @@ AffixMatcherWarehouse::AffixMatcherWarehouse(const AffixPatternProvider& pattern
         bool hasPrefix = false;
         PatternStringUtils::patternInfoToStringBuilder(
                 patternInfo, true, signum, signDisplay, StandardPlural::OTHER, false, sb);
-        fAffixPatternMatchers[numAffixPatternMatchers] = AffixPatternMatcher::fromAffixPattern(
-                sb, warehouse, parseFlags, &hasPrefix, status);
-        AffixPatternMatcher* prefix = hasPrefix ? &fAffixPatternMatchers[numAffixPatternMatchers++]
-                                                : nullptr;
+        warehouse.fAffixPatternMatchers[numAffixPatternMatchers] = AffixPatternMatcher::fromAffixPattern(
+                sb, tokenWarehouse, parseFlags, &hasPrefix, status);
+        AffixPatternMatcher* prefix = hasPrefix
+                                      ? &warehouse.fAffixPatternMatchers[numAffixPatternMatchers++]
+                                      : nullptr;
 
         // Generate Suffix
         bool hasSuffix = false;
         PatternStringUtils::patternInfoToStringBuilder(
                 patternInfo, false, signum, signDisplay, StandardPlural::OTHER, false, sb);
-        fAffixPatternMatchers[numAffixPatternMatchers] = AffixPatternMatcher::fromAffixPattern(
-                sb, warehouse, parseFlags, &hasSuffix, status);
-        AffixPatternMatcher* suffix = hasSuffix ? &fAffixPatternMatchers[numAffixPatternMatchers++]
-                                                : nullptr;
+        warehouse.fAffixPatternMatchers[numAffixPatternMatchers] = AffixPatternMatcher::fromAffixPattern(
+                sb, tokenWarehouse, parseFlags, &hasSuffix, status);
+        AffixPatternMatcher* suffix = hasSuffix
+                                      ? &warehouse.fAffixPatternMatchers[numAffixPatternMatchers++]
+                                      : nullptr;
 
         if (signum == 1) {
             posPrefix = prefix;
@@ -260,62 +338,37 @@ AffixMatcherWarehouse::AffixMatcherWarehouse(const AffixPatternProvider& pattern
 
         // Note: it is indeed possible for posPrefix and posSuffix to both be null.
         // We still need to add that matcher for strict mode to work.
-        fAffixMatchers[numAffixMatchers++] = {prefix, suffix, flags};
+        warehouse.fAffixMatchers[numAffixMatchers++] = {prefix, suffix, flags};
         if (includeUnpaired && prefix != nullptr && suffix != nullptr) {
             // The following if statements are designed to prevent adding two identical matchers.
             if (signum == 1 || equals(prefix, posPrefix)) {
-                fAffixMatchers[numAffixMatchers++] = {prefix, nullptr, flags};
+                warehouse.fAffixMatchers[numAffixMatchers++] = {prefix, nullptr, flags};
             }
             if (signum == 1 || equals(suffix, posSuffix)) {
-                fAffixMatchers[numAffixMatchers++] = {nullptr, suffix, flags};
+                warehouse.fAffixMatchers[numAffixMatchers++] = {nullptr, suffix, flags};
             }
         }
     }
 
     // Put the AffixMatchers in order, and then add them to the output.
-    // TODO
-//    Collections.sort(matchers, COMPARATOR);
-//    output.addMatchers(matchers);
-}
-
-bool AffixMatcherWarehouse::isInteresting(const AffixPatternProvider& patternInfo,
-                                          const IgnorablesMatcher& ignorables, parse_flags_t parseFlags,
-                                          UErrorCode& status) {
-    UnicodeStringCharSequence posPrefixString(patternInfo.getString(AffixPatternProvider::AFFIX_POS_PREFIX));
-    UnicodeStringCharSequence posSuffixString(patternInfo.getString(AffixPatternProvider::AFFIX_POS_SUFFIX));
-    UnicodeStringCharSequence negPrefixString(UnicodeString(u""));
-    UnicodeStringCharSequence negSuffixString(UnicodeString(u""));
-    if (patternInfo.hasNegativeSubpattern()) {
-        negPrefixString = UnicodeStringCharSequence(patternInfo.getString(AffixPatternProvider::AFFIX_NEG_PREFIX));
-        negSuffixString = UnicodeStringCharSequence(patternInfo.getString(AffixPatternProvider::AFFIX_NEG_SUFFIX));
-    }
-
-    if (0 == (parseFlags & PARSE_FLAG_USE_FULL_AFFIXES) &&
-        AffixUtils::containsOnlySymbolsAndIgnorables(posPrefixString, *ignorables.getSet(), status) &&
-        AffixUtils::containsOnlySymbolsAndIgnorables(posSuffixString, *ignorables.getSet(), status) &&
-        AffixUtils::containsOnlySymbolsAndIgnorables(negPrefixString, *ignorables.getSet(), status) &&
-        AffixUtils::containsOnlySymbolsAndIgnorables(negSuffixString, *ignorables.getSet(), status)
-        // HACK: Plus and minus sign are a special case: we accept them trailing only if they are
-        // trailing in the pattern string.
-        && !AffixUtils::containsType(posSuffixString, TYPE_PLUS_SIGN, status) &&
-        !AffixUtils::containsType(posSuffixString, TYPE_MINUS_SIGN, status) &&
-        !AffixUtils::containsType(negSuffixString, TYPE_PLUS_SIGN, status) &&
-        !AffixUtils::containsType(negSuffixString, TYPE_MINUS_SIGN, status)) {
-        // The affixes contain only symbols and ignorables.
-        // No need to generate affix matchers.
-        return false;
+    // Since there are at most 9 elements, do a simple-to-implement bubble sort.
+    bool madeChanges;
+    do {
+        madeChanges = false;
+        for (int32_t i = 1; i < numAffixMatchers; i++) {
+            if (warehouse.fAffixMatchers[i - 1].compareTo(warehouse.fAffixMatchers[i]) > 0) {
+                madeChanges = true;
+                AffixMatcher temp = std::move(warehouse.fAffixMatchers[i - 1]);
+                warehouse.fAffixMatchers[i - 1] = std::move(warehouse.fAffixMatchers[i]);
+                warehouse.fAffixMatchers[i] = std::move(temp);
+            }
+        }
+    } while (madeChanges);
+    for (int32_t i = 0; i < numAffixMatchers; i++) {
+        output.addMatcher(warehouse.fAffixMatchers[i]);
     }
-    return true;
-}
 
-bool AffixMatcherWarehouse::equals(const AffixPatternMatcher* lhs, const AffixPatternMatcher* rhs) {
-    if (lhs == nullptr && rhs == nullptr) {
-        return true;
-    }
-    if (lhs == nullptr || rhs == nullptr) {
-        return false;
-    }
-    return *lhs == *rhs;
+    return warehouse;
 }
 
 
@@ -390,9 +443,15 @@ void AffixMatcher::postProcess(ParsedNumber& result) const {
     }
 }
 
-bool AffixMatcher::matched(const AffixPatternMatcher* affix, const UnicodeString& patternString) {
-    return (affix == nullptr && patternString.isBogus()) ||
-           (affix != nullptr && affix->getPattern() == patternString);
+int8_t AffixMatcher::compareTo(const AffixMatcher& rhs) const {
+    const AffixMatcher& lhs = *this;
+    if (length(lhs.fPrefix) != length(rhs.fPrefix)) {
+        return length(lhs.fPrefix) > length(rhs.fPrefix) ? -1 : 1;
+    } else if (length(lhs.fSuffix) != length(rhs.fSuffix)) {
+        return length(lhs.fSuffix) > length(rhs.fSuffix) ? -1 : 1;
+    } else {
+        return 0;
+    }
 }
 
 
index 69c68227de5fa29e9a0320d6b60c3c2f23e32e2b..17175ce7d90d5803e2468a77faa5e7d9bd0ee5bb 100644 (file)
@@ -60,7 +60,7 @@ class AffixTokenMatcherWarehouse {
                                const UnicodeString* currency2, const DecimalFormatSymbols* dfs,
                                IgnorablesMatcher* ignorables, const Locale* locale);
 
-    AffixTokenMatcherWarehouse(AffixTokenMatcherWarehouse&& src) = default;
+    AffixTokenMatcherWarehouse(AffixTokenMatcherWarehouse&& src) U_NOEXCEPT;
 
     ~AffixTokenMatcherWarehouse();
 
@@ -102,7 +102,7 @@ class AffixTokenMatcherWarehouse {
 };
 
 
-class AffixPatternMatcherBuilder : public TokenConsumer {
+class AffixPatternMatcherBuilder : public TokenConsumer, public MutableMatcherCollection {
   public:
     AffixPatternMatcherBuilder(const UnicodeString& pattern, AffixTokenMatcherWarehouse& warehouse,
                                IgnorablesMatcher* ignorables);
@@ -121,7 +121,7 @@ class AffixPatternMatcherBuilder : public TokenConsumer {
     AffixTokenMatcherWarehouse& fWarehouse;
     IgnorablesMatcher* fIgnorables;
 
-    void addMatcher(NumberParseMatcher& matcher);
+    void addMatcher(NumberParseMatcher& matcher) override;
 };
 
 
@@ -153,25 +153,18 @@ class AffixMatcher : public NumberParseMatcher, public UMemory {
 
     AffixMatcher(AffixPatternMatcher* prefix, AffixPatternMatcher* suffix, result_flags_t flags);
 
-    // static void createMatchers() is the constructor for AffixMatcherWarehouse in C++
-
     bool match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const override;
 
     void postProcess(ParsedNumber& result) const override;
 
     const UnicodeSet& getLeadCodePoints() override;
 
+    int8_t compareTo(const AffixMatcher& rhs) const;
+
   private:
     AffixPatternMatcher* fPrefix;
     AffixPatternMatcher* fSuffix;
     result_flags_t fFlags;
-
-    /**
-     * Helper method to return whether the given AffixPatternMatcher equals the given pattern string.
-     * Either both arguments must be null or the pattern string inside the AffixPatternMatcher must equal
-     * the given pattern string.
-     */
-    static bool matched(const AffixPatternMatcher* affix, const UnicodeString& patternString);
 };
 
 
@@ -182,10 +175,15 @@ class AffixMatcherWarehouse {
   public:
     AffixMatcherWarehouse() = default;  // WARNING: Leaves the object in an unusable state
 
-    // in Java, this is AffixMatcher#createMatchers()
-    AffixMatcherWarehouse(const AffixPatternProvider& patternInfo, NumberParserImpl& output,
-                          AffixTokenMatcherWarehouse& warehouse, const IgnorablesMatcher& ignorables,
-                          parse_flags_t parseFlags, UErrorCode& status);
+    AffixMatcherWarehouse(AffixTokenMatcherWarehouse& warehouse);
+
+    AffixMatcherWarehouse& operator=(AffixMatcherWarehouse&& src);
+
+    static AffixMatcherWarehouse createAffixMatchers(const AffixPatternProvider& patternInfo,
+                                                     MutableMatcherCollection& output,
+                                                     AffixTokenMatcherWarehouse tokenWarehouse,
+                                                     const IgnorablesMatcher& ignorables,
+                                                     parse_flags_t parseFlags, UErrorCode& status);
 
   private:
     // 9 is the limit: positive, zero, and negative, each with prefix, suffix, and prefix+suffix
@@ -195,14 +193,10 @@ class AffixMatcherWarehouse {
     // Store all the tokens used by the AffixPatternMatchers
     AffixTokenMatcherWarehouse fAffixTokenMatcherWarehouse;
 
+    friend class AffixMatcher;
+
     static bool isInteresting(const AffixPatternProvider& patternInfo, const IgnorablesMatcher& ignorables,
                               parse_flags_t parseFlags, UErrorCode& status);
-
-    /**
-     * Helper method to return whether (1) both lhs and rhs are null/invalid, or (2) if they are both
-     * valid, whether they are equal according to operator==.  Similar to Java Objects.equals()
-     */
-    static bool equals(const AffixPatternMatcher* lhs, const AffixPatternMatcher* rhs);
 };
 
 
index efa9b3cab2f2555ef08061fd551c2ba891c1d565..5bf373de58a887ec11de607cb09a7adee111c097 100644 (file)
@@ -32,18 +32,27 @@ NumberParserImpl::createSimpleParser(const Locale& locale, const UnicodeString&
     auto* parser = new NumberParserImpl(parseFlags, true);
     DecimalFormatSymbols symbols(locale, status);
 
-    parser->fLocalMatchers.ignorables = std::move(IgnorablesMatcher(unisets::DEFAULT_IGNORABLES));
+    parser->fLocalMatchers.ignorables = {unisets::DEFAULT_IGNORABLES};
+    IgnorablesMatcher& ignorables = parser->fLocalMatchers.ignorables;
 
-//    MatcherFactory factory = new MatcherFactory();
-//    factory.currency = Currency.getInstance("USD");
-//    factory.symbols = symbols;
-//    factory.ignorables = ignorables;
-//    factory.locale = locale;
-//    factory.parseFlags = parseFlags;
+    UnicodeString currency1(u"IU$");
+    UnicodeString currency2(u"ICU");
 
     ParsedPatternInfo patternInfo;
     PatternParser::parseToPatternInfo(patternString, patternInfo, status);
-//    AffixMatcher.createMatchers(patternInfo, parser, factory, ignorables, parseFlags);
+
+    // The following statement sets up the affix matchers.
+//    AffixMatcherWarehouse warehouse = ;
+
+    parser->fLocalMatchers.affixMatcherWarehouse = std::move(AffixMatcherWarehouse::createAffixMatchers(
+            patternInfo,
+            *parser,
+            AffixTokenMatcherWarehouse(
+                    u"USD", &currency1, &currency2, &symbols, &ignorables, &locale),
+            ignorables,
+            parseFlags,
+            status));
+
 
     Grouper grouper = Grouper::forStrategy(UNUM_GROUPING_AUTO);
     grouper.setLocaleData(patternInfo, locale);
index abc826f590bc7d5e43cf29d17c6a571fe0f33799..cfae156d5644cf26cbad833d27393f611398c9f7 100644 (file)
 #include "numparse_scientific.h"
 #include "unicode/uniset.h"
 #include "numparse_currency.h"
+#include "numparse_affixes.h"
 
 U_NAMESPACE_BEGIN namespace numparse {
 namespace impl {
 
-class NumberParserImpl {
+class NumberParserImpl : public MutableMatcherCollection {
   public:
-    ~NumberParserImpl();
+    virtual ~NumberParserImpl();
 
     static NumberParserImpl* createSimpleParser(const Locale& locale, const UnicodeString& patternString,
                                                 parse_flags_t parseFlags, UErrorCode& status);
 
-    void addMatcher(NumberParseMatcher& matcher);
+    void addMatcher(NumberParseMatcher& matcher) override;
 
     void freeze();
 
@@ -58,6 +59,7 @@ class NumberParserImpl {
         DecimalMatcher decimal;
         ScientificMatcher scientific;
         CurrencyNamesMatcher currencyNames;
+        AffixMatcherWarehouse affixMatcherWarehouse;
     } fLocalMatchers;
 
     NumberParserImpl(parse_flags_t parseFlags, bool computeLeads);
index 8a92dc93fbd7268e8850ed3b5527c9d121023238..d958a97b9d6509202877a7038f43e1dc6869bf38 100644 (file)
@@ -327,6 +327,17 @@ class NumberParseMatcher {
 };
 
 
+/**
+ * Interface for use in arguments.
+ */
+class MutableMatcherCollection {
+  public:
+    virtual ~MutableMatcherCollection() = default;
+
+    virtual void addMatcher(NumberParseMatcher& matcher) = 0;
+};
+
+
 } // namespace impl
 } // namespace numparse
 U_NAMESPACE_END
index 4fc4da370d741443f8a61c12bf2ce16ede26f64d..15cfb40a05c36c4fb081605be5f5afdb440987fd 100644 (file)
@@ -76,10 +76,10 @@ void NumberParserTest::testBasic() {
 //                 {3, u"a 𝟱𝟭𝟰𝟮𝟯 b", u"a0b", 14, 51423.},
 //                 {3, u"-a 𝟱𝟭𝟰𝟮𝟯 b", u"a0b", 15, -51423.},
 //                 {3, u"a -𝟱𝟭𝟰𝟮𝟯 b", u"a0b", 15, -51423.},
-//                 {3, u"𝟱𝟭𝟰𝟮𝟯", u"[0];(0)", 10, 51423.},
-//                 {3, u"[𝟱𝟭𝟰𝟮𝟯", u"[0];(0)", 11, 51423.},
-//                 {3, u"𝟱𝟭𝟰𝟮𝟯]", u"[0];(0)", 11, 51423.},
-//                 {3, u"[𝟱𝟭𝟰𝟮𝟯]", u"[0];(0)", 12, 51423.},
+                 {3, u"𝟱𝟭𝟰𝟮𝟯", u"[0];(0)", 10, 51423.},
+                 {3, u"[𝟱𝟭𝟰𝟮𝟯", u"[0];(0)", 11, 51423.},
+                 {3, u"𝟱𝟭𝟰𝟮𝟯]", u"[0];(0)", 11, 51423.},
+                 {3, u"[𝟱𝟭𝟰𝟮𝟯]", u"[0];(0)", 12, 51423.},
 //                 {3, u"(𝟱𝟭𝟰𝟮𝟯", u"[0];(0)", 11, -51423.},
 //                 {3, u"𝟱𝟭𝟰𝟮𝟯)", u"[0];(0)", 11, -51423.},
 //                 {3, u"(𝟱𝟭𝟰𝟮𝟯)", u"[0];(0)", 12, -51423.},
index 6fccdc293219fd803bea93f533301bd5ddeab646..c749cd409ff3f5a0c09921c829803d67d8279dab 100644 (file)
@@ -29,15 +29,15 @@ public class AffixMatcher implements NumberParseMatcher {
      */
     public static final Comparator<AffixMatcher> COMPARATOR = new Comparator<AffixMatcher>() {
         @Override
-        public int compare(AffixMatcher o1, AffixMatcher o2) {
-            if (length(o1.prefix) != length(o2.prefix)) {
-                return length(o1.prefix) > length(o2.prefix) ? -1 : 1;
-            } else if (length(o1.suffix) != length(o2.suffix)) {
-                return length(o1.suffix) > length(o2.suffix) ? -1 : 1;
-            } else if (!o1.equals(o2)) {
+        public int compare(AffixMatcher lhs, AffixMatcher rhs) {
+            if (length(lhs.prefix) != length(rhs.prefix)) {
+                return length(lhs.prefix) > length(rhs.prefix) ? -1 : 1;
+            } else if (length(lhs.suffix) != length(rhs.suffix)) {
+                return length(lhs.suffix) > length(rhs.suffix) ? -1 : 1;
+            } else if (!lhs.equals(rhs)) {
                 // If the prefix and suffix are the same length, arbitrarily break ties.
                 // We can't return zero unless the elements are equal.
-                return o1.hashCode() > o2.hashCode() ? -1 : 1;
+                return lhs.hashCode() > rhs.hashCode() ? -1 : 1;
             } else {
                 return 0;
             }