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