UNPKG

make-plural-compiler

Version:

Translates Unicode CLDR pluralization rules to executable JavaScript

76 lines (63 loc) 2.61 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Parser = void 0; class Parser { parse(cond) { if (cond === 'i = 0 or n = 1') return 'n >= 0 && n <= 1'; if (cond === 'i = 0,1') return 'n >= 0 && n < 2'; if (cond === 'i = 1 and v = 0') { this.v0 = 1; return 'n == 1 && v0'; } return cond.replace(/([^=\s])([!=%]+)([^=\s])/g, '$1 $2 $3').replace(/[ce] (!?)= ([0-9]+)(?:\.\.[0-9]+)?/g, // assume c & e always have the value 0 (m, noteq, x0) => !noteq === (x0 === '0') ? 'true' : 'false').replace(/^true and |^false or | and true$| or false$/g, '').replace(/([tv]) (!?)= 0/g, (m, sym, noteq) => { const sn = sym + '0'; this[sn] = 1; return noteq ? '!' + sn : sn; }).replace(/\b[fintv]\b/g, m => { this[m] = 1; return m; }).replace(/([fin]) % (10+)/g, (m, sym, num) => { const sn = sym + num; this[sn] = 1; return sn; }).replace(/n10+ = 0/g, 't0 && $&').replace(/(\w+ (!?)= )([0-9.]+,[0-9.,]+)/g, (m, se, noteq, x) => { if (m === 'n = 0,1') return '(n == 0 || n == 1)'; if (noteq) return se + x.split(',').join(' && ' + se); return '(' + se + x.split(',').join(' || ' + se) + ')'; }).replace(/(\w+) (!?)= ([0-9]+)\.\.([0-9]+)/g, (m, sym, noteq, x0, x1) => { if (Number(x0) + 1 === Number(x1)) { /* istanbul ignore if: noteq is not used in current CLDR */ if (noteq) return `${sym} != ${x0} && ${sym} != ${x1}`; return `(${sym} == ${x0} || ${sym} == ${x1})`; } if (noteq) return `(${sym} < ${x0} || ${sym} > ${x1})`; if (sym === 'n') { this.t0 = 1; return `(t0 && n >= ${x0} && n <= ${x1})`; } return `(${sym} >= ${x0} && ${sym} <= ${x1})`; }).replace(/ and /g, ' && ').replace(/ or /g, ' || ').replace(/ = /g, ' == '); } vars() { let vars = []; if (this.i) vars.push('i = s[0]'); if (this.f || this.v) vars.push("f = s[1] || ''"); /* istanbul ignore if: t is not used in current CLDR */ if (this.t) vars.push("t = (s[1] || '').replace(/0+$/, '')"); if (this.v) vars.push('v = f.length'); if (this.v0) vars.push('v0 = !s[1]'); if (this.t0 || this.n10 || this.n100) vars.push('t0 = Number(s[0]) == n'); for (let k in this) { if (/^.10+$/.test(k)) { const k0 = k[0] === 'n' ? 't0 && s[0]' : k[0]; vars.push(`${k} = ${k0}.slice(-${k.substr(2).length})`); } } if (!vars.length) return ''; return 'const ' + ["s = String(n).split('.')", ...vars].join(', '); } } exports.Parser = Parser;