Advertisement
Guest User

Untitled

a guest
Mar 24th, 2019
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.75 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());*/
  208. const indexes = new Map();
  209. indexes.set("x", 0);
  210. indexes.set("y", 1);
  211. indexes.set("z", 2);
  212.  
  213. function createBy(constructor, args) {
  214. let instance = Object.create(constructor.prototype);
  215. constructor.apply(instance, args);
  216. return instance;
  217. }
  218.  
  219. function constructOperation(basicOperation, operationIdentifier) {
  220. function Operation(...args) {
  221. this.operands = args;
  222. }
  223.  
  224. Operation.prototype.toString = function () {
  225. return this.operands.join(" ") + " " + operationIdentifier;
  226. };
  227.  
  228. Operation.prototype.evaluate = function (...args) {
  229. return basicOperation(...this.operands.map(operand => operand.evaluate(...args)));
  230. };
  231.  
  232. Operation.prototype.prefix = function () {
  233. return "(" + operationIdentifier + " " + this.operands.map(operand => operand.prefix()).join(" ") + ")";
  234. };
  235.  
  236. return Operation;
  237. }
  238.  
  239. function Const(value) {
  240. this.constValue = value;
  241. }
  242.  
  243. Const.prototype.toString = function () {
  244. return this.constValue.toString();
  245. };
  246.  
  247. Const.prototype.evaluate = function () {
  248. return this.constValue;
  249. };
  250.  
  251. Const.prototype.prefix = function () {
  252. return this.constValue.toString();
  253. };
  254.  
  255. function Variable(name) {
  256. this.variableName = name;
  257. this.index = indexes.get(name);
  258. }
  259.  
  260. Variable.prototype.toString = function () {
  261. return this.variableName;
  262. };
  263.  
  264. Variable.prototype.evaluate = function () {
  265. return arguments[this.index];
  266. };
  267.  
  268. Variable.prototype.prefix = function () {
  269. return this.variableName;
  270. };
  271.  
  272. let Add = constructOperation((x, y) => (x + y), "+");
  273.  
  274. let Subtract = constructOperation((x, y) => (x - y), "-");
  275.  
  276. let Multiply = constructOperation((x, y) => (x * y), "*");
  277.  
  278. let Divide = constructOperation((x, y) => (x / y), "/");
  279.  
  280. let Negate = constructOperation((x) => (-x), "negate");
  281.  
  282. let Min3 = constructOperation((...args) => Math.min(...args), "min3");
  283.  
  284. let Max5 = constructOperation((...args) => (Math.max(...args)), "max5");
  285.  
  286. let operations = {};
  287. operations['+'] = {Op: Add, argsCount: 2};
  288. operations['-'] = {Op: Subtract, argsCount: 2};
  289. operations['*'] = {Op: Multiply, argsCount: 2};
  290. operations['/'] = {Op: Divide, argsCount: 2};
  291. operations['negate'] = {Op: Negate, argsCount: 1};
  292.  
  293. let exceptions = function () {
  294. let exceptionFactory = function (message) {
  295. let Exception = function (index, token) {
  296. this.name = message + " on position " + index + ", where '" + token + "' is";
  297. };
  298. Exception.prototype = Error.prototype;
  299. return Exception;
  300. };
  301.  
  302. let ClosingParenthesisMissingException = exceptionFactory(
  303. 'Closing parenthesis expected'
  304. );
  305. let ExpressionEndExpectedException = exceptionFactory(
  306. 'End of expression expected'
  307. );
  308. let OperationExpectedException = exceptionFactory(
  309. 'Operation symbol expected'
  310. );
  311. let OperandExpectedException = exceptionFactory(
  312. 'Operand expected'
  313. );
  314. let EndOfConstantExpectedException = exceptionFactory(
  315. 'End of constant expected'
  316. );
  317. let InvalidOperandsAmountException = exceptionFactory(
  318. 'Invalid operands amount found'
  319. );
  320.  
  321. return {
  322. ClosingParenthesisMissingException: ClosingParenthesisMissingException,
  323. ExpressionEndExpectedException: ExpressionEndExpectedException,
  324. OperationExpectedException: OperationExpectedException,
  325. OperandExpectedException: OperandExpectedException,
  326. EndOfConstantExpectedException: EndOfConstantExpectedException,
  327. InvalidOperandsAmountException: InvalidOperandsAmountException,
  328. }
  329. }();
  330.  
  331. let Tokenizer = function (string) {
  332. this.index = 0;
  333. this.prevToken = '';
  334. this.curToken = '';
  335.  
  336. let isWhitespace = function (c) {
  337. return /[\s]/.test("" + c);
  338. };
  339.  
  340. this.nextToken = function () {
  341. this.prevToken = this.curToken;
  342. while (this.index < string.length && isWhitespace(string[this.index])) {
  343. this.index++;
  344. }
  345. this.curToken = '';
  346. if (string[this.index] === '(' || string[this.index] === ')') {
  347. this.curToken = string[this.index++];
  348. } else {
  349. while (this.index < string.length &&
  350. !isWhitespace(string[this.index]) && string[this.index] !== '(' && string[this.index] !== ')') {
  351. this.curToken += string[this.index++];
  352. }
  353. }
  354. };
  355. };
  356.  
  357. let parseOperand = function (tokenizer, parseExpression) {
  358. if (tokenizer.curToken === '(') {
  359. return parseExpression();
  360. } else if (indexes.has(tokenizer.curToken)) {
  361. tokenizer.nextToken();
  362. return new Variable(tokenizer.prevToken)
  363. } else if (tokenizer.curToken !== '' && !isNaN(tokenizer.curToken)) {
  364. tokenizer.nextToken();
  365. return new Const(parseInt(tokenizer.prevToken));
  366. } else {
  367. throw new exceptions.OperandExpectedException(tokenizer.index, tokenizer.curToken);
  368. }
  369. };
  370.  
  371. let parsePrefix = function (str) {
  372. let tokenizer = new Tokenizer(str);
  373.  
  374. let parseExpression = function () {
  375. if (tokenizer.curToken === '(') {
  376. tokenizer.nextToken();
  377. if (!(tokenizer.curToken in operations)) {
  378. throw new exceptions.OperationExpectedException(tokenizer.index, tokenizer.curToken);
  379. }
  380. let operation = operations[tokenizer.curToken];
  381. tokenizer.nextToken();
  382. let args = [];
  383. for (let i = 0; i < operation.argsCount; i++) {
  384. args.push(parseOperand(tokenizer, parseExpression));
  385. }
  386. if (tokenizer.curToken !== ')') {
  387. throw new exceptions.ClosingParenthesisMissingException(tokenizer.index, tokenizer.curToken);
  388. }
  389. tokenizer.nextToken();
  390. //return operation.Op(args);
  391. //return createBy(operation.Op, args);
  392. return new operation.Op.apply(args);
  393. } else {
  394. return parseOperand(tokenizer, parseExpression);
  395. }
  396. };
  397.  
  398. tokenizer.nextToken();
  399. let res = parseExpression();
  400. if (tokenizer.curToken !== '') {
  401. throw new exceptions.ExpressionEndExpectedException(tokenizer.index, tokenizer.curToken);
  402. }
  403. return res;
  404. };
  405.  
  406. /*
  407. let expr = new Subtract(
  408. new Multiply(
  409. new Const(2),
  410. new Variable("x")
  411. ),
  412. new Const(3)
  413. );
  414. console.log(expr.toString());*/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement