{"id":350830,"date":"2023-07-26T21:01:30","date_gmt":"2023-07-26T21:01:30","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=350830"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=350830","title":{"rendered":"<span>\u0421\u0447\u0438\u0442\u0430\u0435\u043c 2+2\u00d72<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0421\u0442\u0430\u0442\u044c\u044f-\u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b \u0434\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0445\u043e\u0447\u0435\u0442 \u0443\u0437\u043d\u0430\u0442\u044c, \u043a\u0430\u043a \u0438\u0437 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u00ab6\u00bb \u043c\u0435\u0442\u043e\u0434\u043e\u043c <em>\u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u0441\u043f\u0443\u0441\u043a\u0430<\/em>. \u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0438 \u0434\u043e\u0439\u0434\u0451\u043c \u0434\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f <code>-1.82<\/code> \u0438\u043b\u0438 \u043e\u043a\u043e\u043b\u043e \u0442\u043e\u0433\u043e \u0438\u0437 \u0441\u0442\u0440\u043e\u043a\u0438 <code>-2.1+ .355 \/ (cos(pi % 3) + sin(0.311))<\/code>.<\/p>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u043d\u0435\u043e\u0434\u043d\u043e\u043a\u0440\u0430\u0442\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u043d \u043d\u0430\u00a0\u0425\u0430\u0431\u0440\u0435 \u0438 \u0437\u0430\u0447\u0438\u0442\u0430\u043d \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0430\u0439\u0442\u0438\u0448\u043d\u043e\u043c\u0443 \u043f\u0435\u0440\u0432\u043e\u043a\u0443\u0440\u0441\u043d\u0438\u043a\u0443. \u0412\u00a0\u0441\u0432\u043e\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u044f \u0445\u043e\u0447\u0443 \u0438\u0437\u043b\u043e\u0436\u0438\u0442\u044c \u0435\u0433\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e, \u0441\u00a0\u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0440\u043d\u043e\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 \u043d\u0430\u00a0JavaScript. \u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430\u00a0\u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043a\u043e\u0434\u00a0\u2014 \u0432\u00a0\u0441\u0430\u043c\u043e\u043c \u043d\u0438\u0437\u0443.<\/p>\n<h2>\u00ab2\u00bb<\/h2>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043d\u0435\u0432\u044b\u043d\u043e\u0441\u0438\u043c\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440: \u043d\u0430 \u0432\u0445\u043e\u0434\u0435 \u0443 \u043d\u0430\u0441 \u0441\u0442\u0440\u043e\u043a\u0430 \u0441 \u0434\u0432\u043e\u0439\u043a\u043e\u0439, \u0430 \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c <em>\u0447\u0438\u0441\u043b\u043e<\/em> 2. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u0442\u0443\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>parseInt<\/code>, \u043d\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u043e\u0442 \u0447\u0435\u0433\u043e \u043e\u0442\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0443\u0440\u043e\u0432\u043d\u044f\u0445.<\/p>\n<pre><code class=\"javascript\">function calc(tokens) { \/\/ ['2']   let result = parseInt(tokens.shift()); \/\/ ['2'] \u2192 '2' \u2192 2   if (tokens.length) throw new Error('expected eof'); \/\/ [empty array]   return result; \/\/ 2 }  console.log(calc('2'.split('')) === 2); \/\/ true<\/code><\/pre>\n<p>\u0417\u0430\u0447\u0435\u043c \u043c\u044b \u0434\u0435\u043b\u0438\u043c \u0441\u0442\u0440\u043e\u043a\u0443 \u043d\u0430 \u0441\u0438\u043c\u0432\u043e\u043b\u044b, \u0434\u0430 \u0435\u0449\u0451 \u043a\u043e\u0433\u0434\u0430 \u043e\u043d\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0432\u0441\u0435\u0433\u043e \u043e\u0434\u043d\u043e\u0433\u043e? \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u043d\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b, \u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043a\u0435\u043d\u0430\u043c\u0438. \u0427\u0438\u0441\u043b\u0430 \u2014 \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0432\u0438\u0434 \u0442\u043e\u043a\u0435\u043d\u043e\u0432, \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b <code>+<\/code>, <code>-<\/code>, <code>*<\/code>, <code>\/<\/code> \u2014 \u0434\u0440\u0443\u0433\u043e\u0439 (\u043f\u0440\u0438\u0447\u0451\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u0432\u0438\u0434\u043e\u043c), \u0441\u043a\u043e\u0431\u043a\u0438 \u2014 \u0442\u0440\u0435\u0442\u0438\u0439 \u0438 \u0442.\u0434. \u041d\u043e \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0443\u0441\u043a\u0430\u0439 \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u043e\u043a\u0435\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u043c, \u0432\u0435\u0434\u044c \u0442\u0430\u043a \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043f\u0440\u043e\u0449\u0435 \u0440\u0430\u0437\u0440\u0435\u0437\u0430\u0442\u044c \u043d\u0430 \u0442\u043e\u043a\u0435\u043d\u044b (\u0442\u043e\u043a\u0435\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c): \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c <code>.split('')<\/code>.<\/p>\n<p>\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0442\u0443\u0442 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u043d\u044f\u0442\u0438\u0435 <code>EOF<\/code> (end of file) \u0438 \u0432\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u0440\u0430\u0437\u0443 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u0434\u0442\u0438 \u043a\u043e\u043d\u0435\u0446 \u0444\u0430\u0439\u043b\u0430\/\u0432\u0432\u043e\u0434\u0430. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435, \u0447\u0442\u043e \u043d\u0430 \u0432\u0445\u043e\u0434 \u043f\u043e\u0434\u0430\u0451\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u043a\u0430 <code>2#<\/code>. \u0411\u0435\u0437 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 EOF \u043c\u044b \u0431\u044b \u0442\u0430\u043a \u0438 \u0432\u044b\u0432\u0435\u043b\u0438 \u0434\u0432\u043e\u0439\u043a\u0443, \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0432 <code>#<\/code>, \u0430 \u0442\u0430\u043a\u0438\u0435 \u0432\u043e\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b. \u0412\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 <code>2+2<\/code> \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a \u0436\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u0431\u0438\u0442\u044c \u0441 \u0442\u043e\u043b\u043a\u0443 \u043d\u0430\u0448 \u043f\u0430\u0440\u0441\u0435\u0440 \u043d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435.<\/p>\n<p>\u041a\u0441\u0442\u0430\u0442\u0438, \u0432 JavaScript \u043c\u0435\u0442\u043e\u0434 <code>shift()<\/code> \u0432\u044b\u0434\u0430\u0451\u0442 \u043f\u0435\u0440\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0438 \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u0435\u0433\u043e \u0438\u0437 \u043c\u0430\u0441\u0441\u0438\u0432\u0430. \u042d\u0442\u0438\u043c \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0438\u0434\u0442\u0438 \u043f\u043e \u0442\u043e\u043a\u0435\u043d\u0430\u043c. \u0418\u043d\u043e\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0442\u043e\u043a\u0435\u043d, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0435\u0433\u043e, \u0442\u0438\u043f\u0430 <code>if (tokens[0] === '+') { tokens.shift(); ... }<\/code>.<\/p>\n<h2>\u00ab2+2\u00bb<\/h2>\n<p>\u041f\u043e\u0439\u0434\u0451\u043c \u0434\u0430\u043b\u044c\u0448\u0435 \u043f\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044e \u0434\u0430\u043b\u044c\u0448\u0435 \u0438, \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044f <code>+<\/code> \u043b\u0438\u0431\u043e <code>-<\/code> , \u0431\u0443\u0434\u0435\u043c \u0440\u0435\u0448\u0430\u0442\u044c, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0437\u0430 \u043d\u0438\u043c\u0438 \u0446\u0438\u0444\u0440\u043e\u0439\u00a0\u2014 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0438\u043b\u0438 \u0432\u044b\u0447\u0435\u0441\u0442\u044c \u0438\u0437 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430.<\/p>\n<pre><code class=\"javascript\">function expr(tokens) { \/\/ ['2', '+', '3', '-', '4']   let result = parseInt(tokens.shift());    \/\/ NEW   while (true) {     if (tokens[0] === '+') {       tokens.shift(); \/\/ throw away the '+'       result += parseInt(tokens.shift());     }     else if (tokens[0] === '-') {       tokens.shift(); \/\/ throw away the '-'       result -= parseInt(tokens.shift());     }     else break;   }      return result; }  function calc(tokens) { \/\/ ['2', '+', '3', '-', '4']   let result = expr(tokens);   if (tokens.length) throw new Error('expected eof');   return result; }  console.log(calc('2+2'.split('')) === 4); \/\/ true console.log(calc('2+3-4'.split('')) === 1); \/\/ true<\/code><\/pre>\n<p>\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043c\u044b \u0432\u044b\u043d\u0435\u0441\u043b\u0438 \u0447\u0430\u0441\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>expr<\/code>, \u0445\u043e\u0442\u044c \u0438 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0441\u0451 \u0432 <code>calc<\/code>. \u0422\u0430\u043a\u043e\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430\u043c \u043f\u043e\u0437\u0436\u0435.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0434\u0441\u0443\u043d\u0435\u043c \u043d\u0430\u0448\u0435\u043c\u0443 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0440\u0441\u0435\u0440\u0443 \u043a\u0430\u043a\u0443\u044e-\u043d\u0438\u0431\u0443\u0434\u044c \u0435\u0440\u0443\u043d\u0434\u0443, \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u043e\u043d \u043d\u0435 \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u0447\u0438\u0441\u043b\u043e\u0432\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u0438 \u0434\u0432\u0438\u043d\u0435\u043c\u0441\u044f \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<pre><code class=\"javascript\">console.log(calc('+'.split(''))); \/\/ NaN console.log(calc('+1'.split(''))); \/\/ Error: expected eof<\/code><\/pre>\n<p>\u041f\u043e\u043a\u0430 \u0441\u043e\u0439\u0434\u0451\u0442. \u041e\u0434\u0438\u043d\u043e\u043a\u0438\u0439 \u043f\u043b\u044e\u0441 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u043d\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442, \u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 <code>+1<\/code> (\u0443\u043d\u0430\u0440\u043d\u044b\u0439 \u043f\u043b\u044e\u0441) \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u0437\u0436\u0435 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0443\u043d\u0430\u0440\u043d\u044b\u043c \u043c\u0438\u043d\u0443\u0441\u043e\u043c.<\/p>\n<h2>\u00ab2+2\u00d72\u00bb<\/h2>\n<p>\u0415\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0442\u0443\u0442 \u043f\u043e\u0434\u0432\u043e\u0445 \u0432 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f\/\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0430\u0434 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u0438 \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u044f\/\u0432\u044b\u0447\u0438\u0442\u0430\u043d\u0438\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u043b\u044c\u0437\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0431\u043b\u043e\u043a <code>else if (tokens[0] === '*') {...}<\/code> \u0432\u0441\u043b\u0435\u0434 \u0437\u0430 \u043f\u043b\u044e\u0441\u043e\u043c \u0438 \u043c\u0438\u043d\u0443\u0441\u043e\u043c, \u0432\u0435\u0434\u044c \u0442\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f 8. \u0417\u0434\u0435\u0441\u044c-\u0442\u043e \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u0438 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044f \u044f\u0437\u044b\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u043f\u0438\u0448\u0435\u043c \u044d\u0442\u043e\u0442 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440. \u0412 JavaScript \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044f \u0435\u0441\u0442\u044c, \u0438 \u043f\u043e\u0442\u043e\u043c\u0443 \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u043b\u0435\u0433\u043a\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f. \u041d\u043e \u0435\u0441\u0442\u044c \u0443\u0441\u043b\u043e\u0432\u043d\u043e \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u044f\u0437\u044b\u043a\u0438 \u0431\u0435\u0437 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438\u00a0\u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, structured text \u0432\u00a0IEC 61\u00a0131\u20133, \u043d\u0430\u00a0\u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0432\u00a0\u0441\u0440\u0435\u0434\u0435 \u043f\u0440\u043e\u043c\u044b\u0448\u043b\u0435\u043d\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u043a\u0438.<\/p>\n<p>\u041e\u0441\u0442\u0430\u0432\u0438\u043c \u0434\u0432\u043e\u0439\u043a\u0438 \u0434\u043b\u044f \u043a\u0440\u0430\u0441\u0438\u0432\u043e\u0433\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430, \u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0449\u0435 \u0431\u044b\u043b\u043e \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u0440\u0443\u043a\u0430\u043c\u0438, \u0432\u043e\u0437\u044c\u043c\u0451\u043c \u043f\u0440\u0438\u043c\u0435\u0440 3+4\u00d75. \u0414\u0430, \u0433\u043e\u0432\u043e\u0440\u044f \u043e\u0431\u044b\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u043c \u044f\u0437\u044b\u043a\u043e\u043c, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e <em>\u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c 4\u00d75<\/em> \u0438 \u0443\u0436\u0435 <em>\u043f\u043e\u0442\u043e\u043c<\/em> \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u0441 \u0442\u0440\u043e\u0439\u043a\u043e\u0439. \u041d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0444\u043e\u0440\u043c\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0434\u043b\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0437\u043e\u043c: <em>\u0441\u043b\u043e\u0436\u0438\u0442\u044c \u0442\u0440\u043e\u0439\u043a\u0443 \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0433\u043b\u0430\u0432\u043d\u0435\u0435 \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/em>. \u0410 \u0437\u043d\u0430\u0447\u0438\u0442, \u043c\u043e\u0436\u043d\u043e \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e \u043d\u0430\u0447\u0430\u0442\u044c \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u0440\u043e\u0439\u043a\u0443, \u043f\u043e\u0442\u043e\u043c <code>+<\/code> \u0437\u0430 \u043d\u0435\u0439, \u0430 \u043f\u043e\u0442\u043e\u043c \u00ab\u043e\u0442\u0432\u043b\u0435\u0447\u044c\u0441\u044f\u00bb \u043d\u0430\u00a0\u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 4\u00d75, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0438 \u0441\u043b\u043e\u0436\u0438\u0442\u044c \u0441\u00a0\u0440\u0430\u043d\u0435\u0435 \u0437\u0430\u043c\u0435\u0447\u0435\u043d\u043d\u043e\u0439 \u0442\u0440\u043e\u0439\u043a\u043e\u0439. \u0412\u043e\u0442 \u043d\u0430\u00a0\u044d\u0442\u043e\u043c \u00ab\u043e\u0442\u0432\u043b\u0435\u0447\u044c\u0441\u044f\u00bb \u0438 \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u0441\u043f\u0443\u0441\u043a\u0430. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0444\u043e\u0440\u043c\u0438\u043c \u00ab\u043e\u0442\u0432\u043b\u0435\u0447\u044c\u0441\u044f\u00bb \u043d\u043e\u0432\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <code>term<\/code>, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u043d\u0430 <code>expr<\/code> \u0432\u044b\u0448\u0435. \u041d\u0443 \u0430 \u0432 <code>expr<\/code> \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c <code>term<\/code> \u0442\u0430\u043c, \u0433\u0434\u0435 \u043f\u0440\u0435\u0436\u0434\u0435 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u043b\u0438 \u0446\u0438\u0444\u0440\u044b.<\/p>\n<pre><code class=\"javascript\">function term(tokens) { \/\/ like old `expr` but * and \/   let result = parseInt(tokens.shift());    while (true) {     if (tokens[0] === '*') {       tokens.shift(); \/\/ throw away the '*'       result *= parseInt(tokens.shift());     }     else if (tokens[0] === '\/') {       tokens.shift(); \/\/ throw away the '\/'       result \/= parseInt(tokens.shift());     }     else break;   }      return result; }  function expr(tokens) {   let result = term(tokens); \/\/ was `parseInt(tokens.shift())`    while (true) {     if (tokens[0] === '+') {       tokens.shift(); \/\/ throw away the '+'       result += term(tokens); \/\/ was `parseInt(tokens.shift())`     }     else if (tokens[0] === '-') {       tokens.shift(); \/\/ throw away the '-'       result -= term(tokens); \/\/ was `parseInt(tokens.shift())`     }     else break;   }      return result; }  function calc(tokens) {   let result = expr(tokens);   if (tokens.length) throw new Error('expected eof');   return result; }  console.log(calc('2+2'.split('')) === 4); \/\/ true console.log(calc('2+3-4'.split('')) === 1); \/\/ true console.log(calc('2+2*2'.split('')) === 6); \/\/ true console.log(calc('3+4*5'.split('')) === 23); \/\/ true console.log(calc('3\/2+4*5'.split('')) === 21.5); \/\/ true<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u043c\u044b \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u0443\u043c\u0435\u043b\u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0430\u0436\u0435 <code>3\/2+4*5<\/code>.<\/p>\n<h2>\u00ab(2+2)\u00d72\u00bb<\/h2>\n<p>\u0427\u0442\u043e \u0435\u0441\u043b\u0438 \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u043d\u0443\u0436\u043d\u0430 \u0432\u043e\u0441\u044c\u043c\u0451\u0440\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0441\u043a\u043e\u0431\u043e\u043a? \u0417\u043d\u0430\u0447\u0438\u0442, \u043d\u0443\u0436\u043d\u043e \u0432 <code>term<\/code> <em>\u043e\u0442\u0432\u043b\u0435\u0447\u044c\u0441\u044f<\/em> \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u0432 \u0441\u043a\u043e\u0431\u043a\u0438. \u0410 \u0432 \u0441\u043a\u043e\u0431\u043a\u0430\u0445 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <code>expr<\/code> , \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u043c\u044b \u0435\u0451 \u0438 \u0432\u044b\u0434\u0435\u043b\u0438\u043b\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0437\u0430\u0434. \u041e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0435 \u043e\u0442\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u043d\u0430\u0437\u043e\u0432\u0451\u043c <code>factor<\/code>, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043b\u0438\u0431\u043e \u0432\u044b\u0437\u043e\u0432\u0435\u043c <code>expr<\/code> \u043c\u0435\u0436\u0434\u0443 \u0441\u043a\u043e\u0431\u043a\u0430\u043c\u0438 (\u043a\u0440\u0443\u0433 \u0437\u0430\u043c\u043a\u043d\u0443\u043b\u0441\u044f), \u043b\u0438\u0431\u043e \u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0447\u0438\u0441\u043b\u043e.<\/p>\n<pre><code class=\"javascript\">function factor(tokens) {   if (tokens[0] === '(') {     tokens.shift();     let result = expr(tokens);     if (tokens[0] !== ')') {       throw new Error('missing closing parenthesis');     } else {       tokens.shift();     }     return result;   }   else return parseInt(tokens.shift()); }  function term(tokens) {   let result = factor(tokens);    while (true) {     if (tokens[0] === '*') {       tokens.shift(); \/\/ throw away the '*'       result *= factor(tokens);     }     else if (tokens[0] === '\/') {       tokens.shift(); \/\/ throw away the '\/'       result \/= factor(tokens);     }     else break;   }      return result; }  function expr(tokens) { \/* omitted for clarity *\/ } function calc(tokens) { \/* omitted for clarity *\/ }  console.log(calc('2+2'.split('')) === 4); \/\/ true console.log(calc('2+3-4'.split('')) === 1); \/\/ true console.log(calc('2+2*2'.split('')) === 6); \/\/ true console.log(calc('3+4*5'.split('')) === 23); \/\/ true console.log(calc('3\/2+4*5'.split('')) === 21.5); \/\/ true console.log(calc('(2+2)*2'.split('')) === 8); \/\/ true<\/code><\/pre>\n<p>\u0412 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435, \u043d\u0430 \u044d\u0442\u043e\u043c \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0441\u043d\u043e\u0432\u0430 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u0441\u043f\u0443\u0441\u043a\u0430. \u0414\u0430\u043b\u044c\u0448\u0435 \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u043a\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ba4\/afd\/198\/ba4afd1986bf0de7622e423320763791.png\" width=\"901\" height=\"368\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ba4\/afd\/198\/ba4afd1986bf0de7622e423320763791.png\"\/><\/figure>\n<h3>\u00ab(02. + 0002.) \u00d7 002.000\u00bb<\/h3>\n<p>\u0414\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u043c\u044b \u043f\u0430\u0440\u0441\u0438\u043b\u0438 \u043c\u0430\u0441\u0441\u0438\u0432 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0438\u0437 \u0446\u0438\u0444\u0440, \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0438 \u043a\u0440\u0443\u0433\u043b\u044b\u0445 \u0441\u043a\u043e\u0431\u043e\u043a. \u041a\u0430\u0436\u0434\u044b\u0439 \u0441\u0438\u043c\u0432\u043e\u043b \u0431\u044b\u043b \u0442\u043e\u043a\u0435\u043d\u043e\u043c, \u0438 \u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0443\u043f\u0440\u043e\u0449\u0430\u043b\u043e \u043d\u0430\u043c \u0436\u0438\u0437\u043d\u044c. \u041d\u043e \u0434\u0430\u043b\u044c\u0448\u0435 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u043e. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0441\u0438\u043c\u0432\u043e\u043b\u044c\u043d\u044b\u0439 <code>split('')<\/code> \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u0447\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0432\u0437\u0440\u043e\u0441\u043b\u044b\u043c <em>\u043b\u0435\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0440\u0430\u0437\u0431\u043e\u0440\u043e\u043c<\/em> (\u043f\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u043c\u0443 \u0441\u0447\u0451\u0442\u0443 \u044d\u0442\u043e \u0441\u0438\u043d\u043e\u043d\u0438\u043c \u0442\u043e\u043a\u0435\u043d\u0438\u0437\u0430\u0446\u0438\u0438).<\/p>\n<p>\u0423 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u043f\u043e \u0432\u0441\u0435\u043c \u0442\u0438\u043f\u0430\u043c \u0442\u043e\u043a\u0435\u043d\u043e\u0432, \u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u043e\u0442\u0440\u0435\u0437\u0430\u0442\u044c \u043e\u0442 \u0432\u0445\u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u043e \u043a\u0443\u0441\u043e\u0447\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0445\u043e\u0442\u044c \u043e\u0434\u043d\u043e\u0439 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0435. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043d\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0441 \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439:<\/p>\n<pre><code class=\"javascript\">const matchers = [   { type: 'word', regex: \/^[a-z]+\/ },   { type: 'number', regex: \/^[0-9]+\/ },   { type: 'whitespace', regex: \/^\\s+\/ }, ];  let test = '123sdm  k282rtk\\tmx11';  while (test) {   for (const { type, regex } of matchers) {     const match = regex.exec(test)?.[0];     if (match) {       console.log({ type, match });       test = test.slice(match.length);     }   } }  \/\/ {type: 'number', match: '123'} \/\/ {type: 'word', match: 'sdm'} \/\/ {type: 'whitespace', match: '  '} \/\/ {type: 'word', match: 'k'} \/\/ {type: 'number', match: '282'} \/\/ {type: 'word', match: 'rtk'} \/\/ {type: 'whitespace', match: ''} \/\/ {type: 'word', match: 'mx'} \/\/ {type: 'number', match: '11'}<\/code><\/pre>\n<p>\u0422\u0443\u0442 \u0432\u0430\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c <code>^<\/code> \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0433\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0449\u0435\u0435 \u043f\u043e\u0438\u0441\u043a \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u0441\u0442\u0440\u043e\u0433\u043e \u0441 \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0442\u0440\u043e\u043a\u0438. \u0412\u043c\u0435\u0441\u0442\u0435 \u0441\u043e <code>slice()<\/code> \u044d\u0442\u043e \u0434\u0430\u0451\u0442 \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0445\u043e\u0434 \u043f\u043e \u0441\u0442\u0440\u043e\u043a\u0435 \u00ab\u043a\u0443\u0441\u043e\u0447\u043a\u0430\u043c\u0438\u00bb. <\/p>\n<p>\u0422\u0430\u043a\u043e\u0439 \u043b\u0435\u043a\u0441\u0435\u0440 \u043d\u0430 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0430\u0445 \u043e\u0447\u0435\u043d\u044c \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u0435\u043d \u0438 \u0447\u0438\u0442\u0430\u0431\u0435\u043b\u0435\u043d, \u043d\u043e \u0435\u0433\u043e \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432\u0435\u0441\u044c\u043c\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u044b \u0434\u043b\u044f \u043f\u043e-\u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u043c\u0443 \u0432\u0437\u0440\u043e\u0441\u043b\u043e\u0433\u043e \u043b\u0435\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0440\u0430\u0437\u0431\u043e\u0440\u0430; \u0438\u043c\u0435\u0439\u0442\u0435 \u044d\u0442\u043e \u0432 \u0432\u0438\u0434\u0443, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u0439\u0434\u0451\u0442\u0435 \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u044f\u0437\u044b\u043a \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u044b JS \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u044e\u0442 \u0440\u0430\u0437\u0440\u0435\u0437\u0430\u043d\u0438\u0435 \u0441\u0442\u0440\u043e\u043a \u0447\u0435\u0440\u0435\u0437 slice, \u043f\u043e \u0441\u0443\u0442\u0438 \u0441\u0432\u043e\u0434\u044f \u0435\u0433\u043e \u043a \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u044f\u043c \u0441 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f\u043c\u0438. \u0412 \u0441\u0443\u043c\u043c\u0435 \u0441 \u043f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0430\u043c\u0438, \u043f\u0440\u0438\u0431\u0438\u0442\u044b\u043c\u0438 \u043a \u043d\u0430\u0447\u0430\u043b\u0443 \u0441\u0442\u0440\u043e\u043a\u0438, \u044d\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0435\u043f\u043b\u043e\u0445\u0443\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0441\u0442\u044f\u043d\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u043b\u0435\u043a\u0441\u0435\u0440 \u043d\u0430 \u043b\u0435\u043a\u0441\u0438\u043a\u0443 \u043d\u0430\u0448\u0438\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439. \u0412\u043c\u0435\u0441\u0442\u043e \u0441\u0442\u0440\u043e\u043a \u0434\u043b\u044f \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432 \u0432\u043e\u0437\u044c\u043c\u0451\u043c JS-\u043e\u0432\u0441\u043a\u0438\u0439 Symbol \u0438 \u0443\u043f\u0430\u043a\u0443\u0435\u043c \u043c\u0430\u0442\u0447\u0438\u043d\u0433 \u0432\u043d\u0443\u0442\u0440\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430 (\u044d\u0442\u043e \u0442\u0430\u043a\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0432\u044b\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0437\u0430 \u043e\u0434\u0438\u043d \u0432\u044b\u0437\u043e\u0432; \u0432 JavaScript \u043e\u043d\u0438 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0442\u0441\u044f \u0437\u0432\u0451\u0437\u0434\u043e\u0447\u043a\u043e\u0439 \u0438 \u00ab\u0432\u044b\u043f\u043b\u0451\u0432\u044b\u0432\u0430\u044e\u0442\u00bb \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 yield).<\/p>\n<pre><code class=\"javascript\">const   WS = Symbol('ws'),   NUMBER = Symbol('num'),   PLUS = Symbol('plus'),   MINUS = Symbol('minus'),   MULTIPLY = Symbol('mul'),   DIVIDE = Symbol('div'),   LEFT_PAR = Symbol('lpar'),   RIGHT_PAR = Symbol('rpar'),   END_OF_FILE = Symbol('eof');  function* tokenize(input) {   const matchers = [     { type: NUMBER, re: \/^[0-9\\.]+\/ },     { type: PLUS, re: \/^\\+\/ },     { type: MINUS, re: \/^[-\u2212]\/ },     { type: MULTIPLY, re: \/^[*\u00d7\u22c5]\/ },     { type: DIVIDE, re: \/^\\\/\/ },     { type: MOD, re: \/^%\/ },     { type: WS, re: \/^[\\s]+\/ },     { type: LEFT_PAR, re: \/^\\(\/ },     { type: RIGHT_PAR, re: \/^\\)\/ },     { type: END_OF_FILE, re: \/^$\/ }   ];   let pos = 0;   while (input) {     for (const { type, re } of matchers) {       const match = re.exec(input.slice(pos))?.[0];       if (typeof(match) === 'string') {         yield { type, pos, match };         if (type === END_OF_FILE) input = null; \/\/ breaks outer loop         pos += match.length;         break;       }     }   } }  for (const token of tokenize('(2+2)\u00d72')) {   console.log(token); }  \/\/ {type: Symbol(lpar), pos: 0, match: '('} \/\/ {type: Symbol(num), pos: 1, match: '2'} \/\/ {type: Symbol(plus), pos: 2, match: '+'} \/\/ {type: Symbol(num), pos: 3, match: '2'} \/\/ {type: Symbol(rpar), pos: 4, match: ')'} \/\/ {type: Symbol(mul), pos: 5, match: '*'} \/\/ {type: Symbol(num), pos: 6, match: '2'} \/\/ {type: Symbol(eof), pos: 7, match: ''}  for (const token of tokenize(' 234 ')) {   console.log(token); }  \/\/ {type: Symbol(num), pos: 1, match: '234'} \/\/ {type: Symbol(ws), pos: 4, match: ' '} \/\/ {type: Symbol(eof), pos: 5, match: ''}<\/code><\/pre>\n<p>\u041d\u0435 \u0437\u043d\u0430\u044e, \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438 \u0432\u044b \u0441\u0430\u043c\u0438 \u0438\u043b\u0438 \u043d\u0435\u0442, \u043d\u043e \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0432\u043f\u0435\u0440\u0432\u044b\u0435 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 (2+2)<strong>\u00d7<\/strong>2 &#8212; \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0437\u043d\u0430\u043a \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f, \u044d\u0442\u043e \u043d\u0435 \u0437\u0432\u0451\u0437\u0434\u043e\u0447\u043a\u0430, \u043f\u0440\u0438\u0447\u0451\u043c \u0432\u043e\u0441\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0440\u0430\u0432\u043d\u0435 \u0441\u043e \u0437\u0432\u0451\u0437\u0434\u043e\u0447\u043a\u043e\u0439. \u0422\u0430\u043c \u0435\u0441\u0442\u044c \u0435\u0449\u0451 \u043e\u0434\u0438\u043d \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f, \u0430 \u0442\u0430\u043a\u0436\u0435 \u00ab\u0442\u0438\u043f\u043e\u0433\u0440\u0430\u0444\u0441\u043a\u0438\u0439\u00bb \u043c\u0438\u043d\u0443\u0441. \u041f\u0443\u0441\u043a\u0430\u0439 \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0444\u0438\u0448\u043a\u043e\u0439 \u043d\u0430\u0448\u0435\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u0434\u043b\u044f \u0443\u043f\u043e\u0440\u043e\u0442\u044b\u0445 \u043f\u043e \u0442\u0438\u043f\u043e\u0433\u0440\u0430\u0444\u0438\u043a\u0435 \u044d\u0441\u0442\u0435\u0442\u043e\u0432.<\/p>\n<p>\u0412 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u044d\u0442\u043e \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u0447\u0442\u043e <code>split('')<\/code>, \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u0443\u0441\u043e\u0447\u043a\u0438 \u043f\u043e\u043a\u0440\u0443\u043f\u043d\u0435\u0435. \u0421\u0440\u0435\u0434\u0438 \u043f\u0440\u043e\u0447\u0435\u0433\u043e \u0443 \u043d\u0430\u0441 \u0442\u0435\u043f\u0435\u0440\u044c \u0435\u0441\u0442\u044c \u044f\u0432\u043d\u043e\u0435 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0431\u0435\u043b\u043e\u0432 (whitespace), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043b\u0435\u0433\u043a\u043e \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c, \u0438 end-of-file \u0432 \u0432\u0438\u0434\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430.<\/p>\n<p>\u041d\u043e \u0434\u0435\u043b\u043e \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u043b\u043e\u0441\u044c \u043e\u0434\u043d\u0438\u043c \u043b\u0438\u0448\u044c <code>split('')<\/code>, \u043f\u0440\u0430\u0432\u0434\u0430? \u041c\u044b \u043f\u043e\u0434\u0433\u043b\u044f\u0434\u044b\u0432\u0430\u043b\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d \u0447\u0435\u0440\u0435\u0437 <code>if (tokens[0] === '*')<\/code>, \u0430 \u0442\u0430\u043a\u0436\u0435 \u00ab\u043f\u0440\u043e\u0433\u043b\u0430\u0442\u044b\u0432\u0430\u043b\u0438\u00bb \u0442\u043e\u043a\u0435\u043d\u044b \u0447\u0435\u0440\u0435\u0437 <code>shift()<\/code>. \u041a\u043e\u0435-\u0433\u0434\u0435 \u043c\u044b \u0434\u0430\u0436\u0435 \u0443\u0431\u0435\u0436\u0434\u0430\u043b\u0438\u0441\u044c, \u0447\u0442\u043e \u0442\u043e\u043a\u0435\u043d \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a\u043e\u0439, \u0430 \u043d\u0435 \u0434\u0440\u0443\u0433\u043e\u0439, \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0443 &#8216;missing closing parenthesis&#8217;. \u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0451\u043c \u044d\u0442\u0438 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435:<\/p>\n<pre><code class=\"javascript\">class ExpressionCalc {   #stream;   #token;    constructor(input) {     this.#stream = tokenize(input);     this.#next();   }    #error(err) {     throw new Error(`${err}, pos=${this.#token?.pos}, token=${this.#token.match}, type=${this.#token.type.description}`);   }    #next() {     do {       this.#token = this.#stream.next()?.value;     } while (this.#token?.type === WS);   }    #accept(type) {     let match;     if (this.#token?.type === type) {       match = this.#token.match;       this.#next();       return match || true;     }     return false;   }    #expect(type) {     return this.#accept(type) || this.error(`expected ${type.description}`);   } }<\/code><\/pre>\n<p>\u042d\u0442\u043e \u0434\u0436\u0435\u043d\u0442\u0435\u043b\u044c\u043c\u0435\u043d\u0441\u043a\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0435\u0433\u043e \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430:<\/p>\n<ul>\n<li>\n<p>\u043c\u0435\u0442\u043e\u0434 <code>next()<\/code>\u00a0\u2014 \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442 <code>shift()<\/code> \u0438\u0437\u00a0\u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u0441\u00a0\u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043e\u043c \u043f\u0440\u043e\u0431\u0435\u043b\u043e\u0432;<\/p>\n<\/li>\n<li>\n<p>\u043c\u0435\u0442\u043e\u0434 <code>accept(type)<\/code>\u00a0\u2014 \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u00a0\u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435\u043c \u0438\u0437\u00a0\u043c\u0430\u0441\u0441\u0438\u0432\u0430; \u0437\u0430\u043e\u0434\u043d\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0435\u043a\u0441\u0442 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>\u043c\u0435\u0442\u043e\u0434 <code>expect(type)<\/code>\u00a0\u2014 \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u00a0\u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u043d\u0438\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438\u00a0\u043d\u0435\u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043c\u0435\u0442\u043e\u0434 <code>error(err)<\/code>\u00a0\u2014 \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0441 \u0438\u043d\u0434\u0438\u043a\u0430\u0446\u0438\u0435\u0439 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u0432\u0441\u0451 \u044d\u0442\u043e \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b\u043e, \u043d\u043e \u043f\u0440\u044f\u043c\u043e \u043f\u043e \u043c\u0435\u0441\u0442\u0443 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430, &#171;inline&#187;. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u0443\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430\/\u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043a\u0430\u043a \u043c\u0435\u0442\u043e\u0434\u044b \u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430:<\/p>\n<pre><code class=\"javascript\">class ExpressionCalc {   ...constructor, #error, #next, #accept, #expect    #factor() {     let result;      let text;     if (this.#accept(LEFT_PAR)) { \/\/ parenthesis (but not function calls)       result = this.#expression();       this.#expect(RIGHT_PAR);     } else if (text = this.#accept(NUMBER)) { \/\/ numeric literals       result = parseFloat(text);     } else {       this.#error('unexpected input');     }      return result   }    #term() {     let result = this.#factor();      while (true) {       if (this.#accept(MULTIPLY)) result *= this.#term();       else if (this.#accept(DIVIDE)) result \/= this.#term();       else if (this.#accept(MOD)) result %= this.#term();       else break;     }      return result;   }    #expression() {     let result = this.#term();      while (true) {       if (this.#accept(PLUS)) result += this.#term();       else if (this.#accept(MINUS)) result -= this.#term();       else break;     }      return result;   } }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0431\u0443\u0435\u043c:<\/p>\n<pre><code class=\"javascript\">console.log(new ExpressionCalc('2+2').calc() === 4); \/\/ true console.log(new ExpressionCalc('2+3-4').calc() === 1); \/\/ true console.log(new ExpressionCalc('2+2*2').calc() === 6); \/\/ true console.log(new ExpressionCalc('3+4*5').calc() === 23); \/\/ true console.log(new ExpressionCalc('3\/2+4*5').calc() === 21.5); \/\/ true console.log(new ExpressionCalc('(2+2)*2').calc() === 8); \/\/ true console.log(new ExpressionCalc('(02. + 0002.) \u00d7 002.000').calc() === 8); \/\/ true console.log(new ExpressionCalc('3%2').calc() === 1); \/\/ true<\/code><\/pre>\n<p>\u0415\u0449\u0451 \u0443 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u0441\u0442\u0430\u0442\u043a\u0430 \u043e\u0442 \u0434\u0435\u043b\u0435\u043d\u0438\u044f (\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 %) \u0438 \u0447\u0438\u0441\u043b\u0430 \u0434\u0440\u043e\u0431\u043d\u044b\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f, \u0442.\u043a. \u0432\u043c\u0435\u0441\u0442\u043e <code>parseInt<\/code> \u0434\u0435\u043b\u0430\u0435\u043c <code>parseFloat<\/code>.<\/p>\n<h2>\u00ab+1\u00bb<\/h2>\n<p>\u041a\u0430\u043a \u0431\u044b \u043d\u0430\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u044e\u0434\u0430 \u0443\u043d\u0430\u0440\u043d\u044b\u0439 \u043f\u043b\u044e\u0441 \u0438 \u0443\u043d\u0430\u0440\u043d\u044b\u0439 \u043c\u0438\u043d\u0443\u0441? \u041f\u043e \u043f\u0435\u0440\u0432\u043e\u0439 \u0438\u043d\u0442\u0443\u0438\u0446\u0438\u0438 \u044d\u0442\u043e \u0437\u043d\u0430\u043a \u0440\u044f\u0434\u043e\u043c \u0441 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u043c \u043b\u0438\u0442\u0435\u0440\u0430\u043b\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0443\u0447\u0435\u0441\u0442\u044c \u043f\u043e\u0434\u043e\u0431\u043d\u043e \u0441\u043a\u043e\u0431\u043a\u0430\u043c \u0432 <code>factor<\/code>. \u041d\u043e \u044d\u0442\u043e \u043e\u0431\u043c\u0430\u043d\u0447\u0438\u0432\u0430\u044f \u0438\u043d\u0442\u0443\u0438\u0446\u0438\u044f. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u044b \u0442\u0430\u043a\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f: <code>-(2+3)<\/code>, <code>-sin(0.33)<\/code>. \u0421\u0442\u0430\u043b\u043e \u0431\u044b\u0442\u044c, \u044d\u0442\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0432\u0435\u0449\u044c c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0435\u0439.<\/p>\n<pre><code class=\"javascript\">#factor() {   let result;   ...   } else if (this.#accept(PLUS)) { \/\/ unary plus     result = +this.#factor();   } else if (this.#accept(MINUS)) { \/\/ unary minus     result = -this.#factor();   }   ...   return result }  console.log(new ExpressionCalc('+1').calc() === 1); \/\/ true console.log(new ExpressionCalc('-(2+3)').calc() === -5); \/\/ true<\/code><\/pre>\n<h2>\u00abcos(2*pi)\u00bb<\/h2>\n<p>\u0418\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u043d\u0434\u044b \u0442\u0438\u043f\u0430 &#171;pi&#187; \u0447\u0435\u043c-\u0442\u043e \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u044e\u0442 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0435 \u043b\u0438\u0442\u0435\u0440\u0430\u043b\u044b, \u043d\u0435 \u043f\u0440\u0430\u0432\u0434\u0430 \u043b\u0438? \u041f\u043e \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043c\u0435\u0440\u0435 \u043e\u043d\u0438 \u0441\u0442\u043e\u044f\u0442 \u0442\u0430\u043c \u0436\u0435 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432. \u041d\u0443, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>2 + -(5 * 3)<\/code> vs <code>2 + -(pi * 3)<\/code>. \u041f\u043e\u0445\u043e\u0436\u0435? \u0418 \u043d\u0435\u0441\u043b\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0435\u0431\u0435 \u043a\u0430\u043a\u0438\u0435-\u043d\u0438\u0431\u0443\u0434\u044c \u0440\u0438\u043c\u0441\u043a\u0438\u0435 \u0447\u0438\u0441\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u043e\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445: <code>10 + 21<\/code> = <code>10 + XXI<\/code>. \u0422\u043e\u043b\u044c\u043a\u043e \u0441 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 \u043a\u0430\u043a\u0430\u044f-\u0442\u043e \u0444\u0438\u0433\u043d\u044f: \u0443 \u043d\u0438\u0445 \u0441\u0432\u043e\u0438 \u0441\u043a\u043e\u0431\u043a\u0438. \u0417\u043d\u0430\u0447\u0438\u0442, \u0438 \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0451 \u0442\u0430\u043c \u0436\u0435, \u0433\u0434\u0435 \u0447\u0438\u0441\u043b\u0430\u00a0\u2014 \u0432 <code>factor<\/code>.<\/p>\n<pre><code class=\"javascript\">#factor() {   let result;   let text;   ...   } else if (text = this.#accept(IDENTIFIER)) { \/\/ identifiers (named constants and function calls)     text = text.toLowerCase();     let func;     if (text === 'pi') result = Math.PI;     else if (text === 'e') result = Math.E;     else if (Math[text] &amp;&amp; typeof (func = Math[text]) === 'function') {       this.#expect(LEFT_PAR);       result = func(this.#expression());       this.#expect(RIGHT_PAR);     }     else this.#error(`unknown id ${text}`);   }   ...   return result }  console.log(new ExpressionCalc('cos(2*pi)').calc() === 1); \/\/ true<\/code><\/pre>\n<p>\u041d\u0430 \u0447\u0442\u043e \u0442\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435? \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043c\u044b \u043d\u0435 \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u043a\u0430\u043a-\u043b\u0438\u0431\u043e \u0440\u0435\u044e\u0437\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0437\u0438\u0440\u0443\u044e\u0449\u0438\u0445 \u0441\u043a\u043e\u0431\u043e\u043a; \u0437\u0434\u0435\u0441\u044c \u0441\u043a\u043e\u0431\u043a\u0438 \u2014 \u044d\u0442\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f. \u0415\u0441\u043b\u0438 \u0431\u044b \u043c\u044b \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0442\u043e \u043f\u0440\u043e\u0448\u043b\u0438\u0441\u044c \u0431\u044b \u0437\u0434\u0435\u0441\u044c \u043f\u043e \u043d\u0438\u043c \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043f\u044f\u0442\u0443\u044e. \u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u0447\u0442\u043e \u043c\u044b \u0440\u0435\u044e\u0437\u0430\u0435\u043c, \u0442\u0430\u043a \u044d\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 Math \u0438\u0437 JavaScript.<\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0435 \u0432 \u044d\u0442\u043e\u043c \u0431\u043b\u043e\u043a\u0435, \u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0442 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u0430\u044f \u0432\u0430\u043c\u0438 \u0444\u043e\u0440\u043c\u0443\u043b\u0430 (\u043d\u0443 \u0438\u043b\u0438 \u00ab\u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432\u0430\u0448 \u0441\u043a\u0440\u0438\u043f\u0442\u00bb \u0435\u0441\u043b\u0438\u00a0\u0431\u044b \u043c\u044b \u043f\u0438\u0441\u0430\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u043a\u0430\u043a\u043e\u0433\u043e\u2011\u043d\u0438\u0431\u0443\u0434\u044c \u044f\u0437\u044b\u043a\u0430).<\/p>\n<h2>\u00ab-2.1+ .355 \/ (cos(pi % 3) + sin(0.311))\u00bb<\/h2>\n<pre><code class=\"javascript\">console.log(new ExpressionCalc('-2.1+ .355 \/ (cos(pi % 3) + sin(0.311))').calc()); -1.8260809473359578  \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435: \/\/ -2.1+ .355 \/ (Math.cos(Math.PI % 3) + Math.sin(0.311)) \/\/ -1.8260809473359578<\/code><\/pre>\n<p>\u041a\u0430\u043a \u043e\u0431\u0435\u0449\u0430\u043d\u043e.<\/p>\n<h2>\u0411\u043e\u043d\u0443\u0441-\u0442\u0440\u0435\u043a: \u043c\u0443\u0441\u043e\u0440 \u0432 \u043b\u0435\u043a\u0441\u0435\u0440\u0435<\/h2>\n<p>\u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0432\u0438\u0434\u0435 \u043b\u0435\u043a\u0441\u0435\u0440 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u0435\u043d \u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c. \u0427\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043f\u0430\u0434\u0435\u043d\u0438\u044f \u043d\u0430 \u043a\u0430\u043a\u043e\u043c-\u043d\u0438\u0431\u0443\u0434\u044c \u0442\u0430\u043c <code>}@5+1<\/code>, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u0441\u0438\u043c\u0432\u043e\u043b\u0443, \u043f\u043e\u043a\u0430 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f \u0432\u043d\u043e\u0432\u044c \u043d\u0435 \u043f\u043e\u044f\u0432\u044f\u0442\u0441\u044f, \u0438 \u0447\u0442\u043e \u0441 \u043d\u0438\u043c\u0438 \u0434\u0430\u043b\u044c\u0448\u0435 \u0434\u0435\u043b\u0430\u0442\u044c, \u0443\u0436\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f; \u0432 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430\u0434\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 \u0438 \u043f\u0440\u0435\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435. \u0425\u043e\u0440\u043e\u0448\u0438\u043c \u0442\u043e\u043d\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u043a\u043e\u043f\u0438\u0442\u044c \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0438 \u0432\u044b\u0434\u0430\u0442\u044c \u0438\u0445 \u043e\u0434\u043d\u043e\u0439 \u043e\u0448\u0438\u0431\u043a\u043e\u0439.<\/p>\n<pre><code class=\"javascript\">const   ...   UNKNOWN = Symbol('unknown'),   ...;  function* tokenize(input) {   const matchers = [     ...   ];   let pos = 0;   let unknownFrom = -1;   while (input) {     const posBefore = pos;     for (const { type, re } of matchers) {       const match = re.exec(input.slice(pos))?.[0];       if (typeof(match) === 'string') {         if (unknownFrom >= 0) {           \/\/ flush the unknown input as one token           yield {             type: UNKNOWN,             pos: unknownFrom,             match: input.slice(unknownFrom, pos),           };           unknownFrom = -1;         }         yield { type, pos, match };         if (type === END_OF_FILE) input = null; \/\/ breaks outer loop         pos += match.length;         break;       }     }     if (input &amp;&amp; posBefore === pos) {       \/\/ nothing matched, track unknown input       if (unknownFrom &lt; 0) unknownFrom = pos;       pos++;     }   } }  [...tokenize('}@5+1')].forEach(t => console.log(t)); \/\/ {type: Symbol(unknown), pos: 0, match: '}@'} \/\/ {type: Symbol(num), pos: 2, match: '5'} \/\/ {type: Symbol(plus), pos: 3, match: '+'} \/\/ {type: Symbol(num), pos: 4, match: '1'} \/\/ {type: Symbol(eof), pos: 5, match: ''}<\/code><\/pre>\n<h2>\u041f\u043e\u0434\u044b\u0442\u043e\u0436\u0438\u0432\u0430\u044f<\/h2>\n<p>\u0426\u0435\u043b\u044c\u044e \u0437\u0430\u043c\u0435\u0442\u043a\u0438 \u0431\u044b\u043b\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u00ab\u043d\u0430 \u043f\u0430\u043b\u044c\u0446\u0430\u0445\u00bb, \u043a\u0430\u043a\u00a0\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u0438\u0437 \u0447\u0435\u0433\u043e \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u043f\u0430\u0440\u0441\u0435\u0440-\u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440 \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439, \u043d\u0435 \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u044f\u0441\u044c \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u044b \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a \u044f\u0437\u044b\u043a\u043e\u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u043f\u0430\u0440\u0441\u0435\u0440\u044b \u043c\u043e\u0436\u043d\u043e \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u0442\u044c \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u0441\u043e\u0444\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0432\u043e\u0434\u0438\u0442\u044c \u0444\u043e\u0440\u043c\u0443\u043b\u044b\/\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u043b\u044f \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0430\u043b\u0435\u0440\u0442\u043e\u0432 \u0438\u043b\u0438 \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0433\u0440\u0430\u0444\u0438\u043a\u043e\u0432. \u0412\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0442\u0441\u044f \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044b \u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439: \u043f\u0435\u0440\u0435\u0432\u043e\u0434 \u0432 \u043f\u043e\u0441\u0442\u0444\u0438\u043a\u0441\u043d\u0443\u044e \u0444\u043e\u0440\u043c\u0443 \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435\u043c, \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u043f\u0430\u0440\u0441\u0435\u0440\u043e\u0432 \u0432\u043c\u0435\u0441\u0442\u043e \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0438\u0445 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f. \u041c\u043d\u043e\u0433\u0438\u0435 \u044f\u0437\u044b\u043a\u0438 \u0438 \u0441\u0440\u0435\u0434\u044b \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e\u0442 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f.<\/p>\n<h2>\u041a\u043e\u0434<\/h2>\n<ul>\n<li>\n<p>S: <a href=\"http:\/\/jdoodle.com\/ia\/Kmu\" rel=\"noopener noreferrer nofollow\">jdoodle.com\/ia\/Kmu<\/a><\/p>\n<\/li>\n<li>\n<p>XXL: <a href=\"http:\/\/jdoodle.com\/ia\/Kmt\" rel=\"noopener noreferrer nofollow\">jdoodle.com\/ia\/Kmt<\/a><\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<p> <!----> <!----><\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/750604\/\"> https:\/\/habr.com\/ru\/articles\/750604\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0421\u0442\u0430\u0442\u044c\u044f-\u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b \u0434\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0445\u043e\u0447\u0435\u0442 \u0443\u0437\u043d\u0430\u0442\u044c, \u043a\u0430\u043a \u0438\u0437 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u00ab6\u00bb \u043c\u0435\u0442\u043e\u0434\u043e\u043c <em>\u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u0441\u043f\u0443\u0441\u043a\u0430<\/em>. \u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0438 \u0434\u043e\u0439\u0434\u0451\u043c \u0434\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f <code>-1.82<\/code> \u0438\u043b\u0438 \u043e\u043a\u043e\u043b\u043e \u0442\u043e\u0433\u043e \u0438\u0437 \u0441\u0442\u0440\u043e\u043a\u0438 <code>-2.1+ .355 \/ (cos(pi % 3) + sin(0.311))<\/code>.<\/p>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u043d\u0435\u043e\u0434\u043d\u043e\u043a\u0440\u0430\u0442\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u043d \u043d\u0430\u00a0\u0425\u0430\u0431\u0440\u0435 \u0438 \u0437\u0430\u0447\u0438\u0442\u0430\u043d \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0430\u0439\u0442\u0438\u0448\u043d\u043e\u043c\u0443 \u043f\u0435\u0440\u0432\u043e\u043a\u0443\u0440\u0441\u043d\u0438\u043a\u0443. \u0412\u00a0\u0441\u0432\u043e\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u044f \u0445\u043e\u0447\u0443 \u0438\u0437\u043b\u043e\u0436\u0438\u0442\u044c \u0435\u0433\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e, \u0441\u00a0\u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0440\u043d\u043e\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 \u043d\u0430\u00a0JavaScript. \u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430\u00a0\u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043a\u043e\u0434\u00a0\u2014 \u0432\u00a0\u0441\u0430\u043c\u043e\u043c \u043d\u0438\u0437\u0443.<\/p>\n<h2>\u00ab2\u00bb<\/h2>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043d\u0435\u0432\u044b\u043d\u043e\u0441\u0438\u043c\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440: \u043d\u0430 \u0432\u0445\u043e\u0434\u0435 \u0443 \u043d\u0430\u0441 \u0441\u0442\u0440\u043e\u043a\u0430 \u0441 \u0434\u0432\u043e\u0439\u043a\u043e\u0439, \u0430 \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c <em>\u0447\u0438\u0441\u043b\u043e<\/em> 2. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u0442\u0443\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>parseInt<\/code>, \u043d\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u043e\u0442 \u0447\u0435\u0433\u043e \u043e\u0442\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0443\u0440\u043e\u0432\u043d\u044f\u0445.<\/p>\n<pre><code class=\"javascript\">function calc(tokens) { \/\/ ['2']   let result = parseInt(tokens.shift()); \/\/ ['2'] \u2192 '2' \u2192 2   if (tokens.length) throw new Error('expected eof'); \/\/ [empty array]   return result; \/\/ 2 }  console.log(calc('2'.split('')) === 2); \/\/ true<\/code><\/pre>\n<p>\u0417\u0430\u0447\u0435\u043c \u043c\u044b \u0434\u0435\u043b\u0438\u043c \u0441\u0442\u0440\u043e\u043a\u0443 \u043d\u0430 \u0441\u0438\u043c\u0432\u043e\u043b\u044b, \u0434\u0430 \u0435\u0449\u0451 \u043a\u043e\u0433\u0434\u0430 \u043e\u043d\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0432\u0441\u0435\u0433\u043e \u043e\u0434\u043d\u043e\u0433\u043e? \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u043d\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b, \u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043a\u0435\u043d\u0430\u043c\u0438. \u0427\u0438\u0441\u043b\u0430 \u2014 \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0432\u0438\u0434 \u0442\u043e\u043a\u0435\u043d\u043e\u0432, \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b <code>+<\/code>, <code>-<\/code>, <code>*<\/code>, <code>\/<\/code> \u2014 \u0434\u0440\u0443\u0433\u043e\u0439 (\u043f\u0440\u0438\u0447\u0451\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u0432\u0438\u0434\u043e\u043c), \u0441\u043a\u043e\u0431\u043a\u0438 \u2014 \u0442\u0440\u0435\u0442\u0438\u0439 \u0438 \u0442.\u0434. \u041d\u043e \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0443\u0441\u043a\u0430\u0439 \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u043e\u043a\u0435\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u043c, \u0432\u0435\u0434\u044c \u0442\u0430\u043a \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043f\u0440\u043e\u0449\u0435 \u0440\u0430\u0437\u0440\u0435\u0437\u0430\u0442\u044c \u043d\u0430 \u0442\u043e\u043a\u0435\u043d\u044b (\u0442\u043e\u043a\u0435\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c): \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c <code>.split('')<\/code>.<\/p>\n<p>\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0442\u0443\u0442 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u043d\u044f\u0442\u0438\u0435 <code>EOF<\/code> (end of file) \u0438 \u0432\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u0440\u0430\u0437\u0443 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u0434\u0442\u0438 \u043a\u043e\u043d\u0435\u0446 \u0444\u0430\u0439\u043b\u0430\/\u0432\u0432\u043e\u0434\u0430. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435, \u0447\u0442\u043e \u043d\u0430 \u0432\u0445\u043e\u0434 \u043f\u043e\u0434\u0430\u0451\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u043a\u0430 <code>2#<\/code>. \u0411\u0435\u0437 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 EOF \u043c\u044b \u0431\u044b \u0442\u0430\u043a \u0438 \u0432\u044b\u0432\u0435\u043b\u0438 \u0434\u0432\u043e\u0439\u043a\u0443, \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0432 <code>#<\/code>, \u0430 \u0442\u0430\u043a\u0438\u0435 \u0432\u043e\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b. \u0412\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 <code>2+2<\/code> \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a \u0436\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u0431\u0438\u0442\u044c \u0441 \u0442\u043e\u043b\u043a\u0443 \u043d\u0430\u0448 \u043f\u0430\u0440\u0441\u0435\u0440 \u043d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435.<\/p>\n<p>\u041a\u0441\u0442\u0430\u0442\u0438, \u0432 JavaScript \u043c\u0435\u0442\u043e\u0434 <code>shift()<\/code> \u0432\u044b\u0434\u0430\u0451\u0442 \u043f\u0435\u0440\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0438 \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u0435\u0433\u043e \u0438\u0437 \u043c\u0430\u0441\u0441\u0438\u0432\u0430. \u042d\u0442\u0438\u043c \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0438\u0434\u0442\u0438 \u043f\u043e \u0442\u043e\u043a\u0435\u043d\u0430\u043c. \u0418\u043d\u043e\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0442\u043e\u043a\u0435\u043d, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0435\u0433\u043e, \u0442\u0438\u043f\u0430 <code>if (tokens[0] === '+') { tokens.shift(); ... }<\/code>.<\/p>\n<h2>\u00ab2+2\u00bb<\/h2>\n<p>\u041f\u043e\u0439\u0434\u0451\u043c \u0434\u0430\u043b\u044c\u0448\u0435 \u043f\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044e \u0434\u0430\u043b\u044c\u0448\u0435 \u0438, \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044f <code>+<\/code> \u043b\u0438\u0431\u043e <code>-<\/code> , \u0431\u0443\u0434\u0435\u043c \u0440\u0435\u0448\u0430\u0442\u044c, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0437\u0430 \u043d\u0438\u043c\u0438 \u0446\u0438\u0444\u0440\u043e\u0439\u00a0\u2014 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0438\u043b\u0438 \u0432\u044b\u0447\u0435\u0441\u0442\u044c \u0438\u0437 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430.<\/p>\n<pre><code class=\"javascript\">function expr(tokens) { \/\/ ['2', '+', '3', '-', '4']   let result = parseInt(tokens.shift());    \/\/ NEW   while (true) {     if (tokens[0] === '+') {       tokens.shift(); \/\/ throw away the '+'       result += parseInt(tokens.shift());     }     else if (tokens[0] === '-') {       tokens.shift(); \/\/ throw away the '-'       result -= parseInt(tokens.shift());     }     else break;   }      return result; }  function calc(tokens) { \/\/ ['2', '+', '3', '-', '4']   let result = expr(tokens);   if (tokens.length) throw new Error('expected eof');   return result; }  console.log(calc('2+2'.split('')) === 4); \/\/ true console.log(calc('2+3-4'.split('')) === 1); \/\/ true<\/code><\/pre>\n<p>\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043c\u044b \u0432\u044b\u043d\u0435\u0441\u043b\u0438 \u0447\u0430\u0441\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>expr<\/code>, \u0445\u043e\u0442\u044c \u0438 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0441\u0451 \u0432 <code>calc<\/code>. \u0422\u0430\u043a\u043e\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430\u043c \u043f\u043e\u0437\u0436\u0435.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0434\u0441\u0443\u043d\u0435\u043c \u043d\u0430\u0448\u0435\u043c\u0443 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0440\u0441\u0435\u0440\u0443 \u043a\u0430\u043a\u0443\u044e-\u043d\u0438\u0431\u0443\u0434\u044c \u0435\u0440\u0443\u043d\u0434\u0443, \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u043e\u043d \u043d\u0435 \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u0447\u0438\u0441\u043b\u043e\u0432\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u0438 \u0434\u0432\u0438\u043d\u0435\u043c\u0441\u044f \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<pre><code class=\"javascript\">console.log(calc('+'.split(''))); \/\/ NaN console.log(calc('+1'.split(''))); \/\/ Error: expected eof<\/code><\/pre>\n<p>\u041f\u043e\u043a\u0430 \u0441\u043e\u0439\u0434\u0451\u0442. \u041e\u0434\u0438\u043d\u043e\u043a\u0438\u0439 \u043f\u043b\u044e\u0441 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u043d\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442, \u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 <code>+1<\/code> (\u0443\u043d\u0430\u0440\u043d\u044b\u0439 \u043f\u043b\u044e\u0441) \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u0437\u0436\u0435 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0443\u043d\u0430\u0440\u043d\u044b\u043c \u043c\u0438\u043d\u0443\u0441\u043e\u043c.<\/p>\n<h2>\u00ab2+2\u00d72\u00bb<\/h2>\n<p>\u0415\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0442\u0443\u0442 \u043f\u043e\u0434\u0432\u043e\u0445 \u0432 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f\/\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0430\u0434 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u0438 \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u044f\/\u0432\u044b\u0447\u0438\u0442\u0430\u043d\u0438\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u043b\u044c\u0437\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0431\u043b\u043e\u043a <code>else if (tokens[0] === '*') {...}<\/code> \u0432\u0441\u043b\u0435\u0434 \u0437\u0430 \u043f\u043b\u044e\u0441\u043e\u043c \u0438 \u043c\u0438\u043d\u0443\u0441\u043e\u043c, \u0432\u0435\u0434\u044c \u0442\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f 8. \u0417\u0434\u0435\u0441\u044c-\u0442\u043e \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u0438 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044f \u044f\u0437\u044b\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u043f\u0438\u0448\u0435\u043c \u044d\u0442\u043e\u0442 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440. \u0412 JavaScript \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044f \u0435\u0441\u0442\u044c, \u0438 \u043f\u043e\u0442\u043e\u043c\u0443 \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u043b\u0435\u0433\u043a\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f. \u041d\u043e \u0435\u0441\u0442\u044c \u0443\u0441\u043b\u043e\u0432\u043d\u043e \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u044f\u0437\u044b\u043a\u0438 \u0431\u0435\u0437 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438\u00a0\u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, structured text \u0432\u00a0IEC 61\u00a0131\u20133, \u043d\u0430\u00a0\u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0432\u00a0\u0441\u0440\u0435\u0434\u0435 \u043f\u0440\u043e\u043c\u044b\u0448\u043b\u0435\u043d\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u043a\u0438.<\/p>\n<p>\u041e\u0441\u0442\u0430\u0432\u0438\u043c \u0434\u0432\u043e\u0439\u043a\u0438 \u0434\u043b\u044f \u043a\u0440\u0430\u0441\u0438\u0432\u043e\u0433\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430, \u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0449\u0435 \u0431\u044b\u043b\u043e \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u0440\u0443\u043a\u0430\u043c\u0438, \u0432\u043e\u0437\u044c\u043c\u0451\u043c \u043f\u0440\u0438\u043c\u0435\u0440 3+4\u00d75. \u0414\u0430, \u0433\u043e\u0432\u043e\u0440\u044f \u043e\u0431\u044b\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u043c \u044f\u0437\u044b\u043a\u043e\u043c, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e <em>\u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c 4\u00d75<\/em> \u0438 \u0443\u0436\u0435 <em>\u043f\u043e\u0442\u043e\u043c<\/em> \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u0441 \u0442\u0440\u043e\u0439\u043a\u043e\u0439. \u041d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0444\u043e\u0440\u043c\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0434\u043b\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0437\u043e\u043c: <em>\u0441\u043b\u043e\u0436\u0438\u0442\u044c \u0442\u0440\u043e\u0439\u043a\u0443 \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0433\u043b\u0430\u0432\u043d\u0435\u0435 \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/em>. \u0410 \u0437\u043d\u0430\u0447\u0438\u0442, \u043c\u043e\u0436\u043d\u043e \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e \u043d\u0430\u0447\u0430\u0442\u044c \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u0440\u043e\u0439\u043a\u0443, \u043f\u043e\u0442\u043e\u043c <code>+<\/code> \u0437\u0430 \u043d\u0435\u0439, \u0430 \u043f\u043e\u0442\u043e\u043c \u00ab\u043e\u0442\u0432\u043b\u0435\u0447\u044c\u0441\u044f\u00bb \u043d\u0430\u00a0\u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 4\u00d75, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0438 \u0441\u043b\u043e\u0436\u0438\u0442\u044c \u0441\u00a0\u0440\u0430\u043d\u0435\u0435 \u0437\u0430\u043c\u0435\u0447\u0435\u043d\u043d\u043e\u0439 \u0442\u0440\u043e\u0439\u043a\u043e\u0439. \u0412\u043e\u0442 \u043d\u0430\u00a0\u044d\u0442\u043e\u043c \u00ab\u043e\u0442\u0432\u043b\u0435\u0447\u044c\u0441\u044f\u00bb \u0438 \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u0441\u043f\u0443\u0441\u043a\u0430. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0444\u043e\u0440\u043c\u0438\u043c \u00ab\u043e\u0442\u0432\u043b\u0435\u0447\u044c\u0441\u044f\u00bb \u043d\u043e\u0432\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <code>term<\/code>, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u043d\u0430 <code>expr<\/code> \u0432\u044b\u0448\u0435. \u041d\u0443 \u0430 \u0432 <code>expr<\/code> \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c <code>term<\/code> \u0442\u0430\u043c, \u0433\u0434\u0435 \u043f\u0440\u0435\u0436\u0434\u0435 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u043b\u0438 \u0446\u0438\u0444\u0440\u044b.<\/p>\n<pre><code class=\"javascript\">function term(tokens) { \/\/ like old `expr` but * and \/   let result = parseInt(tokens.shift());    while (true) {     if (tokens[0] === '*') {       tokens.shift(); \/\/ throw away the '*'       result *= parseInt(tokens.shift());     }     else if (tokens[0] === '\/') {       tokens.shift(); \/\/ throw away the '\/'       result \/= parseInt(tokens.shift());     }     else break;   }      return result; }  function expr(tokens) {   let result = term(tokens); \/\/ was `parseInt(tokens.shift())`    while (true) {     if (tokens[0] === '+') {       tokens.shift(); \/\/ throw away the '+'       result += term(tokens); \/\/ was `parseInt(tokens.shift())`     }     else if (tokens[0] === '-') {       tokens.shift(); \/\/ throw away the '-'       result -= term(tokens); \/\/ was `parseInt(tokens.shift())`     }     else break;   }      return result; }  function calc(tokens) {   let result = expr(tokens);   if (tokens.length) throw new Error('expected eof');   return result; }  console.log(calc('2+2'.split('')) === 4); \/\/ true console.log(calc('2+3-4'.split('')) === 1); \/\/ true console.log(calc('2+2*2'.split('')) === 6); \/\/ true console.log(calc('3+4*5'.split('')) === 23); \/\/ true console.log(calc('3\/2+4*5'.split('')) === 21.5); \/\/ true<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u043c\u044b \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u0443\u043c\u0435\u043b\u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0430\u0436\u0435 <code>3\/2+4*5<\/code>.<\/p>\n<h2>\u00ab(2+2)\u00d72\u00bb<\/h2>\n<p>\u0427\u0442\u043e \u0435\u0441\u043b\u0438 \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u043d\u0443\u0436\u043d\u0430 \u0432\u043e\u0441\u044c\u043c\u0451\u0440\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0441\u043a\u043e\u0431\u043e\u043a? \u0417\u043d\u0430\u0447\u0438\u0442, \u043d\u0443\u0436\u043d\u043e \u0432 <code>term<\/code> <em>\u043e\u0442\u0432\u043b\u0435\u0447\u044c\u0441\u044f<\/em> \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u0432 \u0441\u043a\u043e\u0431\u043a\u0438. \u0410 \u0432 \u0441\u043a\u043e\u0431\u043a\u0430\u0445 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <code>expr<\/code> , \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u043c\u044b \u0435\u0451 \u0438 \u0432\u044b\u0434\u0435\u043b\u0438\u043b\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0437\u0430\u0434. \u041e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0435 \u043e\u0442\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u043d\u0430\u0437\u043e\u0432\u0451\u043c <code>factor<\/code>, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043b\u0438\u0431\u043e \u0432\u044b\u0437\u043e\u0432\u0435\u043c <code>expr<\/code> \u043c\u0435\u0436\u0434\u0443 \u0441\u043a\u043e\u0431\u043a\u0430\u043c\u0438 (\u043a\u0440\u0443\u0433 \u0437\u0430\u043c\u043a\u043d\u0443\u043b\u0441\u044f), \u043b\u0438\u0431\u043e \u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0447\u0438\u0441\u043b\u043e.<\/p>\n<pre><code class=\"javascript\">function factor(tokens) {   if (tokens[0] === '(') {     tokens.shift();     let result = expr(tokens);     if (tokens[0] !== ')') {       throw new Error('missing closing parenthesis');     } else {       tokens.shift();     }     return result;   }   else return parseInt(tokens.shift()); }  function term(tokens) {   let result = factor(tokens);    while (true) {     if (tokens[0] === '*') {       tokens.shift(); \/\/ throw away the '*'       result *= factor(tokens);     }     else if (tokens[0] === '\/') {       tokens.shift(); \/\/ throw away the '\/'       result \/= factor(tokens);     }     else break;   }      return result; }  function expr(tokens) { \/* omitted for clarity *\/ } function calc(tokens) { \/* omitted for clarity *\/ }  console.log(calc('2+2'.split('')) === 4); \/\/ true console.log(calc('2+3-4'.split('')) === 1); \/\/ true console.log(calc('2+2*2'.split('')) === 6); \/\/ true console.log(calc('3+4*5'.split('')) === 23); \/\/ true console.log(calc('3\/2+4*5'.split('')) === 21.5); \/\/ true console.log(calc('(2+2)*2'.split('')) === 8); \/\/ true<\/code><\/pre>\n<p>\u0412 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435, \u043d\u0430 \u044d\u0442\u043e\u043c \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0441\u043d\u043e\u0432\u0430 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u0441\u043f\u0443\u0441\u043a\u0430. \u0414\u0430\u043b\u044c\u0448\u0435 \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u043a\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443.<\/p>\n<figure class=\"full-width\"><\/figure>\n<h3>\u00ab(02. + 0002.) \u00d7 002.000\u00bb<\/h3>\n<p>\u0414\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u043c\u044b \u043f\u0430\u0440\u0441\u0438\u043b\u0438 \u043c\u0430\u0441\u0441\u0438\u0432 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0438\u0437 \u0446\u0438\u0444\u0440, \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0438 \u043a\u0440\u0443\u0433\u043b\u044b\u0445 \u0441\u043a\u043e\u0431\u043e\u043a. \u041a\u0430\u0436\u0434\u044b\u0439 \u0441\u0438\u043c\u0432\u043e\u043b \u0431\u044b\u043b \u0442\u043e\u043a\u0435\u043d\u043e\u043c, \u0438 \u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0443\u043f\u0440\u043e\u0449\u0430\u043b\u043e \u043d\u0430\u043c \u0436\u0438\u0437\u043d\u044c. \u041d\u043e \u0434\u0430\u043b\u044c\u0448\u0435 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u043e. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0441\u0438\u043c\u0432\u043e\u043b\u044c\u043d\u044b\u0439 <code>split('')<\/code> \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u0447\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0432\u0437\u0440\u043e\u0441\u043b\u044b\u043c <em>\u043b\u0435\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0440\u0430\u0437\u0431\u043e\u0440\u043e\u043c<\/em> (\u043f\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u043c\u0443 \u0441\u0447\u0451\u0442\u0443 \u044d\u0442\u043e \u0441\u0438\u043d\u043e\u043d\u0438\u043c \u0442\u043e\u043a\u0435\u043d\u0438\u0437\u0430\u0446\u0438\u0438).<\/p>\n<p>\u0423 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u043f\u043e \u0432\u0441\u0435\u043c \u0442\u0438\u043f\u0430\u043c \u0442\u043e\u043a\u0435\u043d\u043e\u0432, \u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u043e\u0442\u0440\u0435\u0437\u0430\u0442\u044c \u043e\u0442 \u0432\u0445\u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u043e \u043a\u0443\u0441\u043e\u0447\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0445\u043e\u0442\u044c \u043e\u0434\u043d\u043e\u0439 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0435. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043d\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0441 \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439:<\/p>\n<pre><code class=\"javascript\">const matchers = [   { type: 'word', regex: \/^[a-z]+\/ },   { type: 'number', regex: \/^[0-9]+\/ },   { type: 'whitespace', regex: \/^\\s+\/ }, ];  let test = '123sdm  k282rtk\\tmx11';  while (test) {   for (const { type, regex } of matchers) {     const match = regex.exec(test)?.[0];     if (match) {       console.log({ type, match });       test = test.slice(match.length);     }   } }  \/\/ {type: 'number', match: '123'} \/\/ {type: 'word', match: 'sdm'} \/\/ {type: 'whitespace', match: '  '} \/\/ {type: 'word', match: 'k'} \/\/ {type: 'number', match: '282'} \/\/ {type: 'word', match: 'rtk'} \/\/ {type: 'whitespace', match: ''} \/\/ {type: 'word', match: 'mx'} \/\/ {type: 'number', match: '11'}<\/code><\/pre>\n<p>\u0422\u0443\u0442 \u0432\u0430\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c <code>^<\/code> \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0433\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0449\u0435\u0435 \u043f\u043e\u0438\u0441\u043a \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u0441\u0442\u0440\u043e\u0433\u043e \u0441 \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0442\u0440\u043e\u043a\u0438. \u0412\u043c\u0435\u0441\u0442\u0435 \u0441\u043e <code>slice()<\/code> \u044d\u0442\u043e \u0434\u0430\u0451\u0442 \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0445\u043e\u0434 \u043f\u043e \u0441\u0442\u0440\u043e\u043a\u0435 \u00ab\u043a\u0443\u0441\u043e\u0447\u043a\u0430\u043c\u0438\u00bb. <\/p>\n<p>\u0422\u0430\u043a\u043e\u0439 \u043b\u0435\u043a\u0441\u0435\u0440 \u043d\u0430 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0430\u0445 \u043e\u0447\u0435\u043d\u044c \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u0435\u043d \u0438 \u0447\u0438\u0442\u0430\u0431\u0435\u043b\u0435\u043d, \u043d\u043e \u0435\u0433\u043e \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432\u0435\u0441\u044c\u043c\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u044b \u0434\u043b\u044f \u043f\u043e-\u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u043c\u0443 \u0432\u0437\u0440\u043e\u0441\u043b\u043e\u0433\u043e \u043b\u0435\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0440\u0430\u0437\u0431\u043e\u0440\u0430; \u0438\u043c\u0435\u0439\u0442\u0435 \u044d\u0442\u043e \u0432 \u0432\u0438\u0434\u0443, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u0439\u0434\u0451\u0442\u0435 \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u044f\u0437\u044b\u043a \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u044b JS \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u044e\u0442 \u0440\u0430\u0437\u0440\u0435\u0437\u0430\u043d\u0438\u0435 \u0441\u0442\u0440\u043e\u043a \u0447\u0435\u0440\u0435\u0437 slice, \u043f\u043e \u0441\u0443\u0442\u0438 \u0441\u0432\u043e\u0434\u044f \u0435\u0433\u043e \u043a \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u044f\u043c \u0441 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f\u043c\u0438. \u0412 \u0441\u0443\u043c\u043c\u0435 \u0441 \u043f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0430\u043c\u0438, \u043f\u0440\u0438\u0431\u0438\u0442\u044b\u043c\u0438 \u043a \u043d\u0430\u0447\u0430\u043b\u0443 \u0441\u0442\u0440\u043e\u043a\u0438, \u044d\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0435\u043f\u043b\u043e\u0445\u0443\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0441\u0442\u044f\u043d\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u043b\u0435\u043a\u0441\u0435\u0440 \u043d\u0430 \u043b\u0435\u043a\u0441\u0438\u043a\u0443 \u043d\u0430\u0448\u0438\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439. \u0412\u043c\u0435\u0441\u0442\u043e \u0441\u0442\u0440\u043e\u043a \u0434\u043b\u044f \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432 \u0432\u043e\u0437\u044c\u043c\u0451\u043c JS-\u043e\u0432\u0441\u043a\u0438\u0439 Symbol \u0438 \u0443\u043f\u0430\u043a\u0443\u0435\u043c \u043c\u0430\u0442\u0447\u0438\u043d\u0433 \u0432\u043d\u0443\u0442\u0440\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430 (\u044d\u0442\u043e \u0442\u0430\u043a\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0432\u044b\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0437\u0430 \u043e\u0434\u0438\u043d \u0432\u044b\u0437\u043e\u0432; \u0432 JavaScript \u043e\u043d\u0438 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0442\u0441\u044f \u0437\u0432\u0451\u0437\u0434\u043e\u0447\u043a\u043e\u0439 \u0438 \u00ab\u0432\u044b\u043f\u043b\u0451\u0432\u044b\u0432\u0430\u044e\u0442\u00bb \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 yield).<\/p>\n<pre><code class=\"javascript\">const   WS = Symbol('ws'),   NUMBER = Symbol('num'),   PLUS = Symbol('plus'),   MINUS = Symbol('minus'),   MULTIPLY = Symbol('mul'),   DIVIDE = Symbol('div'),   LEFT_PAR = Symbol('lpar'),   RIGHT_PAR = Symbol('rpar'),   END_OF_FILE = Symbol('eof');  function* tokenize(input) {   const matchers = [     { type: NUMBER, re: \/^[0-9\\.]+\/ },     { type:<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-350830","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/350830","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=350830"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/350830\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=350830"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=350830"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=350830"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}