Advertisement
Guest User

Untitled

a guest
Apr 9th, 2020
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. "use strict";
  2.  
  3. let abstractOperation = {};
  4. abstractOperation.prototype = {
  5.     evaluate : function() {
  6.         const result = [];
  7.         for (let f of this.operands) {
  8.             result.push(f.evaluate(...arguments));
  9.         }
  10.         return this.operator(...result);
  11.     },
  12.  
  13.     toString : function() {
  14.         let toStr = "";
  15.         for (let cur of this.operands) {
  16.             toStr += cur.toString() + " ";
  17.         }
  18.         toStr += this.symbol;
  19.         return toStr;
  20.     },
  21.  
  22.     prefix : function() {
  23.         let toStr = this.symbol;
  24.         for (let cur of this.operands) {
  25.             toStr += " " + cur.prefix();
  26.         }
  27.         return "(" + toStr + ")";
  28.     }
  29. }      
  30.  
  31. let abstractAtomic = {};
  32. abstractAtomic.prototype = {
  33.     toString : function() { return this.info + ""; },
  34.     prefix : function() { return this.info + ""; },
  35. }
  36.  
  37. const v = ["x", "y", "z"];
  38. function Atomic(evaluate) {
  39.     function created(info) {
  40.         this.info = (() => info)();
  41.     }
  42.     created.prototype = Object.create(abstractAtomic.prototype);
  43.     created.prototype.evaluate = evaluate;
  44.     return created;
  45. }
  46.  
  47. const Variable = Atomic(function() {return arguments[v.indexOf(this.info)]});
  48.  
  49. const Const = Atomic(function() { return this.info; });
  50.  
  51. // :NOTE: you don't create operations of some specific prototype, you use prototype of global object
  52. // :NOTE: pass `arguments` each time is not well, get rid of that
  53.  
  54. // :NOTE 2: in each instantiation of operator you override prototype of this operator
  55. // :NOTE 2: copy-paste code for operator declaration (at least call for `prototypeCreator`)
  56.  
  57. function Opertion(sign, operator) {
  58.     function created() {
  59.         this.operands = (() => arguments)();
  60.     }
  61.     created.prototype = Object.create(abstractOperation.prototype);
  62.     created.prototype.operator = (() => operator)();
  63.     created.prototype.symbol = (() => sign)();
  64.     return created;
  65. }
  66.  
  67. const Add = Opertion("+", (a, b) => (a + b));
  68.  
  69. const Subtract = Opertion("-", (a, b) => (a - b));
  70.  
  71. const Multiply = Opertion("*", (a, b) => (a * b));
  72.  
  73. const Divide = Opertion("/", (a, b) => (a / b));
  74.  
  75. const Negate = Opertion("negate", a => -a);
  76.  
  77. const Sinh = Opertion("sinh", a => Math.sinh(a));
  78.  
  79. const Cosh = Opertion("cosh", a => Math.cosh(a));
  80.  
  81.  
  82.  
  83. function ParseError(message) {
  84.     this.message = message;
  85. }
  86. ParseError.prototype.constructor = ParseError;
  87. ParseError.prototype.name = "ParseError";
  88.  
  89. function parsePrefix(expression) {
  90.     let position = 0;
  91.     let balance = 0;
  92.  
  93.     for (let i = 0; i < expression.length; i++) {
  94.         if (expression.charAt(i) === '(') {
  95.             balance++;
  96.         }
  97.         if (expression.charAt(i) === ')') {
  98.             balance--;
  99.         }
  100.         if (balance < 0) {
  101.             throw new ParseError("No open bracket for ) at position: " + position);
  102.         }
  103.     }
  104.  
  105.     function skipWS() {
  106.         while (position < expression.length && expression.charAt(position) === ' ') {
  107.             position++;
  108.         }
  109.     }
  110.  
  111.     function getNumber() {
  112.         let start = position;
  113.         while (position < expression.length && expression.charAt(position) >= '0' && expression.charAt(position) <= '9'
  114.             || expression.charAt(position) === '-') {
  115.             position++;
  116.         }
  117.         if (start == position) {
  118.             return {};
  119.         }
  120.         return +expression.substring(start, position);
  121.     }
  122.  
  123.     function getWord() {
  124.         let start = position;
  125.         while (position < expression.length && expression.charAt(position) != ' ' && expression.charAt(position) != '(') {
  126.             position++;
  127.         }
  128.         return expression.substring(start, position);
  129.     }
  130.  
  131.     function parseFunction() {
  132.         switch(expression.charAt(position++)) {
  133.             case '+':
  134.                 return {"f": Add, "arg" : 2};
  135.             case '-':
  136.                 if(expression.charAt(position) != ' ' && expression.charAt(position) != '(') {
  137.                     position--;
  138.                     throw new ParseError("Expected operation, found: " + getWord());
  139.                 }
  140.                 return {"f": Subtract, "arg" : 2};
  141.             case '*':
  142.                 return {"f": Multiply, "arg" : 2};
  143.             case '/':
  144.                 return {"f": Divide, "arg" : 2};
  145.             case 'n':
  146.                 let word_negate = getWord();
  147.                 if (word_negate === "egate") {
  148.                     return {"f": Negate, "arg" : 1};
  149.                 } else {
  150.                     throw new ParseError("Unknown operation: n" + word_negate);
  151.                 }
  152.             case 's':
  153.                 let word_sinh = getWord();
  154.                 if (word_sinh === "inh") {
  155.                     return {"f": Sinh, "arg" : 2};
  156.                 } else {
  157.                     throw new ParseError("Unknown operation: s" + word_sinh);
  158.                 }
  159.             case 'c':
  160.                 let word_cosh = getWord();
  161.                 if (word_cosh === "osh") {
  162.                     return {"f": Cosh, "arg" : 2};
  163.                 } else {
  164.                     throw new ParseError("Unknown operation: c" + word_cosh);
  165.                 }
  166.             default :
  167.                 position--;
  168.                 throw new ParseError("Unknown operation: " + getWord());
  169.  
  170.         }
  171.     }
  172.  
  173.     function parseExpression(inOperation) {
  174.         let exp;
  175.         let isOpened = false;
  176.         skipWS();
  177.  
  178.         switch (expression.charAt(position)) {
  179.             case '(':
  180.                 isOpened = true;
  181.                 position++;
  182.                 skipWS();
  183.                 let func = parseFunction();            
  184.  
  185.                 let args = [];
  186.                 for (let i = 0; i < func.arg; i++) {
  187.                     args[i] = parseExpression(true);
  188.                 }
  189.                 exp = new func.f(...args);
  190.                 skipWS();
  191.                 break;
  192.             case 'x':
  193.             case 'y':
  194.             case 'z':
  195.                 exp = new Variable(expression.charAt(position++));             
  196.                 if (!inOperation) {
  197.                     skipWS();
  198.                     if (position < expression.length - 1) {
  199.                         throw new ParseError("Incorrect \"argument\": " + getWord());
  200.                     }
  201.                 }
  202.  
  203.                 break;
  204.             default :
  205.                 let num = getNumber();
  206.                 if (!inOperation) {
  207.                     skipWS();
  208.                     if (position < expression.length - 1) {
  209.                         throw new PraseError("Incorrect \"argument\" " + getWord());
  210.                     }
  211.                 }
  212.  
  213.                 if (isNaN(num)) {
  214.                     throw new ParseError("Incorrect \"argument\" " + getWord());
  215.                 } else {
  216.                     exp = new Const(+num);
  217.                 }
  218.                 break;
  219.         }
  220.  
  221.         if (!isOpened) {
  222.             if (position != expression.length && expression.charAt(position) != ' '
  223.                 && expression.charAt(position) != ')'  && expression.charAt(position) != '(') {
  224.                 throw new ParseError("Incorrect expression, last symbol: " + expression.charAt(position));
  225.             }
  226.         } else {
  227.             if (expression.charAt(position) != ')') {
  228.                 throw new ParseError("no )");
  229.             }
  230.             position++; // skip ")"
  231.         }
  232.        
  233.         return exp;
  234.     }
  235.  
  236.     return parseExpression(false);
  237. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement