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