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