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