Advertisement
Guest User

Untitled

a guest
Mar 24th, 2019
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.37 KB | None | 0 0
  1. const indexes = new Map();
  2. indexes.set("x", 0);
  3. indexes.set("y", 1);
  4. indexes.set("z", 2);
  5.  
  6. function createBy(constructor, args) {
  7. let instance = Object.create(constructor.prototype);
  8. constructor.apply(instance, args);
  9. return instance;
  10. }
  11.  
  12. function constructOperation(basicOperation, operationIdentifier) {
  13. function Operation(...args) {
  14. this.operands = args;
  15. }
  16.  
  17. Operation.prototype.toString = function () {
  18. return this.operands.join(" ") + " " + operationIdentifier;
  19. };
  20.  
  21. Operation.prototype.evaluate = function (...args) {
  22. return basicOperation(...this.operands.map(operand => operand.evaluate(...args)));
  23. };
  24.  
  25. Operation.prototype.prefix = function () {
  26. return "(" + operationIdentifier + " " + this.operands.map(operand => operand.prefix()).join(" ") + ")";
  27. };
  28.  
  29. return Operation;
  30. }
  31.  
  32. function Const(value) {
  33. this.constValue = value;
  34. }
  35.  
  36. Const.prototype.toString = function () {
  37. return this.constValue.toString();
  38. };
  39.  
  40. Const.prototype.evaluate = function () {
  41. return this.constValue;
  42. };
  43.  
  44. Const.prototype.prefix = function () {
  45. return this.constValue.toString();
  46. };
  47.  
  48. function Variable(name) {
  49. this.variableName = name;
  50. this.index = indexes.get(name);
  51. }
  52.  
  53. Variable.prototype.toString = function () {
  54. return this.variableName;
  55. };
  56.  
  57. Variable.prototype.evaluate = function () {
  58. return arguments[this.index];
  59. };
  60.  
  61. Variable.prototype.prefix = function () {
  62. return this.variableName;
  63. };
  64.  
  65. let Add = constructOperation((x, y) => (x + y), "+");
  66.  
  67. let Subtract = constructOperation((x, y) => (x - y), "-");
  68.  
  69. let Multiply = constructOperation((x, y) => (x * y), "*");
  70.  
  71. let Divide = constructOperation((x, y) => (x / y), "/");
  72.  
  73. let Negate = constructOperation((x) => (-x), "negate");
  74.  
  75. let Min3 = constructOperation((...args) => Math.min(...args), "min3");
  76.  
  77. let Max5 = constructOperation((...args) => (Math.max(...args)), "max5");
  78.  
  79. let operations = {};
  80. operations['+'] = {Op: Add, argsCount: 2};
  81. operations['-'] = {Op: Subtract, argsCount: 2};
  82. operations['*'] = {Op: Multiply, argsCount: 2};
  83. operations['/'] = {Op: Divide, argsCount: 2};
  84. operations['negate'] = {Op: Negate, argsCount: 1};
  85.  
  86. let exceptions = function () {
  87. let exceptionFactory = function (message) {
  88. let Exception = function (index, token) {
  89. this.name = message + " on position " + index + ", where '" + token + "' is";
  90. };
  91. Exception.prototype = Error.prototype;
  92. return Exception;
  93. };
  94.  
  95. let ClosingParenthesisMissingException = exceptionFactory(
  96. 'Closing parenthesis expected'
  97. );
  98. let ExpressionEndExpectedException = exceptionFactory(
  99. 'End of expression expected'
  100. );
  101. let OperationExpectedException = exceptionFactory(
  102. 'Operation symbol expected'
  103. );
  104. let OperandExpectedException = exceptionFactory(
  105. 'Operand expected'
  106. );
  107. let EndOfConstantExpectedException = exceptionFactory(
  108. 'End of constant expected'
  109. );
  110. let InvalidOperandsAmountException = exceptionFactory(
  111. 'Invalid operands amount found'
  112. );
  113.  
  114. return {
  115. ClosingParenthesisMissingException: ClosingParenthesisMissingException,
  116. ExpressionEndExpectedException: ExpressionEndExpectedException,
  117. OperationExpectedException: OperationExpectedException,
  118. OperandExpectedException: OperandExpectedException,
  119. EndOfConstantExpectedException: EndOfConstantExpectedException,
  120. InvalidOperandsAmountException: InvalidOperandsAmountException,
  121. }
  122. }();
  123.  
  124. let Tokenizer = function (string) {
  125. this.index = 0;
  126. this.prevToken = '';
  127. this.curToken = '';
  128.  
  129. let isWhitespace = function (c) {
  130. return /[\s]/.test("" + c);
  131. };
  132.  
  133. this.nextToken = function () {
  134. this.prevToken = this.curToken;
  135. while (this.index < string.length && isWhitespace(string[this.index])) {
  136. this.index++;
  137. }
  138. this.curToken = '';
  139. if (string[this.index] === '(' || string[this.index] === ')') {
  140. this.curToken = string[this.index++];
  141. } else {
  142. while (this.index < string.length &&
  143. !isWhitespace(string[this.index]) && string[this.index] !== '(' && string[this.index] !== ')') {
  144. this.curToken += string[this.index++];
  145. }
  146. }
  147. };
  148. };
  149.  
  150. let parseOperand = function (tokenizer, parseExpression) {
  151. if (tokenizer.curToken === '(') {
  152. return parseExpression();
  153. } else if (indexes.has(tokenizer.curToken)) {
  154. tokenizer.nextToken();
  155. return new Variable(tokenizer.prevToken)
  156. } else if (tokenizer.curToken !== '' && !isNaN(tokenizer.curToken)) {
  157. tokenizer.nextToken();
  158. return new Const(parseInt(tokenizer.prevToken));
  159. } else {
  160. throw new exceptions.OperandExpectedException(tokenizer.index, tokenizer.curToken);
  161. }
  162. };
  163.  
  164. let parsePrefix = function (str) {
  165. let tokenizer = new Tokenizer(str);
  166.  
  167. let parseExpression = function () {
  168. if (tokenizer.curToken === '(') {
  169. tokenizer.nextToken();
  170. if (!(tokenizer.curToken in operations)) {
  171. throw new exceptions.OperationExpectedException(tokenizer.index, tokenizer.curToken);
  172. }
  173. let operation = operations[tokenizer.curToken];
  174. tokenizer.nextToken();
  175. let args = [];
  176. for (let i = 0; i < operation.argsCount; i++) {
  177. args.push(parseOperand(tokenizer, parseExpression));
  178. }
  179. if (tokenizer.curToken !== ')') {
  180. throw new exceptions.ClosingParenthesisMissingException(tokenizer.index, tokenizer.curToken);
  181. }
  182. tokenizer.nextToken();
  183. //return operation.Op(args);
  184. //return createBy(operation.Op, args);
  185. return new operation.Op.apply(args);
  186. } else {
  187. return parseOperand(tokenizer, parseExpression);
  188. }
  189. };
  190.  
  191. tokenizer.nextToken();
  192. let res = parseExpression();
  193. if (tokenizer.curToken !== '') {
  194. throw new exceptions.ExpressionEndExpectedException(tokenizer.index, tokenizer.curToken);
  195. }
  196. return res;
  197. };
  198.  
  199. /*
  200. let expr = new Subtract(
  201. new Multiply(
  202. new Const(2),
  203. new Variable("x")
  204. ),
  205. new Const(3)
  206. );
  207. console.log(expr.toString());*/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement