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