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 = {};
319                             }
320                             if (attr.name === undefined && attr.id === undefined) {
321                                 attr.name = (that.lhs[that.scope.id] !== 0 ? that.lhs[that.scope.id] : '');
322                             }
323                             return that.board.create(vname, parameters, attr);
324                         };
325                     }(this));
326 
327                     f.creator = true;
328                     _ccache[this.board.id + vname] = f;
329                 }
330 
331                 return f;
332             };
333 
334             r.clearCache = function () {
335                 _ccache = {};
336             };
337 
338             return r;
339         }()),
340 
341         /**
342          * Assigns a value to a variable in the current scope.
343          * @param {String} vname Variable name
344          * @param value Anything
345          * @see JXG.JessieCode#sstack
346          * @see JXG.JessieCode#scope
347          */
348         letvar: function (vname, value) {
349             if (this.builtIn[vname]) {
350                 this._warn('"' + vname + '" is a predefined value.');
351             }
352 
353             this.scope.locals[vname] = value;
354         },
355 
356         /**
357          * Checks if the given variable name can be found in the current scope chain.
358          * @param {String} vname
359          * @returns {Object} A reference to the scope object the variable can be found in or null if it can't be found.
360          */
361         isLocalVariable: function (vname) {
362             var s = this.scope;
363 
364             while (s !== null) {
365                 if (Type.exists(s.locals[vname])) {
366                     return s;
367                 }
368 
369                 s = s.previous;
370             }
371 
372             return null;
373         },
374 
375         /**
376          * Checks if the given variable name is a parameter in any scope from the current to the global scope.
377          * @param {String} vname
378          * @returns {Object} A reference to the scope object that contains the variable in its arg list.
379          */
380         isParameter: function (vname) {
381             var s = this.scope;
382 
383             while (s !== null) {
384                 if (Type.indexOf(s.args, vname) > -1) {
385                     return s;
386                 }
387 
388                 s = s.previous;
389             }
390 
391             return null;
392         },
393 
394         /**
395          * Checks if the given variable name is a valid creator method.
396          * @param {String} vname
397          * @returns {Boolean}
398          */
399         isCreator: function (vname) {
400             // check for an element with this name
401             return !!JXG.elements[vname];
402         },
403 
404         /**
405          * Checks if the given variable identifier is a valid member of the JavaScript Math Object.
406          * @param {String} vname
407          * @returns {Boolean}
408          */
409         isMathMethod: function (vname) {
410             return vname !== 'E' && !!Math[vname];
411         },
412 
413         /**
414          * Returns true if the given identifier is a builtIn variable/function.
415          * @param {String} vname
416          * @returns {Boolean}
417          */
418         isBuiltIn: function (vname) {
419             return !!this.builtIn[vname];
420         },
421 
422         /**
423          * Looks up the value of the given variable.
424          * @param {String} vname Name of the variable
425          * @param {Boolean} [local=false] Only look up the internal symbol table and don't look for
426          * the <tt>vname</tt> in Math or the element list.
427          */
428         getvar: function (vname, local) {
429             var s;
430 
431             local = Type.def(local, false);
432 
433             s = this.isLocalVariable(vname);
434             if (s !== null) {
435                 return s.locals[vname];
436             }
437 
438             // check for an element with this name
439             if (this.isCreator(vname)) {
440                 return this.creator(vname);
441             }
442 
443             if (this.isBuiltIn(vname)) {
444                 return this.builtIn[vname];
445             }
446 
447             if (this.isMathMethod(vname)) {
448                 return Math[vname];
449             }
450 
451             if (!local) {
452                 s = this.board.select(vname);
453                 if (s !== vname) {
454                     return s;
455                 }
456             }
457         },
458 
459         /**
460          * Look up the value of a local variable.
461          * @param {string} vname
462          * @returns {*}
463          */
464         resolve: function (vname) {
465             var s = this.scope;
466 
467             while (s !== null) {
468                 if (Type.exists(s.locals[vname])) {
469                     return s.locals[vname];
470                 }
471 
472                 s = s.previous;
473             }
474         },
475 
476         /**
477          * TODO this needs to be called from JS and should not generate JS code
478          * Looks up a variable identifier in various tables and generates JavaScript code that could be eval'd to get the value.
479          * @param {String} vname Identifier
480          * @param {Boolean} [local=false] Don't resolve ids and names of elements
481          * @param {Boolean} [withProps=false]
482          */
483         getvarJS: function (vname, local, withProps) {
484             var s, r = '', re;
485 
486             local = Type.def(local, false);
487             withProps = Type.def(withProps, false);
488 
489             s = this.isParameter(vname);
490             if (s !== null) {
491                 return vname;
492             }
493 
494             s = this.isLocalVariable(vname);
495             if (s !== null && !withProps) {
496                 return '$jc$.resolve(\'' + vname + '\')';
497             }
498 
499             // check for an element with this name
500             if (this.isCreator(vname)) {
501                 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])); })';
502             }
503 
504             if (withProps) {
505                 this._error('Syntax error (attribute values are allowed with element creators only)');
506             }
507 
508             if (this.isBuiltIn(vname)) {
509                 // If src does not exist, it is a number. In that case, just return the value.
510                 r = this.builtIn[vname].src || this.builtIn[vname];
511 
512                 // Get the "real" name of the function
513                 if (Type.isNumber(r)) {
514                     return r;
515                 }
516                 // Search a JSXGraph object in board
517                 if (r.match(/board\.select/)) {
518                     return r;
519                 }
520 
521                 vname = r.split('.').pop();
522                 if (Type.exists(this.board.mathLib)) {
523                     // Handle builtin case: ln(x) -> Math.log
524                     re = new RegExp('^Math\.' + vname);
525                     if (re.exec(r) !== null) {
526                         return r.replace(re, '$jc$.board.mathLib.' + vname);
527                     }
528                 }
529                 if (Type.exists(this.board.mathLibJXG)) {
530                     // Handle builtin case: factorial(x) -> JXG.Math.factorial
531                     re = new RegExp('^JXG\.Math\.');
532                     if (re.exec(r) !== null) {
533                         return r.replace(re, '$jc$.board.mathLibJXG.');
534                     }
535                     return r;
536                 }
537                 return r;
538 
539                 // return this.builtIn[vname].src || this.builtIn[vname];
540             }
541 
542             if (this.isMathMethod(vname)) {
543                 return '$jc$.board.mathLib.' + vname;
544 //                return 'Math.' + vname;
545             }
546 
547             // if (!local) {
548             //     if (Type.isId(this.board, vname)) {
549             //         r = '$jc$.board.objects[\'' + vname + '\']';
550             //     } else if (Type.isName(this.board, vname)) {
551             //         r = '$jc$.board.elementsByName[\'' + vname + '\']';
552             //     } else if (Type.isGroup(this.board, vname)) {
553             //         r = '$jc$.board.groups[\'' + vname + '\']';
554             //     }
555 
556             //     return r;
557             // }
558             if (!local) {
559                 if (Type.isId(this.board, vname)) {
560                     r = '$jc$.board.objects[\'' + vname + '\']';
561                     if (this.board.objects[vname].elType === 'slider') {
562                         r += '.Value()';
563                     }
564                 } else if (Type.isName(this.board, vname)) {
565                     r = '$jc$.board.elementsByName[\'' + vname + '\']';
566                     if (this.board.elementsByName[vname].elType === 'slider') {
567                         r += '.Value()';
568                     }
569                 } else if (Type.isGroup(this.board, vname)) {
570                     r = '$jc$.board.groups[\'' + vname + '\']';
571                 }
572 
573                 return r;
574             }
575 
576             return '';
577         },
578 
579         /**
580          * Adds the property <tt>isMap</tt> to a function and sets it to true.
581          * @param {function} f
582          * @returns {function}
583          */
584         makeMap: function (f) {
585             f.isMap = true;
586 
587             return f;
588         },
589 
590         functionCodeJS: function (node) {
591             var p = node.children[0].join(', '),
592                 bo = '',
593                 bc = '';
594 
595             if (node.value === 'op_map') {
596                 bo = '{ return  ';
597                 bc = ' }';
598             }
599 
600             return 'function (' + p + ') {\n' +
601                     'var $oldscope$ = $jc$.scope;\n' +
602                     '$jc$.scope = $jc$.scopes[' + this.scope.id + '];\n' +
603                     'var r = (function () ' + bo + this.compile(node.children[1], true) + bc + ')();\n' +
604                     '$jc$.scope = $oldscope$;\n' +
605                     'return r;\n' +
606                 '}';
607         },
608 
609         /**
610          * Converts a node type <tt>node_op</tt> and value <tt>op_map</tt> or <tt>op_function</tt> into a executable
611          * function.
612          * @param {Object} node
613          * @returns {function}
614          */
615         defineFunction: function (node) {
616             var fun, i,
617                 list = node.children[0],
618                 scope = this.pushScope(list);
619 
620             if (this.board.options.jc.compile) {
621                 this.isLHS = false;
622 
623                 // we currently need to put the parameters into the local scope
624                 // until the compiled JS variable lookup code is fixed
625                 for (i = 0; i < list.length; i++) {
626                     scope.locals[list[i]] = list[i];
627                 }
628 
629                 this.replaceNames(node.children[1]);
630 
631                 /** @ignore */
632                 fun = (function ($jc$) {
633                     var fun,
634                         str = 'var f = ' + $jc$.functionCodeJS(node) + '; f;';
635 
636                     try {
637                         // yeah, eval is evil, but we don't have much choice here.
638                         // the str is well defined and there is no user input in it that we didn't check before
639 
640                         /*jslint evil:true*/
641                         fun = eval(str);
642                         /*jslint evil:false*/
643 
644                         return fun;
645                     } catch (e) {
646                         $jc$._warn('error compiling function\n\n' + str + '\n\n' + e.toString());
647                         return function () {};
648                     }
649                 }(this));
650 
651                 // clean up scope
652                 this.popScope();
653             } else {
654                 /** @ignore */
655                 fun = (function (_pstack, that, id) {
656                     return function () {
657                         var r, oldscope;
658 
659                         oldscope = that.scope;
660                         that.scope = that.scopes[id];
661 
662                         for (r = 0; r < _pstack.length; r++) {
663                             that.scope.locals[_pstack[r]] = arguments[r];
664                         }
665 
666                         r = that.execute(node.children[1]);
667                         that.scope = oldscope;
668 
669                         return r;
670                     };
671                 }(list, this, scope.id));
672             }
673 
674             fun.node = node;
675             fun.scope = scope;
676             fun.toJS = fun.toString;
677             fun.toString = (function (_that) {
678                 return function () {
679                     return _that.compile(_that.replaceIDs(Type.deepCopy(node)));
680                 };
681             }(this));
682 
683             fun.deps = {};
684             this.collectDependencies(node.children[1], fun.deps);
685 
686             return fun;
687         },
688 
689         /**
690          * Merge all attribute values given with an element creator into one object.
691          * @param {Object} o An arbitrary number of objects
692          * @returns {Object} All given objects merged into one. If properties appear in more (case sensitive) than one
693          * object the last value is taken.
694          */
695         mergeAttributes: function (o) {
696             var i, attr = {};
697 
698             for (i = 0; i < arguments.length; i++) {
699                 attr = Type.deepCopy(attr, arguments[i], true);
700             }
701 
702             return attr;
703         },
704 
705         /**
706          * Sets the property <tt>what</tt> of <tt>o</tt> to <tt>value</tt>
707          * @param {JXG.Point|JXG.Text} o
708          * @param {String} what
709          * @param value
710          */
711         setProp: function (o, what, value) {
712             var par = {}, x, y;
713 
714             if (o.elementClass === Const.OBJECT_CLASS_POINT && (what === 'X' || what === 'Y')) {
715                 // set coords
716 
717                 what = what.toLowerCase();
718 
719                 // we have to deal with three cases here:
720                 // o.isDraggable && typeof value === number:
721                 //   stay draggable, just set the new coords (e.g. via moveTo)
722                 // o.isDraggable && typeof value === function:
723                 //   convert to !o.isDraggable, set the new coords via o.addConstraint()
724                 // !o.isDraggable:
725                 //   stay !o.isDraggable, update the given coord by overwriting X/YEval
726 
727                 if (o.isDraggable && typeof value === 'number') {
728                     x = what === 'x' ? value : o.X();
729                     y = what === 'y' ? value : o.Y();
730 
731                     o.setPosition(Const.COORDS_BY_USER, [x, y]);
732                 } else if (o.isDraggable && (typeof value === 'function' || typeof value === 'string')) {
733                     x = what === 'x' ? value : o.coords.usrCoords[1];
734                     y = what === 'y' ? value : o.coords.usrCoords[2];
735 
736                     o.addConstraint([x, y]);
737                 } else if (!o.isDraggable) {
738                     x = what === 'x' ? value : o.XEval.origin;
739                     y = what === 'y' ? value : o.YEval.origin;
740 
741                     o.addConstraint([x, y]);
742                 }
743 
744                 this.board.update();
745             } else if (o.elementClass === Const.OBJECT_CLASS_TEXT && (what === 'X' || what === 'Y')) {
746                 if (typeof value === 'number') {
747                     o[what] = function () { return value; };
748                 } else if (typeof value === 'function') {
749                     o.isDraggable = false;
750                     o[what] = value;
751                 } else if (typeof value === 'string') {
752                     o.isDraggable = false;
753                     o[what] = Type.createFunction(value, this.board, null, true);
754                     o[what + 'jc'] = value;
755                 }
756 
757                 o[what].origin = value;
758 
759                 this.board.update();
760             } else if (o.type && o.elementClass && o.visProp) {
761                 if (Type.exists(o[o.methodMap[what]]) && typeof o[o.methodMap[what]] !== 'function') {
762                     o[o.methodMap[what]] = value;
763                 } else {
764                     par[what] = value;
765                     o.setAttribute(par);
766                 }
767             } else {
768                 o[what] = value;
769             }
770         },
771 
772         /**
773          * Generic method to parse JessieCode.
774          * This consists of generating an AST with parser.parse,
775          * apply simplifying rules from CA and
776          * manipulate the AST according to the second parameter "cmd".
777          * @param  {String} code      JessieCode code to be parsed
778          * @param  {String} cmd       Type of manipulation to be done with AST
779          * @param {Boolean} [geonext=false] Geonext compatibility mode.
780          * @param {Boolean} dontstore If false, the code string is stored in this.code.
781          * @return {Object}           Returns result of computation as directed in cmd.
782          */
783         _genericParse:  function (code, cmd, geonext, dontstore) {
784             var i, setTextBackup, ast, result,
785                 ccode = code.replace(/\r\n/g, '\n').split('\n'),
786                 cleaned = [];
787 
788             if (!dontstore) {
789                 this.code += code + '\n';
790             }
791 
792             if (Text) {
793                 setTextBackup = Text.Text.prototype.setText;
794                 Text.Text.prototype.setText = Text.Text.prototype.setTextJessieCode;
795             }
796 
797             try {
798                 if (!Type.exists(geonext)) {
799                     geonext = false;
800                 }
801 
802                 for (i = 0; i < ccode.length; i++) {
803                     if (geonext) {
804                         ccode[i] = JXG.GeonextParser.geonext2JS(ccode[i], this.board);
805                     }
806                     cleaned.push(ccode[i]);
807                 }
808 
809                 code = cleaned.join('\n');
810                 ast = parser.parse(code);
811                 if (this.CA) {
812                     ast = this.CA.expandDerivatives(ast, null, ast);
813                     ast = this.CA.removeTrivialNodes(ast);
814                 }
815                 switch (cmd) {
816                     case 'parse':
817                         result = this.execute(ast);
818                         break;
819                     case 'manipulate':
820                         result = this.compile(ast);
821                         break;
822                     case 'getAst':
823                         result = ast;
824                         break;
825                     default:
826                         result = false;
827                 }
828             } catch (e) {  // catch is mandatory in old IEs
829                 // console.log(e);
830                 // We throw the error again,
831                 // so the user can catch it.
832                 throw e;
833             } finally {
834                 // make sure the original text method is back in place
835                 if (Text) {
836                     Text.Text.prototype.setText = setTextBackup;
837                 }
838             }
839 
840             return result;
841         },
842 
843         /**
844          * Parses JessieCode.
845          * This consists of generating an AST with parser.parse, apply simplifying rules
846          * from CA and executing the ast by calling this.execute(ast).
847          *
848          * @param {String} code             JessieCode code to be parsed
849          * @param {Boolean} [geonext=false] Geonext compatibility mode.
850          * @param {Boolean} dontstore       If false, the code string is stored in this.code.
851          * @return {Object}                 Parse JessieCode code and execute it.
852          */
853         parse: function (code, geonext, dontstore) {
854             return this._genericParse(code, 'parse', geonext, dontstore);
855         },
856 
857         /**
858          * Manipulate JessieCode.
859          * This consists of generating an AST with parser.parse,
860          * apply simlifying rules from CA
861          * and compile the AST back to JessieCode.
862          *
863          * @param {String} code             JessieCode code to be parsed
864          * @param {Boolean} [geonext=false] Geonext compatibility mode.
865          * @param {Boolean} dontstore       If false, the code string is stored in this.code.
866          * @return {String}                 Simplified JessieCode code
867          */
868         manipulate: function (code, geonext, dontstore) {
869             return this._genericParse(code, 'manipulate', geonext, dontstore);
870         },
871 
872         /**
873          * Get abstract syntax tree (AST) from JessieCode code.
874          * This consists of generating an AST with parser.parse.
875          *
876          * @param {String} code
877          * @param {Boolean} [geonext=false] Geonext compatibility mode.
878          * @param {Boolean} dontstore
879          * @return {Node}  AST
880          */
881         getAST: function (code, geonext, dontstore) {
882             return this._genericParse(code, 'getAst', geonext, dontstore);
883         },
884 
885         /**
886          * Parses a JessieCode snippet, e.g. "3+4", and wraps it into a function, if desired.
887          * @param {String} code A small snippet of JessieCode. Must not be an assignment.
888          * @param {Boolean} funwrap If true, the code is wrapped in a function.
889          * @param {String} varname Name of the parameter(s)
890          * @param {Boolean} [geonext=false] Geonext compatibility mode.
891          */
892         snippet: function (code, funwrap, varname, geonext) {
893             var c;
894 
895             funwrap = Type.def(funwrap, true);
896             varname = Type.def(varname, '');
897             geonext = Type.def(geonext, false);
898 
899             c = (funwrap ? ' function (' + varname + ') { return ' : '') + code + (funwrap ? '; }' : '') + ';';
900 
901             return this.parse(c, geonext, true);
902         },
903 
904         /**
905          * Traverses through the given subtree and changes all values of nodes with the replaced flag set by
906          * {@link JXG.JessieCode#replaceNames} to the name of the element (if not empty).
907          * @param {Object} node
908          */
909         replaceIDs: function (node) {
910             var i, v;
911 
912             if (node.replaced) {
913                 // these children exist, if node.replaced is set.
914                 v = this.board.objects[node.children[1][0].value];
915 
916                 if (Type.exists(v) && v.name !== "") {
917                     node.type = 'node_var';
918                     node.value = v.name;
919 
920                     // maybe it's not necessary, but just to be sure that everything is cleaned up we better delete all
921                     // children and the replaced flag
922                     node.children.length = 0;
923                     delete node.replaced;
924                 }
925             }
926 
927             if (node.children) {
928                 // assignments are first evaluated on the right hand side
929                 for (i = node.children.length; i > 0; i--) {
930                     if (Type.exists(node.children[i - 1])) {
931                         node.children[i - 1] = this.replaceIDs(node.children[i - 1]);
932                     }
933 
934                 }
935             }
936 
937             return node;
938         },
939 
940         /**
941          * Traverses through the given subtree and changes all elements referenced by names through referencing them by ID.
942          * An identifier is only replaced if it is not found in all scopes above the current scope and if it
943          * has not been blacklisted within the codeblock determined by the given subtree.
944          * @param {Object} node
945          */
946         replaceNames: function (node) {
947             var i, v;
948 
949             v = node.value;
950 
951             // we are interested only in nodes of type node_var and node_op > op_lhs.
952             // currently, we are not checking if the id is a local variable. in this case, we're stuck anyway.
953 
954             if (node.type === 'node_op' && v === 'op_lhs' && node.children.length === 1) {
955                 this.isLHS = true;
956             } else if (node.type === 'node_var') {
957                 if (this.isLHS) {
958                     this.letvar(v, true);
959                 } else if (!Type.exists(this.getvar(v, true)) && Type.exists(this.board.elementsByName[v])) {
960                     node = this.createReplacementNode(node);
961                 }
962             }
963 
964             if (node.children) {
965                 // assignments are first evaluated on the right hand side
966                 for (i = node.children.length; i > 0; i--) {
967                     if (Type.exists(node.children[i - 1])) {
968                         node.children[i - 1] = this.replaceNames(node.children[i - 1]);
969                     }
970                 }
971             }
972 
973             if (node.type === 'node_op' && node.value === 'op_lhs' && node.children.length === 1) {
974                 this.isLHS = false;
975             }
976 
977             return node;
978         },
979 
980         /**
981          * Replaces node_var nodes with node_op>op_execfun nodes, calling the internal $() function with the id of the
982          * element accessed by the node_var node.
983          * @param {Object} node
984          * @returns {Object} op_execfun node
985          */
986         createReplacementNode: function (node) {
987             var v = node.value,
988                 el = this.board.elementsByName[v];
989 
990             node = this.createNode('node_op', 'op_execfun',
991                 this.createNode('node_var', '$'),
992                 [this.createNode('node_str', el.id)]);
993 
994             node.replaced = true;
995 
996             return node;
997         },
998 
999         /**
1000          * Search the parse tree below <tt>node</tt> for <em>stationary</em> dependencies, i.e. dependencies hard coded into
1001          * the function.
1002          * @param {Object} node
1003          * @param {Object} result An object where the referenced elements will be stored. Access key is their id.
1004          */
1005         collectDependencies: function (node, result) {
1006             var i, v, e, le;
1007 
1008             if (Type.isArray(node)) {
1009                 le = node.length;
1010                 for (i = 0; i < le; i++) {
1011                     this.collectDependencies(node[i], result);
1012                 }
1013                 return;
1014             }
1015 
1016             v = node.value;
1017 
1018             if (node.type === 'node_var') {
1019                 e = this.getvar(v);
1020                 if (e && e.visProp && e.type && e.elementClass && e.id) {
1021                     result[e.id] = e;
1022                 }
1023             }
1024 
1025             // the $()-function-calls are special because their parameter is given as a string, not as a node_var.
1026             if (node.type === 'node_op' && node.value === 'op_execfun' &&
1027                 node.children.length > 1 && node.children[0].value === '$' &&
1028                 node.children[1].length > 0) {
1029 
1030                 e = node.children[1][0].value;
1031                 result[e] = this.board.objects[e];
1032             }
1033 
1034             if (node.children) {
1035                 for (i = node.children.length; i > 0; i--) {
1036                     if (Type.exists(node.children[i - 1])) {
1037                         this.collectDependencies(node.children[i - 1], result);
1038                     }
1039 
1040                 }
1041             }
1042         },
1043 
1044         resolveProperty: function (e, v, compile) {
1045             compile = Type.def(compile, false);
1046 
1047             // is it a geometry element or a board?
1048             if (e /*&& e.type && e.elementClass*/ && e.methodMap) {
1049                 // yeah, it is. but what does the user want?
1050                 if (Type.exists(e.subs) && Type.exists(e.subs[v])) {
1051                     // a subelement it is, good sir.
1052                     e = e.subs;
1053                 } else if (Type.exists(e.methodMap[v])) {
1054                     // the user wants to call a method
1055                     v = e.methodMap[v];
1056                 } else {
1057                     // the user wants to change an attribute
1058                     e = e.visProp;
1059                     v = v.toLowerCase();
1060                 }
1061             }
1062 
1063             if (Type.isFunction(e)) {
1064                 this._error('Accessing function properties is not allowed.');
1065             }
1066 
1067             if (!Type.exists(e)) {
1068                 this._error(e + ' is not an object');
1069             }
1070 
1071             if (!Type.exists(e[v])) {
1072                 this._error('unknown property ' + v);
1073             }
1074 
1075             if (compile && typeof e[v] === 'function') {
1076                 return function () { return e[v].apply(e, arguments); };
1077             }
1078 
1079             return e[v];
1080         },
1081 
1082         /**
1083          * Resolves the lefthand side of an assignment operation
1084          * @param node
1085          * @returns {Object} An object with two properties. <strong>o</strong> which contains the object, and
1086          * a string <strong>what</strong> which contains the property name.
1087          */
1088         getLHS: function (node) {
1089             var res;
1090 
1091             if (node.type === 'node_var') {
1092                 res = {
1093                     o: this.scope.locals,
1094                     what: node.value
1095                 };
1096             } else if (node.type === 'node_op' && node.value === 'op_property') {
1097                 res = {
1098                     o: this.execute(node.children[0]),
1099                     what: node.children[1]
1100                 };
1101             } else if (node.type === 'node_op' && node.value === 'op_extvalue') {
1102                 res = {
1103                     o: this.execute(node.children[0]),
1104                     what: this.execute(node.children[1])
1105                 };
1106             } else {
1107                 throw new Error('Syntax error: Invalid left-hand side of assignment.');
1108             }
1109 
1110             return res;
1111         },
1112 
1113         getLHSCompiler: function (node, js) {
1114             var res;
1115 
1116             if (node.type === 'node_var') {
1117                 res = node.value;
1118             } else if (node.type === 'node_op' && node.value === 'op_property') {
1119                 res = [
1120                     this.compile(node.children[0], js),
1121                     "'" + node.children[1] + "'"
1122                 ];
1123             } else if (node.type === 'node_op' && node.value === 'op_extvalue') {
1124                 res = [
1125                     this.compile(node.children[0], js),
1126                     node.children[1].type === 'node_const' ? node.children[1].value : this.compile(node.children[1], js)
1127                 ];
1128             } else {
1129                 throw new Error('Syntax error: Invalid left-hand side of assignment.');
1130             }
1131 
1132             return res;
1133         },
1134 
1135         /**
1136          * Executes a parse subtree.
1137          * @param {Object} node
1138          * @returns {Number|String|Object|Boolean} Something
1139          * @private
1140          */
1141         execute: function (node) {
1142             var ret, v, i, e, l, undef, list, ilist,
1143                 parents = [],
1144                 // exec fun
1145                 fun, attr, sc;
1146 
1147             ret = 0;
1148 
1149             if (!node) {
1150                 return ret;
1151             }
1152 
1153             this.line = node.line;
1154             this.col = node.col;
1155 
1156             switch (node.type) {
1157             case 'node_op':
1158                 switch (node.value) {
1159                 case 'op_none':
1160                     if (node.children[0]) {
1161                         this.execute(node.children[0]);
1162                     }
1163                     if (node.children[1]) {
1164                         ret = this.execute(node.children[1]);
1165                     }
1166                     break;
1167                 case 'op_assign':
1168                     v = this.getLHS(node.children[0]);
1169                     this.lhs[this.scope.id] = v.what;
1170 
1171                     if (v.o.type && v.o.elementClass && v.o.methodMap && v.what === 'label') {
1172                         this._error('Left-hand side of assignment is read-only.');
1173                     }
1174 
1175                     ret = this.execute(node.children[1]);
1176                     if (v.o !== this.scope.locals || (Type.isArray(v.o) && typeof v.what === 'number')) {
1177                         // it is either an array component being set or a property of an object.
1178                         this.setProp(v.o, v.what, ret);
1179                     } else {
1180                         // this is just a local variable inside JessieCode
1181                         this.letvar(v.what, ret);
1182                     }
1183                     this.lhs[this.scope.id] = 0;
1184                     break;
1185                 case 'op_if':
1186                     if (this.execute(node.children[0])) {
1187                         ret = this.execute(node.children[1]);
1188                     }
1189                     break;
1190                 case 'op_conditional':
1191                     // fall through
1192                 case 'op_if_else':
1193                     if (this.execute(node.children[0])) {
1194                         ret = this.execute(node.children[1]);
1195                     } else {
1196                         ret = this.execute(node.children[2]);
1197                     }
1198                     break;
1199                 case 'op_while':
1200                     while (this.execute(node.children[0])) {
1201                         this.execute(node.children[1]);
1202                     }
1203                     break;
1204                 case 'op_do':
1205                     do {
1206                         this.execute(node.children[0]);
1207                     } while (this.execute(node.children[1]));
1208                     break;
1209                 case 'op_for':
1210                     for (this.execute(node.children[0]); this.execute(node.children[1]); this.execute(node.children[2])) {
1211                         this.execute(node.children[3]);
1212                     }
1213                     break;
1214                 case 'op_proplst':
1215                     if (node.children[0]) {
1216                         this.execute(node.children[0]);
1217                     }
1218                     if (node.children[1]) {
1219                         this.execute(node.children[1]);
1220                     }
1221                     break;
1222                 case 'op_emptyobject':
1223                     ret = {};
1224                     break;
1225                 case 'op_proplst_val':
1226                     this.propstack.push({});
1227                     this.propscope++;
1228 
1229                     this.execute(node.children[0]);
1230                     ret = this.propstack[this.propscope];
1231 
1232                     this.propstack.pop();
1233                     this.propscope--;
1234                     break;
1235                 case 'op_prop':
1236                     // child 0: Identifier
1237                     // child 1: Value
1238                     this.propstack[this.propscope][node.children[0]] = this.execute(node.children[1]);
1239                     break;
1240                 case 'op_array':
1241                     ret = [];
1242                     l = node.children[0].length;
1243 
1244                     for (i = 0; i < l; i++) {
1245                         ret.push(this.execute(node.children[0][i]));
1246                     }
1247 
1248                     break;
1249                 case 'op_extvalue':
1250                     ret = this.execute(node.children[0]);
1251                     i = this.execute(node.children[1]);
1252 
1253                     if (typeof i === 'number' && Math.abs(Math.round(i) - i) < Mat.eps) {
1254                         ret = ret[i];
1255                     } else {
1256                         ret = undef;
1257                     }
1258                     break;
1259                 case 'op_return':
1260                     if (this.scope === 0) {
1261                         this._error('Unexpected return.');
1262                     } else {
1263                         return this.execute(node.children[0]);
1264                     }
1265                     break;
1266                 case 'op_map':
1267                     if (!node.children[1].isMath && node.children[1].type !== 'node_var') {
1268                         this._error('execute: In a map only function calls and mathematical expressions are allowed.');
1269                     }
1270 
1271                     /** @ignore */
1272                     fun = this.defineFunction(node);
1273                     fun.isMap = true;
1274 
1275                     ret = fun;
1276                     break;
1277                 case 'op_function':
1278                     // parse the parameter list
1279                     // after this, the parameters are in pstack
1280 
1281                     /** @ignore */
1282                     fun = this.defineFunction(node);
1283                     fun.isMap = false;
1284 
1285                     ret = fun;
1286                     break;
1287                 case 'op_execfun':
1288                     // node.children:
1289                     //   [0]: Name of the function
1290                     //   [1]: Parameter list as a parse subtree
1291                     //   [2]: Properties, only used in case of a create function
1292                     this.dpstack.push([]);
1293                     this.pscope++;
1294 
1295                     // parameter parsing is done below
1296                     list = node.children[1];
1297 
1298                     // parse the properties only if given
1299                     if (Type.exists(node.children[2])) {
1300                         if (node.children[3]) {
1301                             ilist = node.children[2];
1302                             attr = {};
1303 
1304                             for (i = 0; i < ilist.length; i++) {
1305                                 attr = Type.deepCopy(attr, this.execute(ilist[i]), true);
1306                             }
1307                         } else {
1308                             attr = this.execute(node.children[2]);
1309                         }
1310                     }
1311 
1312                     // look up the variables name in the variable table
1313                     fun = this.execute(node.children[0]);
1314 
1315                     // determine the scope the function wants to run in
1316                     if (fun && fun.sc) {
1317                         sc = fun.sc;
1318                     } else {
1319                         sc = this;
1320                     }
1321 
1322                     if (!fun.creator && Type.exists(node.children[2])) {
1323                         this._error('Unexpected value. Only element creators are allowed to have a value after the function call.');
1324                     }
1325 
1326                     // interpret ALL the parameters
1327                     for (i = 0; i < list.length; i++) {
1328                         parents[i] = this.execute(list[i]);
1329                         //parents[i] = Type.evalSlider(this.execute(list[i]));
1330                         this.dpstack[this.pscope].push({
1331                             line: node.children[1][i].line,
1332                             // SketchBin currently works only if the last column of the
1333                             // parent position is taken. This is due to how I patched JS/CC
1334                             // to count the lines and columns. So, ecol will do for now
1335                             col: node.children[1][i].ecol
1336                         });
1337                     }
1338 
1339                     // check for the function in the variable table
1340                     if (typeof fun === 'function' && !fun.creator) {
1341                         ret = fun.apply(sc, parents);
1342                     } else if (typeof fun === 'function' && !!fun.creator) {
1343                         e = this.line;
1344 
1345                         // creator methods are the only ones that take properties, hence this special case
1346                         try {
1347                             ret = fun(parents, attr);
1348                             ret.jcLineStart = e;
1349                             ret.jcLineEnd = node.eline;
1350 
1351                             for (i = e; i <= node.line; i++) {
1352                                 this.lineToElement[i] = ret;
1353                             }
1354 
1355                             ret.debugParents = this.dpstack[this.pscope];
1356                         } catch (ex) {
1357                             this._error(ex.toString());
1358                         }
1359                     } else {
1360                         this._error('Function \'' + fun + '\' is undefined.');
1361                     }
1362 
1363                     // clear parameter stack
1364                     this.dpstack.pop();
1365                     this.pscope--;
1366                     break;
1367                 case 'op_property':
1368                     e = this.execute(node.children[0]);
1369                     v = node.children[1];
1370 
1371                     ret = this.resolveProperty(e, v, false);
1372 
1373                     // set the scope, in case this is a method the user wants to call
1374                     if (Type.exists(ret)) {
1375                         ret.sc = e;
1376                     }
1377 
1378                     break;
1379                 case 'op_use':
1380                     this._warn('Use of the \'use\' operator is deprecated.');
1381                     this.use(node.children[0].toString());
1382                     break;
1383                 case 'op_delete':
1384                     this._warn('Use of the \'delete\' operator is deprecated. Please use the remove() function.');
1385                     v = this.getvar(node.children[0]);
1386                     ret = this.del(v);
1387                     break;
1388                 case 'op_eq':
1389                     // == is intentional
1390                     /*jslint eqeq:true*/
1391                     ret = this.execute(node.children[0]) == this.execute(node.children[1]);
1392                     /*jslint eqeq:false*/
1393                     break;
1394                 case 'op_neq':
1395                     // != is intentional
1396                     /*jslint eqeq:true*/
1397                     ret = this.execute(node.children[0]) != this.execute(node.children[1]);
1398                     /*jslint eqeq:true*/
1399                     break;
1400                 case 'op_approx':
1401                     ret = Math.abs(this.execute(node.children[0]) - this.execute(node.children[1])) < Mat.eps;
1402                     break;
1403                 case 'op_gt':
1404                     ret = this.execute(node.children[0]) > this.execute(node.children[1]);
1405                     break;
1406                 case 'op_lt':
1407                     ret = this.execute(node.children[0]) < this.execute(node.children[1]);
1408                     break;
1409                 case 'op_geq':
1410                     ret = this.execute(node.children[0]) >= this.execute(node.children[1]);
1411                     break;
1412                 case 'op_leq':
1413                     ret = this.execute(node.children[0]) <= this.execute(node.children[1]);
1414                     break;
1415                 case 'op_or':
1416                     ret = this.execute(node.children[0]) || this.execute(node.children[1]);
1417                     break;
1418                 case 'op_and':
1419                     ret = this.execute(node.children[0]) && this.execute(node.children[1]);
1420                     break;
1421                 case 'op_not':
1422                     ret = !this.execute(node.children[0]);
1423                     break;
1424                 case 'op_add':
1425                     ret = this.add(this.execute(node.children[0]), this.execute(node.children[1]));
1426                     break;
1427                 case 'op_sub':
1428                     ret = this.sub(this.execute(node.children[0]), this.execute(node.children[1]));
1429                     break;
1430                 case 'op_div':
1431                     ret = this.div(this.execute(node.children[0]), this.execute(node.children[1]));
1432                     break;
1433                 case 'op_mod':
1434                     // use mathematical modulo, JavaScript implements the symmetric modulo.
1435                     ret = this.mod(this.execute(node.children[0]), this.execute(node.children[1]), true);
1436                     break;
1437                 case 'op_mul':
1438                     ret = this.mul(this.execute(node.children[0]), this.execute(node.children[1]));
1439                     break;
1440                 case 'op_exp':
1441                     ret = this.pow(this.execute(node.children[0]),  this.execute(node.children[1]));
1442                     break;
1443                 case 'op_neg':
1444                     ret = this.neg(this.execute(node.children[0]));
1445                     break;
1446                 }
1447                 break;
1448 
1449             case 'node_var':
1450                 ret = this.getvar(node.value);
1451                 break;
1452 
1453             case 'node_const':
1454                 ret = Number(node.value);
1455                 break;
1456 
1457             case 'node_const_bool':
1458                 ret = node.value;
1459                 break;
1460 
1461             case 'node_str':
1462                 //ret = node.value.replace(/\\'/, "'").replace(/\\"/, '"').replace(/\\\\/, '\\');
1463                 /*jslint regexp:true*/
1464                 ret = node.value.replace(/\\(.)/, '$1');
1465                 /*jslint regexp:false*/
1466                 break;
1467             }
1468 
1469             return ret;
1470         },
1471 
1472         /**
1473          * Compiles a parse tree back to JessieCode.
1474          * @param {Object} node
1475          * @param {Boolean} [js=false] Compile either to JavaScript or back to JessieCode (required for the UI).
1476          * @returns Something
1477          * @private
1478          */
1479         compile: function (node, js) {
1480             var e, i, list, scope,
1481                 ret = '';
1482 
1483             if (!Type.exists(js)) {
1484                 js = false;
1485             }
1486 
1487             if (!node) {
1488                 return ret;
1489             }
1490 
1491             switch (node.type) {
1492             case 'node_op':
1493                 switch (node.value) {
1494                 case 'op_none':
1495                     if (node.children[0]) {
1496                         ret = this.compile(node.children[0], js);
1497                     }
1498                     if (node.children[1]) {
1499                         ret += this.compile(node.children[1], js);
1500                     }
1501                     break;
1502                 case 'op_assign':
1503                     //e = this.compile(node.children[0], js);
1504                     if (js) {
1505                         e = this.getLHSCompiler(node.children[0], js);
1506                         if (Type.isArray(e)) {
1507                             ret = '$jc$.setProp(' + e[0] + ', ' + e[1] + ', ' + this.compile(node.children[1], js) + ');\n';
1508                         } else {
1509                             if (this.isLocalVariable(e) !== this.scope) {
1510                                 this.scope.locals[e] = true;
1511                             }
1512                             ret = '$jc$.scopes[' + this.scope.id + '].locals[\'' + e + '\'] = ' + this.compile(node.children[1], js) + ';\n';
1513                         }
1514                     } else {
1515                         e = this.compile(node.children[0]);
1516                         ret = e + ' = ' + this.compile(node.children[1], js) + ';\n';
1517                     }
1518                     break;
1519                 case 'op_if':
1520                     ret = ' if (' + this.compile(node.children[0], js) + ') ' + this.compile(node.children[1], js);
1521                     break;
1522                 case 'op_if_else':
1523                     ret = ' if (' + this.compile(node.children[0], js) + ')' + this.compile(node.children[1], js);
1524                     ret += ' else ' + this.compile(node.children[2], js);
1525                     break;
1526                 case 'op_conditional':
1527                     ret = '((' + this.compile(node.children[0], js) + ')?(' + this.compile(node.children[1], js);
1528                     ret += '):(' + this.compile(node.children[2], js) + '))';
1529                     break;
1530                 case 'op_while':
1531                     ret = ' while (' + this.compile(node.children[0], js) + ') {\n' + this.compile(node.children[1], js) + '}\n';
1532                     break;
1533                 case 'op_do':
1534                     ret = ' do {\n' + this.compile(node.children[0], js) + '} while (' + this.compile(node.children[1], js) + ');\n';
1535                     break;
1536                 case 'op_for':
1537                     //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';
1538                     ret = ' for (' + this.compile(node.children[0], js) +               // Assignment ends with ";"
1539                                     this.compile(node.children[1], js) + '; ' +         // Logical test comes without ";"
1540                                     this.compile(node.children[2], js).slice(0, -2) +   // Counting comes with ";" which has to be removed
1541                                     ') {\n' + this.compile(node.children[3], js) + '\n}\n';
1542                     break;
1543                 case 'op_proplst':
1544                     if (node.children[0]) {
1545                         ret = this.compile(node.children[0], js) + ', ';
1546                     }
1547 
1548                     ret += this.compile(node.children[1], js);
1549                     break;
1550                 case 'op_prop':
1551                     // child 0: Identifier
1552                     // child 1: Value
1553                     ret = node.children[0] + ': ' + this.compile(node.children[1], js);
1554                     break;
1555                 case 'op_emptyobject':
1556                     ret = js ? '{}' : '<< >>';
1557                     break;
1558                 case 'op_proplst_val':
1559                     ret = this.compile(node.children[0], js);
1560                     break;
1561                 case 'op_array':
1562                     list = [];
1563                     for (i = 0; i < node.children[0].length; i++) {
1564                         list.push(this.compile(node.children[0][i], js));
1565                     }
1566                     ret = '[' + list.join(', ') + ']';
1567                     break;
1568                 case 'op_extvalue':
1569                     ret = this.compile(node.children[0], js) + '[' + this.compile(node.children[1], js) + ']';
1570                     break;
1571                 case 'op_return':
1572                     ret = ' return ' + this.compile(node.children[0], js) + ';\n';
1573                     break;
1574                 case 'op_map':
1575                     if (!node.children[1].isMath && node.children[1].type !== 'node_var') {
1576                         this._error('compile: In a map only function calls and mathematical expressions are allowed.');
1577                     }
1578 
1579                     list = node.children[0];
1580                     if (js) {
1581                         ret = ' $jc$.makeMap(function (' + list.join(', ') + ') { return ' + this.compile(node.children[1], js) + '; })';
1582                     } else {
1583                         ret = 'map (' + list.join(', ') + ') -> ' + this.compile(node.children[1], js);
1584                     }
1585 
1586                     break;
1587                 case 'op_function':
1588                     list = node.children[0];
1589                     scope = this.pushScope(list);
1590                     if (js) {
1591                         ret = this.functionCodeJS(node);
1592                     } else {
1593                         ret = ' function (' + list.join(', ') + ') ' + this.compile(node.children[1], js);
1594                     }
1595                     this.popScope();
1596                     break;
1597                 case 'op_execfunmath':
1598                     console.log('TODO');
1599                     ret = '-1';
1600                     break;
1601                 case 'op_execfun':
1602                     // parse the properties only if given
1603                     if (node.children[2]) {
1604                         list = [];
1605                         for (i = 0; i < node.children[2].length; i++) {
1606                             list.push(this.compile(node.children[2][i], js));
1607                         }
1608 
1609                         if (js) {
1610                             e = '$jc$.mergeAttributes(' + list.join(', ') + ')';
1611                         }
1612                     }
1613                     node.children[0].withProps = !!node.children[2];
1614                     list = [];
1615                     for (i = 0; i < node.children[1].length; i++) {
1616                         list.push(this.compile(node.children[1][i], js));
1617                     }
1618                     ret = this.compile(node.children[0], js) + '(' + list.join(', ') + (node.children[2] && js ? ', ' + e : '') + ')' + (node.children[2] && !js ? e : '');
1619                     if (js) {
1620                         // Inserting a newline here allows simulataneously
1621                         // - procedural calls like Q.moveTo(...); and
1622                         // - function calls in expressions like log(x) + 1;
1623                         // Problem: procedural calls will not be ended by a semicolon.
1624                         ret += '\n';
1625                     }
1626 
1627                     // save us a function call when compiled to javascript
1628                     if (js && node.children[0].value === '$') {
1629                         ret = '$jc$.board.objects[' + this.compile(node.children[1][0], js) + ']';
1630                     }
1631                     break;
1632                 case 'op_property':
1633                     if (js && node.children[1] !== 'X' && node.children[1] !== 'Y') {
1634                         ret = '$jc$.resolveProperty(' + this.compile(node.children[0], js) + ', \'' + node.children[1] + '\', true)';
1635                     } else {
1636                         ret = this.compile(node.children[0], js) + '.' + node.children[1];
1637                     }
1638                     break;
1639                 case 'op_use':
1640                     this._warn('Use of the \'use\' operator is deprecated.');
1641                     if (js) {
1642                         ret = '$jc$.use(\'';
1643                     } else {
1644                         ret = 'use(\'';
1645                     }
1646 
1647                     ret += node.children[0].toString() + '\');';
1648                     break;
1649                 case 'op_delete':
1650                     this._warn('Use of the \'delete\' operator is deprecated. Please use the remove() function.');
1651                     if (js) {
1652                         ret = '$jc$.del(';
1653                     } else {
1654                         ret = 'remove(';
1655                     }
1656 
1657                     ret += this.compile(node.children[0], js) + ')';
1658                     break;
1659                 case 'op_eq':
1660                     ret = '(' + this.compile(node.children[0], js) + ' === ' + this.compile(node.children[1], js) + ')';
1661                     break;
1662                 case 'op_neq':
1663                     ret = '(' + this.compile(node.children[0], js) + ' !== ' + this.compile(node.children[1], js) + ')';
1664                     break;
1665                 case 'op_approx':
1666                     ret = '(' + this.compile(node.children[0], js) + ' ~= ' + this.compile(node.children[1], js) + ')';
1667                     break;
1668                 case 'op_gt':
1669                     if (js) {
1670                         ret = '$jc$.gt(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1671                     } else {
1672                         ret = '(' + this.compile(node.children[0], js) + ' > ' + this.compile(node.children[1], js) + ')';
1673                     }
1674                     break;
1675                 case 'op_lt':
1676                     if (js) {
1677                         ret = '$jc$.lt(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1678                     } else {
1679                         ret = '(' + this.compile(node.children[0], js) + ' < ' + this.compile(node.children[1], js) + ')';
1680                     }
1681                     break;
1682                 case 'op_geq':
1683                     if (js) {
1684                         ret = '$jc$.geq(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1685                     } else {
1686                         ret = '(' + this.compile(node.children[0], js) + ' >= ' + this.compile(node.children[1], js) + ')';
1687                     }
1688                     break;
1689                 case 'op_leq':
1690                     if (js) {
1691                         ret = '$jc$.leq(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1692                     } else {
1693                         ret = '(' + this.compile(node.children[0], js) + ' <= ' + this.compile(node.children[1], js) + ')';
1694                     }
1695                     break;
1696                 case 'op_or':
1697                     ret = '(' + this.compile(node.children[0], js) + ' || ' + this.compile(node.children[1], js) + ')';
1698                     break;
1699                 case 'op_and':
1700                     ret = '(' + this.compile(node.children[0], js) + ' && ' + this.compile(node.children[1], js) + ')';
1701                     break;
1702                 case 'op_not':
1703                     ret = '!(' + this.compile(node.children[0], js) + ')';
1704                     break;
1705                 case 'op_add':
1706                     if (js) {
1707                         ret = '$jc$.add(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1708                     } else {
1709                         ret = '(' + this.compile(node.children[0], js) + ' + ' + this.compile(node.children[1], js) + ')';
1710                     }
1711                     break;
1712                 case 'op_sub':
1713                     if (js) {
1714                         ret = '$jc$.sub(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1715                     } else {
1716                         ret = '(' + this.compile(node.children[0], js) + ' - ' + this.compile(node.children[1], js) + ')';
1717                     }
1718                     break;
1719                 case 'op_div':
1720                     if (js) {
1721                         ret = '$jc$.div(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1722                     } else {
1723                         ret = '(' + this.compile(node.children[0], js) + ' / ' + this.compile(node.children[1], js) + ')';
1724                     }
1725                     break;
1726                 case 'op_mod':
1727                     if (js) {
1728                         ret = '$jc$.mod(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ', true)';
1729                     } else {
1730                         ret = '(' + this.compile(node.children[0], js) + ' % ' + this.compile(node.children[1], js) + ')';
1731                     }
1732                     break;
1733                 case 'op_mul':
1734                     if (js) {
1735                         ret = '$jc$.mul(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1736                     } else {
1737                         ret = '(' + this.compile(node.children[0], js) + ' * ' + this.compile(node.children[1], js) + ')';
1738                     }
1739                     break;
1740                 case 'op_exp':
1741                     if (js) {
1742                         ret = '$jc$.pow(' + this.compile(node.children[0], js) + ', ' + this.compile(node.children[1], js) + ')';
1743                     } else {
1744                         ret = '(' + this.compile(node.children[0], js) + '^' + this.compile(node.children[1], js) + ')';
1745                     }
1746                     break;
1747                 case 'op_neg':
1748                     if (js) {
1749                         ret = '$jc$.neg(' + this.compile(node.children[0], js) + ')';
1750                     } else {
1751                         ret = '(-' + this.compile(node.children[0], js) + ')';
1752                     }
1753                     break;
1754                 }
1755                 break;
1756 
1757             case 'node_var':
1758                 if (js) {
1759                     ret = this.getvarJS(node.value, false, node.withProps);
1760                 } else {
1761                     ret = node.value;
1762                 }
1763                 break;
1764 
1765             case 'node_const':
1766                 ret = node.value;
1767                 break;
1768 
1769             case 'node_const_bool':
1770                 ret = node.value;
1771                 break;
1772 
1773             case 'node_str':
1774                 ret = '\'' + node.value + '\'';
1775                 break;
1776             }
1777 
1778             if (node.needsBrackets) {
1779                 ret = '{\n' + ret + '\n}\n';
1780             }
1781 
1782             return ret;
1783         },
1784 
1785         /**
1786          * This is used as the global X() function.
1787          * @param {JXG.Point|JXG.Text} e
1788          * @returns {Number}
1789          */
1790         X: function (e) {
1791             return e.X();
1792         },
1793 
1794         /**
1795          * This is used as the global Y() function.
1796          * @param {JXG.Point|JXG.Text} e
1797          * @returns {Number}
1798          */
1799         Y: function (e) {
1800             return e.Y();
1801         },
1802 
1803         /**
1804          * This is used as the global V() function.
1805          * @param {Glider|Slider} e
1806          * @returns {Number}
1807          */
1808         V: function (e) {
1809             return e.Value();
1810         },
1811 
1812         /**
1813          * This is used as the global L() function.
1814          * @param {JXG.Line} e
1815          * @returns {Number}
1816          */
1817         L: function (e) {
1818             return e.L();
1819         },
1820 
1821         /**
1822          * This is used as the global dist() function.
1823          * @param {JXG.Point} p1
1824          * @param {JXG.Point} p2
1825          * @returns {Number}
1826          */
1827         dist: function (p1, p2) {
1828             if (!Type.exists(p1) || !Type.exists(p1.Dist)) {
1829                 this._error('Error: Can\'t calculate distance.');
1830             }
1831 
1832             return p1.Dist(p2);
1833         },
1834 
1835         /**
1836          * + operator implementation
1837          * @param {Number|Array|JXG.Point} a
1838          * @param {Number|Array|JXG.Point} b
1839          * @returns {Number|Array}
1840          */
1841         add: function (a, b) {
1842             var i, len, res;
1843 
1844             a = Type.evalSlider(a);
1845             b = Type.evalSlider(b);
1846 
1847             if (Interval.isInterval(a) || Interval.isInterval(b)) {
1848                 res = Interval.add(a, b);
1849             } else if (Type.isArray(a) && Type.isArray(b)) {
1850                 len = Math.min(a.length, b.length);
1851                 res = [];
1852 
1853                 for (i = 0; i < len; i++) {
1854                     res[i] = a[i] + b[i];
1855                 }
1856             } else if (Type.isNumber(a) && Type.isNumber(b)) {
1857                 res = a + b;
1858             } else if (Type.isString(a) || Type.isString(b)) {
1859                 res = a.toString() + b.toString();
1860             } else {
1861                 this._error('Operation + not defined on operands ' + typeof a + ' and ' + typeof b);
1862             }
1863 
1864             return res;
1865         },
1866 
1867         /**
1868          * - operator implementation
1869          * @param {Number|Array|JXG.Point} a
1870          * @param {Number|Array|JXG.Point} b
1871          * @returns {Number|Array}
1872          */
1873         sub: function (a, b) {
1874             var i, len, res;
1875 
1876             a = Type.evalSlider(a);
1877             b = Type.evalSlider(b);
1878 
1879             if (Interval.isInterval(a) || Interval.isInterval(b)) {
1880                 res = Interval.sub(a, b);
1881             } else if (Type.isArray(a) && Type.isArray(b)) {
1882                 len = Math.min(a.length, b.length);
1883                 res = [];
1884 
1885                 for (i = 0; i < len; i++) {
1886                     res[i] = a[i] - b[i];
1887                 }
1888             } else if (Type.isNumber(a) && Type.isNumber(b)) {
1889                 res = a - b;
1890             } else {
1891                 this._error('Operation - not defined on operands ' + typeof a + ' and ' + typeof b);
1892             }
1893 
1894             return res;
1895         },
1896 
1897         /**
1898          * unary - operator implementation
1899          * @param {Number|Array|JXG.Point} a
1900          * @returns {Number|Array}
1901          */
1902         neg: function (a) {
1903             var i, len, res;
1904 
1905             a = Type.evalSlider(a);
1906 
1907             if (Interval.isInterval(a)) {
1908                 res = Interval.negative(a);
1909             } else if (Type.isArray(a)) {
1910                 len = a.length;
1911                 res = [];
1912 
1913                 for (i = 0; i < len; i++) {
1914                     res[i] = -a[i];
1915                 }
1916             } else if (Type.isNumber(a)) {
1917                 res = -a;
1918             } else {
1919                 this._error('Unary operation - not defined on operand ' + typeof a);
1920             }
1921 
1922             return res;
1923         },
1924 
1925         /**
1926          * Multiplication of vectors and numbers
1927          * @param {Number|Array} a
1928          * @param {Number|Array} b
1929          * @returns {Number|Array} (Inner) product of the given input values.
1930          */
1931         mul: function (a, b) {
1932             var i, len, res;
1933 
1934             a = Type.evalSlider(a);
1935             b = Type.evalSlider(b);
1936 
1937             if (Type.isArray(a) && Type.isNumber(b)) {
1938                 // swap b and a
1939                 i = a;
1940                 a = b;
1941                 b = a;
1942             }
1943 
1944             if (Interval.isInterval(a) || Interval.isInterval(b)) {
1945                 res = Interval.mul(a, b);
1946             } else if (Type.isArray(a) && Type.isArray(b)) {
1947                 len = Math.min(a.length, b.length);
1948                 res = Mat.innerProduct(a, b, len);
1949             } else if (Type.isNumber(a) && Type.isArray(b)) {
1950                 len = b.length;
1951                 res = [];
1952 
1953                 for (i = 0; i < len; i++) {
1954                     res[i] = a * b[i];
1955                 }
1956             } else if (Type.isNumber(a) && Type.isNumber(b)) {
1957                 res = a * b;
1958             } else {
1959                 this._error('Operation * not defined on operands ' + typeof a + ' and ' + typeof b);
1960             }
1961 
1962             return res;
1963         },
1964 
1965         /**
1966          * Implementation of the / operator.
1967          * @param {Number|Array} a
1968          * @param {Number} b
1969          * @returns {Number|Array}
1970          */
1971         div: function (a, b) {
1972             var i, len, res;
1973 
1974             a = Type.evalSlider(a);
1975             b = Type.evalSlider(b);
1976 
1977             if (Interval.isInterval(a) || Interval.isInterval(b)) {
1978                 res = Interval.div(a, b);
1979             } else if (Type.isArray(a) && Type.isNumber(b)) {
1980                 len = a.length;
1981                 res = [];
1982 
1983                 for (i = 0; i < len; i++) {
1984                     res[i] = a[i] / b;
1985                 }
1986             } else if (Type.isNumber(a) && Type.isNumber(b)) {
1987                 res = a / b;
1988             } else {
1989                 this._error('Operation * not defined on operands ' + typeof a + ' and ' + typeof b);
1990             }
1991 
1992             return res;
1993         },
1994 
1995         /**
1996          * Implementation of the % operator.
1997          * @param {Number|Array} a
1998          * @param {Number} b
1999          * @returns {Number|Array}
2000          */
2001         mod: function (a, b) {
2002             var i, len, res;
2003 
2004             a = Type.evalSlider(a);
2005             b = Type.evalSlider(b);
2006 
2007             if (Interval.isInterval(a) || Interval.isInterval(b)) {
2008                 return Interval.fmod(a, b);
2009             } else if (Type.isArray(a) && Type.isNumber(b)) {
2010                 len = a.length;
2011                 res = [];
2012 
2013                 for (i = 0; i < len; i++) {
2014                     res[i] = Mat.mod(a[i], b, true);
2015                 }
2016             } else if (Type.isNumber(a) && Type.isNumber(b)) {
2017                 res = Mat.mod(a, b, true);
2018             } else {
2019                 this._error('Operation * not defined on operands ' + typeof a + ' and ' + typeof b);
2020             }
2021 
2022             return res;
2023         },
2024 
2025         /**
2026          * Pow function wrapper to allow direct usage of sliders.
2027          * @param {Number|Slider} a
2028          * @param {Number|Slider} b
2029          * @returns {Number}
2030          */
2031         pow: function (a, b) {
2032             a = Type.evalSlider(a);
2033             b = Type.evalSlider(b);
2034 
2035             if (Interval.isInterval(a) || Interval.isInterval(b)) {
2036                 return Interval.pow(a, b);
2037             }
2038             return Mat.pow(a, b);
2039         },
2040 
2041         lt: function(a, b) {
2042             if (Interval.isInterval(a) || Interval.isInterval(b)) {
2043                 return Interval.lt(a, b);
2044             }
2045             return a < b;
2046         },
2047         leq: function(a, b) {
2048             if (Interval.isInterval(a) || Interval.isInterval(b)) {
2049                 return Interval.leq(a, b);
2050             }
2051             return a <= b;
2052         },
2053         gt: function(a, b) {
2054             if (Interval.isInterval(a) || Interval.isInterval(b)) {
2055                 return Interval.gt(a, b);
2056             }
2057             return a > b;
2058         },
2059         geq: function(a, b) {
2060             if (Interval.isInterval(a) || Interval.isInterval(b)) {
2061                 return Intervalt.geq(a, b);
2062             }
2063             return a >= b;
2064         },
2065 
2066         DDD: function(f) {
2067             console.log('Dummy derivative function. This should never appear!');
2068         },
2069 
2070         /**
2071          * Implementation of the ?: operator
2072          * @param {Boolean} cond Condition
2073          * @param {*} v1
2074          * @param {*} v2
2075          * @returns {*} Either v1 or v2.
2076          */
2077         ifthen: function (cond, v1, v2) {
2078             if (cond) {
2079                 return v1;
2080             }
2081 
2082             return v2;
2083         },
2084 
2085         /**
2086          * Implementation of the delete() builtin function
2087          * @param {JXG.GeometryElement} element
2088          */
2089         del: function (element) {
2090             if (typeof element === 'object' && JXG.exists(element.type) && JXG.exists(element.elementClass)) {
2091                 this.board.removeObject(element);
2092             }
2093         },
2094 
2095         /**
2096          * Implementation of the use() builtin function
2097          * @param {String} board
2098          */
2099         use: function (board) {
2100             var b, ref,
2101                 found = false;
2102 
2103             if (typeof board === 'string') {
2104                 // search all the boards for the one with the appropriate container div
2105                 for (b in JXG.boards) {
2106                     if (JXG.boards.hasOwnProperty(b) && JXG.boards[b].container === board) {
2107                         ref = JXG.boards[b];
2108                         found = true;
2109                         break;
2110                     }
2111                 }
2112             } else {
2113                 ref = board;
2114                 found = true;
2115             }
2116 
2117             if (found) {
2118                 this.board = ref;
2119                 this.builtIn.$board = ref;
2120                 this.builtIn.$board.src = '$jc$.board';
2121             } else {
2122                 this._error('Board \'' + board + '\' not found!');
2123             }
2124         },
2125 
2126         /**
2127          * Find the first symbol to the given value from the given scope upwards.
2128          * @param v Value
2129          * @param {Number} [scope=-1] The scope, default is to start with current scope (-1).
2130          * @returns {Array} An array containing the symbol and the scope if a symbol could be found,
2131          * an empty array otherwise;
2132          */
2133         findSymbol: function (v, scope) {
2134             var i, s;
2135 
2136             scope = Type.def(scope, -1);
2137 
2138             if (scope === -1) {
2139                 s = this.scope;
2140             } else {
2141                 s = this.scopes[scope];
2142             }
2143 
2144             while (s !== null) {
2145                 for (i in s.locals) {
2146                     if (s.locals.hasOwnProperty(i) && s.locals[i] === v) {
2147                         return [i, s];
2148                     }
2149                 }
2150 
2151                 s = s.previous;
2152             }
2153 
2154             return [];
2155         },
2156 
2157         /**
2158          * Import modules into a JessieCode script.
2159          * @param {String} module
2160          */
2161         importModule: function (module) {
2162             return priv.modules[module.toLowerCase()];
2163         },
2164 
2165         /**
2166          * Defines built in methods and constants.
2167          * @returns {Object} BuiltIn control object
2168          */
2169         defineBuiltIn: function () {
2170             var that = this,
2171                 builtIn = {
2172                     PI: Math.PI,
2173                     EULER: Math.E,
2174                     D: that.DDD,
2175                     X: that.X,
2176                     Y: that.Y,
2177                     V: that.V,
2178                     L: that.L,
2179 
2180                     acosh: Mat.acosh,
2181                     acot: Mat.acot,
2182                     asinh: Mat.asinh,
2183                     binomial: Mat.binomial,
2184                     cbrt: Mat.cbrt,
2185                     cosh: Mat.cosh,
2186                     cot: Mat.cot,
2187                     deg: Geometry.trueAngle,
2188                     dist: that.dist,
2189                     erf: Mat.erf,
2190                     erfc: Mat.erfc,
2191                     erfi: Mat.erfi,
2192                     factorial: Mat.factorial,
2193                     gcd: Mat.gcd,
2194                     lb: Mat.log2,
2195                     lcm: Mat.lcm,
2196                     ld: Mat.log2,
2197                     lg: Mat.log10,
2198                     ln: Math.log,
2199                     log: Mat.log,
2200                     log10: Mat.log10,
2201                     log2: Mat.log2,
2202                     ndtr: Mat.ndtr,
2203                     ndtri: Mat.ndtri,
2204                     nthroot: Mat.nthroot,
2205                     pow: Mat.pow,
2206                     rad: Geometry.rad,
2207                     ratpow: Mat.ratpow,
2208                     trunc: Type.trunc,
2209                     sinh: Mat.sinh,
2210 
2211                     IfThen: that.ifthen,
2212                     'import': that.importModule,
2213                     'use': that.use,
2214                     'remove': that.del,
2215                     '$': that.getElementById,
2216                     '$board': that.board,
2217                     '$log': that.log
2218                 };
2219 
2220             // special scopes for factorial, deg, and rad
2221             builtIn.rad.sc = Geometry;
2222             builtIn.deg.sc = Geometry;
2223             builtIn.factorial.sc = Mat;
2224 
2225             // set the javascript equivalent for the builtIns
2226             // some of the anonymous functions should be replaced by global methods later on
2227             // EULER and PI don't get a source attribute - they will be lost anyways and apparently
2228             // some browser will throw an exception when a property is assigned to a primitive value.
2229             builtIn.X.src = '$jc$.X';
2230             builtIn.Y.src = '$jc$.Y';
2231             builtIn.V.src = '$jc$.V';
2232             builtIn.L.src = '$jc$.L';
2233 
2234             builtIn.acosh.src = 'JXG.Math.acosh';
2235             builtIn.acot.src = 'JXG.Math.acot';
2236             builtIn.asinh.src = 'JXG.Math.asinh';
2237             builtIn.binomial.src = 'JXG.Math.binomial';
2238             builtIn.cbrt.src = 'JXG.Math.cbrt';
2239             builtIn.cot.src = 'JXG.Math.cot';
2240             builtIn.cosh.src = 'JXG.Math.cosh';
2241             builtIn.deg.src = 'JXG.Math.Geometry.trueAngle';
2242             builtIn.erf.src = 'JXG.Math.erf';
2243             builtIn.erfc.src = 'JXG.Math.erfc';
2244             builtIn.erfi.src = 'JXG.Math.erfi';
2245             builtIn.dist.src = '$jc$.dist';
2246             builtIn.factorial.src = 'JXG.Math.factorial';
2247             builtIn.gcd.src = 'JXG.Math.gcd';
2248             builtIn.lb.src = 'JXG.Math.log2';
2249             builtIn.lcm.src = 'JXG.Math.lcm';
2250             builtIn.ld.src = 'JXG.Math.log2';
2251             builtIn.lg.src = 'JXG.Math.log10';
2252             builtIn.ln.src = 'Math.log';
2253             builtIn.log.src = 'JXG.Math.log';
2254             builtIn.log10.src = 'JXG.Math.log10';
2255             builtIn.log2.src = 'JXG.Math.log2';
2256             builtIn.ndtr.src = 'JXG.Math.ndtr';
2257             builtIn.ndtri.src = 'JXG.Math.ndtri';
2258             builtIn.nthroot.src = 'JXG.Math.nthroot';
2259             builtIn.pow.src = 'JXG.Math.pow';
2260             builtIn.rad.src = 'JXG.Math.Geometry.rad';
2261             builtIn.ratpow.src = 'JXG.Math.ratpow';
2262             builtIn.trunc.src = 'JXG.trunc';
2263             builtIn.sinh.src = 'JXG.Math.sinh';
2264 
2265             builtIn['import'].src = '$jc$.importModule';
2266             builtIn.use.src = '$jc$.use';
2267             builtIn.remove.src = '$jc$.del';
2268             builtIn.IfThen.src = '$jc$.ifthen';
2269             // usually unused, see node_op > op_execfun
2270             builtIn.$.src = '(function (n) { return $jc$.board.select(n); })';
2271             if (builtIn.$board) {
2272                 builtIn.$board.src = '$jc$.board';
2273             }
2274             builtIn.$log.src = '$jc$.log';
2275 
2276             return builtIn;
2277         },
2278 
2279         /**
2280          * Output a debugging message. Uses debug console, if available. Otherwise an HTML element with the
2281          * id "debug" and an innerHTML property is used.
2282          * @param {String} log
2283          * @private
2284          */
2285         _debug: function (log) {
2286             if (typeof console === 'object') {
2287                 console.log(log);
2288             } else if (Env.isBrowser && document && document.getElementById('debug') !== null) {
2289                 document.getElementById('debug').innerHTML += log + '<br />';
2290             }
2291         },
2292 
2293         /**
2294          * Throws an exception with the given error message.
2295          * @param {String} msg Error message
2296          */
2297         _error: function (msg) {
2298             var e = new Error('Error(' + this.line + '): ' + msg);
2299             e.line = this.line;
2300             throw e;
2301         },
2302 
2303         /**
2304          * Output a warning message using {@link JXG#debug} and precedes the message with "Warning: ".
2305          * @param {String} msg
2306          */
2307         _warn: function (msg) {
2308             if (typeof console === 'object') {
2309                 console.log('Warning(' + this.line + '): ' + msg);
2310             } else if (Env.isBrowser && document && document.getElementById(this.warnLog) !== null) {
2311                 document.getElementById(this.warnLog).innerHTML += 'Warning(' + this.line + '): ' + msg + '<br />';
2312             }
2313         },
2314 
2315         _log: function (msg) {
2316             if (typeof window !== 'object' && typeof self === 'object' && self.postMessage) {
2317                 self.postMessage({type: 'log', msg: 'Log: ' + msg.toString()});
2318             } else {
2319                 console.log('Log: ', arguments);
2320             }
2321         }
2322 
2323     });
2324 
2325 /* parser generated by jison 0.4.18 */
2326 /*
2327   Returns a Parser object of the following structure:
2328 
2329   Parser: {
2330     yy: {}
2331   }
2332 
2333   Parser.prototype: {
2334     yy: {},
2335     trace: function(),
2336     symbols_: {associative list: name ==> number},
2337     terminals_: {associative list: number ==> name},
2338     productions_: [...],
2339     performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
2340     table: [...],
2341     defaultActions: {...},
2342     parseError: function(str, hash),
2343     parse: function(input),
2344 
2345     lexer: {
2346         EOF: 1,
2347         parseError: function(str, hash),
2348         setInput: function(input),
2349         input: function(),
2350         unput: function(str),
2351         more: function(),
2352         less: function(n),
2353         pastInput: function(),
2354         upcomingInput: function(),
2355         showPosition: function(),
2356         test_match: function(regex_match_array, rule_index),
2357         next: function(),
2358         lex: function(),
2359         begin: function(condition),
2360         popState: function(),
2361         _currentRules: function(),
2362         topState: function(),
2363         pushState: function(condition),
2364 
2365         options: {
2366             ranges: boolean           (optional: true ==> token location info will include a .range[] member)
2367             flex: boolean             (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
2368             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)
2369         },
2370 
2371         performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
2372         rules: [...],
2373         conditions: {associative list: name ==> set},
2374     }
2375   }
2376 
2377 
2378   token location info (@$, _$, etc.): {
2379     first_line: n,
2380     last_line: n,
2381     first_column: n,
2382     last_column: n,
2383     range: [start_number, end_number]       (where the numbers are indexes into the input string, regular zero-based)
2384   }
2385 
2386 
2387   the parseError function receives a 'hash' object with these members for lexer and parser errors: {
2388     text:        (matched text)
2389     token:       (the produced terminal token, if any)
2390     line:        (yylineno)
2391   }
2392   while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
2393     loc:         (yylloc)
2394     expected:    (string describing the set of expected tokens)
2395     recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
2396   }
2397 */
2398 var parser = (function(){
2399 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];
2400 var parser = {trace: function trace () { },
2401 yy: {},
2402 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},
2403 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:"->"},
2404 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]],
2405 performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
2406 /* this == yyval */
2407 
2408 var $0 = $$.length - 1;
2409 switch (yystate) {
2410 case 1:
2411  return $$[$0-1]; 
2412 break;
2413 case 2:
2414  this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_if', $$[$0-2], $$[$0]); 
2415 break;
2416 case 3:
2417  this.$ = AST.createNode(lc(_$[$0-6]), 'node_op', 'op_if_else', $$[$0-4], $$[$0-2], $$[$0]); 
2418 break;
2419 case 4:
2420  this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_while', $$[$0-2], $$[$0]); 
2421 break;
2422 case 5:
2423  this.$ = AST.createNode(lc(_$[$0-8]), 'node_op', 'op_for', $$[$0-6], $$[$0-4], $$[$0-2], $$[$0]); 
2424 break;
2425 case 6:
2426  this.$ = AST.createNode(lc(_$[$0-6]), 'node_op', 'op_do', $$[$0-5], $$[$0-2]); 
2427 break;
2428 case 7:
2429  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_use', $$[$0]); 
2430 break;
2431 case 8:
2432  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_delete', $$[$0]); 
2433 break;
2434 case 9:
2435  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_return', undefined); 
2436 break;
2437 case 10:
2438  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_return', $$[$0-1]); 
2439 break;
2440 case 11: case 14:
2441  this.$ = AST.createNode(lc(_$[$0]), 'node_op', 'op_none'); 
2442 break;
2443 case 12:
2444  this.$ = $$[$0-1]; this.$.needsBrackets = true; 
2445 break;
2446 case 13:
2447  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_none', $$[$0-1], $$[$0]); 
2448 break;
2449 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:
2450  this.$ = $$[$0]; 
2451 break;
2452 case 22: case 65: case 93:
2453  this.$ = $$[$0-1]; 
2454 break;
2455 case 25:
2456  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_assign', $$[$0-2], $$[$0]); this.$.isMath = false; 
2457 break;
2458 case 27:
2459  this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_conditional', $$[$0-4], $$[$0-2], $$[$0]); this.$.isMath = false; 
2460 break;
2461 case 29:
2462  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_or', $$[$0-2], $$[$0]); this.$.isMath = false; 
2463 break;
2464 case 31:
2465  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_and', $$[$0-2], $$[$0]); this.$.isMath = false; 
2466 break;
2467 case 33:
2468  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_eq', $$[$0-2], $$[$0]); this.$.isMath = false; 
2469 break;
2470 case 34:
2471  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_neq', $$[$0-2], $$[$0]); this.$.isMath = false; 
2472 break;
2473 case 35:
2474  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_approx', $$[$0-2], $$[$0]); this.$.isMath = false; 
2475 break;
2476 case 37:
2477  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_lt', $$[$0-2], $$[$0]); this.$.isMath = false; 
2478 break;
2479 case 38:
2480  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_gt', $$[$0-2], $$[$0]); this.$.isMath = false; 
2481 break;
2482 case 39:
2483  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_leq', $$[$0-2], $$[$0]); this.$.isMath = false; 
2484 break;
2485 case 40:
2486  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_geq', $$[$0-2], $$[$0]); this.$.isMath = false; 
2487 break;
2488 case 42:
2489  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_add', $$[$0-2], $$[$0]); this.$.isMath = true; 
2490 break;
2491 case 43:
2492  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_sub', $$[$0-2], $$[$0]); this.$.isMath = true; 
2493 break;
2494 case 45:
2495  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_mul', $$[$0-2], $$[$0]); this.$.isMath = true; 
2496 break;
2497 case 46:
2498  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_div', $$[$0-2], $$[$0]); this.$.isMath = true; 
2499 break;
2500 case 47:
2501  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_mod', $$[$0-2], $$[$0]); this.$.isMath = true; 
2502 break;
2503 case 49:
2504  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_exp', $$[$0-2], $$[$0]); this.$.isMath = true; 
2505 break;
2506 case 51:
2507  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_not', $$[$0]); this.$.isMath = false; 
2508 break;
2509 case 53:
2510  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_neg', $$[$0]); this.$.isMath = true; 
2511 break;
2512 case 57: case 63: case 64: case 66: case 67: case 68: case 97:
2513  this.$ = $$[$0]; this.$.isMath = false; 
2514 break;
2515 case 59: case 91:
2516  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_property', $$[$0-2], $$[$0]); this.$.isMath = true; 
2517 break;
2518 case 60: case 90:
2519  this.$ = AST.createNode(lc(_$[$0-3]), 'node_op', 'op_extvalue', $$[$0-3], $$[$0-1]); this.$.isMath = true; 
2520 break;
2521 case 61:
2522  this.$ = AST.createNode(lc(_$[$0]), 'node_var', $$[$0]); 
2523 break;
2524 case 69:
2525  this.$ = $$[$0]; this.$.isMath = true; 
2526 break;
2527 case 70:
2528  this.$ = AST.createNode(lc(_$[$0]), 'node_const', null); 
2529 break;
2530 case 71:
2531  this.$ = AST.createNode(lc(_$[$0]), 'node_const_bool', true); 
2532 break;
2533 case 72:
2534  this.$ = AST.createNode(lc(_$[$0]), 'node_const_bool', false); 
2535 break;
2536 case 73:
2537  this.$ = AST.createNode(lc(_$[$0]), 'node_str', $$[$0].substring(1, $$[$0].length - 1)); 
2538 break;
2539 case 74:
2540  this.$ = AST.createNode(lc(_$[$0]), 'node_const', parseFloat($$[$0])); 
2541 break;
2542 case 75:
2543  this.$ = AST.createNode(lc(_$[$0]), 'node_const', NaN); 
2544 break;
2545 case 76:
2546  this.$ = AST.createNode(lc(_$[$0]), 'node_const', Infinity); 
2547 break;
2548 case 77:
2549  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_array', []); 
2550 break;
2551 case 78:
2552  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_array', $$[$0-1]); 
2553 break;
2554 case 79:
2555  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_emptyobject', {}); this.$.needsBrackets = true; 
2556 break;
2557 case 80:
2558  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_proplst_val', $$[$0-1]); this.$.needsBrackets = true; 
2559 break;
2560 case 82:
2561  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_proplst', $$[$0-2], $$[$0]); 
2562 break;
2563 case 83:
2564  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_prop', $$[$0-2], $$[$0]); 
2565 break;
2566 case 87: case 89:
2567  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_execfun', $$[$0-1], $$[$0]); this.$.isMath = true; 
2568 break;
2569 case 88:
2570  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_execfun', $$[$0-2], $$[$0-1], $$[$0], true); this.$.isMath = false; 
2571 break;
2572 case 92:
2573  this.$ = []; 
2574 break;
2575 case 94: case 98: case 103:
2576  this.$ = [$$[$0]]; 
2577 break;
2578 case 95: case 99: case 104:
2579  this.$ = $$[$0-2].concat($$[$0]); 
2580 break;
2581 case 96:
2582  this.$ = AST.createNode(lc(_$[$0]), 'node_var', $$[$0]); this.$.isMath = true; 
2583 break;
2584 case 100:
2585  this.$ = AST.createNode(lc(_$[$0-3]), 'node_op', 'op_function', [], $$[$0]); this.$.isMath = false; 
2586 break;
2587 case 101:
2588  this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_function', $$[$0-2], $$[$0]); this.$.isMath = false; 
2589 break;
2590 case 102:
2591  this.$ = AST.createNode(lc(_$[$0-5]), 'node_op', 'op_map', $$[$0-3], $$[$0]); 
2592 break;
2593 }
2594 },
2595 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])],
2596 defaultActions: {3:[2,1],97:[2,84],98:[2,85],99:[2,86]},
2597 parseError: function parseError (str, hash) {
2598     if (hash.recoverable) {
2599         this.trace(str);
2600     } else {
2601         var error = new Error(str);
2602         error.hash = hash;
2603         throw error;
2604     }
2605 },
2606 parse: function parse(input) {
2607     var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
2608     var args = lstack.slice.call(arguments, 1);
2609     var lexer = Object.create(this.lexer);
2610     var sharedState = { yy: {} };
2611     for (var k in this.yy) {
2612         if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
2613             sharedState.yy[k] = this.yy[k];
2614         }
2615     }
2616     lexer.setInput(input, sharedState.yy);
2617     sharedState.yy.lexer = lexer;
2618     sharedState.yy.parser = this;
2619     if (typeof lexer.yylloc == 'undefined') {
2620         lexer.yylloc = {};
2621     }
2622     var yyloc = lexer.yylloc;
2623     lstack.push(yyloc);
2624     var ranges = lexer.options && lexer.options.ranges;
2625     if (typeof sharedState.yy.parseError === 'function') {
2626         this.parseError = sharedState.yy.parseError;
2627     } else {
2628         this.parseError = Object.getPrototypeOf(this).parseError;
2629     }
2630     function popStack(n) {
2631         stack.length = stack.length - 2 * n;
2632         vstack.length = vstack.length - n;
2633         lstack.length = lstack.length - n;
2634     }
2635     _token_stack:
2636         var lex = function () {
2637             var token;
2638             token = lexer.lex() || EOF;
2639             if (typeof token !== 'number') {
2640                 token = self.symbols_[token] || token;
2641             }
2642             return token;
2643         };
2644     var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
2645     while (true) {
2646         state = stack[stack.length - 1];
2647         if (this.defaultActions[state]) {
2648             action = this.defaultActions[state];
2649         } else {
2650             if (symbol === null || typeof symbol == 'undefined') {
2651                 symbol = lex();
2652             }
2653             action = table[state] && table[state][symbol];
2654         }
2655                     if (typeof action === 'undefined' || !action.length || !action[0]) {
2656                 var errStr = '';
2657                 expected = [];
2658                 for (p in table[state]) {
2659                     if (this.terminals_[p] && p > TERROR) {
2660                         expected.push('\'' + this.terminals_[p] + '\'');
2661                     }
2662                 }
2663                 if (lexer.showPosition) {
2664                     errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
2665                 } else {
2666                     errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
2667                 }
2668                 this.parseError(errStr, {
2669                     text: lexer.match,
2670                     token: this.terminals_[symbol] || symbol,
2671                     line: lexer.yylineno,
2672                     loc: yyloc,
2673                     expected: expected
2674                 });
2675             }
2676         if (action[0] instanceof Array && action.length > 1) {
2677             throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
2678         }
2679         switch (action[0]) {
2680         case 1:
2681             stack.push(symbol);
2682             vstack.push(lexer.yytext);
2683             lstack.push(lexer.yylloc);
2684             stack.push(action[1]);
2685             symbol = null;
2686             if (!preErrorSymbol) {
2687                 yyleng = lexer.yyleng;
2688                 yytext = lexer.yytext;
2689                 yylineno = lexer.yylineno;
2690                 yyloc = lexer.yylloc;
2691                 if (recovering > 0) {
2692                     recovering--;
2693                 }
2694             } else {
2695                 symbol = preErrorSymbol;
2696                 preErrorSymbol = null;
2697             }
2698             break;
2699         case 2:
2700             len = this.productions_[action[1]][1];
2701             yyval.$ = vstack[vstack.length - len];
2702             yyval._$ = {
2703                 first_line: lstack[lstack.length - (len || 1)].first_line,
2704                 last_line: lstack[lstack.length - 1].last_line,
2705                 first_column: lstack[lstack.length - (len || 1)].first_column,
2706                 last_column: lstack[lstack.length - 1].last_column
2707             };
2708             if (ranges) {
2709                 yyval._$.range = [
2710                     lstack[lstack.length - (len || 1)].range[0],
2711                     lstack[lstack.length - 1].range[1]
2712                 ];
2713             }
2714             r = this.performAction.apply(yyval, [
2715                 yytext,
2716                 yyleng,
2717                 yylineno,
2718                 sharedState.yy,
2719                 action[1],
2720                 vstack,
2721                 lstack
2722             ].concat(args));
2723             if (typeof r !== 'undefined') {
2724                 return r;
2725             }
2726             if (len) {
2727                 stack = stack.slice(0, -1 * len * 2);
2728                 vstack = vstack.slice(0, -1 * len);
2729                 lstack = lstack.slice(0, -1 * len);
2730             }
2731             stack.push(this.productions_[action[1]][0]);
2732             vstack.push(yyval.$);
2733             lstack.push(yyval._$);
2734             newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
2735             stack.push(newState);
2736             break;
2737         case 3:
2738             return true;
2739         }
2740     }
2741     return true;
2742 }};
2743 
2744 
2745     var AST = {
2746         node: function (type, value, children) {
2747             return {
2748                 type: type,
2749                 value: value,
2750                 children: children
2751             };
2752         },
2753 
2754         createNode: function (pos, type, value, children) {
2755             var i,
2756                 n = this.node(type, value, []);
2757 
2758             for (i = 3; i < arguments.length; i++) {
2759                 n.children.push(arguments[i]);
2760             }
2761 
2762             n.line = pos[0];
2763             n.col = pos[1];
2764             n.eline = pos[2];
2765             n.ecol = pos[3];
2766 
2767             return n;
2768         }
2769     };
2770 
2771     var lc = function (lc1) {
2772         return [lc1.first_line, lc1.first_column, lc1.last_line, lc1.last_column];
2773     };
2774 
2775 /* generated by jison-lex 0.3.4 */
2776 var lexer = (function(){
2777 var lexer = ({
2778 
2779 EOF:1,
2780 
2781 parseError:function parseError(str, hash) {
2782         if (this.yy.parser) {
2783             this.yy.parser.parseError(str, hash);
2784         } else {
2785             throw new Error(str);
2786         }
2787     },
2788 
2789 // resets the lexer, sets new input
2790 setInput:function (input, yy) {
2791         this.yy = yy || this.yy || {};
2792         this._input = input;
2793         this._more = this._backtrack = this.done = false;
2794         this.yylineno = this.yyleng = 0;
2795         this.yytext = this.matched = this.match = '';
2796         this.conditionStack = ['INITIAL'];
2797         this.yylloc = {
2798             first_line: 1,
2799             first_column: 0,
2800             last_line: 1,
2801             last_column: 0
2802         };
2803         if (this.options.ranges) {
2804             this.yylloc.range = [0,0];
2805         }
2806         this.offset = 0;
2807         return this;
2808     },
2809 
2810 // consumes and returns one char from the input
2811 input:function () {
2812         var ch = this._input[0];
2813         this.yytext += ch;
2814         this.yyleng++;
2815         this.offset++;
2816         this.match += ch;
2817         this.matched += ch;
2818         var lines = ch.match(/(?:\r\n?|\n).*/g);
2819         if (lines) {
2820             this.yylineno++;
2821             this.yylloc.last_line++;
2822         } else {
2823             this.yylloc.last_column++;
2824         }
2825         if (this.options.ranges) {
2826             this.yylloc.range[1]++;
2827         }
2828 
2829         this._input = this._input.slice(1);
2830         return ch;
2831     },
2832 
2833 // unshifts one char (or a string) into the input
2834 unput:function (ch) {
2835         var len = ch.length;
2836         var lines = ch.split(/(?:\r\n?|\n)/g);
2837 
2838         this._input = ch + this._input;
2839         this.yytext = this.yytext.substr(0, this.yytext.length - len);
2840         //this.yyleng -= len;
2841         this.offset -= len;
2842         var oldLines = this.match.split(/(?:\r\n?|\n)/g);
2843         this.match = this.match.substr(0, this.match.length - 1);
2844         this.matched = this.matched.substr(0, this.matched.length - 1);
2845 
2846         if (lines.length - 1) {
2847             this.yylineno -= lines.length - 1;
2848         }
2849         var r = this.yylloc.range;
2850 
2851         this.yylloc = {
2852             first_line: this.yylloc.first_line,
2853             last_line: this.yylineno + 1,
2854             first_column: this.yylloc.first_column,
2855             last_column: lines ?
2856                 (lines.length === oldLines.length ? this.yylloc.first_column : 0)
2857                  + oldLines[oldLines.length - lines.length].length - lines[0].length :
2858               this.yylloc.first_column - len
2859         };
2860 
2861         if (this.options.ranges) {
2862             this.yylloc.range = [r[0], r[0] + this.yyleng - len];
2863         }
2864         this.yyleng = this.yytext.length;
2865         return this;
2866     },
2867 
2868 // When called from action, caches matched text and appends it on next action
2869 more:function () {
2870         this._more = true;
2871         return this;
2872     },
2873 
2874 // When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
2875 reject:function () {
2876         if (this.options.backtrack_lexer) {
2877             this._backtrack = true;
2878         } else {
2879             return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
2880                 text: "",
2881                 token: null,
2882                 line: this.yylineno
2883             });
2884 
2885         }
2886         return this;
2887     },
2888 
2889 // retain first n characters of the match
2890 less:function (n) {
2891         this.unput(this.match.slice(n));
2892     },
2893 
2894 // displays already matched input, i.e. for error messages
2895 pastInput:function () {
2896         var past = this.matched.substr(0, this.matched.length - this.match.length);
2897         return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
2898     },
2899 
2900 // displays upcoming input, i.e. for error messages
2901 upcomingInput:function () {
2902         var next = this.match;
2903         if (next.length < 20) {
2904             next += this._input.substr(0, 20-next.length);
2905         }
2906         return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
2907     },
2908 
2909 // displays the character position where the lexing error occurred, i.e. for error messages
2910 showPosition:function () {
2911         var pre = this.pastInput();
2912         var c = new Array(pre.length + 1).join("-");
2913         return pre + this.upcomingInput() + "\n" + c + "^";
2914     },
2915 
2916 // test the lexed token: return FALSE when not a match, otherwise return token
2917 test_match:function(match, indexed_rule) {
2918         var token,
2919             lines,
2920             backup;
2921 
2922         if (this.options.backtrack_lexer) {
2923             // save context
2924             backup = {
2925                 yylineno: this.yylineno,
2926                 yylloc: {
2927                     first_line: this.yylloc.first_line,
2928                     last_line: this.last_line,
2929                     first_column: this.yylloc.first_column,
2930                     last_column: this.yylloc.last_column
2931                 },
2932                 yytext: this.yytext,
2933                 match: this.match,
2934                 matches: this.matches,
2935                 matched: this.matched,
2936                 yyleng: this.yyleng,
2937                 offset: this.offset,
2938                 _more: this._more,
2939                 _input: this._input,
2940                 yy: this.yy,
2941                 conditionStack: this.conditionStack.slice(0),
2942                 done: this.done
2943             };
2944             if (this.options.ranges) {
2945                 backup.yylloc.range = this.yylloc.range.slice(0);
2946             }
2947         }
2948 
2949         lines = match[0].match(/(?:\r\n?|\n).*/g);
2950         if (lines) {
2951             this.yylineno += lines.length;
2952         }
2953         this.yylloc = {
2954             first_line: this.yylloc.last_line,
2955             last_line: this.yylineno + 1,
2956             first_column: this.yylloc.last_column,
2957             last_column: lines ?
2958                          lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
2959                          this.yylloc.last_column + match[0].length
2960         };
2961         this.yytext += match[0];
2962         this.match += match[0];
2963         this.matches = match;
2964         this.yyleng = this.yytext.length;
2965         if (this.options.ranges) {
2966             this.yylloc.range = [this.offset, this.offset += this.yyleng];
2967         }
2968         this._more = false;
2969         this._backtrack = false;
2970         this._input = this._input.slice(match[0].length);
2971         this.matched += match[0];
2972         token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
2973         if (this.done && this._input) {
2974             this.done = false;
2975         }
2976         if (token) {
2977             return token;
2978         } else if (this._backtrack) {
2979             // recover context
2980             for (var k in backup) {
2981                 this[k] = backup[k];
2982             }
2983             return false; // rule action called reject() implying the next rule should be tested instead.
2984         }
2985         return false;
2986     },
2987 
2988 // return next match in input
2989 next:function () {
2990         if (this.done) {
2991             return this.EOF;
2992         }
2993         if (!this._input) {
2994             this.done = true;
2995         }
2996 
2997         var token,
2998             match,
2999             tempMatch,
3000             index;
3001         if (!this._more) {
3002             this.yytext = '';
3003             this.match = '';
3004         }
3005         var rules = this._currentRules();
3006         for (var i = 0; i < rules.length; i++) {
3007             tempMatch = this._input.match(this.rules[rules[i]]);
3008             if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
3009                 match = tempMatch;
3010                 index = i;
3011                 if (this.options.backtrack_lexer) {
3012                     token = this.test_match(tempMatch, rules[i]);
3013                     if (token !== false) {
3014                         return token;
3015                     } else if (this._backtrack) {
3016                         match = false;
3017                         continue; // rule action called reject() implying a rule MISmatch.
3018                     } else {
3019                         // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
3020                         return false;
3021                     }
3022                 } else if (!this.options.flex) {
3023                     break;
3024                 }
3025             }
3026         }
3027         if (match) {
3028             token = this.test_match(match, rules[index]);
3029             if (token !== false) {
3030                 return token;
3031             }
3032             // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
3033             return false;
3034         }
3035         if (this._input === "") {
3036             return this.EOF;
3037         } else {
3038             return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
3039                 text: "",
3040                 token: null,
3041                 line: this.yylineno
3042             });
3043         }
3044     },
3045 
3046 // return next match that has a token
3047 lex:function lex () {
3048         var r = this.next();
3049         if (r) {
3050             return r;
3051         } else {
3052             return this.lex();
3053         }
3054     },
3055 
3056 // activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
3057 begin:function begin (condition) {
3058         this.conditionStack.push(condition);
3059     },
3060 
3061 // pop the previously active lexer condition state off the condition stack
3062 popState:function popState () {
3063         var n = this.conditionStack.length - 1;
3064         if (n > 0) {
3065             return this.conditionStack.pop();
3066         } else {
3067             return this.conditionStack[0];
3068         }
3069     },
3070 
3071 // produce the lexer rule set which is active for the currently active lexer condition state
3072 _currentRules:function _currentRules () {
3073         if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
3074             return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
3075         } else {
3076             return this.conditions["INITIAL"].rules;
3077         }
3078     },
3079 
3080 // return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
3081 topState:function topState (n) {
3082         n = this.conditionStack.length - 1 - Math.abs(n || 0);
3083         if (n >= 0) {
3084             return this.conditionStack[n];
3085         } else {
3086             return "INITIAL";
3087         }
3088     },
3089 
3090 // alias for begin(condition)
3091 pushState:function pushState (condition) {
3092         this.begin(condition);
3093     },
3094 
3095 // return the number of states currently on the stack
3096 stateStackSize:function stateStackSize() {
3097         return this.conditionStack.length;
3098     },
3099 options: {},
3100 performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
3101 var YYSTATE=YY_START;
3102 switch($avoiding_name_collisions) {
3103 case 0:/* ignore */
3104 break;
3105 case 1:return 78
3106 break;
3107 case 2:return 78
3108 break;
3109 case 3: return 77; 
3110 break;
3111 case 4: return 77; 
3112 break;
3113 case 5:/* ignore comment */
3114 break;
3115 case 6:/* ignore multiline comment */
3116 break;
3117 case 7:return 7
3118 break;
3119 case 8:return 12
3120 break;
3121 case 9:return 14
3122 break;
3123 case 10:return 17
3124 break;
3125 case 11:return 15
3126 break;
3127 case 12:return 91
3128 break;
3129 case 13:return 93
3130 break;
3131 case 14:return 19
3132 break;
3133 case 15:return 23
3134 break;
3135 case 16:return 21
3136 break;
3137 case 17:return 75
3138 break;
3139 case 18:return 76
3140 break;
3141 case 19:return 74
3142 break;
3143 case 20:return 80
3144 break;
3145 case 21:return 94
3146 break;
3147 case 22:return 82
3148 break;
3149 case 23:return 83
3150 break;
3151 case 24:return 26
3152 break;
3153 case 25:return 27
3154 break;
3155 case 26:return 16
3156 break;
3157 case 27:return '#'
3158 break;
3159 case 28:return 34
3160 break;
3161 case 29:return 35
3162 break;
3163 case 30:return 79
3164 break;
3165 case 31:return 64
3166 break;
3167 case 32:return 65
3168 break;
3169 case 33:return 66
3170 break;
3171 case 34:return 8
3172 break;
3173 case 35:return 10
3174 break;
3175 case 36:return 58
3176 break;
3177 case 37:return 57
3178 break;
3179 case 38:return 53
3180 break;
3181 case 39:return 54
3182 break;
3183 case 40:return 55
3184 break;
3185 case 41:return 50
3186 break;
3187 case 42:return 51
3188 break;
3189 case 43:return 47
3190 break;
3191 case 44:return 45
3192 break;
3193 case 45:return 48
3194 break;
3195 case 46:return 46
3196 break;
3197 case 47:return 41
3198 break;
3199 case 48:return 43
3200 break;
3201 case 49:return 42
3202 break;
3203 case 50:return 39
3204 break;
3205 case 51:return 37
3206 break;
3207 case 52:return 32
3208 break;
3209 case 53:return 86
3210 break;
3211 case 54:return 5
3212 break;
3213 case 55:return 20
3214 break;
3215 case 56:return 'INVALID'
3216 break;
3217 }
3218 },
3219 rules: [/^(?:\s+)/,/^(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+\b)/,/^(?:[0-9]+)/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:\/\/.*)/,/^(?:\/\*(.|\n|\r)*?\*\/)/,/^(?:if\b)/,/^(?:else\b)/,/^(?:while\b)/,/^(?:do\b)/,/^(?:for\b)/,/^(?:function\b)/,/^(?:map\b)/,/^(?:use\b)/,/^(?:return\b)/,/^(?:delete\b)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:Infinity\b)/,/^(?:->)/,/^(?:<<)/,/^(?:>>)/,/^(?:\{)/,/^(?:\})/,/^(?:;)/,/^(?:#)/,/^(?:\?)/,/^(?::)/,/^(?:NaN\b)/,/^(?:\.)/,/^(?:\[)/,/^(?:\])/,/^(?:\()/,/^(?:\))/,/^(?:!)/,/^(?:\^)/,/^(?:\*)/,/^(?:\/)/,/^(?:%)/,/^(?:\+)/,/^(?:-)/,/^(?:<=)/,/^(?:<)/,/^(?:>=)/,/^(?:>)/,/^(?:==)/,/^(?:~=)/,/^(?:!=)/,/^(?:&&)/,/^(?:\|\|)/,/^(?:=)/,/^(?:,)/,/^(?:$)/,/^(?:[A-Za-z_\$][A-Za-z0-9_]*)/,/^(?:.)/],
3220 conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56],"inclusive":true}}
3221 });
3222 return lexer;
3223 })();
3224 parser.lexer = lexer;
3225 function Parser () {
3226   this.yy = {};
3227 }
3228 Parser.prototype = parser;parser.Parser = Parser;
3229 return new Parser;
3230 })();
3231 
3232 
3233 if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
3234 exports.parser = parser;
3235 exports.Parser = parser.Parser;
3236 exports.parse = function () { return parser.parse.apply(parser, arguments); };
3237 exports.main = function commonjsMain (args) {
3238     if (!args[1]) {
3239         console.log('Usage: '+args[0]+' FILE');
3240         process.exit(1);
3241     }
3242     var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
3243     return exports.parser.parse(source);
3244 };
3245 if (typeof module !== 'undefined' && require.main === module) {
3246   exports.main(process.argv.slice(1));
3247 }
3248 }
3249     // Work around an issue with browsers that don't support Object.getPrototypeOf()
3250     parser.yy.parseError = parser.parseError;
3251 
3252     return JXG.JessieCode;
3253 });
3254