summaryrefslogtreecommitdiff
path: root/shared/parse_plural.h
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:15:16 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:15:16 +0200
commitbd6336c629841c6db3a6ca53a936d629d34db53b (patch)
tree3721ef997864108df175ce677a8a7d4342a6f1d2 /shared/parse_plural.h
parent4.0 (diff)
downloadFreeFileSync-bd6336c629841c6db3a6ca53a936d629d34db53b.tar.gz
FreeFileSync-bd6336c629841c6db3a6ca53a936d629d34db53b.tar.bz2
FreeFileSync-bd6336c629841c6db3a6ca53a936d629d34db53b.zip
4.1
Diffstat (limited to 'shared/parse_plural.h')
-rw-r--r--shared/parse_plural.h412
1 files changed, 0 insertions, 412 deletions
diff --git a/shared/parse_plural.h b/shared/parse_plural.h
deleted file mode 100644
index 1d2bcd95..00000000
--- a/shared/parse_plural.h
+++ /dev/null
@@ -1,412 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-
-#ifndef PARSE_PLURAL_H_INCLUDED
-#define PARSE_PLURAL_H_INCLUDED
-
-#include <list>
-#include <memory>
-#include "zbase.h"
-
-
-//http://www.gnu.org/software/hello/manual/gettext/Plural-forms.html
-//http://translate.sourceforge.net/wiki/l10n/pluralforms
-/*
-Grammar for Plural forms parser
--------------------------------
-expression:
- conditional-expression
-
-conditional-expression:
- logical-or-expression
- logical-or-expression ? expression : expression
-
-logical-or-expression:
- logical-and-expression
- logical-or-expression || logical-and-expression
-
-logical-and-expression:
- equality-expression
- logical-and-expression && equality-expression
-
-equality-expression:
- relational-expression
- relational-expression == relational-expression
- relational-expression != relational-expression
-
-relational-expression:
- multiplicative-expression
- multiplicative-expression > multiplicative-expression
- multiplicative-expression < multiplicative-expression
- multiplicative-expression >= multiplicative-expression
- multiplicative-expression <= multiplicative-expression
-
-multiplicative-expression:
- pm-expression
- multiplicative-expression % pm-expression
-
-pm-expression:
- N
- Number
- ( Expression )
-*/
-
-
-
-//expression interface
-struct Expression { virtual ~Expression() {} };
-
-template <class T>
-struct Expr : public Expression
-{
- typedef T ValueType;
- virtual ValueType eval() const = 0;
-};
-
-//specific binary expression based on STL function objects
-template <class StlOp>
-struct BinaryExp : public Expr<typename StlOp::result_type>
-{
- typedef const Expr<typename StlOp::first_argument_type> SourceExp;
-
- BinaryExp(const SourceExp& lhs, const SourceExp& rhs, StlOp biop) : lhs_(lhs), rhs_(rhs), biop_(biop) {}
- virtual typename StlOp::result_type eval() const { return biop_(lhs_.eval(), rhs_.eval()); }
- const SourceExp& lhs_;
- const SourceExp& rhs_;
- StlOp biop_;
-};
-
-template <class StlOp>
-inline
-BinaryExp<StlOp> makeBiExp(const Expression& lhs, const Expression& rhs, StlOp biop) //throw (std::bad_cast)
-{
- return BinaryExp<StlOp>(dynamic_cast<const Expr<typename StlOp::first_argument_type >&>(lhs),
- dynamic_cast<const Expr<typename StlOp::second_argument_type>&>(rhs), biop);
-}
-
-template <class Out>
-struct TernaryExp : public Out
-{
- TernaryExp(const Expr<bool>& ifExp, const Out& thenExp, const Out& elseExp) : ifExp_(ifExp), thenExp_(thenExp), elseExp_(elseExp) {}
- virtual typename Out::ValueType eval() const { return ifExp_.eval() ? thenExp_.eval() : elseExp_.eval(); }
- const Expr<bool>& ifExp_;
- const Out& thenExp_;
- const Out& elseExp_;
-};
-
-struct LiteralNumberEx : public Expr<int>
-{
- LiteralNumberEx(int n) : n_(n) {}
- virtual int eval() const { return n_; }
- int n_;
-};
-
-struct NumberN : public Expr<int>
-{
- NumberN(int& n) : n_(n) {}
- virtual int eval() const { return n_; }
- int& n_;
-};
-
-
-typedef Zbase<char> Wstring;
-
-
-class PluralForm
-{
-public:
- struct ParsingError {};
-
- //.po format,e.g.: (n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)
- PluralForm(const Wstring& phrase) : n_(0)
- {
- Parser(phrase, //in
- expr, n_, dump); //out
- }
-
- int getForm(int n) const { n_ = n ; return expr->eval(); }
-
-private:
- typedef std::list<std::shared_ptr<Expression> > DumpList;
-
- struct Token
- {
- enum Type
- {
- TK_TERNARY_QUEST,
- TK_TERNARY_COLON,
- TK_OR,
- TK_AND,
- TK_EQUAL,
- TK_NOT_EQUAL,
- TK_LESS,
- TK_LESS_EQUAL,
- TK_GREATER,
- TK_GREATER_EQUAL,
- TK_MODULUS,
- TK_N,
- TK_NUMBER,
- TK_BRACKET_LEFT,
- TK_BRACKET_RIGHT,
- TK_END
- };
-
- Token(Type t) : type(t), number(0) {}
-
- Type type;
- int number; //if type == TK_NUMBER
- };
-
- class Scanner
- {
- public:
- Scanner(const Wstring& phrase) : stream(phrase), pos(stream.begin())
- {
- tokens.push_back(std::make_pair("?" , Token::TK_TERNARY_QUEST));
- tokens.push_back(std::make_pair(":" , Token::TK_TERNARY_COLON));
- tokens.push_back(std::make_pair("||", Token::TK_OR ));
- tokens.push_back(std::make_pair("&&", Token::TK_AND ));
- tokens.push_back(std::make_pair("==", Token::TK_EQUAL ));
- tokens.push_back(std::make_pair("!=", Token::TK_NOT_EQUAL ));
- tokens.push_back(std::make_pair("<=", Token::TK_LESS_EQUAL ));
- tokens.push_back(std::make_pair("<" , Token::TK_LESS ));
- tokens.push_back(std::make_pair(">=", Token::TK_GREATER_EQUAL));
- tokens.push_back(std::make_pair(">" , Token::TK_GREATER ));
- tokens.push_back(std::make_pair("%" , Token::TK_MODULUS ));
- tokens.push_back(std::make_pair("n" , Token::TK_N ));
- tokens.push_back(std::make_pair("N" , Token::TK_N ));
- tokens.push_back(std::make_pair("(" , Token::TK_BRACKET_LEFT ));
- tokens.push_back(std::make_pair(")" , Token::TK_BRACKET_RIGHT));
- }
-
- Token nextToken()
- {
- //skip whitespace
- pos = std::find_if(pos, stream.end(), std::not1(std::ptr_fun(std::iswspace)));
-
- if (pos == stream.end()) return Token(Token::TK_END);
-
- for (TokenList::const_iterator i = tokens.begin(); i != tokens.end(); ++i)
- if (startsWith(i->first))
- {
- pos += i->first.size();
- return Token(i->second);
- }
-
- Wstring::const_iterator digitEnd = std::find_if(pos, stream.end(), std::not1(std::ptr_fun(std::iswdigit)));
- int digitCount = digitEnd - pos;
- if (digitCount != 0)
- {
- Token out(Token::TK_NUMBER);
- out.number = Wstring(&*pos, digitCount).toNumber<int>();
- pos += digitCount;
- return out;
- }
-
- throw ParsingError(); //unknown token
- }
-
- private:
- bool startsWith(const Wstring& prefix) const
- {
- if (stream.end() - pos < static_cast<int>(prefix.size()))
- return false;
- return std::equal(prefix.begin(), prefix.end(), pos);
- }
-
- typedef std::vector<std::pair<Wstring, Token::Type> > TokenList;
- TokenList tokens;
-
- const Wstring stream;
- Wstring::const_iterator pos;
- };
-
-
- class Parser
- {
- public:
- Parser(const Wstring& phrase, //in
- const Expr<int>*& expr, int& n, PluralForm::DumpList& dump) ://out
- scn(phrase),
- tk(scn.nextToken()),
- n_(n),
- dump_(dump)
- {
- try
- {
- const Expression& e = parse();
- expr = &dynamic_cast<const Expr<int>&>(e);
- }
- catch (std::bad_cast&) { throw ParsingError(); }
-
- consumeToken(Token::TK_END);
- }
-
- private:
- void nextToken() { tk = scn.nextToken(); }
- const Token& token() const { return tk; }
-
- void consumeToken(Token::Type t)
- {
- if (token().type != t)
- throw ParsingError();
- nextToken();
- }
-
- const Expression& parse() { return parseConditional(); };
-
- const Expression& parseConditional()
- {
- const Expression& e = parseLogicalOr();
-
- if (token().type == Token::TK_TERNARY_QUEST)
- {
- nextToken();
- const Expression& thenEx = parse(); //associativity: <-
- consumeToken(Token::TK_TERNARY_COLON);
- const Expression& elseEx = parse(); //
-
- return manageObj(TernaryExp<Expr<int> >(dynamic_cast<const Expr<bool>&>(e),
- dynamic_cast<const Expr<int>&>(thenEx),
- dynamic_cast<const Expr<int>&>(elseEx)));
- }
- return e;
- }
-
- const Expression& parseLogicalOr()
- {
- const Expression* e = &parseLogicalAnd();
- for (;;) //associativity: ->
- if (token().type == Token::TK_OR)
- {
- nextToken();
- const Expression& rhs = parseLogicalAnd();
- e = &manageObj(makeBiExp(*e, rhs, std::logical_or<bool>()));
- }
- else break;
- return *e;
- }
-
- const Expression& parseLogicalAnd()
- {
- const Expression* e = &parseEquality();
- for (;;) //associativity: ->
- if (token().type == Token::TK_AND)
- {
- nextToken();
- const Expression& rhs = parseEquality();
-
- e = &manageObj(makeBiExp(*e, rhs, std::logical_and<bool>()));
- }
- else break;
- return *e;
- }
-
- const Expression& parseEquality()
- {
- const Expression& e = parseRelational();
-
- Token::Type t = token().type;
- if (t == Token::TK_EQUAL || t == Token::TK_NOT_EQUAL) //associativity: n/a
- {
- nextToken();
- const Expression& rhs = parseRelational();
-
- if (t == Token::TK_EQUAL) return manageObj(makeBiExp(e, rhs, std::equal_to <int>()));
- if (t == Token::TK_NOT_EQUAL) return manageObj(makeBiExp(e, rhs, std::not_equal_to<int>()));
- }
- return e;
- }
-
- const Expression& parseRelational()
- {
- const Expression& e = parseMultiplicative();
-
- Token::Type t = token().type;
- if (t == Token::TK_LESS || //associativity: n/a
- t == Token::TK_LESS_EQUAL ||
- t == Token::TK_GREATER ||
- t == Token::TK_GREATER_EQUAL)
- {
- nextToken();
- const Expression& rhs = parseMultiplicative();
-
- if (t == Token::TK_LESS) return manageObj(makeBiExp(e, rhs, std::less <int>()));
- if (t == Token::TK_LESS_EQUAL) return manageObj(makeBiExp(e, rhs, std::less_equal <int>()));
- if (t == Token::TK_GREATER) return manageObj(makeBiExp(e, rhs, std::greater <int>()));
- if (t == Token::TK_GREATER_EQUAL) return manageObj(makeBiExp(e, rhs, std::greater_equal<int>()));
- }
- return e;
- }
-
- const Expression& parseMultiplicative()
- {
- const Expression* e = &parsePrimary();
-
- for (;;) //associativity: ->
- if (token().type == Token::TK_MODULUS)
- {
- nextToken();
- const Expression& rhs = parsePrimary();
-
- //"compile-time" check: n % 0
- const LiteralNumberEx* literal = dynamic_cast<const LiteralNumberEx*>(&rhs);
- if (literal && literal->eval() == 0)
- throw ParsingError();
-
- e = &manageObj(makeBiExp(*e, rhs, std::modulus<int>()));
- }
- else break;
- return *e;
- }
-
- const Expression& parsePrimary()
- {
- if (token().type == Token::TK_N)
- {
- nextToken();
- return manageObj(NumberN(n_));
- }
- else if (token().type == Token::TK_NUMBER)
- {
- const int number = token().number;
- nextToken();
- return manageObj(LiteralNumberEx(number));
- }
- else if (token().type == Token::TK_BRACKET_LEFT)
- {
- nextToken();
- const Expression& e = parse();
-
- consumeToken(Token::TK_BRACKET_RIGHT);
- return e;
- }
- else
- throw ParsingError();
- }
-
- template <class T>
- const T& manageObj(const T& obj)
- {
- std::shared_ptr<Expression> newEntry(new T(obj));
- dump_.push_back(newEntry);
- return static_cast<T&>(*dump_.back());
- }
-
- Scanner scn;
- Token tk;
-
- int& n_;
- DumpList& dump_; //manage polymorphc object lifetimes
- };
-
- const Expr<int>* expr;
- mutable int n_;
-
- PluralForm::DumpList dump; //manage polymorphc object lifetimes
-};
-
-#endif // PARSE_PLURAL_H_INCLUDED
bgstack15