1 /* 2 ******************************************************************************* 3 * Copyright (C) 2007-2013, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ******************************************************************************* 6 * 7 * File PLURRULE_IMPL.H 8 * 9 ******************************************************************************* 10 */ 11 12 13 #ifndef PLURRULE_IMPLE 14 #define PLURRULE_IMPLE 15 16 // Internal definitions for the PluralRules implementation. 17 18 #if !UCONFIG_NO_FORMATTING 19 20 #include "unicode/format.h" 21 #include "unicode/locid.h" 22 #include "unicode/parseerr.h" 23 #include "unicode/ures.h" 24 #include "unicode/utypes.h" 25 #include "uvector.h" 26 #include "hash.h" 27 28 class PluralRulesTest; 29 30 U_NAMESPACE_BEGIN 31 32 class AndConstraint; 33 class RuleChain; 34 35 static const UChar DOT = ((UChar)0x002E); 36 static const UChar SINGLE_QUOTE = ((UChar)0x0027); 37 static const UChar SLASH = ((UChar)0x002F); 38 static const UChar BACKSLASH = ((UChar)0x005C); 39 static const UChar SPACE = ((UChar)0x0020); 40 static const UChar EXCLAMATION = ((UChar)0x0021); 41 static const UChar QUOTATION_MARK = ((UChar)0x0022); 42 static const UChar NUMBER_SIGN = ((UChar)0x0023); 43 static const UChar PERCENT_SIGN = ((UChar)0x0025); 44 static const UChar ASTERISK = ((UChar)0x002A); 45 static const UChar COMMA = ((UChar)0x002C); 46 static const UChar HYPHEN = ((UChar)0x002D); 47 static const UChar U_ZERO = ((UChar)0x0030); 48 static const UChar U_ONE = ((UChar)0x0031); 49 static const UChar U_TWO = ((UChar)0x0032); 50 static const UChar U_THREE = ((UChar)0x0033); 51 static const UChar U_FOUR = ((UChar)0x0034); 52 static const UChar U_FIVE = ((UChar)0x0035); 53 static const UChar U_SIX = ((UChar)0x0036); 54 static const UChar U_SEVEN = ((UChar)0x0037); 55 static const UChar U_EIGHT = ((UChar)0x0038); 56 static const UChar U_NINE = ((UChar)0x0039); 57 static const UChar COLON = ((UChar)0x003A); 58 static const UChar SEMI_COLON = ((UChar)0x003B); 59 static const UChar EQUALS = ((UChar)0x003D); 60 static const UChar AT = ((UChar)0x0040); 61 static const UChar CAP_A = ((UChar)0x0041); 62 static const UChar CAP_B = ((UChar)0x0042); 63 static const UChar CAP_R = ((UChar)0x0052); 64 static const UChar CAP_Z = ((UChar)0x005A); 65 static const UChar LOWLINE = ((UChar)0x005F); 66 static const UChar LEFTBRACE = ((UChar)0x007B); 67 static const UChar RIGHTBRACE = ((UChar)0x007D); 68 static const UChar TILDE = ((UChar)0x007E); 69 static const UChar ELLIPSIS = ((UChar)0x2026); 70 71 static const UChar LOW_A = ((UChar)0x0061); 72 static const UChar LOW_B = ((UChar)0x0062); 73 static const UChar LOW_C = ((UChar)0x0063); 74 static const UChar LOW_D = ((UChar)0x0064); 75 static const UChar LOW_E = ((UChar)0x0065); 76 static const UChar LOW_F = ((UChar)0x0066); 77 static const UChar LOW_G = ((UChar)0x0067); 78 static const UChar LOW_H = ((UChar)0x0068); 79 static const UChar LOW_I = ((UChar)0x0069); 80 static const UChar LOW_J = ((UChar)0x006a); 81 static const UChar LOW_K = ((UChar)0x006B); 82 static const UChar LOW_L = ((UChar)0x006C); 83 static const UChar LOW_M = ((UChar)0x006D); 84 static const UChar LOW_N = ((UChar)0x006E); 85 static const UChar LOW_O = ((UChar)0x006F); 86 static const UChar LOW_P = ((UChar)0x0070); 87 static const UChar LOW_Q = ((UChar)0x0071); 88 static const UChar LOW_R = ((UChar)0x0072); 89 static const UChar LOW_S = ((UChar)0x0073); 90 static const UChar LOW_T = ((UChar)0x0074); 91 static const UChar LOW_U = ((UChar)0x0075); 92 static const UChar LOW_V = ((UChar)0x0076); 93 static const UChar LOW_W = ((UChar)0x0077); 94 static const UChar LOW_Y = ((UChar)0x0079); 95 static const UChar LOW_Z = ((UChar)0x007A); 96 97 98 static const int32_t PLURAL_RANGE_HIGH = 0x7fffffff; 99 100 enum tokenType { 101 none, 102 tNumber, 103 tComma, 104 tSemiColon, 105 tSpace, 106 tColon, 107 tAt, // '@' 108 tDot, 109 tDot2, 110 tEllipsis, 111 tKeyword, 112 tAnd, 113 tOr, 114 tMod, // 'mod' or '%' 115 tNot, // 'not' only. 116 tIn, // 'in' only. 117 tEqual, // '=' only. 118 tNotEqual, // '!=' 119 tTilde, 120 tWithin, 121 tIs, 122 tVariableN, 123 tVariableI, 124 tVariableF, 125 tVariableV, 126 tVariableT, 127 tDecimal, 128 tInteger, 129 tEOF 130 }; 131 132 133 class PluralRuleParser: public UMemory { 134 public: 135 PluralRuleParser(); 136 virtual ~PluralRuleParser(); 137 138 void parse(const UnicodeString &rules, PluralRules *dest, UErrorCode &status); 139 void getNextToken(UErrorCode &status); 140 void checkSyntax(UErrorCode &status); 141 static int32_t getNumberValue(const UnicodeString &token); 142 143 private: 144 static tokenType getKeyType(const UnicodeString& token, tokenType type); 145 static tokenType charType(UChar ch); 146 static UBool isValidKeyword(const UnicodeString& token); 147 148 const UnicodeString *ruleSrc; // The rules string. 149 int32_t ruleIndex; // String index in the input rules, the current parse position. 150 UnicodeString token; // Token most recently scanned. 151 tokenType type; 152 tokenType prevType; 153 154 // The items currently being parsed & built. 155 // Note: currentChain may not be the last RuleChain in the 156 // list because the "other" chain is forced to the end. 157 AndConstraint *curAndConstraint; 158 RuleChain *currentChain; 159 160 int32_t rangeLowIdx; // Indices in the UVector of ranges of the 161 int32_t rangeHiIdx; // low and hi values currently being parsed. 162 163 enum EParseState { 164 kKeyword, 165 kExpr, 166 kValue, 167 kRangeList, 168 kSamples 169 }; 170 171 }; 172 173 /** 174 * class FixedDecimal serves to communicate the properties 175 * of a formatted number from a decimal formatter to PluralRules::select() 176 * 177 * see DecimalFormat::getFixedDecimal() 178 * @internal 179 */ 180 class U_I18N_API FixedDecimal: public UMemory { 181 public: 182 /** 183 * @param n the number, e.g. 12.345 184 * @param v The number of visible fraction digits, e.g. 3 185 * @param f The fraction digits, e.g. 345 186 */ 187 FixedDecimal(double n, int32_t v, int64_t f); 188 FixedDecimal(double n, int32_t); 189 explicit FixedDecimal(double n); 190 FixedDecimal(); 191 FixedDecimal(const UnicodeString &s, UErrorCode &ec); 192 FixedDecimal(const FixedDecimal &other); 193 194 double get(tokenType operand) const; 195 int32_t getVisibleFractionDigitCount() const; 196 197 void init(double n, int32_t v, int64_t f); 198 void init(double n); 199 UBool quickInit(double n); // Try a fast-path only initialization, 200 // return TRUE if successful. 201 void adjustForMinFractionDigits(int32_t min); 202 static int64_t getFractionalDigits(double n, int32_t v); 203 static int32_t decimals(double n); 204 205 double source; 206 int32_t visibleDecimalDigitCount; 207 int64_t decimalDigits; 208 int64_t decimalDigitsWithoutTrailingZeros; 209 int64_t intValue; 210 UBool hasIntegerValue; 211 UBool isNegative; 212 UBool isNanOrInfinity; 213 }; 214 215 class AndConstraint : public UMemory { 216 public: 217 typedef enum RuleOp { 218 NONE, 219 MOD 220 } RuleOp; 221 RuleOp op; 222 int32_t opNum; // for mod expressions, the right operand of the mod. 223 int32_t value; // valid for 'is' rules only. 224 UVector32 *rangeList; // for 'in', 'within' rules. Null otherwise. 225 UBool negated; // TRUE for negated rules. 226 UBool integerOnly; // TRUE for 'within' rules. 227 tokenType digitsType; // n | i | v | f constraint. 228 AndConstraint *next; 229 230 AndConstraint(); 231 AndConstraint(const AndConstraint& other); 232 virtual ~AndConstraint(); 233 AndConstraint* add(); 234 // UBool isFulfilled(double number); 235 UBool isFulfilled(const FixedDecimal &number); 236 }; 237 238 class OrConstraint : public UMemory { 239 public: 240 AndConstraint *childNode; 241 OrConstraint *next; 242 OrConstraint(); 243 244 OrConstraint(const OrConstraint& other); 245 virtual ~OrConstraint(); 246 AndConstraint* add(); 247 // UBool isFulfilled(double number); 248 UBool isFulfilled(const FixedDecimal &number); 249 }; 250 251 class RuleChain : public UMemory { 252 public: 253 UnicodeString fKeyword; 254 RuleChain *fNext; 255 OrConstraint *ruleHeader; 256 UnicodeString fDecimalSamples; // Samples strings from rule source 257 UnicodeString fIntegerSamples; // without @decimal or @integer, otherwise unprocessed. 258 UBool fDecimalSamplesUnbounded; 259 UBool fIntegerSamplesUnbounded; 260 261 262 RuleChain(); 263 RuleChain(const RuleChain& other); 264 virtual ~RuleChain(); 265 266 UnicodeString select(const FixedDecimal &number) const; 267 void dumpRules(UnicodeString& result); 268 UErrorCode getKeywords(int32_t maxArraySize, UnicodeString *keywords, int32_t& arraySize) const; 269 UBool isKeyword(const UnicodeString& keyword) const; 270 }; 271 272 class PluralKeywordEnumeration : public StringEnumeration { 273 public: 274 PluralKeywordEnumeration(RuleChain *header, UErrorCode& status); 275 virtual ~PluralKeywordEnumeration(); 276 static UClassID U_EXPORT2 getStaticClassID(void); 277 virtual UClassID getDynamicClassID(void) const; 278 virtual const UnicodeString* snext(UErrorCode& status); 279 virtual void reset(UErrorCode& status); 280 virtual int32_t count(UErrorCode& status) const; 281 private: 282 int32_t pos; 283 UVector fKeywordNames; 284 }; 285 286 287 class U_I18N_API PluralAvailableLocalesEnumeration: public StringEnumeration { 288 public: 289 PluralAvailableLocalesEnumeration(UErrorCode &status); 290 virtual ~PluralAvailableLocalesEnumeration(); 291 virtual const char* next(int32_t *resultLength, UErrorCode& status); 292 virtual void reset(UErrorCode& status); 293 virtual int32_t count(UErrorCode& status) const; 294 private: 295 UErrorCode fOpenStatus; 296 UResourceBundle *fLocales; 297 UResourceBundle *fRes; 298 }; 299 300 U_NAMESPACE_END 301 302 #endif /* #if !UCONFIG_NO_FORMATTING */ 303 304 #endif // _PLURRULE_IMPL 305 //eof 306