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>