diff options
author | Luke Shumaker <LukeShu@sbcglobal.net> | 2014-01-28 09:50:25 -0500 |
---|---|---|
committer | Luke Shumaker <LukeShu@sbcglobal.net> | 2014-01-28 09:50:25 -0500 |
commit | 5744df39e15f85c6cc8a9faf8924d77e76d2b216 (patch) | |
tree | a8c8dd40a94d1fa0d5377566aa5548ae55a163da /resources/mediawiki.libs/CLDRPluralRuleParser.js | |
parent | 4bb2aeca1d198391ca856aa16c40b8559c68daec (diff) | |
parent | 224b22a051051f6c2e494c3a2fb4adb42898e2d1 (diff) |
Merge branch 'archwiki'
Conflicts:
extensions/FluxBBAuthPlugin.php
extensions/SyntaxHighlight_GeSHi/README
extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.class.php
extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.i18n.php
extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.php
extensions/SyntaxHighlight_GeSHi/geshi/docs/CHANGES
extensions/SyntaxHighlight_GeSHi/geshi/docs/THANKS
extensions/SyntaxHighlight_GeSHi/geshi/docs/TODO
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractClass.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractClass_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractMethod.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractPrivateClass.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractPrivateClass_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractPrivateMethod.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Class.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Class_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Constant.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Constructor.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Destructor.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Function.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Global.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/I.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Index.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Interface.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Interface_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/L.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Lminus.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Lplus.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Method.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Page.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Page_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/PrivateClass.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/PrivateClass_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/PrivateMethod.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/PrivateVariable.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/StaticMethod.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/StaticVariable.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/T.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Tminus.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Tplus.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Variable.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/blank.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/class_folder.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/file.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/folder.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/function_folder.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/next_button.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/next_button_disabled.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/package.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/package_folder.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/previous_button.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/previous_button_disabled.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/private_class_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/tutorial.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/tutorial_folder.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/up_button.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/geshi-doc.html
extensions/SyntaxHighlight_GeSHi/geshi/docs/geshi-doc.txt
extensions/SyntaxHighlight_GeSHi/geshi/geshi.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/4cs.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/6502acme.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/6502kickass.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/6502tasm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/68000devpac.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/abap.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/actionscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/actionscript3.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ada.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/algol68.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/apache.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/applescript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/apt_sources.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/asm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/asp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/autoconf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/autohotkey.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/autoit.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/avisynth.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/awk.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/bascomavr.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/bash.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/basic4gl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/bf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/bibtex.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/blitzbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/bnf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/boo.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/c.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/c_loadrunner.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/c_mac.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/caddcl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cadlisp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cfdg.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cfm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/chaiscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cil.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/clojure.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cmake.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cobol.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/coffeescript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cpp-qt.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cpp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/csharp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/css.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cuesheet.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/d.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/dcs.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/delphi.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/diff.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/div.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/dos.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/dot.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/e.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ecmascript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/eiffel.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/email.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/epc.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/erlang.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/euphoria.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/f1.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/falcon.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/fo.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/fortran.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/freebasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/fsharp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gambas.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gdb.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/genero.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/genie.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gettext.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/glsl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gml.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gnuplot.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/go.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/groovy.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gwbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/haskell.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/hicest.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/hq9plus.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/html4strict.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/html5.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/icon.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/idl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ini.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/inno.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/intercal.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/io.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/j.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/java.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/java5.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/javascript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/jquery.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/kixtart.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/klonec.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/klonecpp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/latex.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lb.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lisp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/llvm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/locobasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/logtalk.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lolcode.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lotusformulas.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lotusscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lsl2.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lua.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/m68k.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/magiksf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/make.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mapbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/matlab.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mirc.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mmix.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/modula2.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/modula3.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mpasm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mxml.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mysql.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/newlisp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/nsis.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oberon2.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/objc.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/objeck.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ocaml-brief.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ocaml.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oobas.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oracle11.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oracle8.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oxygene.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oz.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pascal.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pcre.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/per.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/perl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/perl6.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/php-brief.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/php.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pic16.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pike.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pixelbender.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pli.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/plsql.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/postgresql.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/povray.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/powerbuilder.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/powershell.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/proftpd.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/progress.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/prolog.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/properties.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/providex.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/purebasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pycon.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/python.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/q.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/qbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/rails.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/rebol.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/reg.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/robots.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/rpmspec.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/rsplus.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ruby.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/sas.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/scala.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/scheme.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/scilab.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/sdlbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/smalltalk.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/smarty.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/sql.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/systemverilog.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/tcl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/teraterm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/text.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/thinbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/tsql.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/typoscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/unicon.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/uscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/vala.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/vb.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/vbnet.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/verilog.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/vhdl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/vim.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/visualfoxpro.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/visualprolog.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/whitespace.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/whois.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/winbatch.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/xbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/xml.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/xorg_conf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/xpp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/yaml.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/z80.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/zxbasic.php
Diffstat (limited to 'resources/mediawiki.libs/CLDRPluralRuleParser.js')
-rw-r--r-- | resources/mediawiki.libs/CLDRPluralRuleParser.js | 357 |
1 files changed, 259 insertions, 98 deletions
diff --git a/resources/mediawiki.libs/CLDRPluralRuleParser.js b/resources/mediawiki.libs/CLDRPluralRuleParser.js index 91bdc07d..3def37c5 100644 --- a/resources/mediawiki.libs/CLDRPluralRuleParser.js +++ b/resources/mediawiki.libs/CLDRPluralRuleParser.js @@ -1,7 +1,7 @@ -/* This is cldrpluralparser 1.0, ported to MediaWiki ResourceLoader */ +/* This is CLDRPluralRuleParser v1.1, ported to MediaWiki ResourceLoader */ /** -* cldrpluralparser.js +* CLDRPluralRuleParser.js * A parser engine for CLDR plural rules. * * Copyright 2012 GPLV3+, Santhosh Thottingal @@ -13,59 +13,83 @@ * @author Amir Aharoni */ +( function ( mw ) { /** * Evaluates a plural rule in CLDR syntax for a number - * @param rule - * @param number - * @return true|false|null + * @param {string} rule + * @param {integer} number + * @return {boolean} true if evaluation passed, false if evaluation failed. */ -( function( mw ) { function pluralRuleParser(rule, number) { /* Syntax: see http://unicode.org/reports/tr35/#Language_Plural_Rules ----------------------------------------------------------------- - condition = and_condition ('or' and_condition)* + ('@integer' samples)? + ('@decimal' samples)? and_condition = relation ('and' relation)* - relation = is_relation | in_relation | within_relation | 'n' <EOL> + relation = is_relation | in_relation | within_relation is_relation = expr 'is' ('not')? value - in_relation = expr ('not')? 'in' range_list + in_relation = expr (('not')? 'in' | '=' | '!=') range_list within_relation = expr ('not')? 'within' range_list - expr = 'n' ('mod' value)? + expr = operand (('mod' | '%') value)? + operand = 'n' | 'i' | 'f' | 't' | 'v' | 'w' range_list = (range | value) (',' range_list)* value = digit+ digit = 0|1|2|3|4|5|6|7|8|9 range = value'..'value - + samples = sampleRange (',' sampleRange)* (',' ('…'|'...'))? + sampleRange = decimalValue '~' decimalValue + decimalValue = value ('.' value)? */ + + // we don't evaluate the samples section of the rule. Ignore it. + rule = rule.split('@')[0].trim(); + + if (!rule.length) { + // empty rule or 'other' rule. + return true; + } // Indicates current position in the rule as we parse through it. // Shared among all parsing functions below. - var pos = 0; - - var whitespace = makeRegexParser(/^\s+/); - var digits = makeRegexParser(/^\d+/); - - var _n_ = makeStringParser('n'); - var _is_ = makeStringParser('is'); - var _mod_ = makeStringParser('mod'); - var _not_ = makeStringParser('not'); - var _in_ = makeStringParser('in'); - var _within_ = makeStringParser('within'); - var _range_ = makeStringParser('..'); - var _comma_ = makeStringParser(','); - var _or_ = makeStringParser('or'); - var _and_ = makeStringParser('and'); + var pos = 0, + operand, + expression, + relation, + result, + whitespace = makeRegexParser(/^\s+/), + value = makeRegexParser(/^\d+/), + _n_ = makeStringParser('n'), + _i_ = makeStringParser('i'), + _f_ = makeStringParser('f'), + _t_ = makeStringParser('t'), + _v_ = makeStringParser('v'), + _w_ = makeStringParser('w'), + _is_ = makeStringParser('is'), + _isnot_ = makeStringParser('is not'), + _isnot_sign_ = makeStringParser('!='), + _equal_ = makeStringParser('='), + _mod_ = makeStringParser('mod'), + _percent_ = makeStringParser('%'), + _not_ = makeStringParser('not'), + _in_ = makeStringParser('in'), + _within_ = makeStringParser('within'), + _range_ = makeStringParser('..'), + _comma_ = makeStringParser(','), + _or_ = makeStringParser('or'), + _and_ = makeStringParser('and'); function debug() { - /* console.log.apply(console, arguments);*/ + // console.log.apply(console, arguments); } debug('pluralRuleParser', rule, number); // Try parsers until one works, if none work return null + function choice(parserSyntax) { - return function () { + return function() { for (var i = 0; i < parserSyntax.length; i++) { var result = parserSyntax[i](); if (result !== null) { @@ -79,6 +103,7 @@ function pluralRuleParser(rule, number) { // Try several parserSyntax-es in a row. // All must succeed; otherwise, return null. // This is the only eager one. + function sequence(parserSyntax) { var originalPos = pos; var result = []; @@ -95,8 +120,9 @@ function pluralRuleParser(rule, number) { // Run the same parser over and over until it fails. // Must succeed a minimum of n times; otherwise, return null. + function nOrMore(n, p) { - return function () { + return function() { var originalPos = pos; var result = []; var parsed = p(); @@ -113,21 +139,21 @@ function pluralRuleParser(rule, number) { } // Helpers -- just make parserSyntax out of simpler JS builtin types - function makeStringParser(s) { var len = s.length; - return function () { + return function() { var result = null; if (rule.substr(pos, len) === s) { result = s; pos += len; } + return result; }; } function makeRegexParser(regex) { - return function () { + return function() { var matches = rule.substr(pos).match(regex); if (matches === null) { return null; @@ -137,62 +163,166 @@ function pluralRuleParser(rule, number) { }; } + /* + * integer digits of n. + */ + function i() { + var result = _i_(); + if (result === null) { + debug(' -- failed i', parseInt(number, 10)); + return result; + } + result = parseInt(number, 10); + debug(' -- passed i ', result); + return result; + } + + /* + * absolute value of the source number (integer and decimals). + */ function n() { var result = _n_(); if (result === null) { - debug(" -- failed n"); + debug(' -- failed n ', number); return result; } - result = parseInt(number, 10); - debug(" -- passed n ", result); + result = parseFloat(number, 10); + debug(' -- passed n ', result); + return result; + } + + /* + * visible fractional digits in n, with trailing zeros. + */ + function f() { + var result = _f_(); + if (result === null) { + debug(' -- failed f ', number); + return result; + } + result = (number + '.').split('.')[1] || 0; + debug(' -- passed f ', result); + return result; + } + + /* + * visible fractional digits in n, without trailing zeros. + */ + function t() { + var result = _t_(); + if (result === null) { + debug(' -- failed t ', number); + return result; + } + result = (number + '.').split('.')[1].replace(/0$/, '') || 0; + debug(' -- passed t ', result); + return result; + } + + /* + * number of visible fraction digits in n, with trailing zeros. + */ + function v() { + var result = _v_(); + if (result === null) { + debug(' -- failed v ', number); + return result; + } + result = (number + '.').split('.')[1].length || 0; + debug(' -- passed v ', result); + return result; + } + + /* + * number of visible fraction digits in n, without trailing zeros. + */ + function w() { + var result = _w_(); + if (result === null) { + debug(' -- failed w ', number); + return result; + } + result = (number + '.').split('.')[1].replace(/0$/, '').length || 0; + debug(' -- passed w ', result); return result; } - var expression = choice([mod, n]); + // operand = 'n' | 'i' | 'f' | 't' | 'v' | 'w' + operand = choice([n, i, f, t, v, w]); + + // expr = operand (('mod' | '%') value)? + expression = choice([mod, operand]); function mod() { - var result = sequence([n, whitespace, _mod_, whitespace, digits]); + var result = sequence([operand, whitespace, choice([_mod_, _percent_]), whitespace, value]); if (result === null) { - debug(" -- failed mod"); + debug(' -- failed mod'); return null; } - debug(" -- passed mod"); + debug(' -- passed ' + parseInt(result[0], 10) + ' ' + result[2] + ' ' + parseInt(result[4], 10)); return parseInt(result[0], 10) % parseInt(result[4], 10); } function not() { var result = sequence([whitespace, _not_]); if (result === null) { - debug(" -- failed not"); + debug(' -- failed not'); return null; - } else { - return result[1]; } + + return result[1]; } + // is_relation = expr 'is' ('not')? value function is() { - var result = sequence([expression, whitespace, _is_, nOrMore(0, not), whitespace, digits]); + var result = sequence([expression, whitespace, choice([_is_]), whitespace, value]); if (result !== null) { - debug(" -- passed is"); - if (result[3][0] === 'not') { - return result[0] !== parseInt(result[5], 10); - } else { - return result[0] === parseInt(result[5], 10); + debug(' -- passed is : ' + result[0] + ' == ' + parseInt(result[4], 10)); + return result[0] === parseInt(result[4], 10); + } + debug(' -- failed is'); + return null; + } + + // is_relation = expr 'is' ('not')? value + function isnot() { + var result = sequence([expression, whitespace, choice([_isnot_, _isnot_sign_]), whitespace, value]); + if (result !== null) { + debug(' -- passed isnot: ' + result[0] + ' != ' + parseInt(result[4], 10)); + return result[0] !== parseInt(result[4], 10); + } + debug(' -- failed isnot'); + return null; + } + + function not_in() { + var result = sequence([expression, whitespace, _isnot_sign_, whitespace, rangeList]); + if (result !== null) { + debug(' -- passed not_in: ' + result[0] + ' != ' + result[4]); + var range_list = result[4]; + for (var i = 0; i < range_list.length; i++) { + if (parseInt(range_list[i], 10) === parseInt(result[0], 10)) { + return false; + } } + return true; } - debug(" -- failed is"); + debug(' -- failed not_in'); return null; } + // range_list = (range | value) (',' range_list)* function rangeList() { - // range_list = (range | value) (',' range_list)* - var result = sequence([choice([range, digits]), nOrMore(0, rangeTail)]); + var result = sequence([choice([range, value]), nOrMore(0, rangeTail)]); var resultList = []; if (result !== null) { - resultList = resultList.concat(result[0], result[1][0]); + resultList = resultList.concat(result[0]); + if (result[1][0]) { + resultList = resultList.concat(result[1][0]); + } return resultList; } - debug(" -- failed rangeList"); + debug(' -- failed rangeList'); return null; } @@ -202,110 +332,141 @@ function pluralRuleParser(rule, number) { if (result !== null) { return result[1]; } - debug(" -- failed rangeTail"); + debug(' -- failed rangeTail'); return null; } + // range = value'..'value + function range() { - var result = sequence([digits, _range_, digits]); + var i; + var result = sequence([value, _range_, value]); if (result !== null) { - debug(" -- passed range"); + debug(' -- passed range'); var array = []; var left = parseInt(result[0], 10); var right = parseInt(result[2], 10); - for ( i = left; i <= right; i++) { + for (i = left; i <= right; i++) { array.push(i); } return array; } - debug(" -- failed range"); + debug(' -- failed range'); return null; } function _in() { // in_relation = expr ('not')? 'in' range_list - var result = sequence([expression, nOrMore(0, not), whitespace, _in_, whitespace, rangeList]); + var result = sequence([expression, nOrMore(0, not), whitespace, choice([_in_, _equal_]), whitespace, rangeList]); if (result !== null) { - debug(" -- passed _in"); + debug(' -- passed _in:' + result); var range_list = result[5]; for (var i = 0; i < range_list.length; i++) { - if (parseInt(range_list[i], 10) === result[0]) { + if (parseInt(range_list[i], 10) === parseInt(result[0], 10)) { return (result[1][0] !== 'not'); } } return (result[1][0] === 'not'); } - debug(" -- failed _in "); + debug(' -- failed _in '); return null; } + /* + * The difference between in and within is that in only includes integers in the specified range, + * while within includes all values. + */ + function within() { - var result = sequence([expression, whitespace, _within_, whitespace, rangeList]); + // within_relation = expr ('not')? 'within' range_list + var result = sequence([expression, nOrMore(0, not), whitespace, _within_, whitespace, rangeList]); if (result !== null) { - debug(" -- passed within "); - var range_list = result[4]; - return (parseInt( range_list[0],10 )<= result[0] && result[0] <= parseInt( range_list[1], 10)); + debug(' -- passed within'); + var range_list = result[5]; + if ((result[0] >= parseInt(range_list[0], 10)) && + (result[0] < parseInt(range_list[range_list.length - 1], 10))) { + return (result[1][0] !== 'not'); + } + return (result[1][0] === 'not'); } - debug(" -- failed within "); + debug(' -- failed within '); return null; } + // relation = is_relation | in_relation | within_relation + relation = choice([is, not_in, isnot, _in, within]); - var relation = choice([is, _in, within]); - + // and_condition = relation ('and' relation)* function and() { - var result = sequence([relation, whitespace, _and_, whitespace, condition]); + var result = sequence([relation, nOrMore(0, andTail)]); if (result) { - debug(" -- passed and"); - return result[0] && result[4]; + if (!result[0]) { + return false; + } + for (var i = 0; i < result[1].length; i++) { + if (!result[1][i]) { + return false; + } + } + return true; } - debug(" -- failed and"); + debug(' -- failed and'); return null; } - function or() { - var result = sequence([relation, whitespace, _or_, whitespace, condition]); - if (result) { - debug(" -- passed or"); - return result[0] || result[4]; + // ('and' relation)* + function andTail() { + var result = sequence([whitespace, _and_, whitespace, relation]); + if (result !== null) { + debug(' -- passed andTail' + result); + return result[3]; } - debug(" -- failed or"); + debug(' -- failed andTail'); return null; - } - var condition = choice([and, or, relation]); + } + // ('or' and_condition)* + function orTail() { + var result = sequence([whitespace, _or_, whitespace, and]); + if (result !== null) { + debug(' -- passed orTail: ' + result[3]); + return result[3]; + } + debug(' -- failed orTail'); + return null; - function isInt(n) { - return parseFloat(n) % 1 === 0; } + // condition = and_condition ('or' and_condition)* + function condition() { + var result = sequence([and, nOrMore(0, orTail)]); + if (result) { + for (var i = 0; i < result[1].length; i++) { + if (result[1][i]) { + return true; + } + } + return result[0]; - function start() { - if (!isInt(number)) { - return false; } - var result = condition(); - return result; + return false; } - - var result = start(); - + result = condition(); /* * For success, the pos must have gotten to the end of the rule * and returned a non-null. * n.b. This is part of language infrastructure, so we do not throw an internationalizable message. */ - if (result === null || pos !== rule.length) { - // throw new Error("Parse error at position " + pos.toString() + " in input: " + rule + " result is " + result); + if (result === null) { + throw new Error('Parse error at position ' + pos.toString() + ' for rule: ' + rule); } - return result; -} + if (pos !== rule.length) { + debug('Warning: Rule not parsed completely. Parser stopped at ' + rule.substr(0, pos) + ' for rule: ' + rule); + } -/* For module loaders, e.g. NodeJS, NPM */ -if (typeof module !== 'undefined' && module.exports) { - module.exports = pluralRuleParser; + return result; } /* pluralRuleParser ends here */ |