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