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