diff options
Diffstat (limited to 'lib/parse_plural.h')
-rw-r--r-- | lib/parse_plural.h | 88 |
1 files changed, 50 insertions, 38 deletions
diff --git a/lib/parse_plural.h b/lib/parse_plural.h index e9e04dbc..bac933c9 100644 --- a/lib/parse_plural.h +++ b/lib/parse_plural.h @@ -8,6 +8,7 @@ #define PARSE_PLURAL_H_INCLUDED #include <memory> +#include <cstdint> #include <functional> #include <zen/string_base.h> @@ -30,11 +31,11 @@ class PluralForm { public: PluralForm(const std::string& stream); //throw ParsingError - int getForm(int n) const { n_ = n ; return expr->eval(); } + int getForm(std::int64_t n) const { n_ = std::abs(n) ; return static_cast<int>(expr->eval()); } private: - std::shared_ptr<Expr<int>> expr; - mutable int n_; + std::shared_ptr<Expr<std::int64_t>> expr; + mutable std::int64_t n_; }; @@ -46,11 +47,18 @@ class PluralFormInfo public: PluralFormInfo(const std::string& definition, int pluralCount); //throw InvalidPluralForm - int getCount() const { return static_cast<int>(formCount.size()); } - bool isSingleNumberForm(int n) const { return 0 <= n && n < static_cast<int>(formCount.size()) ? formCount[n] == 1 : false; } + int getCount() const { return static_cast<int>(forms.size()); } + bool isSingleNumberForm(int index) const { return 0 <= index && index < static_cast<int>(forms.size()) ? forms[index].count == 1 : false; } + int getFirstNumber (int index) const { return 0 <= index && index < static_cast<int>(forms.size()) ? forms[index].firstNumber : -1; } private: - std::vector<int> formCount; + struct FormInfo + { + FormInfo() : count(0), firstNumber(0) {} + int count; + int firstNumber; //which maps to the plural form index position + }; + std::vector<FormInfo> forms; }; @@ -145,20 +153,20 @@ private: std::shared_ptr<Expr<T>> elseExp_; }; -struct ConstNumberExp : public Expr<int> +struct ConstNumberExp : public Expr<std::int64_t> { - ConstNumberExp(int n) : n_(n) {} - virtual int eval() const { return n_; } + ConstNumberExp(std::int64_t n) : n_(n) {} + virtual std::int64_t eval() const { return n_; } private: - int n_; + std::int64_t n_; }; -struct VariableNumberNExp : public Expr<int> +struct VariableNumberNExp : public Expr<std::int64_t> { - VariableNumberNExp(int& n) : n_(n) {} - virtual int eval() const { return n_; } + VariableNumberNExp(std::int64_t& n) : n_(n) {} + virtual std::int64_t eval() const { return n_; } private: - int& n_; + std::int64_t& n_; }; //------------------------------------------------------------------------------- @@ -186,10 +194,10 @@ struct Token }; Token(Type t) : type(t), number(0) {} - Token(int num) : type(TK_CONST_NUMBER), number(num) {} + Token(std::int64_t num) : type(TK_CONST_NUMBER), number(num) {} Type type; - int number; //if type == TK_CONST_NUMBER + std::int64_t number; //if type == TK_CONST_NUMBER }; class Scanner @@ -233,7 +241,7 @@ public: if (digitEnd != pos) { - int number = zen::stringTo<int>(std::string(pos, digitEnd)); + auto number = zen::stringTo<std::int64_t>(std::string(pos, digitEnd)); pos = digitEnd; return number; } @@ -249,7 +257,7 @@ private: return std::equal(prefix.begin(), prefix.end(), pos); } - typedef std::vector<std::pair<std::string, Token::Type> > TokenList; + typedef std::vector<std::pair<std::string, Token::Type>> TokenList; TokenList tokens; const std::string stream_; @@ -261,14 +269,14 @@ private: class Parser { public: - Parser(const std::string& stream, int& n) : + Parser(const std::string& stream, std::int64_t& n) : scn(stream), tk(scn.nextToken()), n_(n) {} - std::shared_ptr<Expr<int>> parse() //throw ParsingError; return value always bound! + std::shared_ptr<Expr<std::int64_t>> parse() //throw ParsingError; return value always bound! { - auto e = std::dynamic_pointer_cast<Expr<int>>(parseExpression()); //throw ParsingError + auto e = std::dynamic_pointer_cast<Expr<std::int64_t>>(parseExpression()); //throw ParsingError if (!e) throw ParsingError(); expectToken(Token::TK_END); @@ -287,15 +295,15 @@ private: nextToken(); auto ifExp = std::dynamic_pointer_cast<Expr<bool>>(e); - auto thenExp = std::dynamic_pointer_cast<Expr<int>>(parseExpression()); //associativity: <- + auto thenExp = std::dynamic_pointer_cast<Expr<std::int64_t>>(parseExpression()); //associativity: <- expectToken(Token::TK_TERNARY_COLON); nextToken(); - auto elseExp = std::dynamic_pointer_cast<Expr<int>>(parseExpression()); // + auto elseExp = std::dynamic_pointer_cast<Expr<std::int64_t>>(parseExpression()); // if (!ifExp || !thenExp || !elseExp) throw ParsingError(); - return std::make_shared<ConditionalExp<int>>(ifExp, thenExp, elseExp); + return std::make_shared<ConditionalExp<std::int64_t>>(ifExp, thenExp, elseExp); } return e; } @@ -337,8 +345,8 @@ private: nextToken(); std::shared_ptr<Expression> rhs = parseRelational(); - if (t == Token::TK_EQUAL) return makeBiExp(e, rhs, std::equal_to <int>()); //throw ParsingError - if (t == Token::TK_NOT_EQUAL) return makeBiExp(e, rhs, std::not_equal_to<int>()); // + if (t == Token::TK_EQUAL) return makeBiExp(e, rhs, std::equal_to <std::int64_t>()); //throw ParsingError + if (t == Token::TK_NOT_EQUAL) return makeBiExp(e, rhs, std::not_equal_to<std::int64_t>()); // } return e; } @@ -356,10 +364,10 @@ private: nextToken(); std::shared_ptr<Expression> rhs = parseMultiplicative(); - if (t == Token::TK_LESS) return makeBiExp(e, rhs, std::less <int>()); // - if (t == Token::TK_LESS_EQUAL) return makeBiExp(e, rhs, std::less_equal <int>()); //throw ParsingError - if (t == Token::TK_GREATER) return makeBiExp(e, rhs, std::greater <int>()); // - if (t == Token::TK_GREATER_EQUAL) return makeBiExp(e, rhs, std::greater_equal<int>()); // + if (t == Token::TK_LESS) return makeBiExp(e, rhs, std::less <std::int64_t>()); // + if (t == Token::TK_LESS_EQUAL) return makeBiExp(e, rhs, std::less_equal <std::int64_t>()); //throw ParsingError + if (t == Token::TK_GREATER) return makeBiExp(e, rhs, std::greater <std::int64_t>()); // + if (t == Token::TK_GREATER_EQUAL) return makeBiExp(e, rhs, std::greater_equal<std::int64_t>()); // } return e; } @@ -378,7 +386,7 @@ private: if (literal->eval() == 0) throw ParsingError(); - e = makeBiExp(e, rhs, std::modulus<int>()); //throw ParsingError + e = makeBiExp(e, rhs, std::modulus<std::int64_t>()); //throw ParsingError } return e; } @@ -392,7 +400,7 @@ private: } else if (token().type == Token::TK_CONST_NUMBER) { - const int number = token().number; + const std::int64_t number = token().number; nextToken(); return std::make_shared<ConstNumberExp>(number); } @@ -420,7 +428,7 @@ private: Scanner scn; Token tk; - int& n_; + std::int64_t& n_; }; } @@ -431,7 +439,7 @@ PluralFormInfo::PluralFormInfo(const std::string& definition, int pluralCount) / if (pluralCount < 1) throw InvalidPluralForm(); - formCount.resize(pluralCount); + forms.resize(pluralCount); try { parse_plural::PluralForm pf(definition); //throw parse_plural::ParsingError @@ -442,8 +450,12 @@ PluralFormInfo::PluralFormInfo(const std::string& definition, int pluralCount) / for (int j = 0; j < 1000; ++j) { int form = pf.getForm(j); - if (0 <= form && form < static_cast<int>(formCount.size())) - ++formCount[form]; + if (0 <= form && form < static_cast<int>(forms.size())) + { + if (forms[form].count == 0) + forms[form].firstNumber = j; + ++forms[form].count; + } else throw InvalidPluralForm(); } @@ -454,7 +466,7 @@ PluralFormInfo::PluralFormInfo(const std::string& definition, int pluralCount) / } //ensure each form is used at least once: - if (!std::all_of(formCount.begin(), formCount.end(), [](int count) { return count >= 1; })) + if (!std::all_of(forms.begin(), forms.end(), [](const FormInfo& fi) { return fi.count >= 1; })) throw InvalidPluralForm(); } @@ -463,4 +475,4 @@ inline PluralForm::PluralForm(const std::string& stream) : expr(implementation::Parser(stream, n_).parse()) {} //throw ParsingError } -#endif // PARSE_PLURAL_H_INCLUDED
\ No newline at end of file +#endif // PARSE_PLURAL_H_INCLUDED |