Merge pull request #403 from M2Ys4U/nick_trunc_fix
[KiwiIRC.git] / client / assets / libs / jed.js
1 /*
2 jed.js
3 v0.5.0beta
4
5 https://github.com/SlexAxton/Jed
6 -----------
7 A gettext compatible i18n library for modern JavaScript Applications
8
9 by Alex Sexton - AlexSexton [at] gmail - @SlexAxton
10 WTFPL license for use
11 Dojo CLA for contributions
12
13 Jed offers the entire applicable GNU gettext spec'd set of
14 functions, but also offers some nicer wrappers around them.
15 The api for gettext was written for a language with no function
16 overloading, so Jed allows a little more of that.
17
18 Many thanks to Joshua I. Miller - unrtst@cpan.org - who wrote
19 gettext.js back in 2008. I was able to vet a lot of my ideas
20 against his. I also made sure Jed passed against his tests
21 in order to offer easy upgrades -- jsgettext.berlios.de
22 */
23 (function (root, undef) {
24
25 // Set up some underscore-style functions, if you already have
26 // underscore, feel free to delete this section, and use it
27 // directly, however, the amount of functions used doesn't
28 // warrant having underscore as a full dependency.
29 // Underscore 1.3.0 was used to port and is licensed
30 // under the MIT License by Jeremy Ashkenas.
31 var ArrayProto = Array.prototype,
32 ObjProto = Object.prototype,
33 slice = ArrayProto.slice,
34 hasOwnProp = ObjProto.hasOwnProperty,
35 nativeForEach = ArrayProto.forEach,
36 breaker = {};
37
38 // We're not using the OOP style _ so we don't need the
39 // extra level of indirection. This still means that you
40 // sub out for real `_` though.
41 var _ = {
42 forEach : function( obj, iterator, context ) {
43 var i, l, key;
44 if ( obj === null ) {
45 return;
46 }
47
48 if ( nativeForEach && obj.forEach === nativeForEach ) {
49 obj.forEach( iterator, context );
50 }
51 else if ( obj.length === +obj.length ) {
52 for ( i = 0, l = obj.length; i < l; i++ ) {
53 if ( i in obj && iterator.call( context, obj[i], i, obj ) === breaker ) {
54 return;
55 }
56 }
57 }
58 else {
59 for ( key in obj) {
60 if ( hasOwnProp.call( obj, key ) ) {
61 if ( iterator.call (context, obj[key], key, obj ) === breaker ) {
62 return;
63 }
64 }
65 }
66 }
67 },
68 extend : function( obj ) {
69 this.forEach( slice.call( arguments, 1 ), function ( source ) {
70 for ( var prop in source ) {
71 obj[prop] = source[prop];
72 }
73 });
74 return obj;
75 }
76 };
77 // END Miniature underscore impl
78
79 // Jed is a constructor function
80 var Jed = function ( options ) {
81 // Some minimal defaults
82 this.defaults = {
83 "locale_data" : {
84 "messages" : {
85 "" : {
86 "domain" : "messages",
87 "lang" : "en",
88 "plural_forms" : "nplurals=2; plural=(n != 1);"
89 }
90 // There are no default keys, though
91 }
92 },
93 // The default domain if one is missing
94 "domain" : "messages"
95 };
96
97 // Mix in the sent options with the default options
98 this.options = _.extend( {}, this.defaults, options );
99 this.textdomain( this.options.domain );
100
101 if ( this.options.domain && ! this.options.locale_data[ this.options.domain ] ) {
102 throw new Error('Text domain set to non-existent domain: `' + this.options.domain + '`');
103 }
104 };
105
106 // The gettext spec sets this character as the default
107 // delimiter for context lookups.
108 // e.g.: context\u0004key
109 // If your translation company uses something different,
110 // just change this at any time and it will use that instead.
111 Jed.context_delimiter = String.fromCharCode( 4 );
112
113 function getPluralFormFunc ( plural_form_string ) {
114 return Jed.PF.compile( plural_form_string || "nplurals=2; plural=(n != 1);");
115 }
116
117 function Chain( key, i18n ){
118 this._key = key;
119 this._i18n = i18n;
120 }
121
122 // Create a chainable api for adding args prettily
123 _.extend( Chain.prototype, {
124 onDomain : function ( domain ) {
125 this._domain = domain;
126 return this;
127 },
128 withContext : function ( context ) {
129 this._context = context;
130 return this;
131 },
132 ifPlural : function ( num, pkey ) {
133 this._val = num;
134 this._pkey = pkey;
135 return this;
136 },
137 fetch : function ( sArr ) {
138 if ( {}.toString.call( sArr ) != '[object Array]' ) {
139 sArr = [].slice.call(arguments);
140 }
141 return ( sArr && sArr.length ? Jed.sprintf : function(x){ return x; } )(
142 this._i18n.dcnpgettext(this._domain, this._context, this._key, this._pkey, this._val),
143 sArr
144 );
145 }
146 });
147
148 // Add functions to the Jed prototype.
149 // These will be the functions on the object that's returned
150 // from creating a `new Jed()`
151 // These seem redundant, but they gzip pretty well.
152 _.extend( Jed.prototype, {
153 // The sexier api start point
154 translate : function ( key ) {
155 return new Chain( key, this );
156 },
157
158 textdomain : function ( domain ) {
159 if ( ! domain ) {
160 return this._textdomain;
161 }
162 this._textdomain = domain;
163 },
164
165 gettext : function ( key ) {
166 return this.dcnpgettext.call( this, undef, undef, key );
167 },
168
169 dgettext : function ( domain, key ) {
170 return this.dcnpgettext.call( this, domain, undef, key );
171 },
172
173 dcgettext : function ( domain , key /*, category */ ) {
174 // Ignores the category anyways
175 return this.dcnpgettext.call( this, domain, undef, key );
176 },
177
178 ngettext : function ( skey, pkey, val ) {
179 return this.dcnpgettext.call( this, undef, undef, skey, pkey, val );
180 },
181
182 dngettext : function ( domain, skey, pkey, val ) {
183 return this.dcnpgettext.call( this, domain, undef, skey, pkey, val );
184 },
185
186 dcngettext : function ( domain, skey, pkey, val/*, category */) {
187 return this.dcnpgettext.call( this, domain, undef, skey, pkey, val );
188 },
189
190 pgettext : function ( context, key ) {
191 return this.dcnpgettext.call( this, undef, context, key );
192 },
193
194 dpgettext : function ( domain, context, key ) {
195 return this.dcnpgettext.call( this, domain, context, key );
196 },
197
198 dcpgettext : function ( domain, context, key/*, category */) {
199 return this.dcnpgettext.call( this, domain, context, key );
200 },
201
202 npgettext : function ( context, skey, pkey, val ) {
203 return this.dcnpgettext.call( this, undef, context, skey, pkey, val );
204 },
205
206 dnpgettext : function ( domain, context, skey, pkey, val ) {
207 return this.dcnpgettext.call( this, domain, context, skey, pkey, val );
208 },
209
210 // The most fully qualified gettext function. It has every option.
211 // Since it has every option, we can use it from every other method.
212 // This is the bread and butter.
213 // Technically there should be one more argument in this function for 'Category',
214 // but since we never use it, we might as well not waste the bytes to define it.
215 dcnpgettext : function ( domain, context, singular_key, plural_key, val ) {
216 // Set some defaults
217
218 plural_key = plural_key || singular_key;
219
220 // Use the global domain default if one
221 // isn't explicitly passed in
222 domain = domain || this._textdomain;
223
224 // Default the value to the singular case
225 val = typeof val == 'undefined' ? 1 : val;
226
227 var fallback;
228
229 // Handle special cases
230
231 // No options found
232 if ( ! this.options ) {
233 // There's likely something wrong, but we'll return the correct key for english
234 // We do this by instantiating a brand new Jed instance with the default set
235 // for everything that could be broken.
236 fallback = new Jed();
237 return fallback.dcnpgettext.call( fallback, undefined, undefined, singular_key, plural_key, val );
238 }
239
240 // No translation data provided
241 if ( ! this.options.locale_data ) {
242 throw new Error('No locale data provided.');
243 }
244
245 if ( ! this.options.locale_data[ domain ] ) {
246 throw new Error('Domain `' + domain + '` was not found.');
247 }
248
249 if ( ! this.options.locale_data[ domain ][ "" ] ) {
250 throw new Error('No locale meta information provided.');
251 }
252
253 // Make sure we have a truthy key. Otherwise we might start looking
254 // into the empty string key, which is the options for the locale
255 // data.
256 if ( ! singular_key ) {
257 throw new Error('No translation key found.');
258 }
259
260 // Handle invalid numbers, but try casting strings for good measure
261 if ( typeof val != 'number' ) {
262 val = parseInt( val, 10 );
263
264 if ( isNaN( val ) ) {
265 throw new Error('The number that was passed in is not a number.');
266 }
267 }
268
269 var key = context ? context + Jed.context_delimiter + singular_key : singular_key,
270 locale_data = this.options.locale_data,
271 dict = locale_data[ domain ],
272 pluralForms = dict[""].plural_forms || (locale_data.messages || this.defaults.locale_data.messages)[""].plural_forms,
273 val_idx = getPluralFormFunc(pluralForms)(val) + 1,
274 val_list,
275 res;
276
277 // Throw an error if a domain isn't found
278 if ( ! dict ) {
279 throw new Error('No domain named `' + domain + '` could be found.');
280 }
281
282 val_list = dict[ key ];
283
284 // If there is no match, then revert back to
285 // english style singular/plural with the keys passed in.
286 if ( ! val_list || val_idx >= val_list.length ) {
287 res = [ null, singular_key, plural_key ];
288 return res[ getPluralFormFunc(pluralForms)( val ) + 1 ];
289 }
290
291 res = val_list[ val_idx ];
292
293 // This includes empty strings on purpose
294 if ( ! res ) {
295 res = [ null, singular_key, plural_key ];
296 return res[ getPluralFormFunc(pluralForms)( val ) + 1 ];
297 }
298 return res;
299 }
300 });
301
302
303 // We add in sprintf capabilities for post translation value interolation
304 // This is not internally used, so you can remove it if you have this
305 // available somewhere else, or want to use a different system.
306
307 // We _slightly_ modify the normal sprintf behavior to more gracefully handle
308 // undefined values.
309
310 /**
311 sprintf() for JavaScript 0.7-beta1
312 http://www.diveintojavascript.com/projects/javascript-sprintf
313
314 Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
315 All rights reserved.
316
317 Redistribution and use in source and binary forms, with or without
318 modification, are permitted provided that the following conditions are met:
319 * Redistributions of source code must retain the above copyright
320 notice, this list of conditions and the following disclaimer.
321 * Redistributions in binary form must reproduce the above copyright
322 notice, this list of conditions and the following disclaimer in the
323 documentation and/or other materials provided with the distribution.
324 * Neither the name of sprintf() for JavaScript nor the
325 names of its contributors may be used to endorse or promote products
326 derived from this software without specific prior written permission.
327
328 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
329 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
330 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
331 DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY
332 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
333 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
334 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
335 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
336 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
337 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
338 */
339 var sprintf = (function() {
340 function get_type(variable) {
341 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
342 }
343 function str_repeat(input, multiplier) {
344 for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
345 return output.join('');
346 }
347
348 var str_format = function() {
349 if (!str_format.cache.hasOwnProperty(arguments[0])) {
350 str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
351 }
352 return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
353 };
354
355 str_format.format = function(parse_tree, argv) {
356 var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
357 for (i = 0; i < tree_length; i++) {
358 node_type = get_type(parse_tree[i]);
359 if (node_type === 'string') {
360 output.push(parse_tree[i]);
361 }
362 else if (node_type === 'array') {
363 match = parse_tree[i]; // convenience purposes only
364 if (match[2]) { // keyword argument
365 arg = argv[cursor];
366 for (k = 0; k < match[2].length; k++) {
367 if (!arg.hasOwnProperty(match[2][k])) {
368 throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
369 }
370 arg = arg[match[2][k]];
371 }
372 }
373 else if (match[1]) { // positional argument (explicit)
374 arg = argv[match[1]];
375 }
376 else { // positional argument (implicit)
377 arg = argv[cursor++];
378 }
379
380 if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
381 throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
382 }
383
384 // Jed EDIT
385 if ( typeof arg == 'undefined' || arg === null ) {
386 arg = '';
387 }
388 // Jed EDIT
389
390 switch (match[8]) {
391 case 'b': arg = arg.toString(2); break;
392 case 'c': arg = String.fromCharCode(arg); break;
393 case 'd': arg = parseInt(arg, 10); break;
394 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
395 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
396 case 'o': arg = arg.toString(8); break;
397 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
398 case 'u': arg = Math.abs(arg); break;
399 case 'x': arg = arg.toString(16); break;
400 case 'X': arg = arg.toString(16).toUpperCase(); break;
401 }
402 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
403 pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
404 pad_length = match[6] - String(arg).length;
405 pad = match[6] ? str_repeat(pad_character, pad_length) : '';
406 output.push(match[5] ? arg + pad : pad + arg);
407 }
408 }
409 return output.join('');
410 };
411
412 str_format.cache = {};
413
414 str_format.parse = function(fmt) {
415 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
416 while (_fmt) {
417 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
418 parse_tree.push(match[0]);
419 }
420 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
421 parse_tree.push('%');
422 }
423 else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
424 if (match[2]) {
425 arg_names |= 1;
426 var field_list = [], replacement_field = match[2], field_match = [];
427 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
428 field_list.push(field_match[1]);
429 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
430 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
431 field_list.push(field_match[1]);
432 }
433 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
434 field_list.push(field_match[1]);
435 }
436 else {
437 throw('[sprintf] huh?');
438 }
439 }
440 }
441 else {
442 throw('[sprintf] huh?');
443 }
444 match[2] = field_list;
445 }
446 else {
447 arg_names |= 2;
448 }
449 if (arg_names === 3) {
450 throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
451 }
452 parse_tree.push(match);
453 }
454 else {
455 throw('[sprintf] huh?');
456 }
457 _fmt = _fmt.substring(match[0].length);
458 }
459 return parse_tree;
460 };
461
462 return str_format;
463 })();
464
465 var vsprintf = function(fmt, argv) {
466 argv.unshift(fmt);
467 return sprintf.apply(null, argv);
468 };
469
470 Jed.parse_plural = function ( plural_forms, n ) {
471 plural_forms = plural_forms.replace(/n/g, n);
472 return Jed.parse_expression(plural_forms);
473 };
474
475 Jed.sprintf = function ( fmt, args ) {
476 if ( {}.toString.call( args ) == '[object Array]' ) {
477 return vsprintf( fmt, [].slice.call(args) );
478 }
479 return sprintf.apply(this, [].slice.call(arguments) );
480 };
481
482 Jed.prototype.sprintf = function () {
483 return Jed.sprintf.apply(this, arguments);
484 };
485 // END sprintf Implementation
486
487 // Start the Plural forms section
488 // This is a full plural form expression parser. It is used to avoid
489 // running 'eval' or 'new Function' directly against the plural
490 // forms.
491 //
492 // This can be important if you get translations done through a 3rd
493 // party vendor. I encourage you to use this instead, however, I
494 // also will provide a 'precompiler' that you can use at build time
495 // to output valid/safe function representations of the plural form
496 // expressions. This means you can build this code out for the most
497 // part.
498 Jed.PF = {};
499
500 Jed.PF.parse = function ( p ) {
501 var plural_str = Jed.PF.extractPluralExpr( p );
502 return Jed.PF.parser.parse.call(Jed.PF.parser, plural_str);
503 };
504
505 Jed.PF.compile = function ( p ) {
506 // Handle trues and falses as 0 and 1
507 function imply( val ) {
508 return (val === true ? 1 : val ? val : 0);
509 }
510
511 var ast = Jed.PF.parse( p );
512 return function ( n ) {
513 return imply( Jed.PF.interpreter( ast )( n ) );
514 };
515 };
516
517 Jed.PF.interpreter = function ( ast ) {
518 return function ( n ) {
519 var res;
520 switch ( ast.type ) {
521 case 'GROUP':
522 return Jed.PF.interpreter( ast.expr )( n );
523 case 'TERNARY':
524 if ( Jed.PF.interpreter( ast.expr )( n ) ) {
525 return Jed.PF.interpreter( ast.truthy )( n );
526 }
527 return Jed.PF.interpreter( ast.falsey )( n );
528 case 'OR':
529 return Jed.PF.interpreter( ast.left )( n ) || Jed.PF.interpreter( ast.right )( n );
530 case 'AND':
531 return Jed.PF.interpreter( ast.left )( n ) && Jed.PF.interpreter( ast.right )( n );
532 case 'LT':
533 return Jed.PF.interpreter( ast.left )( n ) < Jed.PF.interpreter( ast.right )( n );
534 case 'GT':
535 return Jed.PF.interpreter( ast.left )( n ) > Jed.PF.interpreter( ast.right )( n );
536 case 'LTE':
537 return Jed.PF.interpreter( ast.left )( n ) <= Jed.PF.interpreter( ast.right )( n );
538 case 'GTE':
539 return Jed.PF.interpreter( ast.left )( n ) >= Jed.PF.interpreter( ast.right )( n );
540 case 'EQ':
541 return Jed.PF.interpreter( ast.left )( n ) == Jed.PF.interpreter( ast.right )( n );
542 case 'NEQ':
543 return Jed.PF.interpreter( ast.left )( n ) != Jed.PF.interpreter( ast.right )( n );
544 case 'MOD':
545 return Jed.PF.interpreter( ast.left )( n ) % Jed.PF.interpreter( ast.right )( n );
546 case 'VAR':
547 return n;
548 case 'NUM':
549 return ast.val;
550 default:
551 throw new Error("Invalid Token found.");
552 }
553 };
554 };
555
556 Jed.PF.extractPluralExpr = function ( p ) {
557 // trim first
558 p = p.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
559
560 if (! /;\s*$/.test(p)) {
561 p = p.concat(';');
562 }
563
564 var nplurals_re = /nplurals\=(\d+);/,
565 plural_re = /plural\=(.*);/,
566 nplurals_matches = p.match( nplurals_re ),
567 res = {},
568 plural_matches;
569
570 // Find the nplurals number
571 if ( nplurals_matches.length > 1 ) {
572 res.nplurals = nplurals_matches[1];
573 }
574 else {
575 throw new Error('nplurals not found in plural_forms string: ' + p );
576 }
577
578 // remove that data to get to the formula
579 p = p.replace( nplurals_re, "" );
580 plural_matches = p.match( plural_re );
581
582 if (!( plural_matches && plural_matches.length > 1 ) ) {
583 throw new Error('`plural` expression not found: ' + p);
584 }
585 return plural_matches[ 1 ];
586 };
587
588 /* Jison generated parser */
589 Jed.PF.parser = (function(){
590
591 var parser = {trace: function trace() { },
592 yy: {},
593 symbols_: {"error":2,"expressions":3,"e":4,"EOF":5,"?":6,":":7,"||":8,"&&":9,"<":10,"<=":11,">":12,">=":13,"!=":14,"==":15,"%":16,"(":17,")":18,"n":19,"NUMBER":20,"$accept":0,"$end":1},
594 terminals_: {2:"error",5:"EOF",6:"?",7:":",8:"||",9:"&&",10:"<",11:"<=",12:">",13:">=",14:"!=",15:"==",16:"%",17:"(",18:")",19:"n",20:"NUMBER"},
595 productions_: [0,[3,2],[4,5],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,1],[4,1]],
596 performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
597
598 var $0 = $$.length - 1;
599 switch (yystate) {
600 case 1: return { type : 'GROUP', expr: $$[$0-1] };
601 break;
602 case 2:this.$ = { type: 'TERNARY', expr: $$[$0-4], truthy : $$[$0-2], falsey: $$[$0] };
603 break;
604 case 3:this.$ = { type: "OR", left: $$[$0-2], right: $$[$0] };
605 break;
606 case 4:this.$ = { type: "AND", left: $$[$0-2], right: $$[$0] };
607 break;
608 case 5:this.$ = { type: 'LT', left: $$[$0-2], right: $$[$0] };
609 break;
610 case 6:this.$ = { type: 'LTE', left: $$[$0-2], right: $$[$0] };
611 break;
612 case 7:this.$ = { type: 'GT', left: $$[$0-2], right: $$[$0] };
613 break;
614 case 8:this.$ = { type: 'GTE', left: $$[$0-2], right: $$[$0] };
615 break;
616 case 9:this.$ = { type: 'NEQ', left: $$[$0-2], right: $$[$0] };
617 break;
618 case 10:this.$ = { type: 'EQ', left: $$[$0-2], right: $$[$0] };
619 break;
620 case 11:this.$ = { type: 'MOD', left: $$[$0-2], right: $$[$0] };
621 break;
622 case 12:this.$ = { type: 'GROUP', expr: $$[$0-1] };
623 break;
624 case 13:this.$ = { type: 'VAR' };
625 break;
626 case 14:this.$ = { type: 'NUM', val: Number(yytext) };
627 break;
628 }
629 },
630 table: [{3:1,4:2,17:[1,3],19:[1,4],20:[1,5]},{1:[3]},{5:[1,6],6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{4:17,17:[1,3],19:[1,4],20:[1,5]},{5:[2,13],6:[2,13],7:[2,13],8:[2,13],9:[2,13],10:[2,13],11:[2,13],12:[2,13],13:[2,13],14:[2,13],15:[2,13],16:[2,13],18:[2,13]},{5:[2,14],6:[2,14],7:[2,14],8:[2,14],9:[2,14],10:[2,14],11:[2,14],12:[2,14],13:[2,14],14:[2,14],15:[2,14],16:[2,14],18:[2,14]},{1:[2,1]},{4:18,17:[1,3],19:[1,4],20:[1,5]},{4:19,17:[1,3],19:[1,4],20:[1,5]},{4:20,17:[1,3],19:[1,4],20:[1,5]},{4:21,17:[1,3],19:[1,4],20:[1,5]},{4:22,17:[1,3],19:[1,4],20:[1,5]},{4:23,17:[1,3],19:[1,4],20:[1,5]},{4:24,17:[1,3],19:[1,4],20:[1,5]},{4:25,17:[1,3],19:[1,4],20:[1,5]},{4:26,17:[1,3],19:[1,4],20:[1,5]},{4:27,17:[1,3],19:[1,4],20:[1,5]},{6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[1,28]},{6:[1,7],7:[1,29],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{5:[2,3],6:[2,3],7:[2,3],8:[2,3],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,3]},{5:[2,4],6:[2,4],7:[2,4],8:[2,4],9:[2,4],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,4]},{5:[2,5],6:[2,5],7:[2,5],8:[2,5],9:[2,5],10:[2,5],11:[2,5],12:[2,5],13:[2,5],14:[2,5],15:[2,5],16:[1,16],18:[2,5]},{5:[2,6],6:[2,6],7:[2,6],8:[2,6],9:[2,6],10:[2,6],11:[2,6],12:[2,6],13:[2,6],14:[2,6],15:[2,6],16:[1,16],18:[2,6]},{5:[2,7],6:[2,7],7:[2,7],8:[2,7],9:[2,7],10:[2,7],11:[2,7],12:[2,7],13:[2,7],14:[2,7],15:[2,7],16:[1,16],18:[2,7]},{5:[2,8],6:[2,8],7:[2,8],8:[2,8],9:[2,8],10:[2,8],11:[2,8],12:[2,8],13:[2,8],14:[2,8],15:[2,8],16:[1,16],18:[2,8]},{5:[2,9],6:[2,9],7:[2,9],8:[2,9],9:[2,9],10:[2,9],11:[2,9],12:[2,9],13:[2,9],14:[2,9],15:[2,9],16:[1,16],18:[2,9]},{5:[2,10],6:[2,10],7:[2,10],8:[2,10],9:[2,10],10:[2,10],11:[2,10],12:[2,10],13:[2,10],14:[2,10],15:[2,10],16:[1,16],18:[2,10]},{5:[2,11],6:[2,11],7:[2,11],8:[2,11],9:[2,11],10:[2,11],11:[2,11],12:[2,11],13:[2,11],14:[2,11],15:[2,11],16:[2,11],18:[2,11]},{5:[2,12],6:[2,12],7:[2,12],8:[2,12],9:[2,12],10:[2,12],11:[2,12],12:[2,12],13:[2,12],14:[2,12],15:[2,12],16:[2,12],18:[2,12]},{4:30,17:[1,3],19:[1,4],20:[1,5]},{5:[2,2],6:[1,7],7:[2,2],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,2]}],
631 defaultActions: {6:[2,1]},
632 parseError: function parseError(str, hash) {
633 throw new Error(str);
634 },
635 parse: function parse(input) {
636 var self = this,
637 stack = [0],
638 vstack = [null], // semantic value stack
639 lstack = [], // location stack
640 table = this.table,
641 yytext = '',
642 yylineno = 0,
643 yyleng = 0,
644 recovering = 0,
645 TERROR = 2,
646 EOF = 1;
647
648 //this.reductionCount = this.shiftCount = 0;
649
650 this.lexer.setInput(input);
651 this.lexer.yy = this.yy;
652 this.yy.lexer = this.lexer;
653 if (typeof this.lexer.yylloc == 'undefined')
654 this.lexer.yylloc = {};
655 var yyloc = this.lexer.yylloc;
656 lstack.push(yyloc);
657
658 if (typeof this.yy.parseError === 'function')
659 this.parseError = this.yy.parseError;
660
661 function popStack (n) {
662 stack.length = stack.length - 2*n;
663 vstack.length = vstack.length - n;
664 lstack.length = lstack.length - n;
665 }
666
667 function lex() {
668 var token;
669 token = self.lexer.lex() || 1; // $end = 1
670 // if token isn't its numeric value, convert
671 if (typeof token !== 'number') {
672 token = self.symbols_[token] || token;
673 }
674 return token;
675 }
676
677 var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected;
678 while (true) {
679 // retreive state number from top of stack
680 state = stack[stack.length-1];
681
682 // use default actions if available
683 if (this.defaultActions[state]) {
684 action = this.defaultActions[state];
685 } else {
686 if (symbol == null)
687 symbol = lex();
688 // read action for current state and first input
689 action = table[state] && table[state][symbol];
690 }
691
692 // handle parse error
693 _handle_error:
694 if (typeof action === 'undefined' || !action.length || !action[0]) {
695
696 if (!recovering) {
697 // Report error
698 expected = [];
699 for (p in table[state]) if (this.terminals_[p] && p > 2) {
700 expected.push("'"+this.terminals_[p]+"'");
701 }
702 var errStr = '';
703 if (this.lexer.showPosition) {
704 errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'";
705 } else {
706 errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
707 (symbol == 1 /*EOF*/ ? "end of input" :
708 ("'"+(this.terminals_[symbol] || symbol)+"'"));
709 }
710 this.parseError(errStr,
711 {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
712 }
713
714 // just recovered from another error
715 if (recovering == 3) {
716 if (symbol == EOF) {
717 throw new Error(errStr || 'Parsing halted.');
718 }
719
720 // discard current lookahead and grab another
721 yyleng = this.lexer.yyleng;
722 yytext = this.lexer.yytext;
723 yylineno = this.lexer.yylineno;
724 yyloc = this.lexer.yylloc;
725 symbol = lex();
726 }
727
728 // try to recover from error
729 while (1) {
730 // check for error recovery rule in this state
731 if ((TERROR.toString()) in table[state]) {
732 break;
733 }
734 if (state == 0) {
735 throw new Error(errStr || 'Parsing halted.');
736 }
737 popStack(1);
738 state = stack[stack.length-1];
739 }
740
741 preErrorSymbol = symbol; // save the lookahead token
742 symbol = TERROR; // insert generic error symbol as new lookahead
743 state = stack[stack.length-1];
744 action = table[state] && table[state][TERROR];
745 recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
746 }
747
748 // this shouldn't happen, unless resolve defaults are off
749 if (action[0] instanceof Array && action.length > 1) {
750 throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
751 }
752
753 switch (action[0]) {
754
755 case 1: // shift
756 //this.shiftCount++;
757
758 stack.push(symbol);
759 vstack.push(this.lexer.yytext);
760 lstack.push(this.lexer.yylloc);
761 stack.push(action[1]); // push state
762 symbol = null;
763 if (!preErrorSymbol) { // normal execution/no error
764 yyleng = this.lexer.yyleng;
765 yytext = this.lexer.yytext;
766 yylineno = this.lexer.yylineno;
767 yyloc = this.lexer.yylloc;
768 if (recovering > 0)
769 recovering--;
770 } else { // error just occurred, resume old lookahead f/ before error
771 symbol = preErrorSymbol;
772 preErrorSymbol = null;
773 }
774 break;
775
776 case 2: // reduce
777 //this.reductionCount++;
778
779 len = this.productions_[action[1]][1];
780
781 // perform semantic action
782 yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
783 // default location, uses first token for firsts, last for lasts
784 yyval._$ = {
785 first_line: lstack[lstack.length-(len||1)].first_line,
786 last_line: lstack[lstack.length-1].last_line,
787 first_column: lstack[lstack.length-(len||1)].first_column,
788 last_column: lstack[lstack.length-1].last_column
789 };
790 r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
791
792 if (typeof r !== 'undefined') {
793 return r;
794 }
795
796 // pop off stack
797 if (len) {
798 stack = stack.slice(0,-1*len*2);
799 vstack = vstack.slice(0, -1*len);
800 lstack = lstack.slice(0, -1*len);
801 }
802
803 stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)
804 vstack.push(yyval.$);
805 lstack.push(yyval._$);
806 // goto new state = table[STATE][NONTERMINAL]
807 newState = table[stack[stack.length-2]][stack[stack.length-1]];
808 stack.push(newState);
809 break;
810
811 case 3: // accept
812 return true;
813 }
814
815 }
816
817 return true;
818 }};/* Jison generated lexer */
819 var lexer = (function(){
820
821 var lexer = ({EOF:1,
822 parseError:function parseError(str, hash) {
823 if (this.yy.parseError) {
824 this.yy.parseError(str, hash);
825 } else {
826 throw new Error(str);
827 }
828 },
829 setInput:function (input) {
830 this._input = input;
831 this._more = this._less = this.done = false;
832 this.yylineno = this.yyleng = 0;
833 this.yytext = this.matched = this.match = '';
834 this.conditionStack = ['INITIAL'];
835 this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
836 return this;
837 },
838 input:function () {
839 var ch = this._input[0];
840 this.yytext+=ch;
841 this.yyleng++;
842 this.match+=ch;
843 this.matched+=ch;
844 var lines = ch.match(/\n/);
845 if (lines) this.yylineno++;
846 this._input = this._input.slice(1);
847 return ch;
848 },
849 unput:function (ch) {
850 this._input = ch + this._input;
851 return this;
852 },
853 more:function () {
854 this._more = true;
855 return this;
856 },
857 pastInput:function () {
858 var past = this.matched.substr(0, this.matched.length - this.match.length);
859 return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
860 },
861 upcomingInput:function () {
862 var next = this.match;
863 if (next.length < 20) {
864 next += this._input.substr(0, 20-next.length);
865 }
866 return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
867 },
868 showPosition:function () {
869 var pre = this.pastInput();
870 var c = new Array(pre.length + 1).join("-");
871 return pre + this.upcomingInput() + "\n" + c+"^";
872 },
873 next:function () {
874 if (this.done) {
875 return this.EOF;
876 }
877 if (!this._input) this.done = true;
878
879 var token,
880 match,
881 col,
882 lines;
883 if (!this._more) {
884 this.yytext = '';
885 this.match = '';
886 }
887 var rules = this._currentRules();
888 for (var i=0;i < rules.length; i++) {
889 match = this._input.match(this.rules[rules[i]]);
890 if (match) {
891 lines = match[0].match(/\n.*/g);
892 if (lines) this.yylineno += lines.length;
893 this.yylloc = {first_line: this.yylloc.last_line,
894 last_line: this.yylineno+1,
895 first_column: this.yylloc.last_column,
896 last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}
897 this.yytext += match[0];
898 this.match += match[0];
899 this.matches = match;
900 this.yyleng = this.yytext.length;
901 this._more = false;
902 this._input = this._input.slice(match[0].length);
903 this.matched += match[0];
904 token = this.performAction.call(this, this.yy, this, rules[i],this.conditionStack[this.conditionStack.length-1]);
905 if (token) return token;
906 else return;
907 }
908 }
909 if (this._input === "") {
910 return this.EOF;
911 } else {
912 this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
913 {text: "", token: null, line: this.yylineno});
914 }
915 },
916 lex:function lex() {
917 var r = this.next();
918 if (typeof r !== 'undefined') {
919 return r;
920 } else {
921 return this.lex();
922 }
923 },
924 begin:function begin(condition) {
925 this.conditionStack.push(condition);
926 },
927 popState:function popState() {
928 return this.conditionStack.pop();
929 },
930 _currentRules:function _currentRules() {
931 return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
932 },
933 topState:function () {
934 return this.conditionStack[this.conditionStack.length-2];
935 },
936 pushState:function begin(condition) {
937 this.begin(condition);
938 }});
939 lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
940
941 var YYSTATE=YY_START;
942 switch($avoiding_name_collisions) {
943 case 0:/* skip whitespace */
944 break;
945 case 1:return 20
946 break;
947 case 2:return 19
948 break;
949 case 3:return 8
950 break;
951 case 4:return 9
952 break;
953 case 5:return 6
954 break;
955 case 6:return 7
956 break;
957 case 7:return 11
958 break;
959 case 8:return 13
960 break;
961 case 9:return 10
962 break;
963 case 10:return 12
964 break;
965 case 11:return 14
966 break;
967 case 12:return 15
968 break;
969 case 13:return 16
970 break;
971 case 14:return 17
972 break;
973 case 15:return 18
974 break;
975 case 16:return 5
976 break;
977 case 17:return 'INVALID'
978 break;
979 }
980 };
981 lexer.rules = [/^\s+/,/^[0-9]+(\.[0-9]+)?\b/,/^n\b/,/^\|\|/,/^&&/,/^\?/,/^:/,/^<=/,/^>=/,/^</,/^>/,/^!=/,/^==/,/^%/,/^\(/,/^\)/,/^$/,/^./];
982 lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],"inclusive":true}};return lexer;})()
983 parser.lexer = lexer;
984 return parser;
985 })();
986 // End parser
987
988 // Handle node, amd, and global systems
989 if (typeof exports !== 'undefined') {
990 if (typeof module !== 'undefined' && module.exports) {
991 exports = module.exports = Jed;
992 }
993 exports.Jed = Jed;
994 }
995 else {
996 if (typeof define === 'function' && define.amd) {
997 define('jed', function() {
998 return Jed;
999 });
1000 }
1001 // Leak a global regardless of module system
1002 root['Jed'] = Jed;
1003 }
1004
1005 })(this);