1 /*
  2  JessieCode Interpreter and Compiler
  3 
  4     Copyright 2011-2026
  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 <https://www.gnu.org/licenses/>
 25     and <https://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 /**
 32  * @fileoverview JessieCode is a scripting language designed to provide a
 33  * simple scripting language to build constructions
 34  * with JSXGraph. It is similar to JavaScript, but prevents access to the DOM.
 35  * Hence, it can be used in community driven math portals which want to use
 36  * JSXGraph to display interactive math graphics.
 37  */
 38 
 39 import JXG from "../jxg.js";
 40 import Const from "../base/constants.js";
 41 import Text from "../base/text.js";
 42 import Mat from "../math/math.js";
 43 import Interval from "../math/ia.js";
 44 import Geometry from "../math/geometry.js";
 45 import Statistics from "../math/statistics.js";
 46 import Type from "../utils/type.js";
 47 import Env from "../utils/env.js";
 48 
 49 // IE 6-8 compatibility
 50 if (!Object.create) {
 51     Object.create = function (o, properties) {
 52         if (typeof o !== 'object' && typeof o !== 'function') throw new TypeError('Object prototype may only be an Object: ' + o);
 53         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.");
 54 
 55         if (typeof properties != 'undefined') throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument.");
 56 
 57         function F() { }
 58 
 59         F.prototype = o;
 60 
 61         return new F();
 62     };
 63 }
 64 
 65 var priv = {
 66     modules: {
 67         'math': Mat,
 68         'math/geometry': Geometry,
 69         'math/statistics': Statistics,
 70         'math/numerics': Mat.Numerics
 71     }
 72 };
 73 
 74 /**
 75  * A JessieCode object provides an interface to the parser and stores all variables and objects used within a JessieCode script.
 76  * The optional argument <tt>code</tt> is interpreted after initializing. To evaluate more code after initializing a JessieCode instance
 77  * please use {@link JXG.JessieCode#parse}. For code snippets like single expressions use {@link JXG.JessieCode#snippet}.
 78  * @constructor
 79  * @param {String} [code] Code to parse.
 80  * @param {Boolean} [geonext=false] Geonext compatibility mode.
 81  */
 82 JXG.JessieCode = function (code, geonext) {
 83     // Control structures
 84 
 85     /**
 86      * The global scope.
 87      * @type Object
 88      */
 89     this.scope = {
 90         id: 0,
 91         hasChild: true,
 92         args: [],
 93         locals: {},
 94         context: null,
 95         previous: null
 96     };
 97 
 98     /**
 99      * Keeps track of all possible scopes every required.
100      * @type Array
101      */
102     this.scopes = [];
103     this.scopes.push(this.scope);
104 
105     /**
106      * A stack to store debug information (like line and column where it was defined) of a parameter
107      * @type Array
108      * @private
109      */
110     this.dpstack = [[]];
111 
112     /**
113      * Determines the parameter stack scope.
114      * @type Number
115      * @private
116      */
117     this.pscope = 0;
118 
119     /**
120      * Used to store the property-value definition while parsing an object literal.
121      * @type Array
122      * @private
123      */
124     this.propstack = [{}];
125 
126     /**
127      * The current scope of the object literal stack {@link JXG.JessieCode#propstack}.
128      * @type Number
129      * @private
130      */
131     this.propscope = 0;
132 
133     /**
134      * Store the left hand side of an assignment. If an element is constructed and no attributes are given, this is
135      * used as the element's name.
136      * @type Array
137      * @private
138      */
139     this.lhs = [];
140 
141     /**
142      * lhs flag, used by JXG.JessieCode#replaceNames
143      * @type Boolean
144      * @default false
145      */
146     this.isLHS = false;
147 
148     /**
149      * The id of an HTML node in which innerText all warnings are stored (if no <tt>console</tt> object is available).
150      * @type String
151      * @default 'jcwarn'
152      */
153     this.warnLog = 'jcwarn';
154 
155     /**
156      * Store $log messages in case there's no console.
157      * @type Array
158      */
159     this.$log = [];
160 
161     /**
162      * Built-in functions and constants
163      * @type Object
164      */
165     this.builtIn = this.defineBuiltIn();
166 
167     /**
168      * List of all possible operands in JessieCode (except of JSXGraph objects).
169      * @type Object
170      */
171     this.operands = this.getPossibleOperands();
172 
173     /**
174      * The board which currently is used to create and look up elements.
175      * @type JXG.Board
176      */
177     this.board = null;
178 
179     /**
180      * Force slider names to return value instead of node
181      * @type Boolean
182      */
183     this.forceValueCall = false;
184 
185     /**
186      * Keep track of which element is created in which line.
187      * @type Object
188      */
189     this.lineToElement = {};
190 
191     this.parCurLine = 1;
192     this.parCurColumn = 0;
193     this.line = 1;
194     this.col = 1;
195 
196     if (JXG.CA) {
197         // Old simplifier
198         this.CA = new JXG.CA(this.node, this.createNode, this);
199     }
200     if (JXG.CAS) {
201         // New simplifier
202         this.CAS = new JXG.CAS(this.node, this.createNode, this);
203     }
204 
205     this.code = '';
206 
207     if (typeof code === 'string') {
208         this.parse(code, geonext);
209     }
210 };
211 
212 JXG.extend(JXG.JessieCode.prototype, /** @lends JXG.JessieCode.prototype */ {
213     /**
214      * Create a new parse tree node.
215      * @param {String} type Type of node, e.g. node_op, node_var, or node_const
216      * @param value The nodes value, e.g. a variables value or a functions body.
217      * @param {Array} children Arbitrary number of child nodes.
218      */
219     node: function (type, value, children) {
220         return {
221             type: type,
222             value: value,
223             children: children
224         };
225     },
226 
227     /**
228      * Create a new parse tree node. Basically the same as node(), but this builds
229      * the children part out of an arbitrary number of parameters, instead of one
230      * array parameter.
231      * @param {String} type Type of node, e.g. node_op, node_var, or node_const
232      * @param value The nodes value, e.g. a variables value or a functions body.
233      * @param children Arbitrary number of parameters; define the child nodes.
234      */
235     createNode: function (type, value, children) {
236         var n = this.node(type, value, []),
237             i;
238 
239         for (i = 2; i < arguments.length; i++) {
240             n.children.push(arguments[i]);
241         }
242 
243         if (n.type === 'node_const' && Type.isNumber(n.value)) {
244             n.isMath = true;
245         }
246 
247         n.line = this.parCurLine;
248         n.col = this.parCurColumn;
249 
250         return n;
251     },
252 
253     /**
254      * Create a new scope.
255      * @param {Array} args
256      * @returns {Object}
257      */
258     pushScope: function (args) {
259         var scope = {
260             args: args,
261             locals: {},
262             context: null,
263             previous: this.scope
264         };
265 
266         this.scope.hasChild = true;
267         this.scope = scope;
268         scope.id = this.scopes.push(scope) - 1;
269 
270         return scope;
271     },
272 
273     /**
274      * Remove the current scope and reinstate the previous scope
275      * @returns {Object}
276      */
277     popScope: function () {
278         var s = this.scope.previous;
279 
280         // make sure the global scope is not lost
281         this.scope = (s !== null) ? s : this.scope;
282 
283         return this.scope;
284     },
285 
286     /**
287      * Looks up an {@link JXG.GeometryElement} by its id.
288      * @param {String} id
289      * @returns {JXG.GeometryElement}
290      */
291     getElementById: function (id) {
292         return this.board.objects[id];
293     },
294 
295     log: function () {
296         this.$log.push(arguments);
297 
298         if (typeof console === 'object' && console.log) {
299             console.log.apply(console, arguments);
300         }
301     },
302 
303     /**
304      * Returns a element creator function which takes two parameters: the parents array and the attributes object.
305      * @param {String} vname The element type, e.g. 'point', 'line', 'midpoint'
306      * @returns {function}
307      */
308     creator: (function () {
309         // stores the already defined creators
310         var _ccache = {}, r;
311 
312         r = function (vname) {
313             var f;
314 
315             // _ccache is global, i.e. it is the same for ALL JessieCode instances.
316             // That's why we need the board id here
317             if (typeof _ccache[this.board.id + vname] === 'function') {
318                 f = _ccache[this.board.id + vname];
319             } else {
320                 f = (function (that) {
321                     return function (parameters, attributes) {
322                         var attr;
323 
324                         if (Type.exists(attributes)) {
325                             attr = attributes;
326                         } else {
327                             attr = {};
328                         }
329                         if (attr.name === undefined && attr.id === undefined) {
330                             attr.name = ((that.lhs[that.scope.id] !== 0) ? that.lhs[that.scope.id] : '');
331                         }
332                         return that.board.create(vname, parameters, attr);
333                     };
334                 }(this));
335 
336                 f.creator = true;
337                 _ccache[this.board.id + vname] = f;
338             }
339 
340             return f;
341         };
342 
343         r.clearCache = function () {
344             _ccache = {};
345         };
346 
347         return r;
348     }()),
349 
350     /**
351      * Assigns a value to a variable in the current scope.
352      * @param {String} vname Variable name
353      * @param value Anything
354      * @see JXG.JessieCode#sstack
355      * @see JXG.JessieCode#scope
356      */
357     letvar: function (vname, value) {
358         if (this.builtIn[vname]) {
359             this._warn('"' + vname + '" is a predefined value.');
360         }
361 
362         this.scope.locals[vname] = value;
363     },
364 
365     /**
366      * Checks if the given variable name can be found in the current scope chain.
367      * @param {String} vname
368      * @returns {Object} A reference to the scope object the variable can be found in or null if it can't be found.
369      */
370     isLocalVariable: function (vname) {
371         var s = this.scope;
372 
373         while (s !== null) {
374             if (Type.exists(s.locals[vname])) {
375                 return s;
376             }
377 
378             s = s.previous;
379         }
380 
381         return null;
382     },
383 
384     /**
385      * Checks if the given variable name is a parameter in any scope from the current to the global scope.
386      * @param {String} vname
387      * @returns {Object} A reference to the scope object that contains the variable in its arg list.
388      */
389     isParameter: function (vname) {
390         var s = this.scope;
391 
392         while (s !== null) {
393             if (Type.indexOf(s.args, vname) > -1) {
394                 return s;
395             }
396 
397             s = s.previous;
398         }
399 
400         return null;
401     },
402 
403     /**
404      * Checks if the given variable name is a valid creator method.
405      * @param {String} vname
406      * @returns {Boolean}
407      */
408     isCreator: function (vname) {
409         // check for an element with this name
410         return !!JXG.elements[vname];
411     },
412 
413     /**
414      * Checks if the given variable identifier is a valid member of the JavaScript Math Object.
415      * @param {String} vname
416      * @returns {Boolean}
417      */
418     isMathMethod: function (vname) {
419         return vname !== 'E' && !!Math[vname];
420     },
421 
422     /**
423      * Returns true if the given identifier is a builtIn variable/function.
424      * @param {String} vname
425      * @returns {Boolean}
426      */
427     isBuiltIn: function (vname) {
428         return !!this.builtIn[vname];
429     },
430 
431     /**
432      * Looks up the value of the given variable. We use a simple type inspection.
433      *
434      * @param {String} vname Name of the variable
435      * @param {Boolean} [local=false] Only look up the internal symbol table and don't look for
436      * the <tt>vname</tt> in Math or the element list.
437      * @param {Boolean} [isFunctionName=false] Lookup function of type builtIn, Math.*, creator.
438      *
439      * @see JXG.JessieCode#resolveType
440      */
441     getvar: function (vname, local, isFunctionName) {
442         var s;
443 
444         local = Type.def(local, false);
445 
446         // Local scope has always precedence
447         s = this.isLocalVariable(vname);
448 
449         if (s !== null) {
450             return s.locals[vname];
451         }
452 
453         // Handle the - so far only - few constants by hard coding them.
454         if (vname === '$board' || vname === 'EULER' || vname === 'PI') {
455             return this.builtIn[vname];
456         }
457 
458         if (isFunctionName) {
459             if (this.isBuiltIn(vname)) {
460                 return this.builtIn[vname];
461             }
462 
463             if (this.isMathMethod(vname)) {
464                 return Math[vname];
465             }
466 
467             // check for an element with this name
468             if (this.isCreator(vname)) {
469                 return this.creator(vname);
470             }
471         }
472 
473         if (!local) {
474             s = this.board.select(vname);
475             if (s !== vname) {
476                 return s;
477             }
478         }
479     },
480 
481     /**
482      * Look up the value of a local variable.
483      * @param {string} vname
484      * @returns {*}
485      */
486     resolve: function (vname) {
487         var s = this.scope;
488 
489         while (s !== null) {
490             if (Type.exists(s.locals[vname])) {
491                 return s.locals[vname];
492             }
493 
494             s = s.previous;
495         }
496     },
497 
498     /**
499      * TODO this needs to be called from JS and should not generate JS code
500      * Looks up a variable identifier in various tables and generates JavaScript code that could be eval'd to get the value.
501      * @param {String} vname Identifier
502      * @param {Boolean} [local=false] Don't resolve ids and names of elements
503      * @param {Boolean} [withProps=false]
504      */
505     getvarJS: function (vname, local, withProps) {
506         var s, r = '', re;
507 
508         local = Type.def(local, false);
509         withProps = Type.def(withProps, false);
510 
511         s = this.isParameter(vname);
512         if (s !== null) {
513             return vname;
514         }
515 
516         s = this.isLocalVariable(vname);
517         if (s !== null && !withProps) {
518             return '$jc$.resolve(\'' + vname + '\')';
519         }
520 
521         // check for an element with this name
522         if (this.isCreator(vname)) {
523             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])); })';
524         }
525 
526         if (withProps) {
527             this._error('Syntax error (attribute values are allowed with element creators only)');
528         }
529 
530         if (this.isBuiltIn(vname)) {
531             // If src does not exist, it is a number. In that case, just return the value.
532             r = this.builtIn[vname].src || this.builtIn[vname];
533 
534             // Get the "real" name of the function
535             if (Type.isNumber(r)) {
536                 return r;
537             }
538             // Search a JSXGraph object in board
539             if (r.match(/board\.select/)) {
540                 return r;
541             }
542 
543             /* eslint-disable no-useless-escape */
544             vname = r.split('.').pop();
545             if (Type.exists(this.board.mathLib)) {
546                 // Handle builtin case: ln(x) -> Math.log
547                 re = new RegExp('^Math\.' + vname);
548                 if (re.exec(r) !== null) {
549                     return r.replace(re, '$jc$.board.mathLib.' + vname);
550                 }
551             }
552             if (Type.exists(this.board.mathLibJXG)) {
553                 // Handle builtin case: factorial(x) -> JXG.Math.factorial
554                 re = new RegExp('^JXG\.Math\.');
555                 if (re.exec(r) !== null) {
556                     return r.replace(re, '$jc$.board.mathLibJXG.');
557                 }
558                 return r;
559             }
560             /* eslint-enable no-useless-escape */
561             return r;
562 
563             // return this.builtIn[vname].src || this.builtIn[vname];
564         }
565 
566         if (this.isMathMethod(vname)) {
567             return '$jc$.board.mathLib.' + vname;
568             //                return 'Math.' + vname;
569         }
570 
571         // if (!local) {
572         //     if (Type.isId(this.board, vname)) {
573         //         r = '$jc$.board.objects[\'' + vname + '\']';
574         //     } else if (Type.isName(this.board, vname)) {
575         //         r = '$jc$.board.elementsByName[\'' + vname + '\']';
576         //     } else if (Type.isGroup(this.board, vname)) {
577         //         r = '$jc$.board.groups[\'' + vname + '\']';
578         //     }
579 
580         //     return r;
581         // }
582         if (!local) {
583             if (Type.isId(this.board, vname)) {
584                 r = '$jc$.board.objects[\'' + vname + '\']';
585                 if (this.board.objects[vname].elType === 'slider') {
586                     r += '.Value()';
587                 }
588             } else if (Type.isName(this.board, vname)) {
589                 r = '$jc$.board.elementsByName[\'' + vname + '\']';
590                 if (this.board.elementsByName[vname].elType === 'slider') {
591                     r += '.Value()';
592                 }
593             } else if (Type.isGroup(this.board, vname)) {
594                 r = '$jc$.board.groups[\'' + vname + '\']';
595             }
596 
597             return r;
598         }
599 
600         return '';
601     },
602 
603     /**
604      * Adds the property <tt>isMap</tt> to a function and sets it to true.
605      * @param {function} f
606      * @returns {function}
607      */
608     makeMap: function (f) {
609         f.isMap = true;
610 
611         return f;
612     },
613 
614     functionCodeJS: function (node) {
615         var p = node.children[0].join(', '),
616             bo = '',
617             bc = '';
618 
619         if (node.value === 'op_map') {
620             bo = '{ return  ';
621             bc = ' }';
622         }
623 
624         return 'function (' + p + ') {\n' +
625             'var $oldscope$ = $jc$.scope;\n' +
626             '$jc$.scope = $jc$.scopes[' + this.scope.id + '];\n' +
627             'var r = (function () ' + bo + this.compile(node.children[1], true) + bc + ')();\n' +
628             '$jc$.scope = $oldscope$;\n' +
629             'return r;\n' +
630             '}';
631     },
632 
633     /**
634      * Converts a node type <tt>node_op</tt> and value <tt>op_map</tt> or <tt>op_function</tt> into a executable
635      * function. Does a simple type inspection.
636      * @param {Object} node
637      * @returns {function}
638      * @see JXG.JessieCode#resolveType
639      */
640     defineFunction: function (node) {
641         var fun, i, that = this,
642             list = node.children[0],
643             scope = this.pushScope(list);
644 
645         if (this.board.options.jc.compile) {
646             this.isLHS = false;
647 
648             // we currently need to put the parameters into the local scope
649             // until the compiled JS variable lookup code is fixed
650             for (i = 0; i < list.length; i++) {
651                 scope.locals[list[i]] = list[i];
652             }
653 
654             this.replaceNames(node.children[1]);
655 
656             /** @ignore */
657             fun = (function (jc) {
658                 var fun,
659                     // str = 'var f = ' + $jc$.functionCodeJS(node) + '; f;';
660                     str = 'var f = function($jc$) { return ' +
661                         jc.functionCodeJS(node) +
662                         '}; f;';
663 
664                 try {
665                     // yeah, eval is evil, but we don't have much choice here.
666                     // the str is well defined and there is no user input in it that we didn't check before
667 
668                     /*jslint evil:true*/
669                     // fun = eval(str);
670                     fun = eval(str)(jc);
671                     /*jslint evil:false*/
672 
673                     scope.argtypes = [];
674                     for (i = 0; i < list.length; i++) {
675                         scope.argtypes.push(that.resolveType(list[i], node));
676                     }
677 
678                     return fun;
679                 } catch (e) {
680                     // $jc$._warn('error compiling function\n\n' + str + '\n\n' + e.toString());
681                     jc._warn("error compiling function\n\n" + str + "\n\n" + e.toString());
682                     return function () { };
683                 }
684             }(this));
685 
686             // clean up scope
687             this.popScope();
688         } else {
689             /** @ignore */
690             fun = (function (_pstack, that, id) {
691                 return function () {
692                     var r, oldscope;
693 
694                     oldscope = that.scope;
695                     that.scope = that.scopes[id];
696 
697                     for (r = 0; r < _pstack.length; r++) {
698                         that.scope.locals[_pstack[r]] = arguments[r];
699                     }
700 
701                     r = that.execute(node.children[1]);
702                     that.scope = oldscope;
703 
704                     return r;
705                 };
706             }(list, this, scope.id));
707         }
708 
709         fun.node = node;
710         fun.scope = scope;
711         fun.toJS = fun.toString;
712         fun.toString = (function (_that) {
713             return function () {
714                 return _that.compile(_that.replaceIDs(Type.deepCopy(node)));
715             };
716         }(this));
717 
718         fun.deps = {};
719         this.collectDependencies(node.children[1], node.children[0], fun.deps);
720 
721         return fun;
722     },
723 
724     /**
725      * Merge all attribute values given with an element creator into one object.
726      * @param {Object} o An arbitrary number of objects
727      * @returns {Object} All given objects merged into one. If properties appear in more (case sensitive) than one
728      * object the last value is taken.
729      */
730     mergeAttributes: function (o) {
731         var i, attr = {};
732 
733         for (i = 0; i < arguments.length; i++) {
734             attr = Type.deepCopy(attr, arguments[i], true);
735         }
736 
737         return attr;
738     },
739 
740     /**
741      * Sets the property <tt>what</tt> of <tt>o</tt> to <tt>value</tt>
742      * @param {JXG.Point|JXG.Text} o
743      * @param {String} what
744      * @param value
745      */
746     setProp: function (o, what, value) {
747         var par = {}, x, y;
748 
749         if (o.elementClass === Const.OBJECT_CLASS_POINT && (what === 'X' || what === 'Y')) {
750             // set coords
751 
752             what = what.toLowerCase();
753 
754             // we have to deal with three cases here:
755             // o.isDraggable && typeof value === number:
756             //   stay draggable, just set the new coords (e.g. via moveTo)
757             // o.isDraggable && typeof value === function:
758             //   convert to !o.isDraggable, set the new coords via o.addConstraint()
759             // !o.isDraggable:
760             //   stay !o.isDraggable, update the given coord by overwriting X/YEval
761 
762             if (o.isDraggable && typeof value === 'number') {
763                 x = (what === 'x') ? value : o.X();
764                 y = (what === 'y') ? value : o.Y();
765 
766                 o.setPosition(Const.COORDS_BY_USER, [x, y]);
767             } else if (o.isDraggable && (typeof value === 'function' || typeof value === 'string')) {
768                 x = (what === 'x') ? value : o.coords.usrCoords[1];
769                 y = (what === 'y') ? value : o.coords.usrCoords[2];
770 
771                 o.addConstraint([x, y]);
772             } else if (!o.isDraggable) {
773                 x = (what === 'x') ? value : o.XEval.origin;
774                 y = (what === 'y') ? value : o.YEval.origin;
775 
776                 o.addConstraint([x, y]);
777             }
778 
779             this.board.update();
780         } else if (o.elementClass === Const.OBJECT_CLASS_TEXT && (what === 'X' || what === 'Y')) {
781             if (typeof value === 'number') {
782                 o[what] = function () { return value; };
783             } else if (typeof value === 'function') {
784                 o.isDraggable = false;
785                 o[what] = value;
786             } else if (typeof value === 'string') {
787                 o.isDraggable = false;
788                 o[what] = Type.createFunction(value, this.board);
789                 o[what + 'jc'] = value;
790             }
791 
792             o[what].origin = value;
793 
794             this.board.update();
795         } else if (o.type && o.elementClass && o.visProp) {
796             if (Type.exists(o[o.methodMap[what]]) && typeof o[o.methodMap[what]] !== 'function') {
797                 o[o.methodMap[what]] = value;
798             } else {
799                 par[what] = value;
800                 o.setAttribute(par);
801             }
802         } else {
803             o[what] = value;
804         }
805     },
806 
807     /**
808      * Generic method to parse JessieCode.
809      * This consists of generating an AST with parser.parse,
810      * apply simplifying rules from CA and
811      * manipulate the AST according to the second parameter "cmd".
812      * @param  {String} code      JessieCode code to be parsed
813      * @param  {String} cmd       Type of manipulation to be done with AST
814      * @param {Object} [options]  Object with attributes <ul>
815      *     <li>{Boolean} [geonext=false]     Geonext compatibility mode.</li>
816      *     <li>{Boolean} [dontstore=false]   If false, the code string is stored in this.code, i.e. in the JessieCode object, e.g. in board.jc.</li>
817      *     </ul>
818      * @return {Object} Returns result of computation as directed in cmd.
819      */
820     _genericParse: function (code, cmd, options) {
821         var i, setTextBackup, ast, result,
822             ccode = code.replace(/\r\n/g, '\n').split('\n'),
823             cleaned = [];
824 
825         if (!Type.exists(options)) {
826             options = {};
827         }
828 
829         if (!options.dontstore) {
830             this.code += code + '\n';
831         }
832 
833         if (Text) {
834             setTextBackup = Text.prototype.setText;
835             Text.prototype.setText = Text.prototype.setTextJessieCode;
836         }
837 
838         try {
839             for (i = 0; i < ccode.length; i++) {
840                 if (!!options.geonext) {
841                     ccode[i] = JXG.GeonextParser.geonext2JS(ccode[i], this.board);
842                 }
843                 cleaned.push(ccode[i]);
844             }
845 
846             code = cleaned.join('\n');
847             ast = parser.parse(code);
848             if (this.CA) {
849                 ast = this.CA.expandDerivatives(ast, null, ast);
850                 ast = this.CA.removeTrivialNodes(ast);
851             }
852             if (this.CAS) {
853                 // Search for expression of form `D(f, x)` and determine the
854                 // the derivative symbolically.
855                 ast = this.CAS.expandDerivatives(ast, null, ast);
856 
857                 // options.method = options.method || "strong";
858                 // options.form = options.form || "fractions";
859                 // options.steps = options.steps || [];
860                 // options.iterations = options.iterations || 1000;
861                 // ast = this.CAS._simplify_aux(ast, options);
862             }
863             switch (cmd) {
864                 case 'parse':
865                     result = this.execute(ast);
866                     break;
867                 case 'manipulate':
868                     result = this.compile(ast);
869                     break;
870                 case 'simplify':
871                     if (Type.exists(this.CAS)) {
872                         options.method = options.method || "strong";
873                         options.form = options.form || "fractions";
874                         options.steps = options.steps || [];
875                         options.iterations = options.iterations || 1000;
876                         ast = this.CAS.simplify(ast, options);
877                         result = this.CAS.compile(ast);
878                     } else {
879                         result = this.compile(ast);
880                     }
881                     break;
882                 case 'format':
883                     result = this.compile(ast, false, options);
884                     break;
885                 case 'getAst':
886                     result = ast;
887                     break;
888                 default:
889                     result = false;
890             }
891         } catch (e) {  // catch is mandatory in old IEs
892             // console.log(e);
893             // We throw the error again,
894             // so the user can catch it.
895             throw e;
896         } finally {
897             // make sure the original text method is back in place
898             if (Text) {
899                 Text.prototype.setText = setTextBackup;
900             }
901         }
902 
903         return result;
904     },
905 
906     /**
907      * Parses JessieCode.
908      * This consists of generating an AST with parser.parse, apply simplifying rules
909      * from CA and executing the ast by calling this.execute(ast).
910      *
911      * @param {String} code             JessieCode code to be parsed
912      * @param {Boolean} [geonext=false] Geonext compatibility mode.
913      * @param {Boolean} [dontstore=false] If false, the code string is stored in this.code.
914      * @return {Object}                 Parse JessieCode code and execute it.
915      */
916     parse: function (code, geonext, dontstore) {
917         return this._genericParse(code, 'parse', {geonext: geonext, dontstore: dontstore});
918     },
919 
920     /**
921      * Manipulate JessieCode.
922      * This consists of generating an AST with parser.parse,
923      * apply simplifying rules from CA
924      * and compile the AST back to JessieCode.
925      *
926      * @param {String} code             JessieCode code to be parsed
927      * @param {Boolean} [geonext=false] Geonext compatibility mode.
928      * @param {Boolean} [dontstore=false] If false, the code string is stored in this.code.
929      * @return {String}                 Simplified JessieCode code
930      */
931     manipulate: function (code, geonext, dontstore) {
932         return this._genericParse(code, 'manipulate', {geonext: geonext, dontstore: dontstore});
933     },
934 
935     /**
936      * Manipulate JessieCode.
937      * This consists of generating an AST with parser.parse,
938      * apply simplifying rules from CAS
939      * and compile the AST back to JessieCode with minimal number of parentheses.
940      *
941      * @param {String} code             JessieCode code to be parsed
942      * @return {String}                 Simplified JessieCode code
943      */
944     simplify: function (code) {
945         return this._genericParse(code, 'simplify');
946     },
947 
948     /**
949      * Format JessieCode.
950      * This consists of generating an AST with parser.parse,
951      * and compile the AST back to JessieCode with options.
952      *
953      * @param {String} code      JessieCode code to be parsed.
954      * @param {Object} options   For possible options see param "format" in {@link JXG.JessieCode#compile}.
955      * @return {String}          Manipulated JessieCode string. This is no necessarily a parsable JessieCode code!
956      */
957     format: function (code, options) {
958         return this._genericParse(code, 'format', options);
959     },
960 
961     /**
962      * Get abstract syntax tree (AST) from JessieCode code.
963      * This consists of generating an AST with parser.parse.
964      *
965      * @param {String} code
966      * @param {Boolean} [geonext=false] Geonext compatibility mode.
967      * @param {Boolean} [dontstore=false] If false, the code string is stored in this.code.
968      * @return {Node}  AST
969      */
970     getAST: function (code, geonext, dontstore) {
971         return this._genericParse(code, 'getAst', {geonext: geonext, dontstore: dontstore});
972     },
973 
974     /**
975      * Parses a JessieCode snippet, e.g. "3+4", and wraps it into a function, if desired.
976      * @param {String} code A small snippet of JessieCode. Must not be an assignment.
977      * @param {Boolean} [funwrap=true] If true, the code is wrapped in a function.
978      * @param {String} [varname=''] Name of the parameter(s)
979      * @param {Boolean} [geonext=false] Geonext compatibility mode.
980      * @param {Boolean} [forceValueCall=true] Force evaluation of value method of sliders.
981      */
982     snippet: function (code, funwrap, varname, geonext, forceValueCall) {
983         var c;
984 
985         funwrap = Type.def(funwrap, true);
986         varname = Type.def(varname, '');
987         geonext = Type.def(geonext, false);
988         this.forceValueCall = Type.def(forceValueCall, true);
989 
990         c = (funwrap ? ' function (' + varname + ') { return ' : '') +
991                 code +
992             (funwrap ? '; }' : '') + ';';
993 
994         return this.parse(c, geonext, true);
995     },
996 
997     /**
998      * Traverses through the given subtree and changes all values of nodes with the replaced flag set by
999      * {@link JXG.JessieCode#replaceNames} to the name of the element (if not empty).
1000      * @param {Object} node
1001      */
1002     replaceIDs: function (node) {
1003         var i, v;
1004 
1005         if (node.replaced) {
1006             // These children exist, if node.replaced is set.
1007             v = this.board.objects[node.children[1][0].value];
1008 
1009             if (Type.exists(v) && v.name !== "") {
1010                 node.type = 'node_var';
1011                 node.value = v.name;
1012 
1013                 // Maybe it's not necessary, but just to be sure that everything is cleaned up we better delete all
1014                 // children and the replaced flag
1015                 node.children.length = 0;
1016                 delete node.replaced;
1017             }
1018         }
1019 
1020         if (Type.isArray(node)) {
1021             for (i = 0; i < node.length; i++) {
1022                 node[i] = this.replaceIDs(node[i]);
1023             }
1024         }
1025 
1026         if (node.children) {
1027             // assignments are first evaluated on the right hand side
1028             for (i = node.children.length; i > 0; i--) {
1029                 if (Type.exists(node.children[i - 1])) {
1030                     node.children[i - 1] = this.replaceIDs(node.children[i - 1]);
1031                 }
1032 
1033             }
1034         }
1035 
1036         return node;
1037     },
1038 
1039     /**
1040      * Traverses through the given subtree and changes all elements referenced by names through referencing them by ID.
1041      * An identifier is only replaced if it is not found in all scopes above the current scope and if it
1042      * has not been blacklisted within the codeblock determined by the given subtree.
1043      * @param {Object} node
1044      * @param {Boolean} [callValuePar=false] if true, uses $value() instead of $() in createReplacementNode
1045      */
1046     replaceNames: function (node, callValuePar) {
1047         var i, v,
1048             callValue = false;
1049 
1050         if (callValuePar !== undefined) {
1051             callValue = callValuePar;
1052         }
1053 
1054         v = node.value;
1055 
1056         // We are interested only in nodes of type node_var and node_op > op_lhs.
1057         // Currently, we are not checking if the id is a local variable. in this case, we're stuck anyway.
1058 
1059         if (node.type === 'node_op' && v === 'op_lhs' && node.children.length === 1) {
1060             this.isLHS = true;
1061         } else if (node.type === 'node_var') {
1062             if (this.isLHS) {
1063                 this.letvar(v, true);
1064             } else if (!Type.exists(this.getvar(v, true)) && Type.exists(this.board.elementsByName[v])) {
1065                 if (callValue && this.board.elementsByName[v].elType !== 'slider') {
1066                     callValue = false;
1067                 }
1068                 node = this.createReplacementNode(node, callValue);
1069             }
1070         }
1071 
1072         if (Type.isArray(node)) {
1073             for (i = 0; i < node.length; i++) {
1074                 node[i] = this.replaceNames(node[i], callValue);
1075             }
1076         }
1077 
1078         if (node.children) {
1079             // Replace slider reference by call of slider.Value()
1080             if (this.forceValueCall &&              // It must be enforced, see snippet.
1081                 (
1082                     // 1. case: sin(a), max(a, 0), ...
1083                     (node.value === "op_execfun" &&
1084                         // Not in cases V(a), $(a)
1085                         node.children[0].value !== 'V' && node.children[0].value !== '$' &&
1086                         // Function must be a math function. This ensures that a number is required as input.
1087                         (Type.exists(Math[node.children[0].value]) || Type.exists(Mat[node.children[0].value])) &&
1088                         // node.children[1].length === 1 &&
1089                         node.children[1][0].type === 'node_var'
1090                     ) ||
1091                     // 2. case: slider is the whole expression: 'a'
1092                     (node.value === "op_return" &&
1093                         node.children.length === 1 &&
1094                         node.children[0].type === 'node_var'
1095                     )
1096                 )
1097             ) {
1098                     callValue = true;
1099             }
1100 
1101             // Assignments are first evaluated on the right hand side
1102             for (i = node.children.length; i > 0; i--) {
1103                 if (Type.exists(node.children[i - 1])) {
1104                     node.children[i - 1] = this.replaceNames(node.children[i - 1], callValue);
1105                 }
1106             }
1107         }
1108 
1109         if (node.type === 'node_op' && node.value === 'op_lhs' && node.children.length === 1) {
1110             this.isLHS = false;
1111         }
1112 
1113         return node;
1114     },
1115 
1116     /**
1117      * Replaces node_var nodes with node_op>op_execfun nodes, calling the internal $() function with the id of the
1118      * element accessed by the node_var node.
1119      * @param {Object} node
1120      * @param {Boolean} [callValue=undefined] if true, uses $value() instead of $()
1121      * @returns {Object} op_execfun node
1122      */
1123     createReplacementNode: function (node, callValue) {
1124         var v = node.value,
1125             el = this.board.elementsByName[v];
1126 
1127         // If callValue: get handle to this node_var and call its Value method.
1128         // Otherwise return the object.
1129         node = this.createNode('node_op', 'op_execfun',
1130             this.createNode('node_var', ((callValue === true) ? '$value' : '$')),
1131             [this.createNode('node_str', el.id)]);
1132 
1133         node.replaced = true;
1134 
1135         return node;
1136     },
1137 
1138     /**
1139      * Search the parse tree below <tt>node</tt> for <em>stationary</em> dependencies, i.e. dependencies hard coded into
1140      * the function.
1141      * @param {Object} node
1142      * @param {Array} varnames List of variable names of the function
1143      * @param {Object} result An object where the referenced elements will be stored. Access key is their id.
1144      */
1145     collectDependencies: function (node, varnames, result) {
1146         var i, v, e, le;
1147 
1148         if (Type.isArray(node)) {
1149             le = node.length;
1150             for (i = 0; i < le; i++) {
1151                 this.collectDependencies(node[i], varnames, result);
1152             }
1153             return;
1154         }
1155 
1156         v = node.value;
1157 
1158         if (node.type === 'node_var' &&
1159             varnames.indexOf(v) < 0 // v is not contained in the list of variables of that function
1160         ) {
1161             e = this.getvar(v);
1162             if (e && e.visProp && e.elType && e.elementClass && e.id
1163                 // Sliders are the only elements which are given by names.
1164                 // Wrong, a counter example is: circle(c, function() { return p1.Dist(p2); })
1165                 // && e.elType === 'slider'
1166             ) {
1167                 result[e.id] = e;
1168             }
1169         }
1170 
1171         // The $()-function-calls are special because their parameter is given as a string, not as a node_var.
1172         if (node.type === 'node_op' && node.value === 'op_execfun' &&
1173             node.children.length > 1 &&
1174             (node.children[0].value === '$' || node.children[0].value === '$value') &&
1175             node.children[1].length > 0) {
1176 
1177             e = node.children[1][0].value;
1178             result[e] = this.board.objects[e];
1179         }
1180 
1181         if (node.children) {
1182             for (i = node.children.length; i > 0; i--) {
1183                 if (Type.exists(node.children[i - 1])) {
1184                     this.collectDependencies(node.children[i - 1], varnames, result);
1185                 }
1186             }
1187         }
1188     },
1189 
1190     resolveProperty: function (e, v, compile) {
1191         compile = Type.def(compile, false);
1192 
1193         // is it a geometry element or a board?
1194         if (e /*&& e.type && e.elementClass*/ && e.methodMap) {
1195             // yeah, it is. but what does the user want?
1196             if (Type.exists(e.subs) && Type.exists(e.subs[v])) {
1197                 // a subelement it is, good sir.
1198                 e = e.subs;
1199             } else if (Type.exists(e.methodMap[v])) {
1200                 // the user wants to call a method
1201                 v = e.methodMap[v];
1202             } else {
1203                 // the user wants to change an attribute
1204                 e = e.visProp;
1205                 v = v.toLowerCase();
1206             }
1207         }
1208 
1209         if (Type.isFunction(e)) {
1210             this._error('Accessing function properties is not allowed.');
1211         }
1212 
1213         if (!Type.exists(e)) {
1214             this._error(e + ' is not an object');
1215         }
1216 
1217         if (!Type.exists(e[v])) {
1218             this._error('unknown property ' + v);
1219         }
1220 
1221         if (compile && typeof e[v] === 'function') {
1222             return function () { return e[v].apply(e, arguments); };
1223         }
1224 
1225         return e[v];
1226     },
1227 
1228     /**
1229      * Type inspection: check if the string vname appears as function name in the
1230      * AST node. Used in "op_execfun". This allows the JessieCode examples below.
1231      *
1232      * @private
1233      * @param {String} vname
1234      * @param {Object} node
1235      * @returns 'any' or 'function'
1236      * @see JXG.JessieCode#execute
1237      * @see JXG.JessieCode#getvar
1238      *
1239      * @example
1240      *  var p = board.create('point', [2, 0], {name: 'X'});
1241      *  var txt = 'X(X)';
1242      *  console.log(board.jc.parse(txt));
1243      *
1244      * @example
1245      *  var p = board.create('point', [2, 0], {name: 'X'});
1246      *  var txt = 'f = function(el, X) { return X(el); }; f(X, X);';
1247      *  console.log(board.jc.parse(txt));
1248      *
1249      * @example
1250      *  var p = board.create('point', [2, 0], {name: 'point'});
1251      *  var txt = 'B = point(1,3); X(point);';
1252      *  console.log(board.jc.parse(txt));
1253      *
1254      * @example
1255      *  var p = board.create('point', [2, 0], {name: 'A'});
1256      *  var q = board.create('point', [-2, 0], {name: 'X'});
1257      *  var txt = 'getCoord=function(p, f){ return f(p); }; getCoord(A, X);';
1258      *  console.log(board.jc.parse(txt));
1259      */
1260     resolveType: function (vname, node) {
1261         var i, t,
1262             type = 'any'; // Possible values: 'function', 'any'
1263 
1264         if (Type.isArray(node)) {
1265             // node contains the parameters of a function call or function declaration
1266             for (i = 0; i < node.length; i++) {
1267                 t = this.resolveType(vname, node[i]);
1268                 if (t !== 'any') {
1269                     type = t;
1270                     return type;
1271                 }
1272             }
1273         }
1274 
1275         if (node.type === 'node_op' && node.value === 'op_execfun' &&
1276             node.children[0].type === 'node_var' && node.children[0].value === vname) {
1277             return 'function';
1278         }
1279 
1280         if (node.type === 'node_op') {
1281             for (i = 0; i < node.children.length; i++) {
1282                 if (node.children[0].type === 'node_var' && node.children[0].value === vname &&
1283                     (node.value === 'op_add' || node.value === 'op_sub' || node.value === 'op_mul' ||
1284                         node.value === 'op_div' || node.value === 'op_mod' || node.value === 'op_exp' ||
1285                         node.value === 'op_neg')) {
1286                     return 'any';
1287                 }
1288             }
1289 
1290             for (i = 0; i < node.children.length; i++) {
1291                 t = this.resolveType(vname, node.children[i]);
1292                 if (t !== 'any') {
1293                     type = t;
1294                     return type;
1295                 }
1296             }
1297         }
1298 
1299         return 'any';
1300     },
1301 
1302     /**
1303      * Resolves the lefthand side of an assignment operation
1304      * @param node
1305      * @returns {Object} An object with two properties. <strong>o</strong> which contains the object, and
1306      * a string <strong>what</strong> which contains the property name.
1307      */
1308     getLHS: function (node) {
1309         var res;
1310 
1311         if (node.type === 'node_var') {
1312             res = {
1313                 o: this.scope.locals,
1314                 what: node.value
1315             };
1316         } else if (node.type === 'node_op' && node.value === 'op_property') {
1317             res = {
1318                 o: this.execute(node.children[0]),
1319                 what: node.children[1]
1320             };
1321         } else if (node.type === 'node_op' && node.value === 'op_extvalue') {
1322             res = {
1323                 o: this.execute(node.children[0]),
1324                 what: this.execute(node.children[1])
1325             };
1326         } else {
1327             throw new Error('Syntax error: Invalid left-hand side of assignment.');
1328         }
1329 
1330         return res;
1331     },
1332 
1333     getLHSCompiler: function (node, js) {
1334         var res;
1335 
1336         if (node.type === 'node_var') {
1337             res = node.value;
1338         } else if (node.type === 'node_op' && node.value === 'op_property') {
1339             res = [
1340                 this.compile(node.children[0], js),
1341                 "'" + node.children[1] + "'"
1342             ];
1343         } else if (node.type === 'node_op' && node.value === 'op_extvalue') {
1344             res = [
1345                 this.compile(node.children[0], js),
1346                 (node.children[1].type === 'node_const') ? node.children[1].value : this.compile(node.children[1], js)
1347             ];
1348         } else {
1349             throw new Error('Syntax error: Invalid left-hand side of assignment.');
1350         }
1351 
1352         return res;
1353     },
1354 
1355     /**
1356      * Executes a parse subtree.
1357      * @param {Object} node
1358      * @returns {Number|String|Object|Boolean} Something
1359      * @private
1360      */
1361     execute: function (node) {
1362         var ret, v, i, e, l, undef, list, ilist,
1363             parents = [],
1364             // exec fun
1365             fun, attr, sc;
1366 
1367         ret = 0;
1368 
1369         if (!node) {
1370             return ret;
1371         }
1372 
1373         this.line = node.line;
1374         this.col = node.col;
1375 
1376         switch (node.type) {
1377             case 'node_op':
1378                 switch (node.value) {
1379                     case 'op_none':
1380                         if (node.children[0]) {
1381                             this.execute(node.children[0]);
1382                         }
1383                         if (node.children[1]) {
1384                             ret = this.execute(node.children[1]);
1385                         }
1386                         break;
1387                     case 'op_block':
1388                         ret = this.execute(node.children[0]);
1389                         break;
1390                     case 'op_assign':
1391                         v = this.getLHS(node.children[0]);
1392                         this.lhs[this.scope.id] = v.what;
1393 
1394                         if (v.o.type && v.o.elementClass && v.o.methodMap && v.what === 'label') {
1395                             this._error('Left-hand side of assignment is read-only.');
1396                         }
1397 
1398                         ret = this.execute(node.children[1]);
1399                         if (v.o !== this.scope.locals || (Type.isArray(v.o) && typeof v.what === 'number')) {
1400                             // it is either an array component being set or a property of an object.
1401                             this.setProp(v.o, v.what, ret);
1402                         } else {
1403                             // this is just a local variable inside JessieCode
1404                             this.letvar(v.what, ret);
1405                         }
1406                         this.lhs[this.scope.id] = 0;
1407                         break;
1408                     case 'op_if':
1409                         if (this.execute(node.children[0])) {
1410                             ret = this.execute(node.children[1]);
1411                         }
1412                         break;
1413                     case 'op_conditional':
1414                     // fall through
1415                     case 'op_if_else':
1416                         if (this.execute(node.children[0])) {
1417                             ret = this.execute(node.children[1]);
1418                         } else {
1419                             ret = this.execute(node.children[2]);
1420                         }
1421                         break;
1422                     case 'op_while':
1423                         while (this.execute(node.children[0])) {
1424                             this.execute(node.children[1]);
1425                         }
1426                         break;
1427                     case 'op_do':
1428                         do {
1429                             this.execute(node.children[0]);
1430                         } while (this.execute(node.children[1]));
1431                         break;
1432                     case 'op_for':
1433                         for (this.execute(node.children[0]); this.execute(node.children[1]); this.execute(node.children[2])) {
1434                             this.execute(node.children[3]);
1435                         }
1436                         break;
1437                     case 'op_proplst':
1438                         if (node.children[0]) {
1439                             this.execute(node.children[0]);
1440                         }
1441                         if (node.children[1]) {
1442                             this.execute(node.children[1]);
1443                         }
1444                         break;
1445                     case 'op_emptyobject':
1446                         ret = {};
1447                         break;
1448                     case 'op_proplst_val':
1449                         this.propstack.push({});
1450                         this.propscope++;
1451 
1452                         this.execute(node.children[0]);
1453                         ret = this.propstack[this.propscope];
1454 
1455                         this.propstack.pop();
1456                         this.propscope--;
1457                         break;
1458                     case 'op_prop':
1459                         // child 0: Identifier
1460                         // child 1: Value
1461                         this.propstack[this.propscope][node.children[0]] = this.execute(node.children[1]);
1462                         break;
1463                     case 'op_array':
1464                         ret = [];
1465                         l = node.children[0].length;
1466 
1467                         for (i = 0; i < l; i++) {
1468                             ret.push(this.execute(node.children[0][i]));
1469                         }
1470 
1471                         break;
1472                     case 'op_extvalue':
1473                         ret = this.execute(node.children[0]);
1474                         i = this.execute(node.children[1]);
1475 
1476                         if (typeof i === 'number' && Math.abs(Math.round(i) - i) < 1.e-12) {
1477                             ret = ret[i];
1478                         } else {
1479                             ret = undef;
1480                         }
1481                         break;
1482                     case 'op_return':
1483                         if (this.scope === 0) {
1484                             this._error('Unexpected return.');
1485                         } else {
1486                             return this.execute(node.children[0]);
1487                         }
1488                         break;
1489                     case 'op_map':
1490                         if (!node.children[1].isMath && node.children[1].type !== 'node_var') {
1491                             this._error('execute: In a map only function calls and mathematical expressions are allowed.');
1492                         }
1493 
1494                         /** @ignore */
1495                         fun = this.defineFunction(node);
1496                         fun.isMap = true;
1497 
1498                         ret = fun;
1499                         break;
1500                     case 'op_function':
1501                         // parse the parameter list
1502                         // after this, the parameters are in pstack
1503 
1504                         /** @ignore */
1505                         fun = this.defineFunction(node);
1506                         fun.isMap = false;
1507 
1508                         ret = fun;
1509                         break;
1510                     case 'op_execfun':
1511                         // node.children:
1512                         //   [0]: Name of the function
1513                         //   [1]: Parameter list as a parse subtree
1514                         //   [2]: Properties, only used in case of a create function
1515                         this.dpstack.push([]);
1516                         this.pscope++;
1517 
1518                         // parameter parsing is done below
1519                         list = node.children[1];
1520 
1521                         // parse the properties only if given
1522                         if (Type.exists(node.children[2])) {
1523                             if (node.children[3]) {
1524                                 ilist = node.children[2];
1525                                 attr = {};
1526 
1527                                 for (i = 0; i < ilist.length; i++) {
1528                                     attr = Type.deepCopy(attr, this.execute(ilist[i]), true);
1529                                 }
1530                             } else {
1531                                 attr = this.execute(node.children[2]);
1532                             }
1533                         }
1534 
1535                         // look up the variables name in the variable table
1536                         node.children[0]._isFunctionName = true;
1537                         fun = this.execute(node.children[0]);
1538                         delete node.children[0]._isFunctionName;
1539 
1540                         // determine the scope the function wants to run in
1541                         if (Type.exists(fun) && Type.exists(fun.sc)) {
1542                             sc = fun.sc;
1543                         } else {
1544                             sc = this;
1545                         }
1546 
1547                         if (!fun.creator && Type.exists(node.children[2])) {
1548                             this._error('Unexpected value. Only element creators are allowed to have a value after the function call.');
1549                         }
1550 
1551                         // interpret ALL the parameters
1552                         for (i = 0; i < list.length; i++) {
1553                             if (Type.exists(fun.scope) && Type.exists(fun.scope.argtypes) && fun.scope.argtypes[i] === 'function') {
1554                                 // Type inspection
1555                                 list[i]._isFunctionName = true;
1556                                 parents[i] = this.execute(list[i]);
1557                                 delete list[i]._isFunctionName;
1558                             } else {
1559                                 parents[i] = this.execute(list[i]);
1560                             }
1561                             //parents[i] = Type.evalSlider(this.execute(list[i]));
1562                             this.dpstack[this.pscope].push({
1563                                 line: node.children[1][i].line,
1564                                 // SketchBin currently works only if the last column of the
1565                                 // parent position is taken. This is due to how I patched JS/CC
1566                                 // to count the lines and columns. So, ecol will do for now
1567                                 col: node.children[1][i].ecol
1568                             });
1569                         }
1570 
1571                         // check for the function in the variable table
1572                         if (typeof fun === 'function' && !fun.creator) {
1573                             ret = fun.apply(sc, parents);
1574                         } else if (typeof fun === 'function' && !!fun.creator) {
1575                             e = this.line;
1576 
1577                             // creator methods are the only ones that take properties, hence this special case
1578                             try {
1579                                 ret = fun(parents, attr);
1580                                 ret.jcLineStart = e;
1581                                 ret.jcLineEnd = node.eline;
1582 
1583                                 for (i = e; i <= node.line; i++) {
1584                                     this.lineToElement[i] = ret;
1585                                 }
1586 
1587                                 ret.debugParents = this.dpstack[this.pscope];
1588                             } catch (ex) {
1589                                 this._error(ex.toString());
1590                             }
1591                         } else {
1592                             this._error('Function \'' + fun + '\' is undefined.');
1593                         }
1594 
1595                         // clear parameter stack
1596                         this.dpstack.pop();
1597                         this.pscope--;
1598                         break;
1599                     case 'op_property':
1600                         e = this.execute(node.children[0]);
1601                         v = node.children[1];
1602 
1603                         ret = this.resolveProperty(e, v, false);
1604 
1605                         // set the scope, in case this is a method the user wants to call
1606                         if (Type.exists(ret) && ['number', 'string', 'boolean'].indexOf(typeof ret) < 0) {
1607                             ret.sc = e;
1608                         }
1609 
1610                         break;
1611                     case 'op_use':
1612                         this._warn('Use of the \'use\' operator is deprecated.');
1613                         this.use(node.children[0].toString());
1614                         break;
1615                     case 'op_delete':
1616                         this._warn('Use of the \'delete\' operator is deprecated. Please use the remove() function.');
1617                         v = this.getvar(node.children[0]);
1618                         ret = this.del(v);
1619                         break;
1620                     case 'op_eq':
1621                         // == is intentional
1622                         /*jslint eqeq:true*/
1623                         /* eslint-disable eqeqeq */
1624                         ret = this.execute(node.children[0]) == this.execute(node.children[1]);
1625                         /*jslint eqeq:false*/
1626                         /* eslint-enable eqeqeq */
1627                         break;
1628                     case 'op_neq':
1629                         // != is intentional
1630                         /*jslint eqeq:true*/
1631                         /* eslint-disable eqeqeq */
1632                         ret = this.execute(node.children[0]) != this.execute(node.children[1]);
1633                         /*jslint eqeq:true*/
1634                         /* eslint-enable eqeqeq */
1635                         break;
1636                     case 'op_approx':
1637                         ret = Math.abs(this.execute(node.children[0]) - this.execute(node.children[1])) < Mat.eps;
1638                         break;
1639                     case 'op_gt':
1640                         ret = this.execute(node.children[0]) > this.execute(node.children[1]);
1641                         break;
1642                     case 'op_lt':
1643                         ret = this.execute(node.children[0]) < this.execute(node.children[1]);
1644                         break;
1645                     case 'op_geq':
1646                         ret = this.execute(node.children[0]) >= this.execute(node.children[1]);
1647                         break;
1648                     case 'op_leq':
1649                         ret = this.execute(node.children[0]) <= this.execute(node.children[1]);
1650                         break;
1651                     case 'op_or':
1652                         ret = this.execute(node.children[0]) || this.execute(node.children[1]);
1653                         break;
1654                     case 'op_and':
1655                         ret = this.execute(node.children[0]) && this.execute(node.children[1]);
1656                         break;
1657                     case 'op_not':
1658                         ret = !this.execute(node.children[0]);
1659                         break;
1660                     case 'op_add':
1661                         ret = this.add(this.execute(node.children[0]), this.execute(node.children[1]));
1662                         break;
1663                     case 'op_sub':
1664                         ret = this.sub(this.execute(node.children[0]), this.execute(node.children[1]));
1665                         break;
1666                     case 'op_div':
1667                         ret = this.div(this.execute(node.children[0]), this.execute(node.children[1]));
1668                         break;
1669                     case 'op_mod':
1670                         // use mathematical modulo, JavaScript implements the symmetric modulo.
1671                         ret = this.mod(this.execute(node.children[0]), this.execute(node.children[1]), true);
1672                         break;
1673                     case 'op_mul':
1674                         ret = this.mul(this.execute(node.children[0]), this.execute(node.children[1]));
1675                         break;
1676                     case 'op_exp':
1677                         ret = this.pow(this.execute(node.children[0]), this.execute(node.children[1]));
1678                         break;
1679                     case 'op_neg':
1680                         ret = this.neg(this.execute(node.children[0]));
1681                         break;
1682                 }
1683                 break;
1684 
1685             case 'node_var':
1686                 // node._isFunctionName is set in execute: at op_execfun.
1687                 ret = this.getvar(node.value, false, node._isFunctionName);
1688                 break;
1689 
1690             case 'node_const':
1691                 if (node.value === null) {
1692                     ret = null;
1693                 } else {
1694                     ret = Number(node.value);
1695                 }
1696                 break;
1697 
1698             case 'node_const_bool':
1699                 ret = node.value;
1700                 break;
1701 
1702             case 'node_str':
1703                 //ret = node.value.replace(/\\'/, "'").replace(/\\"/, '"').replace(/\\\\/, '\\');
1704                 /*jslint regexp:true*/
1705                 ret = node.value.replace(/\\(.)/g, '$1'); // Remove backslash, important in JessieCode tags
1706                 /*jslint regexp:false*/
1707                 break;
1708         }
1709 
1710         return ret;
1711     },
1712 
1713     /**
1714      * Compiles a parse tree back to JessieCode.
1715      * @param {Object} ast
1716      * @param {Boolean} [js=false] Compile either to JavaScript or back to JessieCode (required for the UI).
1717      * @param {Object} [format] Options for formatting the output. Depending on some options, the function might return a not re-parsable string. This format options have only effect on JessieCode output.<ul>
1718      *     <li>{Boolean} [minParentheses=false]               Use minimal amount of parentheses?</li>
1719      *     <li>{Boolean|Number|Function} [constToFixed=false] Use this number or function to format constant values.</li>
1720      *     <li>{Boolean} [printable=false]                    Adds additional signs or parentheses, e.g. x^0.5 --> x^{0.5}.</li>
1721      *     </ul>
1722      * @returns Something
1723      * @private
1724      */
1725     compile: function (ast, js, format) {
1726         var that = this;
1727 
1728         if (!Type.exists(js)) {
1729             js = false;
1730         }
1731         if (!Type.exists(format) || !Type.isObject(format)) {
1732             format = {};
1733         }
1734         format = Type.deepCopy({
1735             minParentheses: false,
1736             constToFixed: false,
1737             printable: false
1738         }, format);
1739 
1740         // node_const/node_var >> op_execfun >> op_neg >> op_exp >> op_mul/op_div >> op_add/op_sub >> op_map >> op_assign
1741         function prio(node) {
1742             switch (node.type) {
1743                 case "node_const":
1744                 case "node_const_bool":
1745                 case "node_str":
1746                 case "node_var":
1747                     return 10;
1748                 case "node_op":
1749                     switch (node.value) {
1750                         case "op_none":
1751                             return 0;
1752                         case "op_assign":
1753                             return 1;
1754                         case "op_map":
1755                         case "op_function":
1756                         case "op_return":
1757                             return 2;
1758                         case "op_add":
1759                         case "op_sub":
1760                             return 3;
1761                         case "op_mul":
1762                         case "op_div":
1763                         case "op_mod":
1764                             return 5;
1765                         case "op_neg":
1766                             return 4;
1767                         case "op_exp":
1768                             return 6;
1769                         case "op_array":
1770                         case "op_execfun":
1771                             return 7;
1772                         default:
1773                             return 0;
1774                     }
1775                 default:
1776                     return 0;
1777             }
1778         }
1779 
1780         function compile(node, prevOp, position = -1) {
1781             var e, i, c, list, scope, prioParent, prioChild,
1782                 ret = '';
1783 
1784             if (!node) {
1785                 return ret;
1786             }
1787 
1788             switch (node.type) {
1789                 case 'node_op':
1790                     switch (node.value) {
1791                         case 'op_none':
1792                             if (node.children[0]) {
1793                                 ret = compile(node.children[0], "op_none");
1794                             }
1795                             if (node.children[1]) {
1796                                 ret += compile(node.children[1], "op_none");
1797                             }
1798                             break;
1799                         case 'op_block':
1800                             ret = '{\n' + compile(node.children[0], "op_block") + ' }\n';
1801                             break;
1802                         case 'op_assign':
1803                             if (js) {
1804                                 e = that.getLHSCompiler(node.children[0], js);
1805                                 if (Type.isArray(e)) {
1806                                     ret = '$jc$.setProp(' + e[0] + ', ' + e[1] + ', ' + compile(node.children[1], "op_assign") + ');\n';
1807                                 } else {
1808                                     if (that.isLocalVariable(e) !== that.scope) {
1809                                         that.scope.locals[e] = true;
1810                                     }
1811                                     ret = '$jc$.scopes[' + that.scope.id + '].locals[\'' + e + '\'] = ' + compile(node.children[1], "op_assign") + ';\n';
1812                                 }
1813                             } else {
1814                                 e = compile(node.children[0], "op_assign");
1815                                 ret = e + ' = ' + compile(node.children[1], "op_assign") + ';\n';
1816                             }
1817                             break;
1818                         case 'op_if':
1819                             ret = ' if (' + compile(node.children[0], "op_if") + ') ' + compile(node.children[1], "op_if");
1820                             break;
1821                         case 'op_if_else':
1822                             ret = ' if (' + compile(node.children[0], "op_if_else") + ')' + compile(node.children[1], "op_if_else");
1823                             ret += ' else ' + compile(node.children[2], "op_if_else");
1824                             break;
1825                         case 'op_conditional':
1826                             ret = '((' + compile(node.children[0], "op_conditional") + ')?(' + compile(node.children[1], "op_conditional");
1827                             ret += '):(' + compile(node.children[2], "op_conditional") + '))';
1828                             break;
1829                         case 'op_while':
1830                             ret = ' while (' + compile(node.children[0], "op_while") + ') {\n' + compile(node.children[1], "op_while") + '}\n';
1831                             break;
1832                         case 'op_do':
1833                             ret = ' do {\n' + compile(node.children[0], "op_do") + '} while (' + compile(node.children[1], "op_do") + ');\n';
1834                             break;
1835                         case 'op_for':
1836                             //ret = ' for (' + compile(node.children[0]) + '; ' + compile(node.children[1]) + '; ' + compile(node.children[2]) + ') {\n' + compile(node.children[3]) + '\n}\n';
1837                             ret = ' for (' + compile(node.children[0], "op_for") +   // Assignment ends with ";"
1838                                 compile(node.children[1], "op_for") + '; ' +         // Logical test comes without ";"
1839                                 compile(node.children[2], "op_for").slice(0, -2) +   // Counting comes with ";" which has to be removed
1840                                 ') {\n' + compile(node.children[3], "op_for") + '\n}\n';
1841                             break;
1842                         case 'op_proplst':
1843                             if (node.children[0]) {
1844                                 ret = compile(node.children[0], "op_proplst") + ', ';
1845                             }
1846 
1847                             ret += compile(node.children[1], "op_proplst");
1848                             break;
1849                         case 'op_prop':
1850                             // child 0: Identifier
1851                             // child 1: Value
1852                             ret = node.children[0] + ': ' + compile(node.children[1], "op_prop");
1853                             break;
1854                         case 'op_emptyobject':
1855                             ret = js ? '{}' : '<< >>';
1856                             break;
1857                         case 'op_proplst_val':
1858                             ret = compile(node.children[0], "op_proplst_val");
1859                             break;
1860                         case 'op_array':
1861                             list = [];
1862                             for (i = 0; i < node.children[0].length; i++) {
1863                                 list.push(compile(node.children[0][i], "op_array"));
1864                             }
1865                             ret = '[' + list.join(', ') + ']';
1866                             break;
1867                         case 'op_extvalue':
1868                             ret = compile(node.children[0], "op_extvalue") + '[' + compile(node.children[1], "op_extvalue") + ']';
1869                             break;
1870                         case 'op_return':
1871                             ret = ' return ' + compile(node.children[0], "op_return") + ';\n';
1872                             break;
1873                         case 'op_map':
1874                             if (!node.children[1].isMath && node.children[1].type !== 'node_var') {
1875                                 that._error('compile: In a map only function calls and mathematical expressions are allowed.');
1876                             }
1877 
1878                             list = node.children[0];
1879                             if (js) {
1880                                 ret = ' $jc$.makeMap(function (' + list.join(', ') + ') { return ' + compile(node.children[1], "op_map") + '; })';
1881                             } else {
1882                                 ret = 'map (' + list.join(', ') + ') -> ' + compile(node.children[1], "op_map");
1883                             }
1884 
1885                             break;
1886                         case 'op_function':
1887                             list = node.children[0];
1888                             scope = that.pushScope(list);
1889                             if (js) {
1890                                 ret = that.functionCodeJS(node);
1891                             } else {
1892                                 ret = ' function (' + list.join(', ') + ') ' + compile(node.children[1], "op_function");
1893                             }
1894                             that.popScope();
1895                             break;
1896                         case 'op_execfunmath':
1897                             console.log('op_execfunmath: TODO');
1898                             ret = '-1';
1899                             break;
1900                         case 'op_execfun':
1901                             // parse the properties only if given
1902                             if (node.children[2]) {
1903                                 list = [];
1904                                 for (i = 0; i < node.children[2].length; i++) {
1905                                     list.push(compile(node.children[2][i], "op_execfun"));
1906                                 }
1907 
1908                                 if (js) {
1909                                     e = '$jc$.mergeAttributes(' + list.join(', ') + ')';
1910                                 } else {
1911                                     e = list.join(', ');
1912                                 }
1913                             }
1914                             node.children[0].withProps = !!node.children[2];
1915                             list = [];
1916                             for (i = 0; i < node.children[1].length; i++) {
1917                                 list.push(compile(node.children[1][i], "op_execfun"));
1918                             }
1919                             ret = compile(node.children[0], "op_execfun") + '(' + list.join(', ') + (node.children[2] && js ? ', ' + e : '') + ')' + ((node.children[2] && !js) ? ' ' + e : '');
1920                             if (js) {
1921                                 // Inserting a newline here allows simultaneously
1922                                 // - procedural calls like Q.moveTo(...); and
1923                                 // - function calls in expressions like log(x) + 1;
1924                                 // Problem: procedural calls will not be ended by a semicolon.
1925                                 ret += '\n';
1926                             }
1927 
1928                             // save us a function call when compiled to javascript
1929                             if (js && node.children[0].value === '$') {
1930                                 ret = '$jc$.board.objects[' + compile(node.children[1][0], "op_execfun") + ']';
1931                             }
1932                             break;
1933                         case 'op_property':
1934                             if (js && node.children[1] !== 'X' && node.children[1] !== 'Y') {
1935                                 ret = '$jc$.resolveProperty(' + compile(node.children[0], "op_property") + ', \'' + node.children[1] + '\', true)';
1936                             } else {
1937                                 ret = compile(node.children[0], "op_property") + '.' + node.children[1];
1938                             }
1939                             break;
1940                         case 'op_use':
1941                             that._warn('Use of the \'use\' operator is deprecated.');
1942                             if (js) {
1943                                 ret = '$jc$.use(\'';
1944                             } else {
1945                                 ret = 'use(\'';
1946                             }
1947 
1948                             ret += node.children[0].toString() + '\');';
1949                             break;
1950                         case 'op_delete':
1951                             that._warn('Use of the \'delete\' operator is deprecated. Please use the remove() function.');
1952                             if (js) {
1953                                 ret = '$jc$.del(';
1954                             } else {
1955                                 ret = 'remove(';
1956                             }
1957 
1958                             ret += compile(node.children[0], "op_delete") + ')';
1959                             break;
1960                         case 'op_eq':
1961                             ret = '(' + compile(node.children[0], "op_eq") + ' === ' + compile(node.children[1], "op_eq") + ')';
1962                             break;
1963                         case 'op_neq':
1964                             ret = '(' + compile(node.children[0], "op_neq") + ' !== ' + compile(node.children[1], "op_neq") + ')';
1965                             break;
1966                         case 'op_approx':
1967                             ret = '(' + compile(node.children[0], "op_approx") + ' ~= ' + compile(node.children[1], "op_approx") + ')';
1968                             break;
1969                         case 'op_gt':
1970                             if (js) {
1971                                 ret = '$jc$.gt(' + compile(node.children[0], "op_gt") + ', ' + compile(node.children[1], "op_gt") + ')';
1972                             } else {
1973                                 ret = '(' + compile(node.children[0], "op_gt") + ' > ' + compile(node.children[1], "op_gt") + ')';
1974                             }
1975                             break;
1976                         case 'op_lt':
1977                             if (js) {
1978                                 ret = '$jc$.lt(' + compile(node.children[0], "op_lt") + ', ' + compile(node.children[1], "op_lt") + ')';
1979                             } else {
1980                                 ret = '(' + compile(node.children[0], "op_lt") + ' < ' + compile(node.children[1], "op_lt") + ')';
1981                             }
1982                             break;
1983                         case 'op_geq':
1984                             if (js) {
1985                                 ret = '$jc$.geq(' + compile(node.children[0], "op_geq") + ', ' + compile(node.children[1], "op_geq") + ')';
1986                             } else {
1987                                 ret = '(' + compile(node.children[0], "op_geq") + ' >= ' + compile(node.children[1], "op_geq") + ')';
1988                             }
1989                             break;
1990                         case 'op_leq':
1991                             if (js) {
1992                                 ret = '$jc$.leq(' + compile(node.children[0], "op_leq") + ', ' + compile(node.children[1], "op_leq") + ')';
1993                             } else {
1994                                 ret = '(' + compile(node.children[0], "op_leq") + ' <= ' + compile(node.children[1], "op_leq") + ')';
1995                             }
1996                             break;
1997                         case 'op_or':
1998                             ret = '(' + compile(node.children[0], "op_or") + ' || ' + compile(node.children[1], "op_or") + ')';
1999                             break;
2000                         case 'op_and':
2001                             ret = '(' + compile(node.children[0], "op_and") + ' && ' + compile(node.children[1], "op_and") + ')';
2002                             break;
2003                         case 'op_not':
2004                             ret = '!(' + compile(node.children[0], "op_not") + ')';
2005                             break;
2006                         case "op_add":
2007                             if (js) {
2008                                 ret = '$jc$.add(' + compile(node.children[0], "op_add") + ', ' + compile(node.children[1], "op_add") + ')';
2009                             } else if (!format.minParentheses) {
2010                                 ret = '(' + compile(node.children[0], "op_add") + ' + ' + compile(node.children[1], "op_add") + ')';
2011                             } else {
2012                                 prioParent = prio(node);
2013 
2014                                 e = compile(node.children[0], "op_add");
2015                                 prioChild = prio(node.children[0]);
2016                                 ret = (prioParent > prioChild) ? "(" + e + ")" : e;
2017 
2018                                 ret += ' + ';
2019 
2020                                 e = compile(node.children[1], "op_add");
2021                                 prioChild = prio(node.children[1]);
2022                                 ret += (prioParent > prioChild) ? "(" + e + ")" : e;
2023                             }
2024                             break;
2025                         case 'op_sub':
2026                             if (js) {
2027                                 ret = '$jc$.sub(' + compile(node.children[0], "op_sub") + ', ' + compile(node.children[1], "op_sub") + ')';
2028                             } else if (!format.minParentheses) {
2029                                 ret = '(' + compile(node.children[0], "op_sub") + ' - ' + compile(node.children[1], "op_sub") + ')';
2030                             } else {
2031                                 prioParent = prio(node);
2032 
2033                                 e = compile(node.children[0], "op_sub");
2034                                 prioChild = prio(node.children[0]);
2035                                 ret = (prioParent > prioChild) ? "(" + e + ")" : e;
2036 
2037                                 ret += ' - ';
2038 
2039                                 e = compile(node.children[1], "op_sub");
2040                                 prioChild = prio(node.children[1]);
2041                                 ret += (prioParent >= prioChild) ? "(" + e + ")" : e;
2042                             }
2043                             break;
2044                         case 'op_div':
2045                             if (js) {
2046                                 ret = '$jc$.div(' + compile(node.children[0], "op_div") + ', ' + compile(node.children[1], "op_div") + ')';
2047                             } else if (!format.minParentheses) {
2048                                 ret = '(' + compile(node.children[0], "op_div") + ' / ' + compile(node.children[1], "op_div") + ')';
2049                             } else {
2050                                 prioParent = prio(node);
2051 
2052                                 e = compile(node.children[0], "op_div");
2053                                 prioChild = prio(node.children[0]);
2054                                 ret = (prioParent > prioChild) ? "(" + e + ")" : e;
2055 
2056                                 ret += ' / ';
2057 
2058                                 e = compile(node.children[1], "op_div");
2059                                 prioChild = prio(node.children[1]);
2060                                 ret += (prioParent >= prioChild) ? "(" + e + ")" : e;
2061                             }
2062                             break;
2063                         case 'op_mod':
2064                             if (js) {
2065                                 ret = '$jc$.mod(' + compile(node.children[0], "op_mod") + ', ' + compile(node.children[1], "op_mod") + ', true)';
2066                             } else if (!format.minParentheses) {
2067                                 ret = '(' + compile(node.children[0], "op_mod") + ' % ' + compile(node.children[1], "op_mod") + ')';
2068                             } else {
2069                                 prioParent = prio(node);
2070 
2071                                 e = compile(node.children[0], "op_mod");
2072                                 prioChild = prio(node.children[0]);
2073                                 ret = (prioParent > prioChild) ? "(" + e + ")" : e;
2074 
2075                                 ret += ' % ';
2076 
2077                                 e = compile(node.children[1], "op_mod");
2078                                 prioChild = prio(node.children[1]);
2079                                 ret += (prioParent >= prioChild) ? "(" + e + ")" : e;
2080                             }
2081                             break;
2082                         case 'op_mul':
2083                             if (js) {
2084                                 ret = '$jc$.mul(' + compile(node.children[0], "op_mul") + ', ' + compile(node.children[1], "op_mul") + ')';
2085                             } else if (!format.minParentheses) {
2086                                 ret = '(' + compile(node.children[0], "op_mul") + ' * ' + compile(node.children[1], "op_mul") + ')';
2087                             } else {
2088                                 prioParent = prio(node);
2089 
2090                                 e = compile(node.children[0], "op_mul");
2091                                 prioChild = prio(node.children[0]);
2092                                 ret = (prioParent > prioChild) ? "(" + e + ")" : e;
2093 
2094                                 ret += ' * ';
2095 
2096                                 e = compile(node.children[1], "op_mul");
2097                                 prioChild = prio(node.children[1]);
2098                                 ret += (prioParent > prioChild) ? "(" + e + ")" : e;
2099                             }
2100                             break;
2101                         case 'op_exp':
2102                             if (js) {
2103                                 ret = '$jc$.pow(' + compile(node.children[0], "op_exp", 0) + ', ' + compile(node.children[1], "op_exp", 1) + ')';
2104                             } else if (!format.minParentheses) {
2105                                 ret = '('
2106                                     + compile(node.children[0], "op_exp", 0)
2107                                     + '^' + compile(node.children[1], "op_exp", 1)
2108                                     + ')';
2109                             } else {
2110                                 prioParent = prio(node);
2111 
2112                                 e = compile(node.children[0], "op_exp", 0);
2113                                 prioChild = prio(node.children[0]);
2114                                 ret = (prioParent >= prioChild)
2115                                     ? "(" + e + ")"
2116                                     : e;
2117 
2118                                 ret += '^';
2119 
2120                                 e = compile(node.children[1], "op_exp", 1);
2121                                 prioChild = prio(node.children[1]);
2122                                 ret += (prioParent > prioChild && !(format.printable && e[0] === '{' && e[e.length - 1] === '}'))
2123                                     ? "(" + e + ")"
2124                                     : e;
2125                             }
2126                             break;
2127                         case 'op_neg':
2128                             if (js) {
2129                                 ret = '$jc$.neg(' + compile(node.children[0], "op_neg") + ')';
2130                             } else if (!format.minParentheses) {
2131                                 ret = '(-' + compile(node.children[0], "op_neg") + ')';
2132                             } else {
2133                                 prioParent = prio(node);
2134                                 prioChild = prio(node.children[0]);
2135                                 e = compile(node.children[0], "op_neg");
2136                                 if (prioParent >= prioChild) {
2137                                     ret = '-(' + e + ')';
2138                                 } else {
2139                                     ret = '-' + e;
2140                                 }
2141                             }
2142                             break;
2143                     }
2144                     break;
2145 
2146                 case 'node_var':
2147                     if (js) {
2148                         ret = that.getvarJS(node.value, false, node.withProps);
2149                     } else {
2150                         ret = node.value;
2151                     }
2152                     break;
2153 
2154                 case 'node_const':
2155                     if (js) {
2156                         ret = node.value;
2157                         break;
2158                     }
2159 
2160                     c = node.value;
2161                     if (
2162                         format.constToFixed !== false &&
2163                         Type.isNumber(c) &&
2164                         !(prevOp === "op_exp" && position === 1) // exponents will not be formatted
2165                     ) {
2166                         c = parseFloat(c);
2167                         if (Type.isNumber(format.constToFixed)) {
2168                             c = Type.toFixed(c, format.constToFixed);
2169                         } else if (Type.isFunction(format.constToFixed)) {
2170                             c = format.constToFixed(c);
2171                         } else {
2172                             c = node.value;
2173                         }
2174                     }
2175                     if (format.minParentheses && parseFloat(c) < 0 && prevOp !== "op_execfun" && position !== 0) {
2176                         ret = "(" + c + ")";
2177                     } else {
2178                         ret = c;
2179                     }
2180                     break;
2181 
2182                 case 'node_const_bool':
2183                     ret = node.value;
2184                     break;
2185 
2186                 case 'node_str':
2187                     ret = '\'' + node.value + '\'';
2188                     break;
2189             }
2190 
2191             if (node.needsAngleBrackets) {
2192                 if (js) {
2193                     ret = '{\n' + ret + ' }\n';
2194                 } else {
2195                     ret = '<< ' + ret + ' >>\n';
2196                 }
2197             }
2198 
2199             if (format.printable && prevOp === "op_exp" && position === 1) {
2200                 ret = '{' + ret + '}';
2201             }
2202 
2203             if (format.printable && Type.isString(ret)) {
2204                 ret = ret.replaceAll('\n', '');
2205             }
2206 
2207             return ret;
2208         }
2209 
2210         return compile(ast, "");
2211     },
2212 
2213     /**
2214      * This is used as the global getName() function.
2215      * @param {JXG.GeometryElement} obj
2216      * @param {Boolean} useId
2217      * @returns {String}
2218      */
2219     getName: function (obj, useId) {
2220         var name = '';
2221 
2222         if (Type.exists(obj) && Type.exists(obj.getName)) {
2223             name = obj.getName();
2224             if ((!Type.exists(name) || name === '') && useId) {
2225                 name = obj.id;
2226             }
2227         } else if (useId) {
2228             name = obj.id;
2229         }
2230 
2231         return name;
2232     },
2233 
2234     /**
2235      * This is used as the global X() function.
2236      * @param {JXG.Point|JXG.Text} e
2237      * @returns {Number}
2238      */
2239     X: function (e) {
2240         return e.X();
2241     },
2242 
2243     /**
2244      * This is used as the global Y() function.
2245      * @param {JXG.Point|JXG.Text} e
2246      * @returns {Number}
2247      */
2248     Y: function (e) {
2249         return e.Y();
2250     },
2251 
2252     /**
2253      * This is used as the global V() function.
2254      * @param {Glider|Slider} e
2255      * @returns {Number}
2256      */
2257     V: function (e) {
2258         return e.Value();
2259     },
2260 
2261     /**
2262      * This is used as the global L() function.
2263      * @param {JXG.Line} e
2264      * @returns {Number}
2265      */
2266     L: function (e) {
2267         return e.L();
2268     },
2269 
2270     /**
2271      * This is used as the global area() function.
2272      * @param {JXG.Circle|JXG.Polygon} obj
2273      * @returns {Number}
2274      */
2275     area: function (obj) {
2276         if (!Type.exists(obj) || !Type.exists(obj.Area)) {
2277             this._error('Error: Can\'t calculate area.');
2278         }
2279 
2280         return obj.Area();
2281     },
2282 
2283     /**
2284      * This is used as the global perimeter() function.
2285      * @param {JXG.Circle|JXG.Polygon} obj
2286      * @returns {Number}
2287      */
2288     perimeter: function (obj) {
2289         if (!Type.exists(obj) || !Type.exists(obj.Perimeter)) {
2290             this._error('Error: Can\'t calculate perimeter.');
2291         }
2292 
2293         return obj.Perimeter();
2294     },
2295 
2296     /**
2297      * This is used as the global dist() function.
2298      * @param {JXG.Point} p1
2299      * @param {JXG.Point} p2
2300      * @returns {Number}
2301      */
2302     dist: function (p1, p2) {
2303         if (!Type.exists(p1) || !Type.exists(p1.Dist)) {
2304             this._error('Error: Can\'t calculate distance.');
2305         }
2306 
2307         return p1.Dist(p2);
2308     },
2309 
2310     /**
2311      * This is used as the global radius() function.
2312      * @param {JXG.Circle|Sector} obj
2313      * @returns {Number}
2314      */
2315     radius: function (obj) {
2316         if (!Type.exists(obj) || !Type.exists(obj.Radius)) {
2317             this._error('Error: Can\'t calculate radius.');
2318         }
2319 
2320         return obj.Radius();
2321     },
2322 
2323     /**
2324      * This is used as the global slope() function.
2325      * @param {JXG.Line} obj
2326      * @returns {Number}
2327      */
2328     slope: function (obj) {
2329         if (!Type.exists(obj) || !Type.exists(obj.Slope)) {
2330             this._error('Error: Can\'t calculate slope.');
2331         }
2332 
2333         return obj.Slope();
2334     },
2335 
2336     /**
2337      * + operator implementation
2338      * @param {Number|Array|JXG.Point} a
2339      * @param {Number|Array|JXG.Point} b
2340      * @returns {Number|Array}
2341      */
2342     add: function (a, b) {
2343         var i, len, res;
2344 
2345         a = Type.evalSlider(a);
2346         b = Type.evalSlider(b);
2347 
2348         if (Interval.isInterval(a) || Interval.isInterval(b)) {
2349             res = Interval.add(a, b);
2350         } else if (Type.isArray(a) && Type.isArray(b)) {
2351             len = Math.min(a.length, b.length);
2352             res = [];
2353 
2354             for (i = 0; i < len; i++) {
2355                 res[i] = a[i] + b[i];
2356             }
2357         } else if (Type.isNumber(a) && Type.isNumber(b)) {
2358             res = a + b;
2359         } else if (Type.isString(a) || Type.isString(b)) {
2360             res = a.toString() + b.toString();
2361         } else {
2362             this._error('Operation + not defined on operands ' + typeof a + ' and ' + typeof b);
2363         }
2364 
2365         return res;
2366     },
2367 
2368     /**
2369      * - operator implementation
2370      * @param {Number|Array|JXG.Point} a
2371      * @param {Number|Array|JXG.Point} b
2372      * @returns {Number|Array}
2373      */
2374     sub: function (a, b) {
2375         var i, len, res;
2376 
2377         a = Type.evalSlider(a);
2378         b = Type.evalSlider(b);
2379 
2380         if (Interval.isInterval(a) || Interval.isInterval(b)) {
2381             res = Interval.sub(a, b);
2382         } else if (Type.isArray(a) && Type.isArray(b)) {
2383             len = Math.min(a.length, b.length);
2384             res = [];
2385 
2386             for (i = 0; i < len; i++) {
2387                 res[i] = a[i] - b[i];
2388             }
2389         } else if (Type.isNumber(a) && Type.isNumber(b)) {
2390             res = a - b;
2391         } else {
2392             this._error('Operation - not defined on operands ' + typeof a + ' and ' + typeof b);
2393         }
2394 
2395         return res;
2396     },
2397 
2398     /**
2399      * unary - operator implementation
2400      * @param {Number|Array|JXG.Point} a
2401      * @returns {Number|Array}
2402      */
2403     neg: function (a) {
2404         var i, len, res;
2405 
2406         a = Type.evalSlider(a);
2407 
2408         if (Interval.isInterval(a)) {
2409             res = Interval.negative(a);
2410         } else if (Type.isArray(a)) {
2411             len = a.length;
2412             res = [];
2413 
2414             for (i = 0; i < len; i++) {
2415                 res[i] = -a[i];
2416             }
2417         } else if (Type.isNumber(a)) {
2418             res = -a;
2419         } else {
2420             this._error('Unary operation - not defined on operand ' + typeof a);
2421         }
2422 
2423         return res;
2424     },
2425 
2426     /**
2427      * Multiplication of vectors and numbers
2428      * @param {Number|Array} a
2429      * @param {Number|Array} b
2430      * @returns {Number|Array} (Inner) product of the given input values.
2431      */
2432     mul: function (a, b) {
2433         var i, len, res;
2434 
2435         a = Type.evalSlider(a);
2436         b = Type.evalSlider(b);
2437 
2438         if (Type.isArray(a) && Type.isNumber(b)) {
2439             // swap b and a
2440             i = a;
2441             a = b;
2442             b = a;
2443         }
2444 
2445         if (Interval.isInterval(a) || Interval.isInterval(b)) {
2446             res = Interval.mul(a, b);
2447         } else if (Type.isArray(a) && Type.isArray(b)) {
2448             len = Math.min(a.length, b.length);
2449             res = Mat.innerProduct(a, b, len);
2450         } else if (Type.isNumber(a) && Type.isArray(b)) {
2451             len = b.length;
2452             res = [];
2453 
2454             for (i = 0; i < len; i++) {
2455                 res[i] = a * b[i];
2456             }
2457         } else if (Type.isNumber(a) && Type.isNumber(b)) {
2458             res = a * b;
2459         } else {
2460             this._error('Operation * not defined on operands ' + typeof a + ' and ' + typeof b);
2461         }
2462 
2463         return res;
2464     },
2465 
2466     /**
2467      * Implementation of the / operator.
2468      * @param {Number|Array} a
2469      * @param {Number} b
2470      * @returns {Number|Array}
2471      */
2472     div: function (a, b) {
2473         var i, len, res;
2474 
2475         a = Type.evalSlider(a);
2476         b = Type.evalSlider(b);
2477 
2478         if (Interval.isInterval(a) || Interval.isInterval(b)) {
2479             res = Interval.div(a, b);
2480         } else if (Type.isArray(a) && Type.isNumber(b)) {
2481             len = a.length;
2482             res = [];
2483 
2484             for (i = 0; i < len; i++) {
2485                 res[i] = a[i] / b;
2486             }
2487         } else if (Type.isNumber(a) && Type.isNumber(b)) {
2488             res = a / b;
2489         } else {
2490             this._error('Operation * not defined on operands ' + typeof a + ' and ' + typeof b);
2491         }
2492 
2493         return res;
2494     },
2495 
2496     /**
2497      * Implementation of the % operator.
2498      * @param {Number|Array} a
2499      * @param {Number} b
2500      * @returns {Number|Array}
2501      */
2502     mod: function (a, b) {
2503         var i, len, res;
2504 
2505         a = Type.evalSlider(a);
2506         b = Type.evalSlider(b);
2507 
2508         if (Interval.isInterval(a) || Interval.isInterval(b)) {
2509             return Interval.fmod(a, b);
2510         } else if (Type.isArray(a) && Type.isNumber(b)) {
2511             len = a.length;
2512             res = [];
2513 
2514             for (i = 0; i < len; i++) {
2515                 res[i] = Mat.mod(a[i], b, true);
2516             }
2517         } else if (Type.isNumber(a) && Type.isNumber(b)) {
2518             res = Mat.mod(a, b, true);
2519         } else {
2520             this._error('Operation * not defined on operands ' + typeof a + ' and ' + typeof b);
2521         }
2522 
2523         return res;
2524     },
2525 
2526     /**
2527      * Pow function wrapper to allow direct usage of sliders.
2528      * @param {Number|Slider} a
2529      * @param {Number|Slider} b
2530      * @returns {Number}
2531      */
2532     pow: function (a, b) {
2533         a = Type.evalSlider(a);
2534         b = Type.evalSlider(b);
2535 
2536         if (Interval.isInterval(a) || Interval.isInterval(b)) {
2537             return Interval.pow(a, b);
2538         }
2539         return Mat.pow(a, b);
2540     },
2541 
2542     lt: function (a, b) {
2543         if (Interval.isInterval(a) || Interval.isInterval(b)) {
2544             return Interval.lt(a, b);
2545         }
2546         return a < b;
2547     },
2548     leq: function (a, b) {
2549         if (Interval.isInterval(a) || Interval.isInterval(b)) {
2550             return Interval.leq(a, b);
2551         }
2552         return a <= b;
2553     },
2554     gt: function (a, b) {
2555         if (Interval.isInterval(a) || Interval.isInterval(b)) {
2556             return Interval.gt(a, b);
2557         }
2558         return a > b;
2559     },
2560     geq: function (a, b) {
2561         if (Interval.isInterval(a) || Interval.isInterval(b)) {
2562             return Interval.geq(a, b);
2563         }
2564         return a >= b;
2565     },
2566 
2567     randint: function (min, max, step) {
2568         if (!Type.exists(step)) {
2569             step = 1;
2570         }
2571         return Math.round(Math.random() * (max - min) / step) * step + min;
2572     },
2573 
2574     DDD: function (f) {
2575         console.log('Dummy derivative function. This should never appear!');
2576     },
2577 
2578     /**
2579      * Implementation of the ?: operator
2580      * @param {Boolean} cond Condition
2581      * @param {*} v1
2582      * @param {*} v2
2583      * @returns {*} Either v1 or v2.
2584      */
2585     ifthen: function (cond, v1, v2) {
2586         if (cond) {
2587             return v1;
2588         }
2589 
2590         return v2;
2591     },
2592 
2593     /**
2594      * Implementation of the delete() builtin function
2595      * @param {JXG.GeometryElement} element
2596      */
2597     del: function (element) {
2598         if (typeof element === 'object' && JXG.exists(element.type) && JXG.exists(element.elementClass)) {
2599             this.board.removeObject(element);
2600         }
2601     },
2602 
2603     /**
2604      * Implementation of the eval() builtin function. Calls JXG.evaluate().
2605      * @param {String|Number|Function} v
2606      */
2607     eval: function (v) {
2608         return JXG.evaluate(v);
2609     },
2610 
2611     /**
2612      * Implementation of the use() builtin function
2613      * @param {String} board
2614      */
2615     use: function (board) {
2616         var b, ref,
2617             found = false;
2618 
2619         if (typeof board === 'string') {
2620             // search all the boards for the one with the appropriate container div
2621             for (b in JXG.boards) {
2622                 if (JXG.boards.hasOwnProperty(b) && JXG.boards[b].container === board) {
2623                     ref = JXG.boards[b];
2624                     found = true;
2625                     break;
2626                 }
2627             }
2628         } else {
2629             ref = board;
2630             found = true;
2631         }
2632 
2633         if (found) {
2634             this.board = ref;
2635             this.builtIn.$board = ref;
2636             this.builtIn.$board.src = '$jc$.board';
2637         } else {
2638             this._error('Board \'' + board + '\' not found!');
2639         }
2640     },
2641 
2642     /**
2643      * Find the first symbol to the given value from the given scope upwards.
2644      * @param v Value
2645      * @param {Number} [scope=-1] The scope, default is to start with current scope (-1).
2646      * @returns {Array} An array containing the symbol and the scope if a symbol could be found,
2647      * an empty array otherwise;
2648      */
2649     findSymbol: function (v, scope) {
2650         var i, s;
2651 
2652         scope = Type.def(scope, -1);
2653 
2654         if (scope === -1) {
2655             s = this.scope;
2656         } else {
2657             s = this.scopes[scope];
2658         }
2659 
2660         while (s !== null) {
2661             for (i in s.locals) {
2662                 if (s.locals.hasOwnProperty(i) && s.locals[i] === v) {
2663                     return [i, s];
2664                 }
2665             }
2666 
2667             s = s.previous;
2668         }
2669 
2670         return [];
2671     },
2672 
2673     /**
2674      * Import modules into a JessieCode script.
2675      * @param {String} module
2676      */
2677     importModule: function (module) {
2678         return priv.modules[module.toLowerCase()];
2679     },
2680 
2681     /**
2682      * Defines built in methods and constants.
2683      * @returns {Object} BuiltIn control object
2684      */
2685     defineBuiltIn: function () {
2686         var that = this,
2687             builtIn = {
2688                 PI: Math.PI,
2689                 EULER: Math.E,
2690                 D: that.DDD,
2691                 X: that.X,
2692                 Y: that.Y,
2693                 V: that.V,
2694                 Value: that.V,
2695                 L: that.L,
2696                 Length: that.L,
2697 
2698                 acosh: Mat.acosh,
2699                 acot: Mat.acot,
2700                 asinh: Mat.asinh,
2701                 binomial: Mat.binomial,
2702                 cbrt: Mat.cbrt,
2703                 cosh: Mat.cosh,
2704                 cot: Mat.cot,
2705                 deg: Geometry.trueAngle,
2706                 A: that.area,
2707                 area: that.area,
2708                 Area: that.area,
2709                 perimeter: that.perimeter,
2710                 Perimeter: that.perimeter,
2711                 dist: that.dist,
2712                 Dist: that.dist,
2713                 R: that.radius,
2714                 radius: that.radius,
2715                 Radius: that.radius,
2716                 erf: Mat.erf,
2717                 erfc: Mat.erfc,
2718                 erfi: Mat.erfi,
2719                 factorial: Mat.factorial,
2720                 gcd: Mat.gcd,
2721                 lb: Mat.log2,
2722                 lcm: Mat.lcm,
2723                 ld: Mat.log2,
2724                 lg: Mat.log10,
2725                 ln: Math.log,
2726                 log: Mat.log,
2727                 log10: Mat.log10,
2728                 log2: Mat.log2,
2729                 ndtr: Mat.ndtr,
2730                 ndtri: Mat.ndtri,
2731                 nthroot: Mat.nthroot,
2732                 pow: Mat.pow,
2733                 rad: Geometry.rad,
2734                 ratpow: Mat.ratpow,
2735                 trunc: Type.trunc,
2736                 sinh: Mat.sinh,
2737                 slope: that.slope,
2738                 Slope: that.slope,
2739 
2740                 randint: that.randint,
2741 
2742                 IfThen: that.ifthen,
2743                 'import': that.importModule,
2744                 'eval': that.eval,
2745                 'use': that.use,
2746                 'remove': that.del,
2747                 '$': that.getElementById,
2748                 '$value': function(e) {return that.getElementById(e).Value(); },
2749                 getName: that.getName,
2750                 name: that.getName,
2751                 '$board': that.board,
2752                 '$log': that.log
2753             };
2754 
2755         // special scopes for factorial, deg, and rad
2756         builtIn.rad.sc = Geometry;
2757         builtIn.deg.sc = Geometry;
2758         builtIn.factorial.sc = Mat;
2759 
2760         // set the javascript equivalent for the builtIns
2761         // some of the anonymous functions should be replaced by global methods later on
2762         // EULER and PI don't get a source attribute - they will be lost anyways and apparently
2763         // some browser will throw an exception when a property is assigned to a primitive value.
2764         builtIn.X.src = '$jc$.X';
2765         builtIn.Y.src = '$jc$.Y';
2766         builtIn.V.src = '$jc$.V';
2767         builtIn.Value.src = '$jc$.V';
2768         builtIn.L.src = '$jc$.L';
2769         builtIn.Length.src = '$jc$.L';
2770 
2771         builtIn.acosh.src = 'JXG.Math.acosh';
2772         builtIn.acot.src = 'JXG.Math.acot';
2773         builtIn.asinh.src = 'JXG.Math.asinh';
2774         builtIn.binomial.src = 'JXG.Math.binomial';
2775         builtIn.cbrt.src = 'JXG.Math.cbrt';
2776         builtIn.cot.src = 'JXG.Math.cot';
2777         builtIn.cosh.src = 'JXG.Math.cosh';
2778         builtIn.deg.src = 'JXG.Math.Geometry.trueAngle';
2779         builtIn.erf.src = 'JXG.Math.erf';
2780         builtIn.erfc.src = 'JXG.Math.erfc';
2781         builtIn.erfi.src = 'JXG.Math.erfi';
2782         builtIn.A.src = '$jc$.area';
2783         builtIn.area.src = '$jc$.area';
2784         builtIn.Area.src = '$jc$.area';
2785         builtIn.perimeter.src = '$jc$.perimeter';
2786         builtIn.Perimeter.src = '$jc$.perimeter';
2787         builtIn.dist.src = '$jc$.dist';
2788         builtIn.Dist.src = '$jc$.dist';
2789         builtIn.R.src = '$jc$.radius';
2790         builtIn.radius.src = '$jc$.radius';
2791         builtIn.Radius.src = '$jc$.radius';
2792         builtIn.factorial.src = 'JXG.Math.factorial';
2793         builtIn.gcd.src = 'JXG.Math.gcd';
2794         builtIn.lb.src = 'JXG.Math.log2';
2795         builtIn.lcm.src = 'JXG.Math.lcm';
2796         builtIn.ld.src = 'JXG.Math.log2';
2797         builtIn.lg.src = 'JXG.Math.log10';
2798         builtIn.ln.src = 'Math.log';
2799         builtIn.log.src = 'JXG.Math.log';
2800         builtIn.log10.src = 'JXG.Math.log10';
2801         builtIn.log2.src = 'JXG.Math.log2';
2802         builtIn.ndtr.src = 'JXG.Math.ndtr';
2803         builtIn.ndtri.src = 'JXG.Math.ndtri';
2804         builtIn.nthroot.src = 'JXG.Math.nthroot';
2805         builtIn.pow.src = 'JXG.Math.pow';
2806         builtIn.rad.src = 'JXG.Math.Geometry.rad';
2807         builtIn.ratpow.src = 'JXG.Math.ratpow';
2808         builtIn.trunc.src = 'JXG.trunc';
2809         builtIn.sinh.src = 'JXG.Math.sinh';
2810         builtIn.slope.src = '$jc$.slope';
2811         builtIn.Slope.src = '$jc$.slope';
2812 
2813         builtIn.randint.src = '$jc$.randint';
2814 
2815         builtIn['import'].src = '$jc$.importModule';
2816         builtIn.eval.src = '$jc$.eval';
2817         builtIn.use.src = '$jc$.use';
2818         builtIn.remove.src = '$jc$.del';
2819         builtIn.IfThen.src = '$jc$.ifthen';
2820         // usually unused, see node_op > op_execfun
2821         builtIn.$.src = '(function (n) { return $jc$.board.select(n); })';
2822         builtIn.$value.src = '(function (n) { return $jc$.board.select(n).Value(); })';
2823         builtIn.getName.src = '$jc$.getName';
2824         builtIn.name.src = '$jc$.getName';
2825         if (builtIn.$board) {
2826             builtIn.$board.src = '$jc$.board';
2827         }
2828         builtIn.$log.src = '$jc$.log';
2829 
2830         builtIn = JXG.merge(builtIn, that._addedBuiltIn);
2831 
2832         return builtIn;
2833     },
2834 
2835     _addedBuiltIn: {},
2836 
2837     addBuiltIn: function (name, func) {
2838         if (Type.exists(this.builtIn)) {
2839             if (Type.exists(this.builtIn[name])) {
2840                 return;
2841             }
2842             this.builtIn[name] = func;
2843             this.builtIn[name].src = '$jc$.' + name;
2844         }
2845 
2846         if (Type.exists(this._addedBuiltIn[name])) {
2847             return;
2848         }
2849         this._addedBuiltIn[name] = func;
2850         this._addedBuiltIn[name].src = '$jc$.' + name;
2851 
2852         JXG.JessieCode.prototype[name] = func;
2853     },
2854 
2855     /**
2856      * Returns information about the possible functions and constants.
2857      * @returns {Object}
2858      */
2859     getPossibleOperands: function () {
2860         var FORBIDDEN = ['E'],
2861             jessiecode = this.builtIn || this.defineBuiltIn(),
2862             math = Math,
2863             jc, ma, merge,
2864             i, j, p, len, e,
2865             funcs, funcsJC, consts, operands,
2866             sort, pack;
2867 
2868         sort = function (a, b) {
2869             return a.toLowerCase().localeCompare(b.toLowerCase());
2870         };
2871 
2872         pack = function (name, origin) {
2873             var that = null;
2874 
2875             if (origin === 'jc') that = jessiecode[name];
2876             else if (origin === 'Math') that = math[name];
2877             else return;
2878 
2879             if (FORBIDDEN.indexOf(name) >= 0) {
2880                 return;
2881             } else if (JXG.isFunction(that)) {
2882                 return {
2883                     name: name,
2884                     type: 'function',
2885                     numParams: that.length,
2886                     origin: origin,
2887                 };
2888             } else if (JXG.isNumber(that)) {
2889                 return {
2890                     name: name,
2891                     type: 'constant',
2892                     value: that,
2893                     origin: origin,
2894                 };
2895             } else if (name.startsWith('$')) {
2896                 // do nothing
2897             } else if (that !== undefined) {
2898                 console.error('undefined type', that);
2899             }
2900         };
2901 
2902         jc = Object.getOwnPropertyNames(jessiecode).sort(sort);
2903         ma = Object.getOwnPropertyNames(math).sort(sort);
2904         merge = [];
2905         i = 0;
2906         j = 0;
2907 
2908         while (i < jc.length || j < ma.length) {
2909             if (jc[i] === ma[j]) {
2910                 p = pack(ma[j], 'Math');
2911                 if (JXG.exists(p)) merge.push(p);
2912                 i++;
2913                 j++;
2914             } else if (!JXG.exists(ma[j]) || jc[i].toLowerCase().localeCompare(ma[j].toLowerCase()) < 0) {
2915                 p = pack(jc[i], 'jc');
2916                 if (JXG.exists(p)) merge.push(p);
2917                 i++;
2918             } else {
2919                 p = pack(ma[j], 'Math');
2920                 if (JXG.exists(p)) merge.push(p);
2921                 j++;
2922             }
2923         }
2924 
2925         funcs = [];
2926         funcsJC = [];
2927         consts = [];
2928         operands = {};
2929         len = merge.length;
2930         for (i = 0; i < len; i++) {
2931             e = merge[i];
2932             switch (e.type) {
2933                 case 'function':
2934                     funcs.push(e.name);
2935                     if (e.origin === 'jc')
2936                         funcsJC.push(e.name);
2937                     break;
2938                 case 'constant':
2939                     consts.push(e.name);
2940                     break;
2941             }
2942             operands[e.name] = e;
2943         }
2944 
2945         return {
2946             all: operands,
2947             list: merge,
2948             functions: funcs,
2949             functions_jessiecode: funcsJC,
2950             constants: consts,
2951         };
2952     },
2953 
2954     /**
2955      * Output a debugging message. Uses debug console, if available. Otherwise an HTML element with the
2956      * id "debug" and an innerText property is used.
2957      * @param {String} log
2958      * @private
2959      */
2960     _debug: function (log) {
2961         if (typeof console === 'object' && console.log) {
2962             console.log(log);
2963         } else if (Env.isBrowser && document && document.getElementById('debug') !== null) {
2964             document.getElementById('debug').innerText += log + '\n';
2965         }
2966     },
2967 
2968     /**
2969      * Throws an exception with the given error message.
2970      * @param {String} msg Error message
2971      */
2972     _error: function (msg) {
2973         var e = new Error('Error(' + this.line + '): ' + msg);
2974         e.line = this.line;
2975         throw e;
2976     },
2977 
2978     /**
2979      * Output a warning message using {@link JXG#debug} and precedes the message with "Warning: ".
2980      * @param {String} msg
2981      */
2982     _warn: function (msg) {
2983         if (typeof console === 'object' && console.log) {
2984             console.log('Warning(' + this.line + '): ' + msg);
2985         } else if (Env.isBrowser && document && document.getElementById(this.warnLog) !== null) {
2986             document.getElementById(this.warnLog).innerText += 'Warning(' + this.line + '): ' + msg + '\n';
2987         }
2988     },
2989 
2990     _log: function (msg) {
2991         if (typeof window !== 'object' && typeof self === 'object' && self.postMessage) {
2992             self.postMessage({ type: 'log', msg: 'Log: ' + msg.toString() });
2993         } else {
2994             console.log('Log: ', arguments);
2995         }
2996     }
2997 
2998 });
2999 
3000 /* parser generated by jison 0.4.18 */
3001 /*
3002   Returns a Parser object of the following structure:
3003 
3004   Parser: {
3005     yy: {}
3006   }
3007 
3008   Parser.prototype: {
3009     yy: {},
3010     trace: function(),
3011     symbols_: {associative list: name ==> number},
3012     terminals_: {associative list: number ==> name},
3013     productions_: [...],
3014     performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
3015     table: [...],
3016     defaultActions: {...},
3017     parseError: function(str, hash),
3018     parse: function(input),
3019 
3020     lexer: {
3021         EOF: 1,
3022         parseError: function(str, hash),
3023         setInput: function(input),
3024         input: function(),
3025         unput: function(str),
3026         more: function(),
3027         less: function(n),
3028         pastInput: function(),
3029         upcomingInput: function(),
3030         showPosition: function(),
3031         test_match: function(regex_match_array, rule_index),
3032         next: function(),
3033         lex: function(),
3034         begin: function(condition),
3035         popState: function(),
3036         _currentRules: function(),
3037         topState: function(),
3038         pushState: function(condition),
3039 
3040         options: {
3041             ranges: boolean           (optional: true ==> token location info will include a .range[] member)
3042             flex: boolean             (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
3043             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)
3044         },
3045 
3046         performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
3047         rules: [...],
3048         conditions: {associative list: name ==> set},
3049     }
3050   }
3051 
3052 
3053   token location info (@$, _$, etc.): {
3054     first_line: n,
3055     last_line: n,
3056     first_column: n,
3057     last_column: n,
3058     range: [start_number, end_number]       (where the numbers are indexes into the input string, regular zero-based)
3059   }
3060 
3061 
3062   the parseError function receives a 'hash' object with these members for lexer and parser errors: {
3063     text:        (matched text)
3064     token:       (the produced terminal token, if any)
3065     line:        (yylineno)
3066   }
3067   while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
3068     loc:         (yylloc)
3069     expected:    (string describing the set of expected tokens)
3070     recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
3071   }
3072 */
3073 /**
3074  * @class
3075  * @ignore
3076  */
3077 var parser = (function(){
3078 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,150],$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,167],$VX=[10,86];
3079 /**
3080  * @class
3081  * @ignore
3082  */
3083 var parser = {trace: function trace () { },
3084 yy: {},
3085 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},
3086 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:"->"},
3087 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,5],[63,6],[92,1],[92,3]],
3088 /**
3089  * @class
3090  * @ignore
3091  */
3092 performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
3093 /* this == yyval */
3094 
3095 var $0 = $$.length - 1;
3096 switch (yystate) {
3097 case 1:
3098  return $$[$0-1];
3099 break;
3100 case 2:
3101  this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_if', $$[$0-2], $$[$0]);
3102 break;
3103 case 3:
3104  this.$ = AST.createNode(lc(_$[$0-6]), 'node_op', 'op_if_else', $$[$0-4], $$[$0-2], $$[$0]);
3105 break;
3106 case 4:
3107  this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_while', $$[$0-2], $$[$0]);
3108 break;
3109 case 5:
3110  this.$ = AST.createNode(lc(_$[$0-8]), 'node_op', 'op_for', $$[$0-6], $$[$0-4], $$[$0-2], $$[$0]);
3111 break;
3112 case 6:
3113  this.$ = AST.createNode(lc(_$[$0-6]), 'node_op', 'op_do', $$[$0-5], $$[$0-2]);
3114 break;
3115 case 7:
3116  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_use', $$[$0]);
3117 break;
3118 case 8:
3119  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_delete', $$[$0]);
3120 break;
3121 case 9:
3122  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_return', undefined);
3123 break;
3124 case 10:
3125  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_return', $$[$0-1]);
3126 break;
3127 case 11: case 14:
3128  this.$ = AST.createNode(lc(_$[$0]), 'node_op', 'op_none');
3129 break;
3130 case 12:
3131  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_block', $$[$0-1]);
3132 break;
3133 case 13:
3134  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_none', $$[$0-1], $$[$0]);
3135 break;
3136 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:
3137  this.$ = $$[$0];
3138 break;
3139 case 22: case 65: case 93:
3140  this.$ = $$[$0-1];
3141 break;
3142 case 25:
3143  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_assign', $$[$0-2], $$[$0]); this.$.isMath = false;
3144 break;
3145 case 27:
3146  this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_conditional', $$[$0-4], $$[$0-2], $$[$0]); this.$.isMath = false;
3147 break;
3148 case 29:
3149  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_or', $$[$0-2], $$[$0]); this.$.isMath = false;
3150 break;
3151 case 31:
3152  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_and', $$[$0-2], $$[$0]); this.$.isMath = false;
3153 break;
3154 case 33:
3155  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_eq', $$[$0-2], $$[$0]); this.$.isMath = false;
3156 break;
3157 case 34:
3158  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_neq', $$[$0-2], $$[$0]); this.$.isMath = false;
3159 break;
3160 case 35:
3161  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_approx', $$[$0-2], $$[$0]); this.$.isMath = false;
3162 break;
3163 case 37:
3164  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_lt', $$[$0-2], $$[$0]); this.$.isMath = false;
3165 break;
3166 case 38:
3167  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_gt', $$[$0-2], $$[$0]); this.$.isMath = false;
3168 break;
3169 case 39:
3170  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_leq', $$[$0-2], $$[$0]); this.$.isMath = false;
3171 break;
3172 case 40:
3173  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_geq', $$[$0-2], $$[$0]); this.$.isMath = false;
3174 break;
3175 case 42:
3176  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_add', $$[$0-2], $$[$0]); this.$.isMath = true;
3177 break;
3178 case 43:
3179  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_sub', $$[$0-2], $$[$0]); this.$.isMath = true;
3180 break;
3181 case 45:
3182  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_mul', $$[$0-2], $$[$0]); this.$.isMath = true;
3183 break;
3184 case 46:
3185  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_div', $$[$0-2], $$[$0]); this.$.isMath = true;
3186 break;
3187 case 47:
3188  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_mod', $$[$0-2], $$[$0]); this.$.isMath = true;
3189 break;
3190 case 49:
3191  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_exp', $$[$0-2], $$[$0]); this.$.isMath = true;
3192 break;
3193 case 51:
3194  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_not', $$[$0]); this.$.isMath = false;
3195 break;
3196 case 53:
3197  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_neg', $$[$0]); this.$.isMath = true;
3198 break;
3199 case 57: case 63: case 64: case 66: case 67: case 68: case 97:
3200  this.$ = $$[$0]; this.$.isMath = false;
3201 break;
3202 case 59: case 91:
3203  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_property', $$[$0-2], $$[$0]); this.$.isMath = true;
3204 break;
3205 case 60: case 90:
3206  this.$ = AST.createNode(lc(_$[$0-3]), 'node_op', 'op_extvalue', $$[$0-3], $$[$0-1]); this.$.isMath = true;
3207 break;
3208 case 61:
3209  this.$ = AST.createNode(lc(_$[$0]), 'node_var', $$[$0]);
3210 break;
3211 case 69:
3212  this.$ = $$[$0]; this.$.isMath = true;
3213 break;
3214 case 70:
3215  this.$ = AST.createNode(lc(_$[$0]), 'node_const', null);
3216 break;
3217 case 71:
3218  this.$ = AST.createNode(lc(_$[$0]), 'node_const_bool', true);
3219 break;
3220 case 72:
3221  this.$ = AST.createNode(lc(_$[$0]), 'node_const_bool', false);
3222 break;
3223 case 73:
3224  this.$ = AST.createNode(lc(_$[$0]), 'node_str', $$[$0].substring(1, $$[$0].length - 1));
3225 break;
3226 case 74:
3227  this.$ = AST.createNode(lc(_$[$0]), 'node_const', parseFloat($$[$0]));
3228 break;
3229 case 75:
3230  this.$ = AST.createNode(lc(_$[$0]), 'node_const', NaN);
3231 break;
3232 case 76:
3233  this.$ = AST.createNode(lc(_$[$0]), 'node_const', Infinity);
3234 break;
3235 case 77:
3236  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_array', []);
3237 break;
3238 case 78:
3239  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_array', $$[$0-1]);
3240 break;
3241 case 79:
3242  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_emptyobject', {}); this.$.needsAngleBrackets = true;
3243 break;
3244 case 80:
3245  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_proplst_val', $$[$0-1]); this.$.needsAngleBrackets = true;
3246 break;
3247 case 82:
3248  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_proplst', $$[$0-2], $$[$0]);
3249 break;
3250 case 83:
3251  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_prop', $$[$0-2], $$[$0]);
3252 break;
3253 case 87: case 89:
3254  this.$ = AST.createNode(lc(_$[$0-1]), 'node_op', 'op_execfun', $$[$0-1], $$[$0]); this.$.isMath = true;
3255 break;
3256 case 88:
3257  this.$ = AST.createNode(lc(_$[$0-2]), 'node_op', 'op_execfun', $$[$0-2], $$[$0-1], $$[$0], true); this.$.isMath = false;
3258 break;
3259 case 92:
3260  this.$ = [];
3261 break;
3262 case 94: case 98: case 104:
3263  this.$ = [$$[$0]];
3264 break;
3265 case 95: case 99: case 105:
3266  this.$ = $$[$0-2].concat($$[$0]);
3267 break;
3268 case 96:
3269  this.$ = AST.createNode(lc(_$[$0]), 'node_var', $$[$0]); this.$.isMath = true;
3270 break;
3271 case 100:
3272  this.$ = AST.createNode(lc(_$[$0-3]), 'node_op', 'op_function', [], $$[$0]); this.$.isMath = false;
3273 break;
3274 case 101:
3275  this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_function', $$[$0-2], $$[$0]); this.$.isMath = false;
3276 break;
3277 case 102:
3278  this.$ = AST.createNode(lc(_$[$0-4]), 'node_op', 'op_map', [], $$[$0]);
3279 break;
3280 case 103:
3281  this.$ = AST.createNode(lc(_$[$0-5]), 'node_op', 'op_map', $$[$0-3], $$[$0]);
3282 break;
3283 }
3284 },
3285 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},{10:[1,140],20:$VR,92:141},{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},{8:$V2,20:$V8,31:109,44:145,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,146],86:[1,147]},o($VS,[2,81]),{35:[1,148]},{35:[2,84]},{35:[2,85]},{35:[2,86]},o($Vs,[2,77]),{66:[1,149],86:$VT},o($VU,[2,98]),{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,49:152,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: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},{8:$V2,20:$V8,31:109,50:$Vc,51:$Vd,52:155,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,156]},{10:[1,157]},{16:[1,158]},{8:[1,159]},o($Vr,[2,10]),o($Vs,[2,25]),o($Vs,[2,49]),{35:[1,160]},o($Vx,[2,29],{39:$Vy}),o($Vs,[2,59]),{66:[1,161]},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,162]}),o($Vs,[2,94]),o($Vs,[2,96]),o($Vs,[2,97]),o($VV,[2,92]),{10:[1,163],86:$VT},{66:[1,164]},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:165,26:$Vb},{10:[1,166],86:$VW},o($VX,[2,104]),{94:[1,168]},{10:[1,169],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:170,87:96},{8:$V2,20:$V8,29:171,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:172,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:173,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:174,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:175,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:176,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:177,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:178},o($VV,[2,93]),o($Vs,[2,90]),o($Vs,[2,100]),{25:179,26:$Vb},{20:[1,180]},{8:$V2,9:181,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},{94:[1,182]},o($VS,[2,82]),o($VS,[2,83]),o($VU,[2,99]),o($Vq,[2,2],{12:[1,183]}),o($Vr,[2,4]),{16:[1,184]},{10:[1,185]},o($Vs,[2,27]),o($Vs,[2,95]),o($Vs,[2,101]),o($VX,[2,105]),o($Vs,[2,102]),{8:$V2,9:186,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:187,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:188,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,189]},o($Vs,[2,103]),o($Vr,[2,3]),{10:[1,190]},o($Vr,[2,6]),{6:6,7:$V1,8:$V2,9:20,11:191,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])],
3286 defaultActions: {3:[2,1],97:[2,84],98:[2,85],99:[2,86]},
3287 parseError: function parseError (str, hash) {
3288     if (hash.recoverable) {
3289         this.trace(str);
3290     } else {
3291         var error = new Error(str);
3292         error.hash = hash;
3293         throw error;
3294     }
3295 },
3296 /**
3297  * @class
3298  * @ignore
3299  */
3300 parse: function parse(input) {
3301     var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
3302     var args = lstack.slice.call(arguments, 1);
3303     var lexer = Object.create(this.lexer);
3304     var sharedState = { yy: {} };
3305     for (var k in this.yy) {
3306         if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
3307             sharedState.yy[k] = this.yy[k];
3308         }
3309     }
3310     lexer.setInput(input, sharedState.yy);
3311     sharedState.yy.lexer = lexer;
3312     sharedState.yy.parser = this;
3313     if (typeof lexer.yylloc == 'undefined') {
3314         lexer.yylloc = {};
3315     }
3316     var yyloc = lexer.yylloc;
3317     lstack.push(yyloc);
3318     var ranges = lexer.options && lexer.options.ranges;
3319     if (typeof sharedState.yy.parseError === 'function') {
3320         this.parseError = sharedState.yy.parseError;
3321     } else {
3322         this.parseError = Object.getPrototypeOf(this).parseError;
3323     }
3324     function popStack(n) {
3325         stack.length = stack.length - 2 * n;
3326         vstack.length = vstack.length - n;
3327         lstack.length = lstack.length - n;
3328     }
3329     _token_stack:
3330         var lex = function () {
3331             var token;
3332             token = lexer.lex() || EOF;
3333             if (typeof token !== 'number') {
3334                 token = self.symbols_[token] || token;
3335             }
3336             return token;
3337         };
3338     var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
3339     while (true) {
3340         state = stack[stack.length - 1];
3341         if (this.defaultActions[state]) {
3342             action = this.defaultActions[state];
3343         } else {
3344             if (symbol === null || typeof symbol == 'undefined') {
3345                 symbol = lex();
3346             }
3347             action = table[state] && table[state][symbol];
3348         }
3349                     if (typeof action === 'undefined' || !action.length || !action[0]) {
3350                 var errStr = '';
3351                 expected = [];
3352                 for (p in table[state]) {
3353                     if (this.terminals_[p] && p > TERROR) {
3354                         expected.push('\'' + this.terminals_[p] + '\'');
3355                     }
3356                 }
3357                 if (lexer.showPosition) {
3358                     errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
3359                 } else {
3360                     errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
3361                 }
3362                 this.parseError(errStr, {
3363                     text: lexer.match,
3364                     token: this.terminals_[symbol] || symbol,
3365                     line: lexer.yylineno,
3366                     loc: yyloc,
3367                     expected: expected
3368                 });
3369             }
3370         if (action[0] instanceof Array && action.length > 1) {
3371             throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
3372         }
3373         switch (action[0]) {
3374         case 1:
3375             stack.push(symbol);
3376             vstack.push(lexer.yytext);
3377             lstack.push(lexer.yylloc);
3378             stack.push(action[1]);
3379             symbol = null;
3380             if (!preErrorSymbol) {
3381                 yyleng = lexer.yyleng;
3382                 yytext = lexer.yytext;
3383                 yylineno = lexer.yylineno;
3384                 yyloc = lexer.yylloc;
3385                 if (recovering > 0) {
3386                     recovering--;
3387                 }
3388             } else {
3389                 symbol = preErrorSymbol;
3390                 preErrorSymbol = null;
3391             }
3392             break;
3393         case 2:
3394             len = this.productions_[action[1]][1];
3395             yyval.$ = vstack[vstack.length - len];
3396             yyval._$ = {
3397                 first_line: lstack[lstack.length - (len || 1)].first_line,
3398                 last_line: lstack[lstack.length - 1].last_line,
3399                 first_column: lstack[lstack.length - (len || 1)].first_column,
3400                 last_column: lstack[lstack.length - 1].last_column
3401             };
3402             if (ranges) {
3403                 yyval._$.range = [
3404                     lstack[lstack.length - (len || 1)].range[0],
3405                     lstack[lstack.length - 1].range[1]
3406                 ];
3407             }
3408             r = this.performAction.apply(yyval, [
3409                 yytext,
3410                 yyleng,
3411                 yylineno,
3412                 sharedState.yy,
3413                 action[1],
3414                 vstack,
3415                 lstack
3416             ].concat(args));
3417             if (typeof r !== 'undefined') {
3418                 return r;
3419             }
3420             if (len) {
3421                 stack = stack.slice(0, -1 * len * 2);
3422                 vstack = vstack.slice(0, -1 * len);
3423                 lstack = lstack.slice(0, -1 * len);
3424             }
3425             stack.push(this.productions_[action[1]][0]);
3426             vstack.push(yyval.$);
3427             lstack.push(yyval._$);
3428             newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
3429             stack.push(newState);
3430             break;
3431         case 3:
3432             return true;
3433         }
3434     }
3435     return true;
3436 }};
3437 
3438 
3439     var AST = {
3440         node: function (type, value, children) {
3441             return {
3442                 type: type,
3443                 value: value,
3444                 children: children
3445             };
3446         },
3447 
3448         createNode: function (pos, type, value, children) {
3449             var i,
3450                 n = this.node(type, value, []);
3451 
3452             for (i = 3; i < arguments.length; i++) {
3453                 n.children.push(arguments[i]);
3454             }
3455 
3456             n.line = pos[0];
3457             n.col = pos[1];
3458             n.eline = pos[2];
3459             n.ecol = pos[3];
3460 
3461             return n;
3462         }
3463     };
3464 
3465     var lc = function (lc1) {
3466         return [lc1.first_line, lc1.first_column, lc1.last_line, lc1.last_column];
3467     };
3468 
3469 /* generated by jison-lex 0.3.4 */
3470 var lexer = (function(){
3471 var lexer = ({
3472 
3473 EOF:1,
3474 
3475 parseError:function parseError(str, hash) {
3476         if (this.yy.parser) {
3477             this.yy.parser.parseError(str, hash);
3478         } else {
3479             throw new Error(str);
3480         }
3481     },
3482 
3483 // resets the lexer, sets new input
3484 setInput:function (input, yy) {
3485         this.yy = yy || this.yy || {};
3486         this._input = input;
3487         this._more = this._backtrack = this.done = false;
3488         this.yylineno = this.yyleng = 0;
3489         this.yytext = this.matched = this.match = '';
3490         this.conditionStack = ['INITIAL'];
3491         this.yylloc = {
3492             first_line: 1,
3493             first_column: 0,
3494             last_line: 1,
3495             last_column: 0
3496         };
3497         if (this.options.ranges) {
3498             this.yylloc.range = [0,0];
3499         }
3500         this.offset = 0;
3501         return this;
3502     },
3503 
3504 // consumes and returns one char from the input
3505 input:function () {
3506         var ch = this._input[0];
3507         this.yytext += ch;
3508         this.yyleng++;
3509         this.offset++;
3510         this.match += ch;
3511         this.matched += ch;
3512         var lines = ch.match(/(?:\r\n?|\n).*/g);
3513         if (lines) {
3514             this.yylineno++;
3515             this.yylloc.last_line++;
3516         } else {
3517             this.yylloc.last_column++;
3518         }
3519         if (this.options.ranges) {
3520             this.yylloc.range[1]++;
3521         }
3522 
3523         this._input = this._input.slice(1);
3524         return ch;
3525     },
3526 
3527 // unshifts one char (or a string) into the input
3528 unput:function (ch) {
3529         var len = ch.length;
3530         var lines = ch.split(/(?:\r\n?|\n)/g);
3531 
3532         this._input = ch + this._input;
3533         this.yytext = this.yytext.substr(0, this.yytext.length - len);
3534         //this.yyleng -= len;
3535         this.offset -= len;
3536         var oldLines = this.match.split(/(?:\r\n?|\n)/g);
3537         this.match = this.match.substr(0, this.match.length - 1);
3538         this.matched = this.matched.substr(0, this.matched.length - 1);
3539 
3540         if (lines.length - 1) {
3541             this.yylineno -= lines.length - 1;
3542         }
3543         var r = this.yylloc.range;
3544 
3545         this.yylloc = {
3546             first_line: this.yylloc.first_line,
3547             last_line: this.yylineno + 1,
3548             first_column: this.yylloc.first_column,
3549             last_column: lines ?
3550                 (lines.length === oldLines.length ? this.yylloc.first_column : 0)
3551                  + oldLines[oldLines.length - lines.length].length - lines[0].length :
3552               this.yylloc.first_column - len
3553         };
3554 
3555         if (this.options.ranges) {
3556             this.yylloc.range = [r[0], r[0] + this.yyleng - len];
3557         }
3558         this.yyleng = this.yytext.length;
3559         return this;
3560     },
3561 
3562 // When called from action, caches matched text and appends it on next action
3563 more:function () {
3564         this._more = true;
3565         return this;
3566     },
3567 
3568 // 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.
3569 reject:function () {
3570         if (this.options.backtrack_lexer) {
3571             this._backtrack = true;
3572         } else {
3573             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(), {
3574                 text: "",
3575                 token: null,
3576                 line: this.yylineno
3577             });
3578 
3579         }
3580         return this;
3581     },
3582 
3583 // retain first n characters of the match
3584 less:function (n) {
3585         this.unput(this.match.slice(n));
3586     },
3587 
3588 // displays already matched input, i.e. for error messages
3589 pastInput:function () {
3590         var past = this.matched.substr(0, this.matched.length - this.match.length);
3591         return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "").replace(/[&<>]/g, function (c) {
3592             return c === '&' ? '&' : (c === '<' ? '<' : '>');
3593         });
3594     },
3595 
3596 // displays upcoming input, i.e. for error messages
3597 upcomingInput:function () {
3598         var next = this.match;
3599         if (next.length < 20) {
3600             next += this._input.substr(0, 20-next.length);
3601         }
3602         return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "").replace(/[&<>]/g, function (c) {
3603             return c === '&' ? '&' : (c === '<' ? '<' : '>');
3604         });
3605     },
3606 
3607 // displays the character position where the lexing error occurred, i.e. for error messages
3608 showPosition:function () {
3609         var pre = this.pastInput();
3610         var c = new Array(pre.length + 1).join("-");
3611         return pre + this.upcomingInput() + "\n" + c + "^";
3612     },
3613 
3614 // test the lexed token: return FALSE when not a match, otherwise return token
3615 test_match:function(match, indexed_rule) {
3616         var token,
3617             lines,
3618             backup;
3619 
3620         if (this.options.backtrack_lexer) {
3621             // save context
3622             backup = {
3623                 yylineno: this.yylineno,
3624                 yylloc: {
3625                     first_line: this.yylloc.first_line,
3626                     last_line: this.last_line,
3627                     first_column: this.yylloc.first_column,
3628                     last_column: this.yylloc.last_column
3629                 },
3630                 yytext: this.yytext,
3631                 match: this.match,
3632                 matches: this.matches,
3633                 matched: this.matched,
3634                 yyleng: this.yyleng,
3635                 offset: this.offset,
3636                 _more: this._more,
3637                 _input: this._input,
3638                 yy: this.yy,
3639                 conditionStack: this.conditionStack.slice(0),
3640                 done: this.done
3641             };
3642             if (this.options.ranges) {
3643                 backup.yylloc.range = this.yylloc.range.slice(0);
3644             }
3645         }
3646 
3647         lines = match[0].match(/(?:\r\n?|\n).*/g);
3648         if (lines) {
3649             this.yylineno += lines.length;
3650         }
3651         this.yylloc = {
3652             first_line: this.yylloc.last_line,
3653             last_line: this.yylineno + 1,
3654             first_column: this.yylloc.last_column,
3655             last_column: lines ?
3656                          lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
3657                          this.yylloc.last_column + match[0].length
3658         };
3659         this.yytext += match[0];
3660         this.match += match[0];
3661         this.matches = match;
3662         this.yyleng = this.yytext.length;
3663         if (this.options.ranges) {
3664             this.yylloc.range = [this.offset, this.offset += this.yyleng];
3665         }
3666         this._more = false;
3667         this._backtrack = false;
3668         this._input = this._input.slice(match[0].length);
3669         this.matched += match[0];
3670         token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
3671         if (this.done && this._input) {
3672             this.done = false;
3673         }
3674         if (token) {
3675             return token;
3676         } else if (this._backtrack) {
3677             // recover context
3678             for (var k in backup) {
3679                 this[k] = backup[k];
3680             }
3681             return false; // rule action called reject() implying the next rule should be tested instead.
3682         }
3683         return false;
3684     },
3685 
3686 // return next match in input
3687 next:function () {
3688         if (this.done) {
3689             return this.EOF;
3690         }
3691         if (!this._input) {
3692             this.done = true;
3693         }
3694 
3695         var token,
3696             match,
3697             tempMatch,
3698             index;
3699         if (!this._more) {
3700             this.yytext = '';
3701             this.match = '';
3702         }
3703         var rules = this._currentRules();
3704         for (var i = 0; i < rules.length; i++) {
3705             tempMatch = this._input.match(this.rules[rules[i]]);
3706             if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
3707                 match = tempMatch;
3708                 index = i;
3709                 if (this.options.backtrack_lexer) {
3710                     token = this.test_match(tempMatch, rules[i]);
3711                     if (token !== false) {
3712                         return token;
3713                     } else if (this._backtrack) {
3714                         match = false;
3715                         continue; // rule action called reject() implying a rule MISmatch.
3716                     } else {
3717                         // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
3718                         return false;
3719                     }
3720                 } else if (!this.options.flex) {
3721                     break;
3722                 }
3723             }
3724         }
3725         if (match) {
3726             token = this.test_match(match, rules[index]);
3727             if (token !== false) {
3728                 return token;
3729             }
3730             // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
3731             return false;
3732         }
3733         if (this._input === "") {
3734             return this.EOF;
3735         } else {
3736             return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
3737                 text: "",
3738                 token: null,
3739                 line: this.yylineno
3740             });
3741         }
3742     },
3743 
3744 // return next match that has a token
3745 lex:function lex () {
3746         var r = this.next();
3747         if (r) {
3748             return r;
3749         } else {
3750             return this.lex();
3751         }
3752     },
3753 
3754 // activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
3755 begin:function begin (condition) {
3756         this.conditionStack.push(condition);
3757     },
3758 
3759 // pop the previously active lexer condition state off the condition stack
3760 popState:function popState () {
3761         var n = this.conditionStack.length - 1;
3762         if (n > 0) {
3763             return this.conditionStack.pop();
3764         } else {
3765             return this.conditionStack[0];
3766         }
3767     },
3768 
3769 // produce the lexer rule set which is active for the currently active lexer condition state
3770 _currentRules:function _currentRules () {
3771         if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
3772             return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
3773         } else {
3774             return this.conditions["INITIAL"].rules;
3775         }
3776     },
3777 
3778 // return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
3779 topState:function topState (n) {
3780         n = this.conditionStack.length - 1 - Math.abs(n || 0);
3781         if (n >= 0) {
3782             return this.conditionStack[n];
3783         } else {
3784             return "INITIAL";
3785         }
3786     },
3787 
3788 // alias for begin(condition)
3789 pushState:function pushState (condition) {
3790         this.begin(condition);
3791     },
3792 
3793 // return the number of states currently on the stack
3794 stateStackSize:function stateStackSize() {
3795         return this.conditionStack.length;
3796     },
3797 options: {},
3798 /**
3799  * @class
3800  * @ignore
3801  */
3802 performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
3803 var YYSTATE=YY_START;
3804 switch($avoiding_name_collisions) {
3805 case 0:/* ignore */
3806 break;
3807 case 1:return 78  /* New 123.1234e+-12 */
3808 break;
3809 case 2:return 78  /* Old 123.1234 or .1234 */
3810 break;
3811 case 3:return 78  /* Old 123 */
3812 break;
3813 case 4: return 77;
3814 break;
3815 case 5: return 77;
3816 break;
3817 case 6:/* ignore comment */
3818 break;
3819 case 7:/* ignore multiline comment */
3820 break;
3821 case 8:return 7
3822 break;
3823 case 9:return 12
3824 break;
3825 case 10:return 14
3826 break;
3827 case 11:return 17
3828 break;
3829 case 12:return 15
3830 break;
3831 case 13:return 91
3832 break;
3833 case 14:return 93
3834 break;
3835 case 15:return 19
3836 break;
3837 case 16:return 23
3838 break;
3839 case 17:return 21
3840 break;
3841 case 18:return 75
3842 break;
3843 case 19:return 76
3844 break;
3845 case 20:return 74
3846 break;
3847 case 21:return 80
3848 break;
3849 case 22:return 94
3850 break;
3851 case 23:return 94
3852 break;
3853 case 24:return 82
3854 break;
3855 case 25:return 83
3856 break;
3857 case 26:return 26
3858 break;
3859 case 27:return 27
3860 break;
3861 case 28:return 16
3862 break;
3863 case 29:return '#'
3864 break;
3865 case 30:return 34
3866 break;
3867 case 31:return 35
3868 break;
3869 case 32:return 79
3870 break;
3871 case 33:return 64
3872 break;
3873 case 34:return 65
3874 break;
3875 case 35:return 66
3876 break;
3877 case 36:return 8
3878 break;
3879 case 37:return 10
3880 break;
3881 case 38:return 58
3882 break;
3883 case 39:return 57
3884 break;
3885 case 40:return 57
3886 break;
3887 case 41:return 53
3888 break;
3889 case 42:return 54
3890 break;
3891 case 43:return 55
3892 break;
3893 case 44:return 50
3894 break;
3895 case 45:return 51
3896 break;
3897 case 46:return 47
3898 break;
3899 case 47:return 45
3900 break;
3901 case 48:return 48
3902 break;
3903 case 49:return 46
3904 break;
3905 case 50:return 41
3906 break;
3907 case 51:return 43
3908 break;
3909 case 52:return 42
3910 break;
3911 case 53:return 39
3912 break;
3913 case 54:return 37
3914 break;
3915 case 55:return 32
3916 break;
3917 case 56:return 86
3918 break;
3919 case 57:return 5
3920 break;
3921 case 58:return 20
3922 break;
3923 case 59:return 'INVALID'
3924 break;
3925 }
3926 },
3927 rules: [/^(?:\s+)/,/^(?:[0-9]*\.?[0-9]+([eE][-+]?[0-9]+))/,/^(?:[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_]*)/,/^(?:.)/],
3928 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,57,58,59],"inclusive":true}}
3929 });
3930 return lexer;
3931 })();
3932 parser.lexer = lexer;
3933 /**
3934  * @class
3935  * @ignore
3936  */
3937 function Parser () {
3938   this.yy = {};
3939 }
3940 Parser.prototype = parser;parser.Parser = Parser;
3941 return new Parser;
3942 })();
3943 // Work around an issue with browsers that don't support Object.getPrototypeOf()
3944 parser.yy.parseError = parser.parseError;
3945 
3946 export default JXG.JessieCode;
3947