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