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
28class PluralRulesTest;
29
30U_NAMESPACE_BEGIN
31
32class AndConstraint;
33class RuleChain;
34
35static const UChar DOT             = ((UChar)0x002E);
36static const UChar SINGLE_QUOTE    = ((UChar)0x0027);
37static const UChar SLASH           = ((UChar)0x002F);
38static const UChar BACKSLASH       = ((UChar)0x005C);
39static const UChar SPACE           = ((UChar)0x0020);
40static const UChar EXCLAMATION     = ((UChar)0x0021);
41static const UChar QUOTATION_MARK  = ((UChar)0x0022);
42static const UChar NUMBER_SIGN     = ((UChar)0x0023);
43static const UChar PERCENT_SIGN    = ((UChar)0x0025);
44static const UChar ASTERISK        = ((UChar)0x002A);
45static const UChar COMMA           = ((UChar)0x002C);
46static const UChar HYPHEN          = ((UChar)0x002D);
47static const UChar U_ZERO          = ((UChar)0x0030);
48static const UChar U_ONE           = ((UChar)0x0031);
49static const UChar U_TWO           = ((UChar)0x0032);
50static const UChar U_THREE         = ((UChar)0x0033);
51static const UChar U_FOUR          = ((UChar)0x0034);
52static const UChar U_FIVE          = ((UChar)0x0035);
53static const UChar U_SIX           = ((UChar)0x0036);
54static const UChar U_SEVEN         = ((UChar)0x0037);
55static const UChar U_EIGHT         = ((UChar)0x0038);
56static const UChar U_NINE          = ((UChar)0x0039);
57static const UChar COLON           = ((UChar)0x003A);
58static const UChar SEMI_COLON      = ((UChar)0x003B);
59static const UChar EQUALS          = ((UChar)0x003D);
60static const UChar AT              = ((UChar)0x0040);
61static const UChar CAP_A           = ((UChar)0x0041);
62static const UChar CAP_B           = ((UChar)0x0042);
63static const UChar CAP_R           = ((UChar)0x0052);
64static const UChar CAP_Z           = ((UChar)0x005A);
65static const UChar LOWLINE         = ((UChar)0x005F);
66static const UChar LEFTBRACE       = ((UChar)0x007B);
67static const UChar RIGHTBRACE      = ((UChar)0x007D);
68static const UChar TILDE           = ((UChar)0x007E);
69static const UChar ELLIPSIS        = ((UChar)0x2026);
70
71static const UChar LOW_A           = ((UChar)0x0061);
72static const UChar LOW_B           = ((UChar)0x0062);
73static const UChar LOW_C           = ((UChar)0x0063);
74static const UChar LOW_D           = ((UChar)0x0064);
75static const UChar LOW_E           = ((UChar)0x0065);
76static const UChar LOW_F           = ((UChar)0x0066);
77static const UChar LOW_G           = ((UChar)0x0067);
78static const UChar LOW_H           = ((UChar)0x0068);
79static const UChar LOW_I           = ((UChar)0x0069);
80static const UChar LOW_J           = ((UChar)0x006a);
81static const UChar LOW_K           = ((UChar)0x006B);
82static const UChar LOW_L           = ((UChar)0x006C);
83static const UChar LOW_M           = ((UChar)0x006D);
84static const UChar LOW_N           = ((UChar)0x006E);
85static const UChar LOW_O           = ((UChar)0x006F);
86static const UChar LOW_P           = ((UChar)0x0070);
87static const UChar LOW_Q           = ((UChar)0x0071);
88static const UChar LOW_R           = ((UChar)0x0072);
89static const UChar LOW_S           = ((UChar)0x0073);
90static const UChar LOW_T           = ((UChar)0x0074);
91static const UChar LOW_U           = ((UChar)0x0075);
92static const UChar LOW_V           = ((UChar)0x0076);
93static const UChar LOW_W           = ((UChar)0x0077);
94static const UChar LOW_Y           = ((UChar)0x0079);
95static const UChar LOW_Z           = ((UChar)0x007A);
96
97
98static const int32_t PLURAL_RANGE_HIGH = 0x7fffffff;
99
100enum 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
133class PluralRuleParser: public UMemory {
134public:
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
143private:
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 */
180class 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
215class AndConstraint : public UMemory  {
216public:
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
238class OrConstraint : public UMemory  {
239public:
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
251class RuleChain : public UMemory  {
252public:
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
272class PluralKeywordEnumeration : public StringEnumeration {
273public:
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;
281private:
282    int32_t         pos;
283    UVector         fKeywordNames;
284};
285
286
287class 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
300U_NAMESPACE_END
301
302#endif /* #if !UCONFIG_NO_FORMATTING */
303
304#endif // _PLURRULE_IMPL
305//eof
306