1 /*
  2  JessieCode Interpreter and Compiler
  3 
  4     Copyright 2011-2019
  5         Michael Gerhaeuser,
  6         Alfred Wassermann
  7 
  8     JessieCode is free software dual licensed under the GNU LGPL or MIT License.
  9 
 10     You can redistribute it and/or modify it under the terms of the
 11 
 12       * GNU Lesser General Public License as published by
 13         the Free Software Foundation, either version 3 of the License, or
 14         (at your option) any later version
 15       OR
 16       * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
 17 
 18     JessieCode is distributed in the hope that it will be useful,
 19     but WITHOUT ANY WARRANTY; without even the implied warranty of
 20     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 21     GNU Lesser General Public License for more details.
 22 
 23     You should have received a copy of the GNU Lesser General Public License and
 24     the MIT License along with JessieCode. If not, see <http://www.gnu.org/licenses/>
 25     and <http://opensource.org/licenses/MIT/>.
 26  */
 27 
 28 /*global JXG: true, define: true, window: true, console: true, self: true, document: true, parser: true*/
 29 /*jslint nomen: true, plusplus: true*/
 30 
 31 /* depends:
 32  jxg
 33  parser/geonext
 34  base/constants
 35  base/text
 36  math/math
 37  math/geometry
 38  math/statistics
 39  utils/type
 40  utils/uuid
 41  */
 42 
 43 /**
 44  * @fileoverview JessieCode is a scripting language designed to provide a
 45  * simple scripting language to build constructions
 46  * with JSXGraph. It is similar to JavaScript, but prevents access to the DOM.
 47  * Hence, it can be used in community driven math portals which want to use
 48  * JSXGraph to display interactive math graphics.
 49  */
 50 
 51 define([
 52     'jxg', 'base/constants', 'base/text', 'math/math', 'math/ia', 'math/geometry', 'math/statistics', 'utils/type', 'utils/uuid', 'utils/env'
 53 ], function (JXG, Const, Text, Mat, Interval, Geometry, Statistics, Type, UUID, Env) {
 54 
 55     ;
 56 
 57     // IE 6-8 compatibility
 58     if (!Object.create) {
 59         Object.create = function(o, properties) {
 60             if (typeof o !== 'object' && typeof o !== 'function') throw new TypeError('Object prototype may only be an Object: ' + o);
 61             else if (o === null) throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument.");
 62 
 63             if (typeof properties != 'undefined') throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument.");
 64 
 65             function F() {}
 66 
 67             F.prototype = o;
 68 
 69             return new F();
 70         };
 71     }
 72 
 73     var priv = {
 74             modules: {
 75                 'math': Mat,
 76                 'math/geometry': Geometry,
 77                 'math/statistics': Statistics,
 78                 'math/numerics': Mat.Numerics
 79             }
 80         };
 81 
 82     /**
 83      * A JessieCode object provides an interface to the parser and stores all variables and objects used within a JessieCode script.
 84      * The optional argument <tt>code</tt> is interpreted after initializing. To evaluate more code after initializing a JessieCode instance
 85      * please use {@link JXG.JessieCode#parse}. For code snippets like single expressions use {@link JXG.JessieCode#snippet}.
 86      * @constructor
 87      * @param {String} [code] Code to parse.
 88      * @param {Boolean} [geonext=false] Geonext compatibility mode.
 89      */
 90     JXG.JessieCode = function (code, geonext) {
 91         // Control structures
 92 
 93         /**
 94          * The global scope.
 95          * @type {Object}
 96          */
 97         this.scope = {
 98             id: 0,
 99             hasChild: true,
100             args: [],
101             locals: {},
102             context: null,
103             previous: null
104         };
105 
106         /**
107          * Keeps track of all possible scopes every required.
108          * @type {Array}
109          */
110         this.scopes = [];
111         this.scopes.push(this.scope);
112 
113         /**
114          * A stack to store debug information (like line and column where it was defined) of a parameter
115          * @type Array
116          * @private
117          */
118         this.dpstack = [[]];
119 
120         /**
121          * Determines the parameter stack scope.
122          * @type Number
123          * @private
124          */
125         this.pscope = 0;
126 
127         /**
128          * Used to store the property-value definition while parsing an object literal.
129          * @type Array
130          * @private
131          */
132         this.propstack = [{}];
133 
134         /**
135          * The current scope of the object literal stack {@link JXG.JessieCode#propstack}.
136          * @type Number
137          * @private
138          */
139         this.propscope = 0;
140 
141         /**
142          * Store the left hand side of an assignment. If an element is constructed and no attributes are given, this is
143          * used as the element's name.
144          * @type Array
145          * @private
146          */
147         this.lhs = [];
148 
149         /**
150          * lhs flag, used by JXG.JessieCode#replaceNames
151          * @type Boolean
152          * @default false
153          */
154         this.isLHS = false;
155 
156         /**
157          * The id of an HTML node in which innerHTML all warnings are stored (if no <tt>console</tt> object is available).
158          * @type String
159          * @default 'jcwarn'
160          */
161         this.warnLog = 'jcwarn';
162 
163         /**
164          * Store $log messages in case there's no console.
165          * @type {Array}
166          */
167         this.$log = [];
168 
169         /**
170          * Built-in functions and constants
171          * @type Object
172          */
173         this.builtIn = this.defineBuiltIn();
174 
175         /**
176          * The board which currently is used to create and look up elements.
177          * @type JXG.Board
178          */
179         this.board = null;
180 
181         /**
182          * Keep track of which element is created in which line.
183          * @type Object
184          */
185         this.lineToElement = {};
186 
187         this.parCurLine = 1;
188         this.parCurColumn = 0;
189         this.line = 1;
190         this.col = 1;
191 
192         if (JXG.CA) {
193             this.CA = new JXG.CA(this.node, this.createNode, this);
194         }
195 
196         this.code = '';
197 
198         if (typeof code === 'string') {
199             this.parse(code, geonext);
200         }
201     };
202 
203     JXG.extend(JXG.JessieCode.prototype, /** @lends JXG.JessieCode.prototype */ {
204         /**
205          * Create a new parse tree node.
206          * @param {String} type Type of node, e.g. node_op, node_var, or node_const
207          * @param value The nodes value, e.g. a variables value or a functions body.
208          * @param {Array} children Arbitrary number of child nodes.
209          */
210         node: function (type, value, children) {
211             return {
212                 type: type,
213                 value: value,
214                 children: children
215             };
216         },
217 
218         /**
219          * Create a new parse tree node. Basically the same as node(), but this builds
220          * the children part out of an arbitrary number of parameters, instead of one
221          * array parameter.
222          * @param {String} type Type of node, e.g. node_op, node_var, or node_const
223          * @param value The nodes value, e.g. a variables value or a functions body.
224          * @param children Arbitrary number of parameters; define the child nodes.
225          */
226         createNode: function (type, value, children) {
227             var n = this.node(type, value, []),
228                 i;
229 
230             for (i = 2; i < arguments.length; i++) {
231                 n.children.push(arguments[i]);
232             }
233 
234             if (n.type == 'node_const' && Type.isNumber(n.value)) {
235                 n.isMath = true;
236             }
237 
238             n.line = this.parCurLine;
239             n.col = this.parCurColumn;
240 
241             return n;
242         },
243 
244         /**
245          * Create a new scope.
246          * @param {Array} args
247          * @returns {Object}
248          */
249         pushScope: function (args) {
250             var scope = {
251                     args: args,
252                     locals: {},
253                     context: null,
254                     previous: this.scope
255                 };
256 
257             this.scope.hasChild = true;
258             this.scope = scope;
259             scope.id = this.scopes.push(scope) - 1;
260 
261             return scope;
262         },
263 
264         /**
265          * Remove the current scope and reinstate the previous scope
266          * @returns {Object}
267          */
268         popScope: function () {
269             var s = this.scope.previous;
270 
271             // make sure the global scope is not lost
272             this.scope = s !== null ? s : this.scope;
273 
274             return this.scope;
275         },
276 
277         /**
278          * Looks up an {@link JXG.GeometryElement} by its id.
279          * @param {String} id
280          * @returns {JXG.GeometryElement}
281          */
282         getElementById: function (id) {
283             return this.board.objects[id];
284         },
285 
286         log: function () {
287             this.$log.push(arguments);
288 
289             if (typeof console === 'object' && console.log) {
290                 console.log.apply(console, arguments);
291             }
292         },
293 
294         /**
295          * Returns a element creator function which takes two parameters: the parents array and the attributes object.
296          * @param {String} vname The element type, e.g. 'point', 'line', 'midpoint'
297          * @returns {function}
298          */
299         creator: (function () {
300             // stores the already defined creators
301             var _ccache = {}, r;
302 
303             r = function (vname) {
304                 var f;
305 
306                 // _ccache is global, i.e. it is the same for ALL JessieCode instances.
307                 // That's why we need the board id here
308                 if (typeof _ccache[this.board.id + vname] === 'function') {
309                     f =  _ccache[this.board.id + vname];
310                 } else {
311                     f = (function (that) {
312                         return function (parameters, attributes) {
313                             var attr;
314 
315                             if (Type.exists(attributes)) {
316                                 attr = attributes;
317                             } else {
318                                 attr = {name: (that.lhs[that.scope] !== 0 ? that.lhs[that.scope] : '')};
319                             }
320                             return that.board.create(vname, parameters, attr);
321                         };
322                     }(this));
323 
324                     f.creator = true;
325                     _ccache[this.board.id + vname] = f;
326                 }
327 
328                 return f;
329             };
330 
331             r.clearCache = function () {
332                 _ccache = {};
333             };
334 
335             return r;
336         }()),
337 
338         /**
339          * Assigns a value to a variable in the current scope.
340          * @param {String} vname Variable name
341          * @param value Anything
342          * @see JXG.JessieCode#sstack
343          * @see JXG.JessieCode#scope
344          */
345         letvar: function (vname, value) {
346             if (this.builtIn[vname]) {
347                 this._warn('"' + vname + '" is a predefined value.');
348             }
349 
350             this.scope.locals[vname] = value;
351         },
352 
353         /**
354          * Checks if the given variable name can be found in the current scope chain.
355          * @param {String} vname
356          * @returns {Object} A reference to the scope object the variable can be found in or null if it can't be found.
357          */
358         isLocalVariable: function (vname) {
359             var s = this.scope;
360 
361             while (s !== null) {
362                 if (Type.exists(s.locals[vname])) {
363                     return s;
364                 }
365 
366                 s = s.previous;
367             }
368 
369             return null;
370         },
371 
372         /**
373          * Checks if the given variable name is a parameter in any scope from the current to the global scope.
374          * @param {String} vname
375          * @returns {Object} A reference to the scope object that contains the variable in its arg list.
376          */
377         isParameter: function (vname) {
378             var s = this.scope;
379 
380             while (s !== null) {
381                 if (Type.indexOf(s.args, vname) > -1) {
382                     return s;
383                 }
384 
385                 s = s.previous;
386             }
387 
388             return null;
389         },
390 
391         /**
392          * Checks if the given variable name is a valid creator method.
393          * @param {String} vname
394          * @returns {Boolean}
395          */
396         isCreator: function (vname) {
397             // check for an element with this name
398             return !!JXG.elements[vname];
399         },
400 
401         /**
402          * Checks if the given variable identifier is a valid member of the JavaScript Math Object.
403          * @param {String} vname
404          * @returns {Boolean}
405          */
406         isMathMethod: function (vname) {
407             return vname !== 'E' && !!Math[vname];
408         },
409 
410         /**
411          * Returns true if the given identifier is a builtIn variable/function.
412          * @param {String} vname
413          * @returns {Boolean}
414          */
415         isBuiltIn: function (vname) {
416             return !!this.builtIn[vname];
417         },
418 
419         /**
420          * Looks up the value of the given variable.
421          * @param {String} vname Name of the variable
422          * @param {Boolean} [local=false] Only look up the internal symbol table and don't look for
423          * the <tt>vname</tt> in Math or the element list.
424          */
425         getvar: function (vname, local) {
426             var s;
427 
428             local = Type.def(local, false);
429 
430             s = this.isLocalVariable(vname);
431             if (s !== null) {
432                 return s.locals[vname];
433             }
434 
435             // check for an element with this name
436             if (this.isCreator(vname)) {
437                 return this.creator(vname);
438             }
439 
440             if (this.isBuiltIn(vname)) {
441                 return this.builtIn[vname];
442             }
443 
444             if (this.isMathMethod(vname)) {
445                 return Math[vname];
446             }
447 
448             if (!local) {
449                 s = this.board.select(vname);
450                 if (s !== vname) {
451                     return s;
452                 }
453             }
454         },
455 
456         /**
457          * Look up the value of a local variable.
458          * @param {string} vname
459          * @returns {*}
460          */
461         resolve: function (vname) {
462             var s = this.scope;
463 
464             while (s !== null) {
465                 if (Type.exists(s.locals[vname])) {
466                     return s.locals[vname];
467                 }
468 
469                 s = s.previous;
470             }
471         },
472 
473         /**
474          * TODO this needs to be called from JS and should not generate JS code
475          * Looks up a variable identifier in various tables and generates JavaScript code that could be eval'd to get the value.
476          * @param {String} vname Identifier
477          * @param {Boolean} [local=false] Don't resolve ids and names of elements
478          * @param {Boolean} [withProps=false]
479          */
480         getvarJS: function (vname, local, withProps) {
481             var s, r = '', re;
482 
483             local = Type.def(local, false);
484             withProps = Type.def(withProps, false);
485 
486             s = this.isParameter(vname);
487             if (s !== null) {
488                 return vname;
489             }
490 
491             s = this.isLocalVariable(vname);
492             if (s !== null && !withProps) {
493                 return '$jc$.resolve(\'' + vname + '\')';
494             }
495 
496             // check for an element with this name
497             if (this.isCreator(vname)) {
498                 return '(function () { var a = Array.prototype.slice.call(arguments, 0), props = ' + (withProps ? 'a.pop()' : '{}') + '; return $jc$.board.create.apply($jc$.board, [\'' + vname + '\'].concat([a, props])); })';
499             }
500 
501             if (withProps) {
502                 this._error('Syntax error (attribute values are allowed with element creators only)');
503             }
504 
505             if (this.isBuiltIn(vname)) {
506                 // If src does not exist, it is a number. In that case, just return the value.
507                 r = this.builtIn[vname].src || this.builtIn[vname];
508 
509                 // Get the "real" name of the function
510                 if (Type.isNumber(r)) {
511                     return r;
512                 }
513                 // Search a JSXGraph object in board
514                 if (r.match(/board\.select/)) {
515                     return r;
516                 }
517 
518                 vname = r.split('.').pop();
519                 if (Type.exists(this.board.mathLib)) {
520                     // Handle builtin case: ln(x) -> Math.log
521                     re = new RegExp('^Math\.' + vname);
522                     if (re.exec(r) !== null) {
523                         return r.replace(re, '$jc$.board.mathLib.' + vname);
524                     }
525                 }
526                 if (Type.exists(this.board.mathLibJXG)) {
527                     // Handle builtin case: factorial(x) -> JXG.Math.factorial
528                     re = new RegExp('^JXG\.Math\.');
529                     if (re.exec(r) !== null) {
530                         return r.replace(re, '$jc$.board.mathLibJXG.');
531                     }
532                     return r;
533                 }
534                 return r;
535 
536                 // return this.builtIn[vname].src || this.builtIn[vname];
537             }
538 
539             if (this.isMathMethod(vname)) {
540                 return '$jc$.board.mathLib.' + vname;
541 //                return 'Math.' + vname;
542             }
543 
544             // if (!local) {
545             //     if (Type.isId(this.board, vname)) {
546             //         r = '$jc$.board.objects[\'' + vname + '\']';
547             //     } else if (Type.isName(this.board, vname)) {
548             //         r = '$jc$.board.elementsByName[\'' + vname + '\']';
549             //     } else if (Type.isGroup(this.board, vname)) {
550             //         r = '$jc$.board.groups[\'' + vname + '\']';
551             //     }
552 
553             //     return r;
554             // }
555             if (!local) {
556                 if (Type.isId(this.board, vname)) {
557                     r = '$jc$.board.objects[\'' + vname + '\']';
558                     if (this.board.objects[vname].elType === 'slider') {
559                         r += '.Value()';
560                     }
561                 } else if (Type.isName(this.board, vname)) {
562                     r = '$jc$.board.elementsByName[\'' + vname + '\']';
563                     if (this.board.elementsByName[vname].elType === 'slider') {
564                         r += '.Value()';
565                     }
566                 } else if (Type.isGroup(this.board, vname)) {
567                     r = '$jc$.board.groups[\'' + vname + '\']';
568                 }
569 
570                 return r;
571             }
572 
573             return '';
574         },
575 
576         /**
577          * Adds the property <tt>isMap</tt> to a function and sets it to true.
578          * @param {function} f
579          * @returns {function}
580          */
581         makeMap: function (f) {
582             f.isMap = true;
583 
584             return f;
585         },
586 
587         functionCodeJS: function (node) {
588             var p = node.children[0].join(', '),
589                 bo = '',
590                 bc = '';
591 
592             if (node.value === 'op_map') {
593                 bo = '{ return  ';
594                 bc = ' }';
595             }
596 
597             return 'function (' + p + ') {\n' +
598                     'var $oldscope$ = $jc$.scope;\n' +
599                     '$jc$.scope = $jc$.scopes[' + this.scope.id + '];\n' +
600                     'var r = (function () ' + bo + this.compile(node.children[1], true) + bc + ')();\n' +
601                     '$jc$.scope = $oldscope$;\n' +
602                     'return r;\n' +
603                 '}';
604         },
605 
606         /**
607          * Converts a node type <tt>node_op</tt> and value <tt>op_map</tt> or <tt>op_function</tt> into a executable
608          * function.
609          * @param {Object} node
610          * @returns {function}
611          */
612         defineFunction: function (node) {
613             var fun, i,
614                 list = node.children[0],
615                 scope = this.pushScope(list);
616 
617             if (this.board.options.jc.compile) {
618                 this.isLHS = false;
619 
620                 // we currently need to put the parameters into the local scope
621                 // until the compiled JS variable lookup code is fixed
622                 for (i = 0; i < list.length; i++) {
623                     scope.locals[list[i]] = list[i];
624                 }
625 
626                 this.replaceNames(node.children[1]);
627 
628                 /** @ignore */
629                 fun = (function ($jc$) {
630                     var fun,
631                         str = 'var f = ' + $jc$.functionCodeJS(node) + '; f;';
632 
633                     try {
634                         // yeah, eval is evil, but we don't have much choice here.
635                         // the str is well defined and there is no user input in it that we didn't check before
636 
637                         /*jslint evil:true*/
638                         fun = eval(str);
639                         /*jslint evil:false*/
640 
641                         return fun;
642                     } catch (e) {
643                         $jc$._warn('error compiling function\n\n' + str + '\n\n' + e.toString());
644                         return function () {};
645                     }
646                 }(this));
647 
648                 // clean up scope
649                 this.popScope();
650             } else {
651                 /** @ignore */
652                 fun = (function (_pstack, that, id) {
653                     return function () {
654                         var r, oldscope;
655 
656                         oldscope = that.scope;
657                         that.scope = that.scopes[id];
658 
659                         for (r = 0; r < _pstack.length; r++) {
660                             that.scope.locals[_pstack[r]] = arguments[r];
661                         }
662 
663                         r = that.execute(node.children[1]);
664                         that.scope = oldscope;
665 
666                         return r;
667                     };
668                 }(list, this, scope.id));
669             }
670 
671             fun.node = node;
672             fun.scope = scope;
673             fun.toJS = fun.toString;
674             fun.toString = (function (_that) {
675                 return function () {
676                     return _that.compile(_that.replaceIDs(Type.deepCopy(node)));
677                 };
678             }(this));
679 
680             fun.deps = {};
681             this.collectDependencies(node.children[1], fun.deps);
682 
683             return fun;
684         },
685 
686         /**
687          * Merge all attribute values given with an element creator into one object.
688          * @param {Object} o An arbitrary number of objects
689          * @returns {Object} All given objects merged into one. If properties appear in more (case sensitive) than one
690          * object the last value is taken.
691          */
692         mergeAttributes: function (o) {
693             var i, attr = {};
694 
695             for (i = 0; i < arguments.length; i++) {
696                 attr = Type.deepCopy(attr, arguments[i], true);
697             }
698 
699             return attr;
700         },
701 
702         /**
703          * Sets the property <tt>what</tt> of <tt>o</tt> to <tt>value</tt>
704          * @param {JXG.Point|JXG.Text} o
705          * @param {String} what
706          * @param value
707          */
708         setProp: function (o, what, value) {
709             var par = {}, x, y;
710 
711             if (o.elementClass === Const.OBJECT_CLASS_POINT && (what === 'X' || what === 'Y')) {
712                 // set coords
713 
714                 what = what.toLowerCase();
715 
716                 // we have to deal with three cases here:
717                 // o.isDraggable && typeof value === number:
718                 //   stay draggable, just set the new coords (e.g. via moveTo)
719                 // o.isDraggable && typeof value === function:
720                 //   convert to !o.isDraggable, set the new coords via o.addConstraint()
721                 // !o.isDraggable:
722                 //   stay !o.isDraggable, update the given coord by overwriting X/YEval
723 
724                 if (o.isDraggable && typeof value === 'number') {
725                     x = what === 'x' ? value : o.X();
726                     y = what === 'y' ? value : o.Y();
727 
728                     o.setPosition(Const.COORDS_BY_USER, [x, y]);
729                 } else if (o.isDraggable && (typeof value === 'function' || typeof value === 'string')) {
730                     x = what === 'x' ? value : o.coords.usrCoords[1];
731                     y = what === 'y' ? value : o.coords.usrCoords[2];
732 
733                     o.addConstraint([x, y]);
734                 } else if (!o.isDraggable) {
735                     x = what === 'x' ? value : o.XEval.origin;
736                     y = what === 'y' ? value : o.YEval.origin;
737 
738                     o.addConstraint([x, y]);
739                 }
740 
741                 this.board.update();
742             } else if (o.elementClass === Const.OBJECT_CLASS_TEXT && (what === 'X' || what === 'Y')) {
743                 if (typeof value === 'number') {
744                     o[what] = function () { return value; };
745                 } else if (typeof value === 'function') {
746                     o.isDraggable = false;
747                     o[what] = value;
748                 } else if (typeof value === 'string') {
749                     o.isDraggable = false;
750                     o[what] = Type.createFunction(value, this.board, null, true);
751                     o[what + 'jc'] = value;
752                 }
753 
754                 o[what].origin = value;
755 
756                 this.board.update();
757             } else if (o.type && o.elementClass && o.visProp) {
758                 if (Type.exists(o[o.methodMap[what]]) && typeof o[o.methodMap[what]] !== 'function') {
759                     o[o.methodMap[what]] = value;
760                 } else {
761                     par[what] = value;
762                     o.setAttribute(par);
763                 }
764             } else {
765                 o[what] = value;
766             }
767         },
768 
769         /**
770          * Generic method to parse JessieCode.
771          * This consists of generating an AST with parser.parse,
772          * apply simplifying rules from CA and
773          * manipulate the AST according to the second parameter "cmd".
774          * @param  {String} code      JessieCode code to be parsed
775          * @param  {String} cmd       Type of manipulation to be done with AST
776          * @param {Boolean} [geonext=false] Geonext compatibility mode.
777          * @param {Boolean} dontstore If false, the code string is stored in this.code.
778          * @return {Object}           Returns result of computation as directed in cmd.
779          */
780         _genericParse:  function (code, cmd, geonext, dontstore) {
781             var i, setTextBackup, ast, result,
782                 ccode = code.replace(/\r\n/g, '\n').split('\n'),
783                 cleaned = [];
784 
785             if (!dontstore) {
786                 this.code += code + '\n';
787             }
788 
789             if (Text) {
790                 setTextBackup = Text.Text.prototype.setText;
791                 Text.Text.prototype.setText = Text.Text.prototype.setTextJessieCode;
792             }
793 
794             try {
795                 if (!Type.exists(geonext)) {
796                     geonext = false;
797                 }
798 
799                 for (i = 0; i < ccode.length; i++) {
800                     if (geonext) {
801                         ccode[i] = JXG.GeonextParser.geonext2JS(ccode[i], this.board);
802                     }
803                     cleaned.push(ccode[i]);
804                 }
805 
806                 code = cleaned.join('\n');
807                 ast = parser.parse(code);
808                 if (this.CA) {
809                     ast = this.CA.expandDerivatives(ast, null, ast);
810                     ast = this.CA.removeTrivialNodes(ast);
811                 }
812                 switch (cmd) {
813                     case 'parse':
814                         result = this.execute(ast);
815                         break;
816                     case 'manipulate':
817                         result = this.compile(ast);
818                         break;
819                     case 'getAst':
820                         result = ast;
821                         break;
822                     default:
823                         result = false;
824                 }
825             } catch (e) {  // catch is mandatory in old IEs
826                 // console.log(e);
827                 // We throw the error again,
828                 // so the user can catch it.
829                 throw e;
830             } finally {
831                 // make sure the original text method is back in place
832                 if (Text) {
833                     Text.Text.prototype.setText = setTextBackup;
834                 }
835             }
836 
837             return result;
838         },
839 
840         /**
841          * Parses JessieCode.
842          * This consists of generating an AST with parser.parse, apply simplifying rules
843          * from CA and executing the ast by calling this.execute(ast).
844          *
845          * @param {String} code             JessieCode code to be parsed
846          * @param {Boolean} [geonext=false] Geonext compatibility mode.
847          * @param {Boolean} dontstore       If false, the code string is stored in this.code.
848          * @return {Object}                 Parse JessieCode code and execute it..
849          */
850         parse: function (code, geonext, dontstore) {
851             return this._genericParse(code, 'parse', geonext, dontstore);
852         },
853 
854         /**
855          * Manipulate JessieCode.
856          * This consists of generating an AST with parser.parse,
857          * apply simlifying rules from CA
858          * and compile the AST back to JessieCode.
859          *
860          * @param {String} code             JessieCode code to be parsed
861          * @param {Boolean} [geonext=false] Geonext compatibility mode.
862          * @param {Boolean} dontstore       If false, the code string is stored in this.code.
863          * @return {String}                 Simplified JessieCode code
864          */
865         manipulate: function (code, geonext, dontstore) {
866             return this._genericParse(code, 'manipulate', geonext, dontstore);
867         },
868 
869         /**
870          * Get abstract syntax tree (AST) from JessieCode code.
871          * This consists of generating an AST with parser.parse.
872          *
873          * @param {String} code
874          * @param {Boolean} [geonext=false] Geonext compatibility mode.
875          * @param {Boolean} dontstore
876          * @return {Node}  AST
877          */
878         getAST: function (code, geonext, dontstore) {
879             return this._genericParse(code, 'getAst', geonext, dontstore);
880         },
881 
882         /**
883          * Parses a JessieCode snippet, e.g. "3+4", and wraps it into a function, if desired.
884          * @param {String} code A small snippet of JessieCode. Must not be an assignment.
885          * @param {Boolean} funwrap If true, the code is wrapped in a function.
886          * @param {String} varname Name of the parameter(s)
887          * @param {Boolean} [geonext=false] Geonext compatibility mode.
888          */
889         snippet: function (code, funwrap, varname, geonext) {
890             var c;
891 
892             funwrap = Type.def(funwrap, true);
893             varname = Type.def(varname, '');
894             geonext = Type.def(geonext, false);
895 
896             c = (funwrap ? ' function (' + varname + ') { return ' : '') + code + (funwrap ? '; }' : '') + ';';
897 
898             return this.parse(c, geonext, true);
899         },
900 
901         /**
902          * Traverses through the given subtree and changes all values of nodes with the replaced flag set by
903          * {@link JXG.JessieCode#replaceNames} to the name of the element (if not empty).
904          * @param {Object} node
905          */
906         replaceIDs: function (node) {
907             var i, v;
908 
909             if (node.replaced) {
910                 // these children exist, if node.replaced is set.
911                 v = this.board.objects[node.children[1][0].value];
912 
913                 if (Type.exists(v) && v.name !== "") {
914                     node.type = 'node_var';
915                     node.value = v.name;
916 
917                     // maybe it's not necessary, but just to be sure that everything is cleaned up we better delete all
918                     // children and the replaced flag
919                     node.children.length = 0;
920                     delete node.replaced;
921                 }
922             }
923 
924             if (node.children) {
925                 // assignments are first evaluated on the right hand side
926                 for (i = node.children.length; i > 0; i--) {
927                     if (Type.exists(node.children[i - 1])) {
928                         node.children[i - 1] = this.replaceIDs(node.children[i - 1]);
929                     }
930 
931                 }
932             }
933 
934             return node;
935         },
936 
937         /**
938          * Traverses through the given subtree and changes all elements referenced by names through referencing them by ID.
939          * An identifier is only replaced if it is not found in all scopes above the current scope and if it
940          * has not been blacklisted within the codeblock determined by the given subtree.
941          * @param {Object} node
942          */
943         replaceNames: function (node) {
944             var i, v;
945 
946             v = node.value;
947 
948             // we are interested only in nodes of type node_var and node_op > op_lhs.
949             // currently, we are not checking if the id is a local variable. in this case, we're stuck anyway.
950 
951             if (node.type === 'node_op' && v === 'op_lhs' && node.children.length === 1) {
952                 this.isLHS = true;
953             } else if (node.type === 'node_var') {
954                 if (this.isLHS) {
955                     this.letvar(v, true);
956                 } else if (!Type.exists(this.getvar(v, true)) && Type.exists(this.board.elementsByName[v])) {
957                     node = this.createReplacementNode(node);
958                 }
959             }
960 
961             if (node.children) {
962                 // assignments are first evaluated on the right hand side
963                 for (i = node.children.length; i > 0; i--) {
964                     if (Type.exists(node.children[i - 1])) {
965                         node.children[i - 1] = this.replaceNames(node.children[i - 1]);
966                     }
967                 }
968             }
969 
970             if (node.type === 'node_op' && node.value === 'op_lhs' && node.children.length === 1) {
971                 this.isLHS = false;
972             }
973 
974             return node;
975         },
976 
977         /**
978          * Replaces node_var nodes with node_op>op_execfun nodes, calling the internal $() function with the id of the
979          * element accessed by the node_var node.
980          * @param {Object} node
981          * @returns {Object} op_execfun node
982          */
983         createReplacementNode: function (node) {
984             var v = node.value,
985                 el = this.board.elementsByName[v];
986 
987             node = this.createNode('node_op', 'op_execfun',
988                 this.createNode('node_var', '$'),
989                 [this.createNode('node_str', el.id)]);
990 
991             node.replaced = true;
992 
993             return node;
994         },
995 
996         /**
997          * Search the parse tree below <tt>node</tt> for <em>stationary</em> dependencies, i.e. dependencies hard coded into
998          * the function.
999          * @param {Object} node
1000          * @param {Object} result An object where the referenced elements will be stored. Access key is their id.
1001          */
1002         collectDependencies: function (node, result) {
1003             var i, v, e, le;
1004 
1005             if (Type.isArray(node)) {
1006                 le = node.length;
1007                 for (i = 0; i < le; i++) {
1008                     this.collectDependencies(node[i], result);
1009                 }
1010                 return;
1011             }
1012 
1013             v = node.value;
1014 
1015             if (node.type === 'node_var') {
1016                 e = this.getvar(v);
1017                 if (e && e.visProp && e.type && e.elementClass && e.id) {
1018                     result[e.id] = e;
1019                 }
1020             }
1021 
1022             // the $()-function-calls are special because their parameter is given as a string, not as a node_var.
1023             if (node.type === 'node_op' && node.value === 'op_execfun' &&
1024                 node.children.length > 1 && node.children[0].value === '$' &&
1025                 node.children[1].length > 0) {
1026 
1027                 e = node.children[1][0].value;
1028                 result[e] = this.board.objects[e];
1029             }
1030 
1031             if (node.children) {
1032                 for (i = node.children.length; i > 0; i--) {
1033                     if (Type.exists(node.children[i - 1])) {
1034                         this.collectDependencies(node.children[i - 1], result);
1035                     }
1036 
1037                 }
1038             }
1039         },
1040 
1041         resolveProperty: function (e, v, compile) {
1042             compile = Type.def(compile, false);
1043 
1044             // is it a geometry element or a board?
1045             if (e /*&& e.type && e.elementClass*/ && e.methodMap) {
1046                 // yeah, it is. but what does the user want?
1047                 if (Type.exists(e.subs) && Type.exists(e.subs[v])) {
1048                     // a subelement it is, good sir.
1049                     e = e.subs;
1050                 } else if (Type.exists(e.methodMap[v])) {
1051                     // the user wants to call a method
1052                     v = e.methodMap[v];
1053                 } else {
1054                     // the user wants to change an attribute
1055                     e = e.visProp;
1056                     v = v.toLowerCase();
1057                 }
1058             }
1059 
1060             if (Type.isFunction(e)) {
1061                 this._error('Accessing function properties is not allowed.');
1062             }
1063 
1064             if (!Type.exists(e)) {
1065                 this._error(e + ' is not an object');
1066             }
1067 
1068             if (!Type.exists(e[v])) {
1069                 this._error('unknown property ' + v);
1070             }
1071 
1072             if (compile && typeof e[v] === 'function') {
1073                 return function () { return e[v].apply(e, arguments); };
1074             }
1075 
1076             return e[v];
1077         },
1078 
1079         /**
1080          * Resolves the lefthand side of an assignment operation
1081          * @param node
1082          * @returns {Object} An object with two properties. <strong>o</strong> which contains the object, and
1083          * a string <strong>what</strong> which contains the property name.
1084          */
1085         getLHS: function (node) {
1086             var res;
1087 
1088             if (node.type === 'node_var') {
1089                 res = {
1090                     o: this.scope.locals,
1091                     what: node.value
1092                 };
1093             } else if (node.type === 'node_op' && node.value === 'op_property') {
1094                 res = {
1095                     o: this.execute(node.children[0]),
1096                     what: node.children[1]
1097                 };
1098             } else if (node.type === 'node_op' && node.value === 'op_extvalue') {
1099                 res = {
1100                     o: this.execute(node.children[0]),
1101                     what: this.execute(node.children[1])
1102                 };
1103             } else {
1104                 throw new Error('Syntax error: Invalid left-hand side of assignment.');
1105             }
1106 
1107             return res;
1108         },
1109 
1110         getLHSCompiler: function (node, js) {
1111             var res;
1112 
1113             if (node.type === 'node_var') {
1114                 res = node.value;
1115             } else if (node.type === 'node_op' && node.value === 'op_property') {
1116                 res = [
1117                     this.compile(node.children[0], js),
1118                     "'" + node.children[1] + "'"
1119                 ];
1120             } else if (node.type === 'node_op' && node.value === 'op_extvalue') {
1121                 res = [
1122                     this.compile(node.children[0], js),
1123                     node.children[1].type === 'node_const' ? node.children[1].value : this.compile(node.children[1], js)
1124                 ];
1125             } else {
1126                 throw new Error('Syntax error: Invalid left-hand side of assignment.');
1127             }
1128 
1129             return res;
1130         },
1131 
1132         /**
1133          * Executes a parse subtree.
1134          * @param {Object} node
1135          * @returns {Number|String|Object|Boolean} Something
1136          * @private
1137          */
1138         execute: function (node) {
1139             var ret, v, i, e, l, undef, list, ilist,
1140                 parents = [],
1141                 // exec fun
1142                 fun, attr, sc;
1143 
1144             ret = 0;
1145 
1146             if (!node) {
1147                 return ret;
1148             }
1149 
1150             this.line = node.line;
1151             this.col = node.col;
1152 
1153             switch (node.type) {
1154             case 'node_op':
1155                 switch (node.value) {
1156                 case 'op_none':
1157                     if (node.children[0]) {
1158                         this.execute(node.children[0]);
1159                     }
1160                     if (node.children[1]) {
1161                         ret = this.execute(node.children[1]);
1162                     }
1163                     break;
1164                 case 'op_assign':
1165                     v = this.getLHS(node.children[0]);
1166                     this.lhs[this.scope.id] = v[1];
1167 
1168                     if (v.o.type && v.o.elementClass && v.o.methodMap && v.what === 'label') {
1169                         this._error('Left-hand side of assignment is read-only.');
1170                     }
1171 
1172                     ret = this.execute(node.children[1]);
1173                     if (v.o !== this.scope.locals || (Type.isArray(v.o) && typeof v.what === 'number')) {
1174                         // it is either an array component being set or a property of an object.
1175                         this.setProp(v.o, v.what, ret);
1176                     } else {
1177                         // this is just a local variable inside JessieCode
1178                         this.letvar(v.what, ret);
1179                     }
1180                     this.lhs[this.scope.id] = 0;
1181                     break;
1182                 case 'op_if':
1183                     if (this.execute(node.children[0])) {
1184                         ret = this.execute(node.children[1]);
1185                     }
1186                     break;
1187                 case 'op_conditional':
1188                     // fall through
1189                 case 'op_if_else':
1190                     if (this.execute(node.children[0])) {
1191                         ret = this.execute(node.children[1]);
1192                     } else {
1193                         ret = this.execute(node.children[2]);
1194                     }
1195                     break;
1196                 case 'op_while':
1197                     while (this.execute(node.children[0])) {
1198                         this.execute(node.children[1]);
1199                     }
1200                     break;
1201                 case 'op_do':
1202                     do {
1203                         this.execute(node.children[0]);
1204                     } while (this.execute(node.children[1]));
1205                     break;
1206                 case 'op_for':
1207                     for (this.execute(node.children[0]); this.execute(node.children[1]); this.execute(node.children[2])) {
1208                         this.execute(node.children[3]);
1209                     }
1210                     break;
1211                 case 'op_proplst':
1212                     if (node.children[0]) {
1213                         this.execute(node.children[0]);
1214                     }
1215                     if (node.children[1]) {
1216                         this.execute(node.children[1]);
1217                     }
1218                     break;
1219                 case 'op_emptyobject':
1220                     ret = {};
1221                     break;
1222                 case 'op_proplst_val':
1223                     this.propstack.push({});
1224                     this.propscope++;
1225 
1226                     this.execute(node.children[0]);
1227                     ret = this.propstack[this.propscope];
1228 
1229                     this.propstack.pop();
1230                     this.propscope--;
1231                     break;
1232                 case 'op_prop':
1233                     // child 0: Identifier
1234                     // child 1: Value
1235                     this.propstack[this.propscope][node.children[0]] = this.execute(node.children[1]);
1236                     break;
1237                 case 'op_array':
1238                     ret = [];
1239                     l = node.children[0].length;
1240 
1241                     for (i = 0; i < l; i++) {
1242                         ret.push(this.execute(node.children[0][i]));
1243                     }
1244 
1245                     break;
1246                 case 'op_extvalue':
1247                     ret = this.execute(node.children[0]);
1248                     i = this.execute(node.children[1]);
1249 
1250                     if (typeof i === 'number' && Math.abs(Math.round(i) - i) < Mat.eps) {
1251                         ret = ret[i];
1252                     } else {
1253                         ret = undef;
1254                     }
1255                     break;
1256                 case 'op_return':
1257                     if (this.scope === 0) {
1258                         this._error('Unexpected return.');
1259                     } else {
1260                         return this.execute(node.children[0]);
1261                     }
1262                     break;
1263                 case 'op_map':
1264                     if (!node.children[1].isMath && node.children[1].type !== 'node_var') {
1265                         this._error('execute: In a map only function calls and mathematical expressions are allowed.');
1266                     }
1267 
1268                     /** @ignore */
1269                     fun = this.defineFunction(node);
1270                     fun.isMap = true;
1271 
1272                     ret = fun;
1273                     break;
1274                 case 'op_function':
1275                     // parse the parameter list
1276                     // after this, the parameters are in pstack
1277 
1278                     /** @ignore */
1279                     fun = this.defineFunction(node);
1280                     fun.isMap = false;
1281 
1282                     ret = fun;
1283                     break;
1284                 case 'op_execfun':
1285                     // node.children:
1286                     //   [0]: Name of the function
1287                     //   [1]: Parameter list as a parse subtree
1288                     //   [2]: Properties, only used in case of a create function
1289                     this.dpstack.push([]);
1290                     this.pscope++;
1291 
1292                     // parameter parsing is done below
1293                     list = node.children[1];
1294 
1295                     // parse the properties only if given
1296                     if (Type.exists(node.children[2])) {
1297                         if (node.children[3]) {
1298                             ilist = node.children[2];
1299                             attr = {};
1300 
1301                             for (i = 0; i < ilist.length; i++) {
1302                                 attr = Type.deepCopy(attr, this.execute(ilist[i]), true);
1303                             }
1304                         } else {
1305                             attr = this.execute(node.children[2]);
1306                         }
1307                     }
1308 
1309                     // look up the variables name in the variable table
1310                     fun = this.execute(node.children[0]);
1311 
1312                     // determine the scope the function wants to run in
1313                     if (fun && fun.sc) {
1314                         sc = fun.sc;
1315                     } else {
1316                         sc = this;
1317                     }
1318 
1319                     if (!fun.creator && Type.exists(node.children[2])) {
1320                         this._error('Unexpected value. Only element creators are allowed to have a value after the function call.');
1321                     }
1322 
1323                     // interpret ALL the parameters
1324                     for (i = 0; i < list.length; i++) {
1325                         parents[i] = this.execute(list[i]);
1326                         //parents[i] = Type.evalSlider(this.execute(list[i]));
1327                         this.dpstack[this.pscope].push({
1328                             line: node.children[1][i].line,
1329                             // SketchBin currently works only if the last column of the
1330                             // parent position is taken. This is due to how I patched JS/CC
1331                             // to count the lines and columns. So, ecol will do for now
1332                             col: node.children[1][i].ecol
1333                         });
1334                     }
1335 
1336                     // check for the function in the variable table
1337                     if (typeof fun === 'function' && !fun.creator) {
1338                         ret = fun.apply(sc, parents);
1339                     } else if (typeof fun === 'function' && !!fun.creator) {
1340                         e = this.line;
1341 
1342                         // creator methods are the only ones that take properties, hence this special case
1343                         try {
1344                             ret = fun(parents, attr);
1345                             ret.jcLineStart = e;
1346                             ret.jcLineEnd = node.eline;
1347 
1348                             for (i = e; i <= node.line; i++) {
1349                                 this.lineToElement[i] = ret;
1350                             }
1351 
1352                             ret.debugParents = this.dpstack[this.pscope];
1353                         } catch (ex) {
1354                             this._error(ex.toString());
1355                         }
1356                     } else {
1357                         this._error('Function \'' + fun + '\' is undefined.');
1358                     }
1359 
1360                     // clear parameter stack
1361                     this.dpstack.pop();
1362                     this.pscope--;
1363                     break;
1364                 case 'op_property':
1365                     e = this.execute(node.children[0]);
1366                     v = node.children[1];
1367 
1368                     ret = this.resolveProperty(e, v, false);
1369 
1370                     // set the scope, in case this is a method the user wants to call
1371                     if (Type.exists(ret)) {
1372                         ret.sc = e;
1373                     }
1374 
1375                     break;
1376                 case 'op_use':
1377                     this._warn('Use of the \'use\' operator is deprecated.');
1378                     this.use(node.children[0].toString());
1379                     break;
1380                 case 'op_delete':
1381                     this._warn('Use of the \'delete\' operator is deprecated. Please use the remove() function.');
1382                     v = this.getvar(node.children[0]);
1383                     ret = this.del(v);
1384                     break;
1385                 case 'op_equ':
1386                     // == is intentional
1387                     /*jslint eqeq:true*/
1388                     ret = this.execute(node.children[0]) == this.execute(node.children[1]);
1389                     /*jslint eqeq:false*/
1390                     break;
1391                 case 'op_neq':
1392                     // != is intentional
1393                     /*jslint eqeq:true*/
1394                     ret = this.execute(node.children[0]) != this.execute(node.children[1]);
1395                     /*jslint eqeq:true*/
1396                     break;
1397                 case 'op_approx':
1398                     ret = Math.abs(this.execute(node.children[0]) - this.execute(node.children[1])) < Mat.eps;
1399                     break;
1400                 case 'op_grt':
1401                     ret = this.execute(node.children[0]) > this.execute(node.children[1]);
1402                     break;
1403                 case 'op_lot':
1404                     ret = this.execute(node.children[0]) < this.execute(node.children[1]);
1405                     break;
1406                 case 'op_gre':
1407                     ret = this.execute(node.children[0]) >= this.execute(node.children[1]);
1408                     break;
1409                 case 'op_loe':
1410                     ret = this.execute(node.children[0]) <= this.execute(node.children[1]);
1411                     break;
1412                 case 'op_or':
1413                     ret = this.execute(node.children[0]) || this.execute(node.children[1]);
1414                     break;
1415                 case 'op_and':
1416                     ret = this.execute(node.children[0]) && this.execute(node.children[1]);
1417                     break;
1418                 case 'op_not':
1419                     ret = !this.execute(node.children[0]);
1420                     break;
1421                 case 'op_add':
1422                     ret = this.add(this.execute(node.children[0]), this.execute(node.children[1]));
1423                     break;
1424                 case 'op_sub':
1425                     ret = this.sub(this.execute(node.children[0]), this.execute(node.children[1]));
1426                     break;
1427                 case 'op_div':
1428                     ret = this.div(this.execute(node.children[0]), this.execute(node.children[1]));
1429                     break;
1430                 case 'op_mod':
1431                     // use mathematical modulo, JavaScript implements the symmetric modulo.
1432                     ret = this.mod(this.execute(node.children[0]), this.execute(node.children[1]), true);
1433                     break;
1434                 case 'op_mul':
1435                     ret = this.mul(this.execute(node.children[0]), this.execute(node.children[1]));
1436                     break;
1437                 case 'op_exp':
1438                     ret = this.pow(this.execute(node.children[0]),  this.execute(node.children[1]));
1439                     break;
1440                 case 'op_neg':
1441                     ret = this.neg(this.execute(node.children[0]));
1442                     break;
1443                 }
1444                 break;
1445 
1446             case 'node_var':
1447                 ret = this.getvar(node.value);
1448                 break;
1449 
1450             case 'node_const':
1451                 ret = Number(node.value);
1452                 break;
1453 
1454             case 'node_const_bool':
1455                 ret = node.value;
1456                 break;
1457 
1458             case 'node_str':
1459                 //ret = node.value.replace(/\\'/, "'").replace(/\\"/, '"').replace(/\\\\/, '\\');
1460                 /*jslint regexp:true*/
1461                 ret = node.value.replace(/\\(.)/, '$1');
1462                 /*jslint regexp:false*/
1463                 break;
1464             }
1465 
1466             return ret;
1467         },
1468 
1469         /**
1470          * Compiles a parse tree back to JessieCode.
1471          * @param {Object} node
1472          * @param {Boolean} [js=false] Compile either to JavaScript or back to JessieCode (required for the UI).
1473          * @returns Something
1474          * @private
1475          */
1476         compile: function (node, js) {
1477             var e, i, list, scope,
1478                 ret = '';
1479 
1480             if (!Type.exists(js)) {
1481                 js = false;
1482             }
1483 
1484             if (!node) {
1485                 return ret;
1486             }
1487 
1488             switch (node.type) {
1489             case 'node_op':
1490                 switch (node.value) {
1491                 case 'op_none':
1492                     if (node.children[0]) {
1493                         ret = this.compile(node.children[0], js);
1494                     }
1495                     if (node.children[1]) {
1496                         ret += this.compile(node.children[1], js);
1497                     }
1498                     break;
1499                 case 'op_assign':
1500                     //e = this.compile(node.children[0], js);
1501                     if (js) {
1502                         e = this.getLHSCompiler(node.children[0], js);
1503                         if (Type.isArray(e)) {
1504                             ret = '$jc$.setProp(' + e[0] + ', ' + e[1] + ', ' + this.compile(node.children[1], js) + ');\n';
1505                         } else {
1506                             if (this.isLocalVariable(e) !== this.scope) {
1507                                 this.scope.locals[e] = true;
1508                             }
1509                             ret = '$jc$.scopes[' + this.scope.id + '].locals[\'' + e + '\'] = ' + this.compile(node.children[1], js) + ';\n';
1510                         }
1511                     } else {
1512                         e = this.compile(node.children[0]);
1513                         ret = e + ' = ' + this.compile(node.children[1], js) + ';\n';
1514                     }
1515                     break;
1516                 case 'op_if':
1517                     ret = ' if (' + this.compile(node.children[0], js) + ') ' + this.compile(node.children[1], js);
1518                     break;
1519                 case 'op_if_else':
1520                     ret = ' if (' + this.compile(node.children[0], js) + ')' + this.compile(node.children[1], js);
1521                     ret += ' else ' + this.compile(node.children[2], js);
1522                     break;
1523                 case 'op_conditional':
1524                     ret = '((' + this.compile(node.children[0], js) + ')?(' + this.compile(node.children[1], js);
1525                     ret += '):(' + this.compile(node.children[2], js) + '))';
1526                     break;
1527                 case 'op_while':
1528                     ret = ' while (' + this.compile(node.children[0], js) + ') {\n' + this.compile(node.children[1], js) + '}\n';
1529                     break;
1530                 case 'op_do':
1531                     ret = ' do {\n' + this.compile(node.children[0], js) + '} while (' + this.compile(node.children[1], js) + ');\n';
1532                     break;
1533                 case 'op_for':
1534                     //ret = ' for (' + this.compile(node.children[0], js) + '; ' + this.compile(node.children[1], js) + '; ' + this.compile(node.children[2], js) + ') {\n' + this.compile(node.children[3], js) + '\n}\n';
1535                     ret = ' for (' + this.compile(node.children[0], js) +               // Assignment ends with ";"
1536                                     this.compile(node.children[1], js) + '; ' +         // Logical test comes without ";"
1537                                     this.compile(node.children[2], js).slice(0, -2) +   // Counting comes with ";" which has to be removed
1538                                     ') {\n' + this.compile(node.children[3], js) + '\n}\n';
1539                     break;
1540                 case 'op_proplst':
1541                     if (node.children[0]) {
1542                         ret = this.compile(node.children[0], js) + ', ';
1543                     }
1544 
1545                     ret += this.compile(node.children[1], js);
1546                     break;
1547                 case 'op_prop':
1548                     // child 0: Identifier
1549                     // child 1: Value
1550                     ret = node.children[0] + ': ' + this.compile(node.children[1], js);
1551                     break;
1552                 case 'op_emptyobject':
1553                     ret = js ? '{}' : '<< >>';
1554                     break;
1555                 case 'op_proplst_val':
1556                     ret = this.compile(node.children[0], js);
1557                     break;
1558                 case 'op_array':
1559                     list = [];
1560                     for (i = 0; i < node.children[0].length; i++) {
1561                         list.push(this.compile(node.children[0][i], js));
1562                     }
1563                     ret = '[' + list.join(', ') + ']';
1564                     break;
1565                 case 'op_extvalue':
1566                     ret = this.compile(node.children[0], js) + '[' + this.compile(node.children[1], js) + ']';
1567                     break;
1568                 case 'op_return':
1569                     ret = ' return ' + this.compile(node.children[0], js) + ';\n';
1570                     break;
1571                 case 'op_map':
1572                     if (!node.children[1].isMath && node.children[1].type !== 'node_var') {
1573                         this._error('compile: In a map only function calls and mathematical expressions are allowed.');
1574                     }
1575 
1576                     list = node.children[0];
1577                     if (js) {
1578                         ret = ' $jc$.makeMap(function (' + list.join(', ') + ') { return ' + this.compile(node.children[1], js) + '; })';
1579                     } else {
1580                         ret = 'map (' + list.join(', ') + ') -> ' + this.compile(node.children[1], js);
1581                     }
1582 
1583                     break;
1584                 case 'op_function':
1585                     list = node.children[0];
1586                     scope = this.pushScope(list);
1587                     if (js) {
1588                         ret = this.functionCodeJS(node);
1589                     } else {
1590                         ret = ' function (' + list.join(', ') + ') ' + this.compile(node.children[1], js);
1591                     }
1592                     this.popScope();
1593                     break;
1594                 case 'op_execfunmath':
1595                     console.log('TODO');
1596                     ret = '-1';
1597                     break;
1598                 case 'op_execfun':
1599                     // parse the properties only if given
1600                     if (node.children[2]) {
1601                         list = [];
1602                         for (i = 0; i < node.children[2].length; i++) {
1603                             list.push(this.compile(node.children[2][i], js));
1604                         }
1605 
1606                         if (js) {
1607                             e = '$jc$.mergeAttributes(' + list.join(', ') + ')';
1608                         }
1609                     }
1610                     node.children[0].withProps = !!node.children[2];
1611                     list = [];
1612                     for (i = 0; i < node.children[1].length; i++) {
1613                         list.push(this.compile(node.children[1][i], js));
1614                     }
1615                     ret = this.compile(node.children[0], js) + '(' + list.join(', ') + (node.children[2] && js ? ', ' + e : '') + ')' + (node.children[2] && !js ? e : '');
1616                     if (js) {
1617                         // Inserting a newline here allows simulataneously
1618                         // - procedural calls like Q.moveTo(...); and
1619                         // - function calls in expressions like log(x) + 1;
1620                         // Problem: procedural calls will not be ended by a semicolon.
1621                         ret += '\n';
1622                     }
1623 
1624                     // save us a function call when compiled to javascript
1625                     if (js && node.children[0].value === '$') {
1626                         ret = '$jc$.board.objects[' + this.compile(node.children[1][0], js) + ']';
1627                     }
1628                     break;
1629                 case 'op_property':
1630                     if (js && node.children[1] !== 'X' && node.children[1] !== 'Y') {
1631                         ret = '$jc$.resolveProperty(' + this.compile(node.children[0], js) + ', \'' + node.children[1] + '\', true)';
1632                     } else {
1633                         ret = this.compile(node.children[0], js) + '.' + node.children[1];
1634                     }
1635                     break;
1636                 case 'op_use':
1637                     this._warn('Use of the \'use\' operator is deprecated.');
1638                     if (js) {
1639                         ret = '$jc$.use(\'';
1640                     } else {
1641                         ret = 'use(\'';
1642                     }
1643 
1644                     ret += node.children[0].toString() + '\');';
1645                     break;
1646                 case 'op_delete':
1647                     this._warn('Use of the \'delete\' operator is deprecated. Please use the remove() function.');
1648                     if (js) {
1649                         ret = '$jc$.del(';
1650                     } else {
1651                         ret = 'remove(';
1652                     }
1653 
1654                     ret += this.compile(node.children[0], js) + ')';
1655                     break;
1656                 case 'op_equ':
1657                     ret = '(' + this.compile(node.children[0], js) + ' == ' + this.compile(node.children[1], js) + ')';
1658                     break;
1659                 case 'op_neq':
1660                     ret = '(' + this.compile(node.children[0], js) + ' != ' + this.compile(node.children[1], js) + ')';
1661                     break;
1662                 case 'op_approx':
1663                     ret = '(' + this.compile(node.children[0], js) + ' ~= ' + this.compile(node.children[1], js) + ')';
1664                     break;
1665                 case 'op_grt':
1666                     if (js) {
1667                         ret = '$jc$.gt(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1668                     } else {
1669                         ret = '(' + this.compile(node.children[0], js) + ' > ' + this.compile(node.children[1], js) + ')';
1670                     }
1671                     break;
1672                 case 'op_lot':
1673                     if (js) {
1674                         ret = '$jc$.lt(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1675                     } else {
1676                         ret = '(' + this.compile(node.children[0], js) + ' < ' + this.compile(node.children[1], js) + ')';
1677                     }
1678                     break;
1679                 case 'op_gre':
1680                     if (js) {
1681                         ret = '$jc$.geq(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1682                     } else {
1683                         ret = '(' + this.compile(node.children[0], js) + ' >= ' + this.compile(node.children[1], js) + ')';
1684                     }
1685                     break;
1686                 case 'op_loe':
1687                     if (js) {
1688                         ret = '$jc$.leq(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1689                     } else {
1690                         ret = '(' + this.compile(node.children[0], js) + ' <= ' + this.compile(node.children[1], js) + ')';
1691                     }
1692                     break;
1693                 case 'op_or':
1694                     ret = '(' + this.compile(node.children[0], js) + ' || ' + this.compile(node.children[1], js) + ')';
1695                     break;
1696                 case 'op_and':
1697                     ret = '(' + this.compile(node.children[0], js) + ' && ' + this.compile(node.children[1], js) + ')';
1698                     break;
1699                 case 'op_not':
1700                     ret = '!(' + this.compile(node.children[0], js) + ')';
1701                     break;
1702                 case 'op_add':
1703                     if (js) {
1704                         ret = '$jc$.add(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1705                     } else {
1706                         ret = '(' + this.compile(node.children[0], js) + ' + ' + this.compile(node.children[1], js) + ')';
1707                     }
1708                     break;
1709                 case 'op_sub':
1710                     if (js) {
1711                         ret = '$jc$.sub(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1712                     } else {
1713                         ret = '(' + this.compile(node.children[0], js) + ' - ' + this.compile(node.children[1], js) + ')';
1714                     }
1715                     break;
1716                 case 'op_div':
1717                     if (js) {
1718                         ret = '$jc$.div(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1719                     } else {
1720                         ret = '(' + this.compile(node.children[0], js) + ' / ' + this.compile(node.children[1], js) + ')';
1721                     }
1722                     break;
1723                 case 'op_mod':
1724                     if (js) {
1725                         ret = '$jc$.mod(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ', true)';
1726                     } else {
1727                         ret = '(' + this.compile(node.children[0], js) + ' % ' + this.compile(node.children[1], js) + ')';
1728                     }
1729                     break;
1730                 case 'op_mul':
1731                     if (js) {
1732                         ret = '$jc$.mul(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1733                     } else {
1734                         ret = '(' + this.compile(node.children[0], js) + ' * ' + this.compile(node.children[1], js) + ')';
1735                     }
1736                     break;
1737                 case 'op_exp':
1738                     if (js) {
1739                         ret = '$jc$.pow(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1740                     } else {
1741                         ret = '(' + this.compile(node.children[0], js) + '^' + this.compile(node.children[1], js) + ')';
1742                     }
1743                     break;
1744                 case 'op_neg':
1745                     if (js) {
1746                         ret = '$jc$.neg(' + this.compile(node.children[0], js) + ')';
1747                     } else {
1748                         ret = '(-' + this.compile(node.children[0], js) + ')';
1749                     }
1750                     break;
1751                 }
1752                 break;
1753 
1754             case 'node_var':
1755                 if (js) {
1756                     ret = this.getvarJS(node.value, false, node.withProps);
1757                 } else {
1758                     ret = node.value;
1759                 }
1760                 break;
1761 
1762             case 'node_const':
1763                 ret = node.value;
1764                 break;
1765 
1766             case 'node_const_bool':
1767                 ret = node.value;
1768                 break;
1769 
1770             case 'node_str':
1771                 ret = '\'' + node.value + '\'';
1772                 break;
1773             }
1774 
1775             if (node.needsBrackets) {
1776                 ret = '{\n' + ret + '}\n';
1777             }
1778 
1779             return ret;
1780         },
1781 
1782         /**
1783          * This is used as the global X() function.
1784          * @param {JXG.Point|JXG.Text} e
1785          * @returns {Number}
1786          */
1787         X: function (e) {
1788             return e.X();
1789         },
1790 
1791         /**
1792          * This is used as the global Y() function.
1793          * @param {JXG.Point|JXG.Text} e
1794          * @returns {Number}
1795          */
1796         Y: function (e) {
1797             return e.Y();
1798         },
1799 
1800         /**
1801          * This is used as the global V() function.
1802          * @param {Glider|Slider} e
1803          * @returns {Number}
1804          */
1805         V: function (e) {
1806             return e.Value();
1807         },
1808 
1809         /**
1810          * This is used as the global L() function.
1811          * @param {JXG.Line} e
1812          * @returns {Number}
1813          */
1814         L: function (e) {
1815             return e.L();
1816         },
1817 
1818         /**
1819          * This is used as the global dist() function.
1820          * @param {JXG.Point} p1
1821          * @param {JXG.Point} p2
1822          * @returns {Number}
1823          */
1824         dist: function (p1, p2) {
1825             if (!Type.exists(p1) || !Type.exists(p1.Dist)) {
1826                 this._error('Error: Can\'t calculate distance.');
1827             }
1828 
1829             return p1.Dist(p2);
1830         },
1831 
1832         /**
1833          * + operator implementation
1834          * @param {Number|Array|JXG.Point} a
1835          * @param {Number|Array|JXG.Point} b
1836          * @returns {Number|Array}
1837          */
1838         add: function (a, b) {
1839             var i, len, res;
1840 
1841             a = Type.evalSlider(a);
1842             b = Type.evalSlider(b);
1843 
1844             if (Interval.isInterval(a) || Interval.isInterval(b)) {
1845                 res = Interval.add(a, b);
1846             } else if (Type.isArray(a) && Type.isArray(b)) {
1847                 len = Math.min(a.length, b.length);
1848                 res = [];
1849 
1850                 for (i = 0; i < len; i++) {
1851                     res[i] = a[i] + b[i];
1852                 }
1853             } else if (Type.isNumber(a) && Type.isNumber(b)) {
1854                 res = a + b;
1855             } else if (Type.isString(a) || Type.isString(b)) {
1856                 res = a.toString() + b.toString();
1857             } else {
1858                 this._error('Operation + not defined on operands ' + typeof a + ' and ' + typeof b);
1859             }
1860 
1861             return res;
1862         },
1863 
1864         /**
1865          * - operator implementation
1866          * @param {Number|Array|JXG.Point} a
1867          * @param {Number|Array|JXG.Point} b
1868          * @returns {Number|Array}
1869          */
1870         sub: function (a, b) {
1871             var i, len, res;
1872 
1873             a = Type.evalSlider(a);
1874             b = Type.evalSlider(b);
1875 
1876             if (Interval.isInterval(a) || Interval.isInterval(b)) {
1877                 res = Interval.sub(a, b);
1878             } else if (Type.isArray(a) && Type.isArray(b)) {
1879                 len = Math.min(a.length, b.length);
1880                 res = [];
1881 
1882                 for (i = 0; i < len; i++) {
1883                     res[i] = a[i] - b[i];
1884                 }
1885             } else if (Type.isNumber(a) && Type.isNumber(b)) {
1886                 res = a - b;
1887             } else {
1888                 this._error('Operation - not defined on operands ' + typeof a + ' and ' + typeof b);
1889             }
1890 
1891             return res;
1892         },
1893 
1894         /**
1895          * unary - operator implementation
1896          * @param {Number|Array|JXG.Point} a
1897          * @returns {Number|Array}
1898          */
1899         neg: function (a) {
1900             var i, len, res;
1901 
1902             a = Type.evalSlider(a);
1903 
1904             if (Interval.isInterval(a)) {
1905                 res = Interval.negative(a);
1906             } else if (Type.isArray(a)) {
1907                 len = a.length;
1908                 res = [];
1909 
1910                 for (i = 0; i < len; i++) {
1911                     res[i] = -a[i];
1912                 }
1913             } else if (Type.isNumber(a)) {
1914                 res = -a;
1915             } else {
1916                 this._error('Unary operation - not defined on operand ' + typeof a);
1917             }
1918 
1919             return res;
1920         },
1921 
1922         /**
1923          * Multiplication of vectors and numbers
1924          * @param {Number|Array} a
1925          * @param {Number|Array} b
1926          * @returns {Number|Array} (Inner) product of the given input values.
1927          */
1928         mul: function (a, b) {
1929             var i, len, res;
1930 
1931             a = Type.evalSlider(a);
1932             b = Type.evalSlider(b);
1933 
1934             if (Type.isArray(a) && Type.isNumber(b)) {
1935                 // swap b and a
1936                 i = a;
1937                 a = b;
1938                 b = a;
1939             }
1940 
1941             if (Interval.isInterval(a) || Interval.isInterval(b)) {
1942                 res = Interval.mul(a, b);
1943             } else if (Type.isArray(a) && Type.isArray(b)) {
1944                 len = Math.min(a.length, b.length);
1945                 res = Mat.innerProduct(a, b, len);
1946             } else if (Type.isNumber(a) && Type.isArray(b)) {
1947                 len = b.length;
1948                 res = [];
1949 
1950                 for (i = 0; i < len; i++) {
1951                     res[i] = a * b[i];
1952                 }
1953             } else if (Type.isNumber(a) && Type.isNumber(b)) {
1954                 res = a * b;
1955             } else {
1956                 this._error('Operation * not defined on operands ' + typeof a + ' and ' + typeof b);
1957             }
1958 
1959             return res;
1960         },
1961 
1962         /**
1963          * Implementation of the / operator.
1964          * @param {Number|Array} a
1965          * @param {Number} b
1966          * @returns {Number|Array}
1967          */
1968         div: function (a, b) {
1969             var i, len, res;
1970 
1971             a = Type.evalSlider(a);
1972             b = Type.evalSlider(b);
1973 
1974             if (Interval.isInterval(a) || Interval.isInterval(b)) {
1975                 res = Interval.div(a, b);
1976             } else if (Type.isArray(a) && Type.isNumber(b)) {
1977                 len = a.length;
1978                 res = [];
1979 
1980                 for (i = 0; i < len; i++) {
1981                     res[i] = a[i] / b;
1982                 }
1983             } else if (Type.isNumber(a) && Type.isNumber(b)) {
1984                 res = a / b;
1985             } else {
1986                 this._error('Operation * not defined on operands ' + typeof a + ' and ' + typeof b);
1987             }
1988 
1989             return res;
1990         },
1991 
1992         /**
1993          * Implementation of the % operator.
1994          * @param {Number|Array} a
1995          * @param {Number} b
1996          * @returns {Number|Array}
1997          */
1998         mod: function (a, b) {
1999             var i, len, res;
2000 
2001             a = Type.evalSlider(a);
2002             b = Type.evalSlider(b);
2003 
2004             if (Interval.isInterval(a) || Interval.isInterval(b)) {
2005                 return Interval.fmod(a, b);
2006             } else if (Type.isArray(a) && Type.isNumber(b)) {
2007                 len = a.length;
2008                 res = [];
2009 
2010                 for (i = 0; i < len; i++) {
2011                     res[i] = Mat.mod(a[i], b, true);
2012                 }
2013             } else if (Type.isNumber(a) && Type.isNumber(b)) {
2014                 res = Mat.mod(a, b, true);
2015             } else {
2016                 this._error('Operation * not defined on operands ' + typeof a + ' and ' + typeof b);
2017             }
2018 
2019             return res;
2020         },
2021 
2022         /**
2023          * Pow function wrapper to allow direct usage of sliders.
2024          * @param {Number|Slider} a
2025          * @param {Number|Slider} b
2026          * @returns {Number}
2027          */
2028         pow: function (a, b) {
2029             a = Type.evalSlider(a);
2030             b = Type.evalSlider(b);
2031 
2032             if (Interval.isInterval(a) || Interval.isInterval(b)) {
2033                 return Interval.pow(a, b);
2034             }
2035             return Mat.pow(a, b);
2036         },
2037 
2038         lt: function(a, b) {
2039             if (Interval.isInterval(a) || Interval.isInterval(b)) {
2040                 return Interval.lt(a, b);
2041             }
2042             return a < b;
2043         },
2044         leq: function(a, b) {
2045             if (Interval.isInterval(a) || Interval.isInterval(b)) {
2046                 return Interval.leq(a, b);
2047             }
2048             return a <= b;
2049         },
2050         gt: function(a, b) {
2051             if (Interval.isInterval(a) || Interval.isInterval(b)) {
2052                 return Interval.gt(a, b);
2053             }
2054             return a > b;
2055         },
2056         geq: function(a, b) {
2057             if (Interval.isInterval(a) || Interval.isInterval(b)) {
2058                 return Intervalt.geq(a, b);
2059             }
2060             return a >= b;
2061         },
2062 
2063         DDD: function(f) {
2064             console.log('Dummy derivative function. This should never appear!');
2065         },
2066 
2067         /**
2068          * Implementation of the ?: operator
2069          * @param {Boolean} cond Condition
2070          * @param {*} v1
2071          * @param {*} v2
2072          * @returns {*} Either v1 or v2.
2073          */
2074         ifthen: function (cond, v1, v2) {
2075             if (cond) {
2076                 return v1;
2077             }
2078 
2079             return v2;
2080         },
2081 
2082         /**
2083          * Implementation of the delete() builtin function
2084          * @param {JXG.GeometryElement} element
2085          */
2086         del: function (element) {
2087             if (typeof element === 'object' && JXG.exists(element.type) && JXG.exists(element.elementClass)) {
2088                 this.board.removeObject(element);
2089             }
2090         },
2091 
2092         /**
2093          * Implementation of the use() builtin function
2094          * @param {String} board
2095          */
2096         use: function (board) {
2097             var b, ref,
2098                 found = false;
2099 
2100             if (typeof board === 'string') {
2101                 // search all the boards for the one with the appropriate container div
2102                 for (b in JXG.boards) {
2103                     if (JXG.boards.hasOwnProperty(b) && JXG.boards[b].container === board) {
2104                         ref = JXG.boards[b];
2105                         found = true;
2106                         break;
2107                     }
2108                 }
2109             } else {
2110                 ref = board;
2111                 found = true;
2112             }
2113 
2114             if (found) {
2115                 this.board = ref;
2116                 this.builtIn.$board = ref;
2117                 this.builtIn.$board.src = '$jc$.board';
2118             } else {
2119                 this._error('Board \'' + board + '\' not found!');
2120             }
2121         },
2122 
2123         /**
2124          * Find the first symbol to the given value from the given scope upwards.
2125          * @param v Value
2126          * @param {Number} [scope=-1] The scope, default is to start with current scope (-1).
2127          * @returns {Array} An array containing the symbol and the scope if a symbol could be found,
2128          * an empty array otherwise;
2129          */
2130         findSymbol: function (v, scope) {
2131             var i, s;
2132 
2133             scope = Type.def(scope, -1);
2134 
2135             if (scope === -1) {
2136                 s = this.scope;
2137             } else {
2138                 s = this.scopes[scope];
2139             }
2140 
2141             while (s !== null) {
2142                 for (i in s.locals) {
2143                     if (s.locals.hasOwnProperty(i) && s.locals[i] === v) {
2144                         return [i, s];
2145                     }
2146                 }
2147 
2148                 s = s.previous;
2149             }
2150 
2151             return [];
2152         },
2153 
2154         /**
2155          * Import modules into a JessieCode script.
2156          * @param {String} module
2157          */
2158         importModule: function (module) {
2159             return priv.modules[module.toLowerCase()];
2160         },
2161 
2162         /**
2163          * Defines built in methods and constants.
2164          * @returns {Object} BuiltIn control object
2165          */
2166         defineBuiltIn: function () {
2167             var that = this,
2168                 builtIn = {
2169                     PI: Math.PI,
2170                     EULER: Math.E,
2171                     X: that.X,
2172                     Y: that.Y,
2173                     V: that.V,
2174                     L: that.L,
2175                     dist: that.dist,
2176                     rad: Geometry.rad,
2177                     deg: Geometry.trueAngle,
2178                     factorial: Mat.factorial,
2179                     trunc: Type.trunc,
2180                     log: Mat.log,
2181                     ln: Math.log,
2182                     log10: Mat.log10,
2183                     lg: Mat.log10,
2184                     log2: Mat.log2,
2185                     lb: Mat.log2,
2186                     ld: Mat.log2,
2187                     cosh: Mat.cosh,
2188                     sinh: Mat.sinh,
2189                     cot: Mat.cot,
2190                     acot: Mat.acot,
2191 
2192                     nthroot: Mat.nthroot,
2193                     cbrt: Mat.cbrt,
2194                     pow: Mat.pow,
2195                     ratpow: Mat.ratpow,
2196                     gcd: Mat.gcd,
2197                     lcm: Mat.lcm,
2198                     binomial: Mat.binomial,
2199                     IfThen: that.ifthen,
2200                     'import': that.importModule,
2201                     'use': that.use,
2202                     'remove': that.del,
2203                     '$': that.getElementById,
2204                     '$board': that.board,
2205                     '$log': that.log,
2206                     D: that.DDD
2207                 };
2208 
2209             // special scopes for factorial, deg, and rad
2210             builtIn.rad.sc = Geometry;
2211             builtIn.deg.sc = Geometry;
2212             builtIn.factorial.sc = Mat;
2213 
2214             // set the javascript equivalent for the builtIns
2215             // some of the anonymous functions should be replaced by global methods later on
2216             // EULER and PI don't get a source attribute - they will be lost anyways and apparently
2217             // some browser will throw an exception when a property is assigned to a primitive value.
2218             builtIn.X.src = '$jc$.X';
2219             builtIn.Y.src = '$jc$.Y';
2220             builtIn.V.src = '$jc$.V';
2221             builtIn.L.src = '$jc$.L';
2222             builtIn.dist.src = '$jc$.dist';
2223             builtIn.rad.src = 'JXG.Math.Geometry.rad';
2224             builtIn.deg.src = 'JXG.Math.Geometry.trueAngle';
2225             builtIn.factorial.src = 'JXG.Math.factorial';
2226             builtIn.trunc.src = 'JXG.trunc';
2227             builtIn.log.src = 'JXG.Math.log';
2228             builtIn.ln.src = 'Math.log';
2229             builtIn.log10.src = 'JXG.Math.log10';
2230             builtIn.lg.src = 'JXG.Math.log10';
2231             builtIn.log2.src = 'JXG.Math.log2';
2232             builtIn.lb.src = 'JXG.Math.log2';
2233             builtIn.ld.src = 'JXG.Math.log2';
2234             builtIn.cosh.src = 'JXG.Math.cosh';
2235             builtIn.sinh.src = 'JXG.Math.sinh';
2236             builtIn.cot.src = 'JXG.Math.cot';
2237             builtIn.acot.src = 'JXG.Math.acot';
2238             builtIn.nthroot.src = 'JXG.Math.nthroot';
2239             builtIn.cbrt.src = 'JXG.Math.cbrt';
2240             builtIn.pow.src = 'JXG.Math.pow';
2241             builtIn.ratpow.src = 'JXG.Math.ratpow';
2242             builtIn.gcd.src = 'JXG.Math.gcd';
2243             builtIn.lcm.src = 'JXG.Math.lcm';
2244             builtIn.binomial.src = 'JXG.Math.binomial';
2245             builtIn['import'].src = '$jc$.importModule';
2246             builtIn.use.src = '$jc$.use';
2247             builtIn.remove.src = '$jc$.del';
2248             builtIn.IfThen.src = '$jc$.ifthen';
2249             // usually unused, see node_op > op_execfun
2250             builtIn.$.src = '(function (n) { return $jc$.board.select(n); })';
2251             if (builtIn.$board) {
2252                 builtIn.$board.src = '$jc$.board';
2253             }
2254             builtIn.$log.src = '$jc$.log';
2255 
2256             return builtIn;
2257         },
2258 
2259         /**
2260          * Output a debugging message. Uses debug console, if available. Otherwise an HTML element with the
2261          * id "debug" and an innerHTML property is used.
2262          * @param {String} log
2263          * @private
2264          */
2265         _debug: function (log) {
2266             if (typeof console === 'object') {
2267                 console.log(log);
2268             } else if (Env.isBrowser && document && document.getElementById('debug') !== null) {
2269                 document.getElementById('debug').innerHTML += log + '<br />';
2270             }
2271         },
2272 
2273         /**
2274          * Throws an exception with the given error message.
2275          * @param {String} msg Error message
2276          */
2277         _error: function (msg) {
2278             var e = new Error('Error(' + this.line + '): ' + msg);
2279             e.line = this.line;
2280             throw e;
2281         },
2282 
2283         /**
2284          * Output a warning message using {@link JXG#debug} and precedes the message with "Warning: ".
2285          * @param {String} msg
2286          */
2287         _warn: function (msg) {
2288             if (typeof console === 'object') {
2289                 console.log('Warning(' + this.line + '): ' + msg);
2290             } else if (Env.isBrowser && document && document.getElementById(this.warnLog) !== null) {
2291                 document.getElementById(this.warnLog).innerHTML += 'Warning(' + this.line + '): ' + msg + '<br />';
2292             }
2293         },
2294 
2295         _log: function (msg) {
2296             if (typeof window !== 'object' && typeof self === 'object' && self.postMessage) {
2297                 self.postMessage({type: 'log', msg: 'Log: ' + msg.toString()});
2298             } else {
2299                 console.log('Log: ', arguments);
2300             }
2301         }
2302 
2303     });
2304 
2305 /* parser generated by jison 0.4.18 */
2306 /*
2307   Returns a Parser object of the following structure:
2308 
2309   Parser: {
2310     yy: {}
2311   }
2312 
2313   Parser.prototype: {
2314     yy: {},
2315     trace: function(),
2316     symbols_: {associative list: name ==> number},
2317     terminals_: {associative list: number ==> name},
2318     productions_: [...],
2319     performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
2320     table: [...],
2321     defaultActions: {...},
2322     parseError: function(str, hash),
2323     parse: function(input),
2324 
2325     lexer: {
2326         EOF: 1,
2327         parseError: function(str, hash),
2328         setInput: function(input),
2329         input: function(),
2330         unput: function(str),
2331         more: function(),
2332         less: function(n),
2333         pastInput: function(),
2334         upcomingInput: function(),
2335         showPosition: function(),
2336         test_match: function(regex_match_array, rule_index),
2337         next: function(),
2338         lex: function(),
2339         begin: function(condition),
2340         popState: function(),
2341         _currentRules: function(),
2342         topState: function(),
2343         pushState: function(condition),
2344 
2345         options: {
2346             ranges: boolean           (optional: true ==> token location info will include a .range[] member)
2347             flex: boolean             (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
2348             backtrack_lexer: boolean  (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
2349         },
2350 
2351         performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
2352         rules: [...],
2353         conditions: {associative list: name ==> set},
2354     }
2355   }
2356 
2357 
2358   token location info (@$, _$, etc.): {
2359     first_line: n,
2360     last_line: n,
2361     first_column: n,
2362     last_column: n,
2363     range: [start_number, end_number]       (where the numbers are indexes into the input string, regular zero-based)
2364   }
2365 
2366 
2367   the parseError function receives a 'hash' object with these members for lexer and parser errors: {
2368     text:        (matched text)
2369     token:       (the produced terminal token, if any)
2370     line:        (yylineno)
2371   }
2372   while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
2373     loc:         (yylloc)
2374     expected:    (string describing the set of expected tokens)
2375     recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
2376   }
2377 */
2378 var parser = (function(){
2379 var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[2,14],$V1=[1,13],$V2=[1,37],$V3=[1,14],$V4=[1,15],$V5=[1,21],$V6=[1,16],$V7=[1,17],$V8=[1,33],$V9=[1,18],$Va=[1,19],$Vb=[1,12],$Vc=[1,59],$Vd=[1,60],$Ve=[1,58],$Vf=[1,46],$Vg=[1,48],$Vh=[1,49],$Vi=[1,50],$Vj=[1,51],$Vk=[1,52],$Vl=[1,53],$Vm=[1,54],$Vn=[1,45],$Vo=[1,38],$Vp=[1,39],$Vq=[5,7,8,14,15,16,17,19,20,21,23,26,27,50,51,58,65,74,75,76,77,78,79,80,82,91,93],$Vr=[5,7,8,12,14,15,16,17,19,20,21,23,26,27,50,51,58,65,74,75,76,77,78,79,80,82,91,93],$Vs=[8,10,16,32,34,35,37,39,41,42,43,45,46,47,48,50,51,53,54,55,57,64,65,66,83,86],$Vt=[2,48],$Vu=[1,72],$Vv=[10,16,32,34,35,37,39,41,42,43,45,46,47,48,50,51,53,54,55,57,66,83,86],$Vw=[1,78],$Vx=[8,10,16,32,34,35,37,41,42,43,45,46,47,48,50,51,53,54,55,57,64,65,66,83,86],$Vy=[1,82],$Vz=[8,10,16,32,34,35,37,39,45,46,47,48,50,51,53,54,55,57,64,65,66,83,86],$VA=[1,83],$VB=[1,84],$VC=[1,85],$VD=[8,10,16,32,34,35,37,39,41,42,43,50,51,53,54,55,57,64,65,66,83,86],$VE=[1,89],$VF=[1,90],$VG=[1,91],$VH=[1,92],$VI=[1,97],$VJ=[8,10,16,32,34,35,37,39,41,42,43,45,46,47,48,53,54,55,57,64,65,66,83,86],$VK=[1,103],$VL=[1,104],$VM=[8,10,16,32,34,35,37,39,41,42,43,45,46,47,48,50,51,57,64,65,66,83,86],$VN=[1,105],$VO=[1,106],$VP=[1,107],$VQ=[1,126],$VR=[1,139],$VS=[83,86],$VT=[1,149],$VU=[10,66,86],$VV=[8,10,16,20,32,34,35,37,39,41,42,43,45,46,47,48,50,51,53,54,55,57,64,65,66,82,83,86],$VW=[1,166],$VX=[10,86];
2380 var parser = {trace: function trace () { },
2381 yy: {},
2382 symbols_: {"error":2,"Program":3,"StatementList":4,"EOF":5,"IfStatement":6,"IF":7,"(":8,"Expression":9,")":10,"Statement":11,"ELSE":12,"LoopStatement":13,"WHILE":14,"FOR":15,";":16,"DO":17,"UnaryStatement":18,"USE":19,"IDENTIFIER":20,"DELETE":21,"ReturnStatement":22,"RETURN":23,"EmptyStatement":24,"StatementBlock":25,"{":26,"}":27,"ExpressionStatement":28,"AssignmentExpression":29,"ConditionalExpression":30,"LeftHandSideExpression":31,"=":32,"LogicalORExpression":33,"?":34,":":35,"LogicalANDExpression":36,"||":37,"EqualityExpression":38,"&&":39,"RelationalExpression":40,"==":41,"!=":42,"~=":43,"AdditiveExpression":44,"<":45,">":46,"<=":47,">=":48,"MultiplicativeExpression":49,"+":50,"-":51,"UnaryExpression":52,"*":53,"/":54,"%":55,"ExponentExpression":56,"^":57,"!":58,"MemberExpression":59,"CallExpression":60,"PrimaryExpression":61,"FunctionExpression":62,"MapExpression":63,".":64,"[":65,"]":66,"BasicLiteral":67,"ObjectLiteral":68,"ArrayLiteral":69,"NullLiteral":70,"BooleanLiteral":71,"StringLiteral":72,"NumberLiteral":73,"NULL":74,"TRUE":75,"FALSE":76,"STRING":77,"NUMBER":78,"NAN":79,"INFINITY":80,"ElementList":81,"<<":82,">>":83,"PropertyList":84,"Property":85,",":86,"PropertyName":87,"Arguments":88,"AttributeList":89,"Attribute":90,"FUNCTION":91,"ParameterDefinitionList":92,"MAP":93,"->":94,"$accept":0,"$end":1},
2383 terminals_: {2:"error",5:"EOF",7:"IF",8:"(",10:")",12:"ELSE",14:"WHILE",15:"FOR",16:";",17:"DO",19:"USE",20:"IDENTIFIER",21:"DELETE",23:"RETURN",26:"{",27:"}",32:"=",34:"?",35:":",37:"||",39:"&&",41:"==",42:"!=",43:"~=",45:"<",46:">",47:"<=",48:">=",50:"+",51:"-",53:"*",54:"/",55:"%",57:"^",58:"!",64:".",65:"[",66:"]",74:"NULL",75:"TRUE",76:"FALSE",77:"STRING",78:"NUMBER",79:"NAN",80:"INFINITY",82:"<<",83:">>",86:",",91:"FUNCTION",93:"MAP",94:"->"},
2384 productions_: [0,[3,2],[6,5],[6,7],[13,5],[13,9],[13,7],[18,2],[18,2],[22,2],[22,3],[24,1],[25,3],[4,2],[4,0],[11,1],[11,1],[11,1],[11,1],[11,1],[11,1],[11,1],[28,2],[9,1],[29,1],[29,3],[30,1],[30,5],[33,1],[33,3],[36,1],[36,3],[38,1],[38,3],[38,3],[38,3],[40,1],[40,3],[40,3],[40,3],[40,3],[44,1],[44,3],[44,3],[49,1],[49,3],[49,3],[49,3],[56,1],[56,3],[52,1],[52,2],[52,2],[52,2],[31,1],[31,1],[59,1],[59,1],[59,1],[59,3],[59,4],[61,1],[61,1],[61,1],[61,1],[61,3],[67,1],[67,1],[67,1],[67,1],[70,1],[71,1],[71,1],[72,1],[73,1],[73,1],[73,1],[69,2],[69,3],[68,2],[68,3],[84,1],[84,3],[85,3],[87,1],[87,1],[87,1],[60,2],[60,3],[60,2],[60,4],[60,3],[88,2],[88,3],[89,1],[89,3],[90,1],[90,1],[81,1],[81,3],[62,4],[62,5],[63,6],[92,1],[92,3]],
2385 performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
2386 /* this == yyval */
2387 
2388 var $0 = $$.length - 1;
2389 switch (yystate) {
2390 case 1:
2391  return $$[$0-1]; 
2392 break;
2393 case 2:
2394  this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_if', $$[$0-2], $$[$0]); 
2395 break;
2396 case 3:
2397  this.$ = AST.createNode(lc(_$[$0-6]), 'node_op', 'op_if_else', $$[$0-4], $$[$0-2], $$[$0]); 
2398 break;
2399 case 4:
2400  this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_while', $$[$0-2], $$[$0]); 
2401 break;
2402 case 5:
2403  this.$ = AST.createNode(lc(_$[$0-8]), 'node_op', 'op_for', $$[$0-6], $$[$0-4], $$[$0-2], $$[$0]); 
2404 break;
2405 case 6:
2406  this.$ = AST.createNode(lc(_$[$0-6]), 'node_op', 'op_do', $$[$0-5], $$[$0-2]); 
2407 break;
2408 case 7:
2409  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_use', $$[$0]); 
2410 break;
2411 case 8:
2412  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_delete', $$[$0]); 
2413 break;
2414 case 9:
2415  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_return', undefined); 
2416 break;
2417 case 10:
2418  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_return', $$[$0-1]); 
2419 break;
2420 case 11: case 14:
2421  this.$ = AST.createNode(lc(_$[$0]), 'node_op', 'op_none'); 
2422 break;
2423 case 12:
2424  this.$ = $$[$0-1]; this.$.needsBrackets = true; 
2425 break;
2426 case 13:
2427  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_none', $$[$0-1], $$[$0]); 
2428 break;
2429 case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 23: case 24: case 26: case 28: case 30: case 32: case 36: case 41: case 44: case 48: case 50: case 52: case 54: case 55: case 56: case 58: case 62: case 81: case 84: case 85: case 86:
2430  this.$ = $$[$0]; 
2431 break;
2432 case 22: case 65: case 93:
2433  this.$ = $$[$0-1]; 
2434 break;
2435 case 25:
2436  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_assign', $$[$0-2], $$[$0]); this.$.isMath = false; 
2437 break;
2438 case 27:
2439  this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_conditional', $$[$0-4], $$[$0-2], $$[$0]); this.$.isMath = false; 
2440 break;
2441 case 29:
2442  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_or', $$[$0-2], $$[$0]); this.$.isMath = false; 
2443 break;
2444 case 31:
2445  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_and', $$[$0-2], $$[$0]); this.$.isMath = false; 
2446 break;
2447 case 33:
2448  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_equ', $$[$0-2], $$[$0]); this.$.isMath = false; 
2449 break;
2450 case 34:
2451  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_neq', $$[$0-2], $$[$0]); this.$.isMath = false; 
2452 break;
2453 case 35:
2454  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_approx', $$[$0-2], $$[$0]); this.$.isMath = false; 
2455 break;
2456 case 37:
2457  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_lot', $$[$0-2], $$[$0]); this.$.isMath = false; 
2458 break;
2459 case 38:
2460  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_grt', $$[$0-2], $$[$0]); this.$.isMath = false; 
2461 break;
2462 case 39:
2463  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_loe', $$[$0-2], $$[$0]); this.$.isMath = false; 
2464 break;
2465 case 40:
2466  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_gre', $$[$0-2], $$[$0]); this.$.isMath = false; 
2467 break;
2468 case 42:
2469  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_add', $$[$0-2], $$[$0]); this.$.isMath = true; 
2470 break;
2471 case 43:
2472  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_sub', $$[$0-2], $$[$0]); this.$.isMath = true; 
2473 break;
2474 case 45:
2475  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_mul', $$[$0-2], $$[$0]); this.$.isMath = true; 
2476 break;
2477 case 46:
2478  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_div', $$[$0-2], $$[$0]); this.$.isMath = true; 
2479 break;
2480 case 47:
2481  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_mod', $$[$0-2], $$[$0]); this.$.isMath = true; 
2482 break;
2483 case 49:
2484  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_exp', $$[$0-2], $$[$0]); this.$.isMath = true; 
2485 break;
2486 case 51:
2487  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_not', $$[$0]); this.$.isMath = false; 
2488 break;
2489 case 53:
2490  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_neg', $$[$0]); this.$.isMath = true; 
2491 break;
2492 case 57: case 63: case 64: case 66: case 67: case 68: case 97:
2493  this.$ = $$[$0]; this.$.isMath = false; 
2494 break;
2495 case 59: case 91:
2496  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_property', $$[$0-2], $$[$0]); this.$.isMath = true; 
2497 break;
2498 case 60: case 90:
2499  this.$ = AST.createNode(lc(_$[$0-3]), 'node_op', 'op_extvalue', $$[$0-3], $$[$0-1]); this.$.isMath = true; 
2500 break;
2501 case 61:
2502  this.$ = AST.createNode(lc(_$[$0]), 'node_var', $$[$0]); 
2503 break;
2504 case 69:
2505  this.$ = $$[$0]; this.$.isMath = true; 
2506 break;
2507 case 70:
2508  this.$ = AST.createNode(lc(_$[$0]), 'node_const', null); 
2509 break;
2510 case 71:
2511  this.$ = AST.createNode(lc(_$[$0]), 'node_const_bool', true); 
2512 break;
2513 case 72:
2514  this.$ = AST.createNode(lc(_$[$0]), 'node_const_bool', false); 
2515 break;
2516 case 73:
2517  this.$ = AST.createNode(lc(_$[$0]), 'node_str', $$[$0].substring(1, $$[$0].length - 1)); 
2518 break;
2519 case 74:
2520  this.$ = AST.createNode(lc(_$[$0]), 'node_const', parseFloat($$[$0])); 
2521 break;
2522 case 75:
2523  this.$ = AST.createNode(lc(_$[$0]), 'node_const', NaN); 
2524 break;
2525 case 76:
2526  this.$ = AST.createNode(lc(_$[$0]), 'node_const', Infinity); 
2527 break;
2528 case 77:
2529  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_array', []); 
2530 break;
2531 case 78:
2532  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_array', $$[$0-1]); 
2533 break;
2534 case 79:
2535  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_emptyobject', {}); 
2536 break;
2537 case 80:
2538  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_proplst_val', $$[$0-1]); 
2539 break;
2540 case 82:
2541  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_proplst', $$[$0-2], $$[$0]); 
2542 break;
2543 case 83:
2544  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_prop', $$[$0-2], $$[$0]); 
2545 break;
2546 case 87: case 89:
2547  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_execfun', $$[$0-1], $$[$0]); this.$.isMath = true; 
2548 break;
2549 case 88:
2550  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_execfun', $$[$0-2], $$[$0-1], $$[$0], true); this.$.isMath = false; 
2551 break;
2552 case 92:
2553  this.$ = []; 
2554 break;
2555 case 94: case 98: case 103:
2556  this.$ = [$$[$0]]; 
2557 break;
2558 case 95: case 99: case 104:
2559  this.$ = $$[$0-2].concat($$[$0]); 
2560 break;
2561 case 96:
2562  this.$ = AST.createNode(lc(_$[$0]), 'node_var', $$[$0]); this.$.isMath = true; 
2563 break;
2564 case 100:
2565  this.$ = AST.createNode(lc(_$[$0-3]), 'node_op', 'op_function', [], $$[$0]); this.$.isMath = false; 
2566 break;
2567 case 101:
2568  this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_function', $$[$0-2], $$[$0]); this.$.isMath = false; 
2569 break;
2570 case 102:
2571  this.$ = AST.createNode(lc(_$[$0-5]), 'node_op', 'op_map', $$[$0-3], $$[$0]); 
2572 break;
2573 }
2574 },
2575 table: [o([5,7,8,14,15,16,17,19,20,21,23,26,50,51,58,65,74,75,76,77,78,79,80,82,91,93],$V0,{3:1,4:2}),{1:[3]},{5:[1,3],6:6,7:$V1,8:$V2,9:20,11:4,13:7,14:$V3,15:$V4,16:$V5,17:$V6,18:8,19:$V7,20:$V8,21:$V9,22:9,23:$Va,24:11,25:5,26:$Vb,28:10,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{1:[2,1]},o($Vq,[2,13]),o($Vr,[2,15]),o($Vr,[2,16]),o($Vr,[2,17]),o($Vr,[2,18]),o($Vr,[2,19]),o($Vr,[2,20]),o($Vr,[2,21]),o([7,8,14,15,16,17,19,20,21,23,26,27,50,51,58,65,74,75,76,77,78,79,80,82,91,93],$V0,{4:61}),{8:[1,62]},{8:[1,63]},{8:[1,64]},{6:6,7:$V1,8:$V2,9:20,11:65,13:7,14:$V3,15:$V4,16:$V5,17:$V6,18:8,19:$V7,20:$V8,21:$V9,22:9,23:$Va,24:11,25:5,26:$Vb,28:10,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{20:[1,66]},{20:[1,67]},{8:$V2,9:69,16:[1,68],20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{16:[1,70]},o($Vr,[2,11]),o($Vs,[2,23]),o($Vs,[2,24]),o([8,10,16,34,35,37,39,41,42,43,45,46,47,48,50,51,53,54,55,64,65,66,83,86],$Vt,{32:[1,71],57:$Vu}),o([8,10,16,32,35,39,41,42,43,45,46,47,48,50,51,53,54,55,57,64,65,66,83,86],[2,26],{34:[1,73],37:[1,74]}),o($Vv,[2,54],{88:77,8:$Vw,64:[1,75],65:[1,76]}),o($Vv,[2,55],{88:79,8:$Vw,64:[1,81],65:[1,80]}),o($Vx,[2,28],{39:$Vy}),o($Vs,[2,56]),o($Vs,[2,57]),o($Vs,[2,58]),o($Vz,[2,30],{41:$VA,42:$VB,43:$VC}),o($Vs,[2,61]),o($Vs,[2,62]),o($Vs,[2,63]),o($Vs,[2,64]),{8:$V2,9:86,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:[1,87]},{8:[1,88]},o($VD,[2,32],{45:$VE,46:$VF,47:$VG,48:$VH}),o($Vs,[2,66]),o($Vs,[2,67]),o($Vs,[2,68]),o($Vs,[2,69]),{20:$VI,72:98,73:99,77:$Vj,78:$Vk,79:$Vl,80:$Vm,83:[1,93],84:94,85:95,87:96},{8:$V2,20:$V8,29:102,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,66:[1,100],67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,81:101,82:$Vn,91:$Vo,93:$Vp},o($VJ,[2,36],{50:$VK,51:$VL}),o($Vs,[2,70]),o($Vs,[2,71]),o($Vs,[2,72]),o($Vs,[2,73]),o($Vs,[2,74]),o($Vs,[2,75]),o($Vs,[2,76]),o($VM,[2,41],{53:$VN,54:$VO,55:$VP}),o($Vs,[2,44]),o($Vs,[2,50]),{8:$V2,20:$V8,31:109,50:$Vc,51:$Vd,52:108,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,50:$Vc,51:$Vd,52:110,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,50:$Vc,51:$Vd,52:111,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{6:6,7:$V1,8:$V2,9:20,11:4,13:7,14:$V3,15:$V4,16:$V5,17:$V6,18:8,19:$V7,20:$V8,21:$V9,22:9,23:$Va,24:11,25:5,26:$Vb,27:[1,112],28:10,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,9:113,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,9:114,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,9:115,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{14:[1,116]},o($Vr,[2,7]),o($Vr,[2,8]),o($Vr,[2,9]),{16:[1,117]},o($Vr,[2,22]),{8:$V2,20:$V8,29:118,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,50:$Vc,51:$Vd,52:119,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,29:120,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,36:121,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{20:[1,122]},{8:$V2,9:123,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},o($Vs,[2,87],{89:124,90:125,68:127,20:$VQ,82:$Vn}),{8:$V2,10:[1,128],20:$V8,29:102,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,81:129,82:$Vn,91:$Vo,93:$Vp},o($Vs,[2,89]),{8:$V2,9:130,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{20:[1,131]},{8:$V2,20:$V8,31:109,38:132,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,40:133,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,40:134,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,40:135,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{10:[1,136]},{10:[1,137],20:$VR,92:138},{20:$VR,92:140},{8:$V2,20:$V8,31:109,44:141,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,44:142,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,44:143,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,44:144,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},o($Vs,[2,79]),{83:[1,145],86:[1,146]},o($VS,[2,81]),{35:[1,147]},{35:[2,84]},{35:[2,85]},{35:[2,86]},o($Vs,[2,77]),{66:[1,148],86:$VT},o($VU,[2,98]),{8:$V2,20:$V8,31:109,49:150,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,49:151,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,50:$Vc,51:$Vd,52:152,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,50:$Vc,51:$Vd,52:153,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,31:109,50:$Vc,51:$Vd,52:154,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},o($Vs,[2,51]),o([8,10,16,32,34,35,37,39,41,42,43,45,46,47,48,50,51,53,54,55,64,65,66,83,86],$Vt,{57:$Vu}),o($Vs,[2,52]),o($Vs,[2,53]),o([5,7,8,10,12,14,15,16,17,19,20,21,23,26,27,32,34,35,37,39,41,42,43,45,46,47,48,50,51,53,54,55,57,58,64,65,66,74,75,76,77,78,79,80,82,83,86,91,93],[2,12]),{10:[1,155]},{10:[1,156]},{16:[1,157]},{8:[1,158]},o($Vr,[2,10]),o($Vs,[2,25]),o($Vs,[2,49]),{35:[1,159]},o($Vx,[2,29],{39:$Vy}),o($Vs,[2,59]),{66:[1,160]},o([8,10,16,32,34,35,37,39,41,42,43,45,46,47,48,50,51,53,54,55,57,64,65,66,83],[2,88],{86:[1,161]}),o($Vs,[2,94]),o($Vs,[2,96]),o($Vs,[2,97]),o($VV,[2,92]),{10:[1,162],86:$VT},{66:[1,163]},o($Vs,[2,91]),o($Vz,[2,31],{41:$VA,42:$VB,43:$VC}),o($VD,[2,33],{45:$VE,46:$VF,47:$VG,48:$VH}),o($VD,[2,34],{45:$VE,46:$VF,47:$VG,48:$VH}),o($VD,[2,35],{45:$VE,46:$VF,47:$VG,48:$VH}),o($Vs,[2,65]),{25:164,26:$Vb},{10:[1,165],86:$VW},o($VX,[2,103]),{10:[1,167],86:$VW},o($VJ,[2,37],{50:$VK,51:$VL}),o($VJ,[2,38],{50:$VK,51:$VL}),o($VJ,[2,39],{50:$VK,51:$VL}),o($VJ,[2,40],{50:$VK,51:$VL}),o($Vs,[2,80]),{20:$VI,72:98,73:99,77:$Vj,78:$Vk,79:$Vl,80:$Vm,85:168,87:96},{8:$V2,20:$V8,29:169,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},o($Vs,[2,78]),{8:$V2,20:$V8,29:170,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},o($VM,[2,42],{53:$VN,54:$VO,55:$VP}),o($VM,[2,43],{53:$VN,54:$VO,55:$VP}),o($Vs,[2,45]),o($Vs,[2,46]),o($Vs,[2,47]),{6:6,7:$V1,8:$V2,9:20,11:171,13:7,14:$V3,15:$V4,16:$V5,17:$V6,18:8,19:$V7,20:$V8,21:$V9,22:9,23:$Va,24:11,25:5,26:$Vb,28:10,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{6:6,7:$V1,8:$V2,9:20,11:172,13:7,14:$V3,15:$V4,16:$V5,17:$V6,18:8,19:$V7,20:$V8,21:$V9,22:9,23:$Va,24:11,25:5,26:$Vb,28:10,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,9:173,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,9:174,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,20:$V8,29:175,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},o($Vs,[2,60]),{20:$VQ,68:127,82:$Vn,90:176},o($VV,[2,93]),o($Vs,[2,90]),o($Vs,[2,100]),{25:177,26:$Vb},{20:[1,178]},{94:[1,179]},o($VS,[2,82]),o($VS,[2,83]),o($VU,[2,99]),o($Vq,[2,2],{12:[1,180]}),o($Vr,[2,4]),{16:[1,181]},{10:[1,182]},o($Vs,[2,27]),o($Vs,[2,95]),o($Vs,[2,101]),o($VX,[2,104]),{8:$V2,9:183,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{6:6,7:$V1,8:$V2,9:20,11:184,13:7,14:$V3,15:$V4,16:$V5,17:$V6,18:8,19:$V7,20:$V8,21:$V9,22:9,23:$Va,24:11,25:5,26:$Vb,28:10,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{8:$V2,9:185,20:$V8,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},{16:[1,186]},o($Vs,[2,102]),o($Vr,[2,3]),{10:[1,187]},o($Vr,[2,6]),{6:6,7:$V1,8:$V2,9:20,11:188,13:7,14:$V3,15:$V4,16:$V5,17:$V6,18:8,19:$V7,20:$V8,21:$V9,22:9,23:$Va,24:11,25:5,26:$Vb,28:10,29:22,30:23,31:24,33:25,36:28,38:32,40:40,44:47,49:55,50:$Vc,51:$Vd,52:56,56:57,58:$Ve,59:26,60:27,61:29,62:30,63:31,65:$Vf,67:34,68:35,69:36,70:41,71:42,72:43,73:44,74:$Vg,75:$Vh,76:$Vi,77:$Vj,78:$Vk,79:$Vl,80:$Vm,82:$Vn,91:$Vo,93:$Vp},o($Vr,[2,5])],
2576 defaultActions: {3:[2,1],97:[2,84],98:[2,85],99:[2,86]},
2577 parseError: function parseError (str, hash) {
2578     if (hash.recoverable) {
2579         this.trace(str);
2580     } else {
2581         var error = new Error(str);
2582         error.hash = hash;
2583         throw error;
2584     }
2585 },
2586 parse: function parse(input) {
2587     var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
2588     var args = lstack.slice.call(arguments, 1);
2589     var lexer = Object.create(this.lexer);
2590     var sharedState = { yy: {} };
2591     for (var k in this.yy) {
2592         if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
2593             sharedState.yy[k] = this.yy[k];
2594         }
2595     }
2596     lexer.setInput(input, sharedState.yy);
2597     sharedState.yy.lexer = lexer;
2598     sharedState.yy.parser = this;
2599     if (typeof lexer.yylloc == 'undefined') {
2600         lexer.yylloc = {};
2601     }
2602     var yyloc = lexer.yylloc;
2603     lstack.push(yyloc);
2604     var ranges = lexer.options && lexer.options.ranges;
2605     if (typeof sharedState.yy.parseError === 'function') {
2606         this.parseError = sharedState.yy.parseError;
2607     } else {
2608         this.parseError = Object.getPrototypeOf(this).parseError;
2609     }
2610     function popStack(n) {
2611         stack.length = stack.length - 2 * n;
2612         vstack.length = vstack.length - n;
2613         lstack.length = lstack.length - n;
2614     }
2615     _token_stack:
2616         var lex = function () {
2617             var token;
2618             token = lexer.lex() || EOF;
2619             if (typeof token !== 'number') {
2620                 token = self.symbols_[token] || token;
2621             }
2622             return token;
2623         };
2624     var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
2625     while (true) {
2626         state = stack[stack.length - 1];
2627         if (this.defaultActions[state]) {
2628             action = this.defaultActions[state];
2629         } else {
2630             if (symbol === null || typeof symbol == 'undefined') {
2631                 symbol = lex();
2632             }
2633             action = table[state] && table[state][symbol];
2634         }
2635                     if (typeof action === 'undefined' || !action.length || !action[0]) {
2636                 var errStr = '';
2637                 expected = [];
2638                 for (p in table[state]) {
2639                     if (this.terminals_[p] && p > TERROR) {
2640                         expected.push('\'' + this.terminals_[p] + '\'');
2641                     }
2642                 }
2643                 if (lexer.showPosition) {
2644                     errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
2645                 } else {
2646                     errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
2647                 }
2648                 this.parseError(errStr, {
2649                     text: lexer.match,
2650                     token: this.terminals_[symbol] || symbol,
2651                     line: lexer.yylineno,
2652                     loc: yyloc,
2653                     expected: expected
2654                 });
2655             }
2656         if (action[0] instanceof Array && action.length > 1) {
2657             throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
2658         }
2659         switch (action[0]) {
2660         case 1:
2661             stack.push(symbol);
2662             vstack.push(lexer.yytext);
2663             lstack.push(lexer.yylloc);
2664             stack.push(action[1]);
2665             symbol = null;
2666             if (!preErrorSymbol) {
2667                 yyleng = lexer.yyleng;
2668                 yytext = lexer.yytext;
2669                 yylineno = lexer.yylineno;
2670                 yyloc = lexer.yylloc;
2671                 if (recovering > 0) {
2672                     recovering--;
2673                 }
2674             } else {
2675                 symbol = preErrorSymbol;
2676                 preErrorSymbol = null;
2677             }
2678             break;
2679         case 2:
2680             len = this.productions_[action[1]][1];
2681             yyval.$ = vstack[vstack.length - len];
2682             yyval._$ = {
2683                 first_line: lstack[lstack.length - (len || 1)].first_line,
2684                 last_line: lstack[lstack.length - 1].last_line,
2685                 first_column: lstack[lstack.length - (len || 1)].first_column,
2686                 last_column: lstack[lstack.length - 1].last_column
2687             };
2688             if (ranges) {
2689                 yyval._$.range = [
2690                     lstack[lstack.length - (len || 1)].range[0],
2691                     lstack[lstack.length - 1].range[1]
2692                 ];
2693             }
2694             r = this.performAction.apply(yyval, [
2695                 yytext,
2696                 yyleng,
2697                 yylineno,
2698                 sharedState.yy,
2699                 action[1],
2700                 vstack,
2701                 lstack
2702             ].concat(args));
2703             if (typeof r !== 'undefined') {
2704                 return r;
2705             }
2706             if (len) {
2707                 stack = stack.slice(0, -1 * len * 2);
2708                 vstack = vstack.slice(0, -1 * len);
2709                 lstack = lstack.slice(0, -