Annotation of loncom/html/adm/LC_math_editor/src/definitions.js, revision 1.1
1.1 ! damieng 1: /*
! 2:
! 3: Copyright (C) 2014 Michigan State University Board of Trustees
! 4:
! 5: The JavaScript code in this page is free software: you can
! 6: redistribute it and/or modify it under the terms of the GNU
! 7: General Public License (GNU GPL) as published by the Free Software
! 8: Foundation, either version 3 of the License, or (at your option)
! 9: any later version. The code is distributed WITHOUT ANY WARRANTY;
! 10: without even the implied warranty of MERCHANTABILITY or FITNESS
! 11: FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
! 12:
! 13: As additional permission under GNU GPL version 3 section 7, you
! 14: may distribute non-source (e.g., minimized or compacted) forms of
! 15: that code without the copy of the GNU GPL normally required by
! 16: section 4, provided you include this license notice and a URL
! 17: through which recipients can access the Corresponding Source.
! 18:
! 19: */
! 20:
! 21: /**
! 22: * Operator definitions (see function define() at the end).
! 23: * @constructor
! 24: */
! 25: function Definitions() {
! 26: this.operators = []; /* Array of Operator */
! 27: }
! 28:
! 29: Definitions.ARG_SEPARATOR = ";";
! 30: Definitions.DECIMAL_SIGN_1 = ".";
! 31: Definitions.DECIMAL_SIGN_2 = ",";
! 32:
! 33: /**
! 34: * Creates a new operator.
! 35: * @param {string} id - Operator id (text used to recognize it)
! 36: * @param {number} arity - Operator.UNARY, BINARY or TERNARY
! 37: * @param {number} lbp - Left binding power
! 38: * @param {number} rbp - Right binding power
! 39: * @param {function} nud - Null denotation function
! 40: * @param {function} led - Left denotation function
! 41: */
! 42: Definitions.prototype.operator = function(id, arity, lbp, rbp, nud, led) {
! 43: this.operators.push(new Operator(id, arity, lbp, rbp, nud, led));
! 44: };
! 45:
! 46: /**
! 47: * Creates a new separator operator.
! 48: * @param {string} id - Operator id (text used to recognize it)
! 49: */
! 50: Definitions.prototype.separator = function(id) {
! 51: this.operator(id, Operator.BINARY, 0, 0, null, null);
! 52: };
! 53:
! 54: /**
! 55: * Creates a new infix operator.
! 56: * @param {string} id - Operator id (text used to recognize it)
! 57: * @param {number} lbp - Left binding power
! 58: * @param {number} rbp - Right binding power
! 59: * @param {ledFunction} [led] - Left denotation function
! 60: */
! 61: Definitions.prototype.infix = function(id, lbp, rbp, led) {
! 62: var arity, nud;
! 63: arity = Operator.BINARY;
! 64: nud = null;
! 65: led = led || function(p, left) {
! 66: var children = [left, p.expression(rbp)];
! 67: return new ENode(ENode.OPERATOR, this, id, children);
! 68: };
! 69: this.operator(id, arity, lbp, rbp, nud, led);
! 70: };
! 71:
! 72: /**
! 73: * Creates a new prefix operator.
! 74: * @param {string} id - Operator id (text used to recognize it)
! 75: * @param {number} rbp - Right binding power
! 76: * @param {nudFunction} [nud] - Null denotation function
! 77: */
! 78: Definitions.prototype.prefix = function(id, rbp, nud) {
! 79: var arity, lbp, led;
! 80: arity = Operator.UNARY;
! 81: lbp = 0;
! 82: nud = nud || function(p) {
! 83: var children = [p.expression(rbp)];
! 84: return new ENode(ENode.OPERATOR, this, id, children);
! 85: };
! 86: led = null;
! 87: this.operator(id, arity, lbp, rbp, nud, led);
! 88: };
! 89:
! 90: /**
! 91: * Creates a new suffix operator.
! 92: * @param {string} id - Operator id (text used to recognize it)
! 93: * @param {number} lbp - Left binding power
! 94: * @param {ledFunction} [led] - Left denotation function
! 95: */
! 96: Definitions.prototype.suffix = function(id, lbp, led) {
! 97: var arity, rbp, nud;
! 98: arity = Operator.UNARY;
! 99: rbp = 0;
! 100: nud = null;
! 101: led = led || function(p, left) {
! 102: var children = [left];
! 103: return new ENode(ENode.OPERATOR, this, id, children);
! 104: };
! 105: this.operator(id, arity, lbp, rbp, nud, led);
! 106: };
! 107:
! 108: /**
! 109: * Returns the defined operator with the given id
! 110: * @param {string} id - Operator id (text used to recognize it)
! 111: * @returns {Operator}
! 112: */
! 113: Definitions.prototype.findOperator = function(id) {
! 114: for (var i=0; i<this.operators.length; i++) {
! 115: if (this.operators[i].id == id) {
! 116: return(this.operators[i]);
! 117: }
! 118: }
! 119: return null;
! 120: }
! 121:
! 122: /**
! 123: * Defines all the operators.
! 124: */
! 125: Definitions.prototype.define = function() {
! 126: this.suffix("!", 160);
! 127: this.infix("^", 140, 139);
! 128: this.infix(".", 130, 129);
! 129: this.infix("`", 125, 125, function(p, left) {
! 130: // led (infix operator)
! 131: // this led for units gathers all the units in an ENode
! 132: var right = p.expression(125);
! 133: while (p.current_token != null && "*/".indexOf(p.current_token.value) != -1) {
! 134: var token2 = p.tokens[p.token_nr];
! 135: if (token2 == null)
! 136: break;
! 137: if (token2.type != Token.NAME && token2.value != "(")
! 138: break;
! 139: var token3 = p.tokens[p.token_nr+1];
! 140: if (token3 != null && (token3.value == "(" || token3.type == Token.NUMBER))
! 141: break;
! 142: if (p.unit_mode && p.tokens[p.token_nr].type == Token.NAME) {
! 143: var nv = p.tokens[p.token_nr].value;
! 144: var cst = false;
! 145: for (var i=0; i<p.constants.length; i++) {
! 146: if (nv == p.constants[i]) {
! 147: cst = true;
! 148: break;
! 149: }
! 150: }
! 151: if (cst)
! 152: break;
! 153: }
! 154: var t = p.current_token;
! 155: p.advance();
! 156: right = t.op.led(p, right);
! 157: }
! 158: var children = [left, right];
! 159: return new ENode(ENode.OPERATOR, this, "`", children);
! 160: });
! 161: this.infix("*", 120, 120);
! 162: this.infix("/", 120, 120);
! 163: this.infix("%", 120, 120);
! 164: this.infix("+", 100, 100);
! 165: this.operator("-", Operator.BINARY, 100, 134, function(p) {
! 166: // nud (prefix operator)
! 167: var children = [p.expression(134)];
! 168: return new ENode(ENode.OPERATOR, this, "-", children);
! 169: }, function(p, left) {
! 170: // led (infix operator)
! 171: var children = [left, p.expression(100)];
! 172: return new ENode(ENode.OPERATOR, this, "-", children);
! 173: });
! 174: this.infix("=", 80, 80);
! 175: this.infix("#", 80, 80);
! 176: this.infix("<=", 80, 80);
! 177: this.infix(">=", 80, 80);
! 178: this.infix("<", 80, 80);
! 179: this.infix(">", 80, 80);
! 180:
! 181: this.separator(")");
! 182: this.separator(Definitions.ARG_SEPARATOR);
! 183: this.operator("(", Operator.BINARY, 200, 200, function(p) {
! 184: // nud (for parenthesis)
! 185: var e = p.expression(0);
! 186: p.advance(")");
! 187: return e;
! 188: }, function(p, left) {
! 189: // led (for functions)
! 190: if (left.type != ENode.NAME && left.type != ENode.SUBSCRIPT)
! 191: throw new ParseException("Function name expected before a parenthesis.", p.tokens[p.token_nr - 1].from);
! 192: var children = [left];
! 193: if (p.current_token == null || p.current_token.op == null || p.current_token.op.id !== ")") {
! 194: while (true) {
! 195: children.push(p.expression(0));
! 196: if (p.current_token == null || p.current_token.op == null || p.current_token.op.id !== Definitions.ARG_SEPARATOR) {
! 197: break;
! 198: }
! 199: p.advance(Definitions.ARG_SEPARATOR);
! 200: }
! 201: }
! 202: p.advance(")");
! 203: return new ENode(ENode.FUNCTION, this, "(", children);
! 204: });
! 205:
! 206: this.separator("]");
! 207: this.operator("[", Operator.BINARY, 200, 70, function(p) {
! 208: // nud (for vectors)
! 209: var children = [];
! 210: if (p.current_token == null || p.current_token.op == null || p.current_token.op.id !== "]") {
! 211: while (true) {
! 212: children.push(p.expression(0));
! 213: if (p.current_token == null || p.current_token.op == null || p.current_token.op.id !== Definitions.ARG_SEPARATOR) {
! 214: break;
! 215: }
! 216: p.advance(Definitions.ARG_SEPARATOR);
! 217: }
! 218: }
! 219: p.advance("]");
! 220: return new ENode(ENode.VECTOR, this, null, children);
! 221: }, function(p, left) {
! 222: // led (for subscript)
! 223: if (left.type != ENode.NAME && left.type != ENode.SUBSCRIPT)
! 224: throw new ParseException("Name expected before a square bracket.", p.tokens[p.token_nr - 1].from);
! 225: var children = [left];
! 226: if (p.current_token == null || p.current_token.op == null || p.current_token.op.id !== "]") {
! 227: while (true) {
! 228: children.push(p.expression(0));
! 229: if (p.current_token == null || p.current_token.op == null || p.current_token.op.id !== Definitions.ARG_SEPARATOR) {
! 230: break;
! 231: }
! 232: p.advance(Definitions.ARG_SEPARATOR);
! 233: }
! 234: }
! 235: p.advance("]");
! 236: return new ENode(ENode.SUBSCRIPT, this, "[", children);
! 237: });
! 238: };
! 239:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>