{"id":232097,"date":"2014-08-05T10:30:03","date_gmt":"2014-08-05T06:30:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=232097"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=232097","title":{"rendered":"<span class=\"post_title\">\u041f\u0438\u0448\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u043d\u0430 C++ \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e TDD, \u0447\u0430\u0441\u0442\u044c 3<\/span>"},"content":{"rendered":"<div class=\"content html_format\">     \t\u0412 <a href=\"http:\/\/habrahabr.ru\/post\/231657\/\">\u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0431\u044b\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043b\u0435\u043a\u0441\u0435\u0440<\/a>, \u0430 \u0432\u043e <a href=\"http:\/\/habrahabr.ru\/post\/232081\/\">\u0432\u0442\u043e\u0440\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u2014 \u043f\u0430\u0440\u0441\u0435\u0440<\/a>. \u0414\u0430\u043b\u0435\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044f \u0438 \u0444\u0430\u0441\u0430\u0434\u0430 \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u0432\u0441\u0435\u0433\u043e \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0443\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<h4> \u0412\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c<\/h4>\n<p>  \u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c\u0443. \u0412\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u043f\u043e\u0441\u0442\u0444\u0438\u043a\u0441\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u044c \u0434\u0432\u0443\u043c\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438: \u0447\u0435\u0440\u0435\u0437 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e, \u043d\u0435\u044f\u0432\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0441\u0442\u0435\u043a \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430, \u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u044f\u0432\u043d\u044b\u0439 \u0441\u0442\u0435\u043a. \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0432\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442. \u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u044f\u0432\u043d\u043e\u0433\u043e \u0441\u0442\u0435\u043a\u0430 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<ul>\n<li> \u0415\u0441\u043b\u0438 \u043d\u0430 \u0432\u0445\u043e\u0434 \u043f\u043e\u0434\u0430\u043d \u043e\u043f\u0435\u0440\u0430\u043d\u0434, \u043e\u043d \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0432\u0435\u0440\u0448\u0438\u043d\u0443 \u0441\u0442\u0435\u043a\u0430. <\/li>\n<li> \u0415\u0441\u043b\u0438 \u043d\u0430 \u0432\u0445\u043e\u0434 \u043f\u043e\u0434\u0430\u043d \u0437\u043d\u0430\u043a \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438, \u0442\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0434 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439, \u0438\u0437\u0432\u043b\u0435\u0447\u0451\u043d\u043d\u044b\u0445 \u0438\u0437 \u0441\u0442\u0435\u043a\u0430, \u0432\u0437\u044f\u0442\u044b\u0445 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043b\u0430\u0434\u0451\u0442\u0441\u044f \u043d\u0430 \u0432\u0435\u0440\u0448\u0438\u043d\u0443 \u0441\u0442\u0435\u043a\u0430. <\/li>\n<li> \u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043b\u0435\u0436\u0438\u0442 \u043d\u0430 \u0432\u0435\u0440\u0448\u0438\u043d\u0435 \u0441\u0442\u0435\u043a\u0430. <\/li>\n<\/ul>\n<p>  \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u043c:<\/p>\n<ul>\n<li> \u0415\u0441\u043b\u0438 \u043d\u0430 \u0432\u0445\u043e\u0434\u0435 \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u043f\u0438\u0441\u043e\u043a, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c 0. <\/li>\n<li> \u0415\u0441\u043b\u0438 \u043d\u0430 \u0432\u0445\u043e\u0434\u0435 \u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u043e\u0434\u043d\u0438\u043c \u0447\u0438\u0441\u043b\u043e\u043c, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u044d\u0442\u043e \u0447\u0438\u0441\u043b\u043e. <\/li>\n<li> \u0415\u0441\u043b\u0438 \u043d\u0430 \u0432\u0445\u043e\u0434\u0435 [1 2 +], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c 3. <\/li>\n<\/ul>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u0442\u0435\u0441\u0442.<\/p>\n<pre><code class=\"cpp\">TEST_CLASS(EvaluatorTests) { public:     TEST_METHOD(Should_return_zero_when_evaluate_empty_list) {         double result = Evaluator::Evaluate({});         Assert::AreEqual(0.0, result);     } }; <\/code><\/pre>\n<p>  <a name=\"habracut\"><\/a><br \/>  \u041f\u0440\u0438\u0432\u044b\u0447\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0443\u0441\u0442\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0432 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u0438\u043c\u0451\u043d.<\/p>\n<pre><code class=\"cpp\">namespace Evaluator { inline double Evaluate(Tokens) { return 0; } } \/\/ namespace Evaluator <\/code><\/pre>\n<p>  \u041d\u0430\u043f\u0438\u0448\u0435\u043c \u0432\u0442\u043e\u0440\u043e\u0439 \u0442\u0435\u0441\u0442.<\/p>\n<pre><code class=\"cpp\">    TEST_METHOD(Should_return_number_when_evaluate_list_with_number) {         double result = Evaluator::Evaluate({ _1 });         Assert::AreEqual(1.0, result);     } <\/code><\/pre>\n<p>  \u041f\u0440\u043e\u0441\u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c, \u0442\u043e \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c. \u041c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043f\u0440\u043e\u0449\u0435, \u043d\u043e \u043f\u043e\u0442\u043e\u043c \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0446\u0438\u043a\u043b.<\/p>\n<pre><code class=\"cpp\">inline double Evaluate(const Tokens &tokens) {     double result = 0;     for(const Token &token : tokens) {         result = token;     }     return result; } <\/code><\/pre>\n<p>  \u0414\u0430\u043b\u044c\u0448\u0435 \u2014 \u0441\u043b\u043e\u0436\u043d\u0435\u0435. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u044c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441 \u043e\u0434\u043d\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u043c.<\/p>\n<pre><code class=\"cpp\">    TEST_METHOD(Should_eval_expression_with_one_operator) {         double result = Evaluator::Evaluate({ _1, _2, plus });         Assert::AreEqual(3.0, result);     } <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u043e\u0442 \u0442\u0435\u0441\u0442 \u043f\u0440\u043e\u0448\u0451\u043b, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u0441\u0435\u0433\u043e \u043e\u0434\u0438\u043d \u0441\u0438\u043c\u0432\u043e\u043b \u043a \u043a\u043e\u0434\u0443.<\/p>\n<pre><code class=\"cpp\">    for(const Token &token : tokens) {         if(token.Type() == TokenType::Number) {             result += token;         }     } <\/code><\/pre>\n<p>  \u042d\u0442\u043e\u0433\u043e \u0431\u044b\u043b\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u0430. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u043b\u043e\u043c\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c, \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"cpp\">    TEST_METHOD(Should_eval_expression_with_one_multiplication) {         double result = Evaluator::Evaluate({ _2, _3, mul });         Assert::AreEqual(6.0, result);     } <\/code><\/pre>\n<p>  \u0422\u0435\u0441\u0442 \u043d\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442, \u0442\u0430\u043a \u043a\u0430\u043a \u0443 \u043d\u0430\u0441 \u0436\u0451\u0441\u0442\u043a\u043e \u0437\u0430\u0431\u0438\u0442\u043e \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u0442\u0438\u043f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u0435\u0442\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0441 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u043d\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440.<\/p>\n<pre><code class=\"cpp\">inline double Evaluate(const Tokens &tokens) {     std::vector&lt;double&gt; result{ 0 };     auto pop = [&]() { double d = result.back(); result.pop_back(); return d; };     for(const Token &token : tokens) {         if(token.Type() == TokenType::Number) {             result.push_back(token);         }         else if(token == Token(Operator::Plus)) {             result.push_back(pop() + pop());         }         else if(token == Token(Operator::Mul)) {             result.push_back(pop() * pop());         }     }     return pop(); } <\/code><\/pre>\n<p>  \u0417\u0430\u043c\u0435\u0442\u0438\u043c, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0443\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0438 \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f. \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0435\u0441\u0442 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u043c\u0438\u043d\u0443\u0441. \u0415\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043f\u0443\u0442\u0430\u0442\u044c \u043c\u0435\u0441\u0442\u0430\u043c\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u044f \u0438\u0445 \u0438\u0437 \u0441\u0442\u0435\u043a\u0430.<\/p>\n<pre><code class=\"cpp\">    TEST_METHOD(Should_eval_expression_with_one_subtraction) {         double result = Evaluator::Evaluate({ _2, _3, minus });         Assert::AreEqual(-1.0, result);     } <\/code><\/pre>\n<p>  \u0412\u043e\u043e\u0431\u0449\u0435, \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0443 C++, \u043d\u0435\u043b\u044c\u0437\u044f \u0434\u0435\u043b\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u043d\u0434\u044b \u0438\u0437 \u0441\u0442\u0435\u043a\u0430 \u043d\u0443\u0436\u043d\u043e \u0432 \u044f\u0432\u043d\u043e\u0439 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/p>\n<pre><code class=\"cpp\">        \u2026         else if(token == Token(Operator::Minus)) {             double d = pop();             result.push_back(pop() - d);         } <\/code><\/pre>\n<p>  \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u0442\u0435\u0441\u0442 \u0434\u043b\u044f \u0434\u0435\u043b\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"cpp\">    TEST_METHOD(Should_eval_expression_with_one_division) {         double result = Evaluator::Evaluate({ _5, _2, div });         Assert::AreEqual(2.5, result);     } <\/code><\/pre>\n<p>  \u0412 \u043d\u0430\u0447\u0430\u043b\u0435 \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0442\u0435\u0441\u0442 \u043d\u0430 \u0434\u0435\u043b\u0435\u043d\u0438\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 <code>4\/2=2<\/code>, \u0438 \u043e\u043d \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043f\u0440\u043e\u0448\u0451\u043b, \u043d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0435 \u0431\u044b\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430. \u042d\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u043f\u043e \u0442\u043e\u0439 \u043f\u0440\u0438\u0447\u0438\u043d\u0435, \u0447\u0442\u043e \u0438\u0437 \u0441\u0442\u0435\u043a\u0430 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0435 \u0432 \u043d\u0435\u0433\u043e \u0447\u0438\u0441\u043b\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435, \u043f\u043e \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044e, \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0440\u0430\u0432\u043d\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0443 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f. \u0418\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0435\u0441\u0442\u044b \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0430\u0434\u0430\u0442\u044c, \u0438\u043d\u0430\u0447\u0435 \u0435\u0441\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0442\u0435\u0441\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043d\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u0442.<\/p>\n<pre><code class=\"cpp\">        \u2026         else if(token == Token(Operator::Div)) {             double d = pop();             result.push_back(pop() \/ d);         } <\/code><\/pre>\n<p>  \u0427\u0442\u043e\u0431\u044b \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u0434\u043e, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0442\u0435\u0441\u0442 \u043d\u0430 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"cpp\">    TEST_METHOD(Should_eval_complex_expression) {         \/\/ (4+1)*2\/(4\/(3-1)) = 4 1 + 2 * 4 3 1 - \/ \/  = 5         double result = Evaluator::Evaluate({ _4, _1, plus, _2, mul, _4, _3, _1, minus, div, div });         Assert::AreEqual(5.0, result);     } <\/code><\/pre>\n<p>  \u041e\u043d \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442, \u043d\u043e \u0442\u0430\u043a \u0438 \u0431\u044b\u043b\u043e \u0437\u0430\u0434\u0443\u043c\u0430\u043d\u043e. \u0412 \u043d\u0430\u0448\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0412\u044b\u043d\u0435\u0441\u0435\u043c \u0435\u0451 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0438 \u043e\u0442\u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043c.<\/p>\n<pre><code class=\"cpp\">inline double Evaluate(const Tokens &tokens) {     Detail::StackEvaluator evaluator(tokens);     evaluator.Evaluate();     return evaluator.Result(); } <\/code><\/pre>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043b\u0430\u0441\u0441 Detail::StackEvaluator<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">namespace Detail {  class StackEvaluator { public:     StackEvaluator(const Tokens &tokens) : m_current(tokens.cbegin()), m_end(tokens.cend()) {}      void Evaluate() {         for(; m_current != m_end; ++m_current) {             EvaluateCurrentToken();         }     }      double Result() const { return m_stack.empty() ? 0 : m_stack.back(); }  private:     void EvaluateCurrentToken() {         switch(m_current-&gt;Type()) {             case TokenType::Operator:                 EvaluateOperator();                 break;             case TokenType::Number:                 EvaluateNumber();                 break;             default:                 throw std::out_of_range(&quot;TokenType&quot;);         }     }      void EvaluateOperator() {         double second = PopOperand();         double first = PopOperand();         m_stack.push_back(BinaryFunctionFor(*m_current)(first, second));     }      void EvaluateNumber() {         m_stack.push_back(*m_current);     }      double PopOperand() {         double back = m_stack.back();         m_stack.pop_back();         return back;     }      static const std::function&lt;double(double, double)&gt; &BinaryFunctionFor(Operator op) {         static const std::map&lt;Operator, std::function&lt;double(double, double)&gt;&gt; functions{                 { Operator::Plus, std::plus&lt;double&gt;() },                 { Operator::Minus, std::minus&lt;double&gt;() },                 { Operator::Mul, std::multiplies&lt;double&gt;() },                 { Operator::Div, std::divides&lt;double&gt;() },         };         auto found = functions.find(op);         if(found == functions.cend()) {             throw std::logic_error(&quot;Operator not found.&quot;);         }         return found-&gt;second;     }      Tokens::const_iterator m_current, m_end;     std::vector&lt;double&gt; m_stack; };  } \/\/ namespace Detail <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<h4> \u0418\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440<\/h4>\n<p>  \u0414\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u044f\u0432\u043b\u044f\u044e\u0449\u0443\u044e\u0441\u044f \u0444\u0430\u0441\u0430\u0434\u043e\u043c \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0430\u0440\u0443 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<pre><code class=\"cpp\">TEST_CLASS(InterpreterIntegrationTests) { public:     TEST_METHOD(Should_interprete_empty_experssion) {         double result = Interpreter::InterpreteExperssion(L&quot;  &quot;);         Assert::AreEqual(0.0, result);     }      TEST_METHOD(Should_interprete_experssion) {         double result = Interpreter::InterpreteExperssion(L&quot;1+2&quot;);         Assert::AreEqual(3.0, result);     } }; <\/code><\/pre>\n<p>  \u041d\u0430\u043f\u0438\u0448\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>InterpreteExperssion<\/code> \u0432 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435 \u0438\u043c\u0451\u043d <code>Interpreter<\/code>.<\/p>\n<pre><code class=\"cpp\">inline double InterpreteExperssion(const std::wstring &expression) {     return Evaluator::Evaluate(Parser::Parse(Lexer::Tokenize(expression))); } <\/code><\/pre>\n<p>  \u0423\u0440\u0430, \u0442\u0435\u0441\u0442\u044b \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442, \u0437\u043d\u0430\u0447\u0438\u0442 \u0432\u0441\u0435 \u0447\u0430\u0441\u0442\u0438 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0442 \u0442\u0430\u043a, \u043a\u0430\u043a \u0438 \u0431\u044b\u043b\u043e \u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e.<\/p>\n<h4> \u0420\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433<\/h4>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u0432\u0435\u0441\u044c \u043a\u043e\u0434 \u043f\u043e\u043a\u0440\u044b\u0442 \u0442\u0435\u0441\u0442\u0430\u043c\u0438, \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u0435\u0441\u0442\u044c \u043b\u0438 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u043c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0435 \u0438 \u0443\u0441\u0442\u0440\u0430\u043d\u0438\u0442\u044c \u0435\u0433\u043e. \u0421\u0440\u0430\u0437\u0443 \u0436\u0435 \u0431\u0440\u043e\u0441\u0430\u0435\u0442\u0441\u044f \u0432 \u0433\u043b\u0430\u0437\u0430 \u043a\u0443\u0447\u0430 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 <code>switch<\/code>, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0438\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430 \u0442\u0438\u043f \u0442\u043e\u043a\u0435\u043d\u0430. \u0414\u0430 \u0438 \u0432 \u0441\u0430\u043c\u043e\u043c \u0442\u043e\u043a\u0435\u043d\u0435 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043a\u0430\u043a \u0447\u0438\u0441\u043b\u043e, \u0442\u0430\u043a \u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440. \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0443\u0439\u0442\u0438 \u043e\u0442 \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u043c \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u044c. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>TokenVisitor<\/code>:<\/p>\n<pre><code class=\"cpp\">struct TokenVisitor {     virtual void VisitNumber(double) {}     virtual void VisitOperator(Operator) {}  protected:     ~TokenVisitor() {} }; <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b, \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0431\u0443\u0434\u0443\u0442 \u0438\u043c\u0435\u0442\u044c \u043f\u0443\u0441\u0442\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. \u0414\u043b\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438, \u043e\u0431\u044a\u044f\u0432\u0438\u043c \u0434\u0435\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043a\u0430\u043a \u0437\u0430\u0449\u0438\u0449\u0451\u043d\u043d\u044b\u0439 \u0438 \u043d\u0435 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u0442\u043e\u043a\u0435\u043d \u043c\u0435\u0442\u043e\u0434, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0439 \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u044f \u0438 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0451\u043c \u0432 \u043d\u0435\u0433\u043e \u0437\u043b\u043e\u043f\u043e\u043b\u0443\u0447\u043d\u044b\u0439 <code>switch<\/code>.<\/p>\n<pre><code class=\"cpp\">    void Accept(TokenVisitor &visitor) const {         switch(m_type) {             case TokenType::Operator:                 visitor.VisitOperator(m_operator);                 break;             case TokenType::Number:                 visitor.VisitNumber(m_number);                 break;             default: throw std::out_of_range(&quot;TokenType&quot;);         }     } <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043a\u043b\u0430\u0441\u0441 <code>ShuntingYardParser<\/code> \u0438 \u0435\u0433\u043e \u043c\u0435\u0442\u043e\u0434 <code>ParseCurrentToken<\/code>.<\/p>\n<pre><code class=\"cpp\">    void ParseCurrentToken() {         switch(m_current-&gt;Type()) {             case TokenType::Operator:                 ParseOperator();                 break;             case TokenType::Number:                 ParseNumber();                 break;             default: throw std::out_of_range(&quot;TokenType&quot;);         }     } <\/code><\/pre>\n<p>  \u0421\u0445\u043e\u0434\u0441\u0442\u0432\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e. \u0423\u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u043c \u044d\u0442\u043e \u043a\u043b\u0430\u0441\u0441 \u043e\u0442 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u044f \u0438 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0435\u043c \u043c\u0435\u0442\u043e\u0434\u044b <code>Parse*<\/code> \u0432 <code>Visit*<\/code>. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441 \u0438\u0437\u0440\u044f\u0434\u043d\u043e \u043f\u043e\u0445\u0443\u0434\u0435\u0435\u0442, \u0430 \u043c\u0435\u0442\u043e\u0434 <code>Parse<\/code> \u043f\u0440\u0438\u043c\u0435\u0442 \u0442\u0430\u043a\u043e\u0439 \u0432\u0438\u0434:<\/p>\n<pre><code class=\"cpp\">    void Parse() {         for(; m_current != m_end; ++m_current) {             m_current-&gt;Accept(*this);         }         PopToOutputUntil([this]() {return StackHasNoOperators(); });     } <\/code><\/pre>\n<p>  \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043c \u0441 \u043a\u043b\u0430\u0441\u0441\u043e\u043c <code>StackEvaluator<\/code>.<\/p>\n<pre><code class=\"cpp\">class StackEvaluator : TokenVisitor { public:     void Evaluate(const Tokens &tokens) {         for(const Token &token : tokens) {             token.Accept(*this);         }     }     \u2026     void VisitOperator(Operator op) override {         double second = PopOperand();         double first = PopOperand();         m_stack.push_back(BinaryFunctionFor(op)(first, second));     }      void VisitNumber(double number) override {         m_stack.push_back(number);     } }; <\/code><\/pre>\n<p>  \u041c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0437\u0430\u043c\u0435\u043d\u0438\u0432 \u0432\u0441\u0451 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438, \u043d\u043e \u0442\u043e\u0433\u0434\u0430 \u043f\u043e\u0442\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0432\u0441\u044f\u043a\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b IDE \u0438 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u043d\u0435\u044f\u0432\u043d\u044b\u0435 \u0441\u043e\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u044f. \u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f \u0441 \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u043c\u0438\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430\u043c\u0438 <code>switch<\/code> \u0438 <code>union<\/code>. \u0422\u0443\u0442 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u043a\u0441\u0442\u0430\u0442\u0438, \u043d\u0435\u044f\u0432\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 <code>std::function<\/code>. \u041f\u043e\u0441\u0442\u0443\u043f\u0438\u043c \u043f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0437\u0430\u043a\u0440\u044b\u0442\u044b\u0439 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>TokenConcept<\/code> \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 \u0442\u043e\u043a\u0435\u043d\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438, \u0437\u0430\u0432\u0438\u0441\u044f\u0449\u0438\u0435 \u043e\u0442 \u0442\u0438\u043f\u0430 \u0442\u043e\u043a\u0435\u043d\u0430. \u041a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 std::shared_ptr, \u0442\u0430\u043a \u043a\u0430\u043a \u0442\u043e\u043a\u0435\u043d \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u043c, \u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c\u044b\u043c \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e.<\/p>\n<pre><code class=\"cpp\">    struct TokenConcept {         virtual ~TokenConcept() {}         virtual void Accept(TokenVisitor &) const = 0;         virtual std::wstring ToString() const = 0;         virtual bool Equals(const TokenConcept &) const = 0;         virtual TokenType Type() const = 0;         virtual double ToNumber() const { throw std::logic_error(&quot;Invalid token type&quot;); }         virtual Operator ToOperator() const { throw std::logic_error(&quot;Invalid token type&quot;); }     }; <\/code><\/pre>\n<p>  \u041d\u0435 \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043a\u0430 \u0447\u0442\u043e \u0438\u0437\u0431\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043e\u0442 <code>TokenType<\/code> \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043b\u043e\u043c\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b. \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u0447\u0438\u0441\u043b\u0430 \u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u043b\u043e\u0433\u0438\u043a\u0443 \u0432 \u043c\u0435\u0442\u043e\u0434\u0430\u0445 \u0442\u043e\u043a\u0435\u043d\u0430 \u043d\u0430 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u0443.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043b\u0430\u0441\u0441 Token \u043f\u043e\u0441\u043b\u0435 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">class Token {     struct TokenConcept {         virtual ~TokenConcept() {}          virtual void Accept(TokenVisitor &) const = 0;          virtual std::wstring ToString() const = 0;          virtual bool Equals(const TokenConcept &) const = 0;          virtual TokenType Type() const = 0;          virtual double ToNumber() const { throw std::logic_error(&quot;Invalid token type&quot;); }          virtual Operator ToOperator() const { throw std::logic_error(&quot;Invalid token type&quot;); }     };      struct NumberToken : TokenConcept {         NumberToken(double val) : m_number(val) {}          void Accept(TokenVisitor &visitor) const override { visitor.VisitNumber(m_number); }          std::wstring ToString() const override { return std::to_wstring(m_number); }          bool Equals(const TokenConcept &other) const  override {             return other.Type() == Type() && other.ToNumber() == m_number;         }          TokenType Type() const  override { return TokenType::Number; }          double ToNumber() const override { return m_number; }      private:         double m_number;     };      struct OperatorToken : TokenConcept {         OperatorToken(Operator val) : m_operator(val) {}          void Accept(TokenVisitor &visitor) const override { visitor.VisitOperator(m_operator); }          std::wstring ToString() const override { return Interpreter::ToString(m_operator); }          bool Equals(const TokenConcept &other) const  override {             return other.Type() == Type() && other.ToOperator() == m_operator;         }          TokenType Type() const  override { return TokenType::Operator; }          Operator ToOperator() const override { return m_operator; }      private:         Operator m_operator;     };  public:     Token(Operator val) : m_concept(std::make_shared&lt;OperatorToken&gt;(val)) {}      Token(double val) : m_concept(std::make_shared&lt;NumberToken&gt;(val)) {}      TokenType Type() const { return m_concept-&gt;Type(); }      void Accept(TokenVisitor &visitor) const { m_concept-&gt;Accept(visitor); }      operator Operator() const { return m_concept-&gt;ToOperator(); }      operator double() const { return m_concept-&gt;ToNumber(); }      friend inline bool operator==(const Token &left, const Token &right) {         return left.m_concept-&gt;Equals(*right.m_concept);     }      friend inline std::wstring ToString(const Token &token) {         return token.m_concept-&gt;ToString();     }  private:     std::shared_ptr&lt;const TokenConcept&gt; m_concept; }; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0417\u0430\u043c\u0435\u0442\u0438\u043c, \u0447\u0442\u043e \u043d\u0438 \u043e\u0434\u0438\u043d \u0442\u0435\u0441\u0442 \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430 \u043d\u0435 \u0441\u043b\u043e\u043c\u0430\u043b\u0441\u044f, \u0445\u043e\u0442\u044f \u0432\u0438\u0434 \u043a\u043e\u0434\u0430 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0441\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e. \u041f\u043e\u0439\u0434\u0451\u043c \u0434\u0430\u043b\u044c\u0448\u0435 \u0438 \u0443\u0434\u0430\u043b\u0438\u043c \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 <code>TokenType<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <code>Token<\/code>. \u041f\u0435\u0440\u0435\u0434 \u044d\u0442\u0438\u043c \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0442\u0435\u0441\u0442\u044b <code>Should_get_type_for_operator_token<\/code> \u0438 <code>Should_get_type_for_number_token<\/code> \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0438 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0442\u0438\u043f \u0442\u043e\u043a\u0435\u043d\u0430, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0432 \u0438\u0445 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0443.<\/p>\n<pre><code class=\"cpp\">    TEST_METHOD(Should_check_for_equality_operator_tokens) {         Assert::AreEqual(minus, minus);         Assert::AreNotEqual(minus, plus);         Assert::AreNotEqual(minus, _1);     }      TEST_METHOD(Should_check_for_equality_number_tokens) {         Assert::AreEqual(_1, _1);         Assert::AreNotEqual(_1, _2);         Assert::AreNotEqual(_1, minus);     } <\/code><\/pre>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432. RTTY \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>TokenConcept<\/code>, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443  \u0434\u0432\u043e\u0439\u043d\u043e\u0439 \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 <code>Equals<\/code>.<\/p>\n<pre><code class=\"cpp\">    struct TokenConcept {         \u2026         virtual bool Equals(const TokenConcept &other) const = 0;         virtual bool EqualsToNumber(double) const { return false; }         virtual bool EqualsToOperator(Operator) const { return false; }     };       struct NumberToken : TokenConcept {         \u2026         bool EqualsToNumber(double value) const override { return value == m_number; }         bool Equals(const TokenConcept &other) const { return other.EqualsToNumber(m_number); }     };      struct OperatorToken : TokenConcept {         \u2026         bool EqualsToOperator(Operator value) const  override { return value == m_operator; }         bool Equals(const TokenConcept &other) const { return other.EqualsToOperator(m_operator); }     }; <\/code><\/pre>\n<p>  \u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>Equals<\/code> \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442 \u043f\u0435\u0440\u0432\u044b\u0439 \u0448\u0430\u0433 \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u0430 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0442\u043e\u043a\u0435\u043d \u0443\u0436\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u0442\u0438\u043f\u043e\u043c \u0442\u043e\u043a\u0435\u043d\u0430. \u0422\u043e\u043a\u0435\u043d\u044b \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u043d\u0435 \u0440\u0430\u0432\u043d\u044b \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u043c\u0435\u0442\u043e\u0434, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0442\u0438\u043f\u0430.<\/p>\n<h4> \u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h4>\n<p>  \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e\u043f\u044b\u0442\u0430\u043b\u0441\u044f \u043e\u0442\u043e\u0439\u0442\u0438 \u043e\u0442 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u043e\u0439 \u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0438 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043f\u043e TDD, \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0435\u043d\u043d\u044b\u0445 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0430 \u0442\u0435\u043e\u0440\u0438\u0438 \u0438 \u0443\u0433\u043b\u0443\u0431\u0438\u0442\u044c\u0441\u044f \u0432 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0439 \u0442\u0435\u0445\u043d\u0438\u043a\u0438. \u041a\u0430\u043a \u0431\u044b\u043b\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e, \u0434\u0430\u0436\u0435 \u043d\u0430 C++ \u043c\u043e\u0436\u043d\u043e \u0432\u0435\u0441\u0442\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0447\u0435\u0440\u0435\u0437 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0435\u0437 \u043e\u0441\u043e\u0431\u044b\u0445 \u0437\u0430\u0442\u0440\u0443\u0434\u043d\u0435\u043d\u0438\u0439. \u0422\u0435\u043c \u0431\u043e\u043b\u0435\u0435, \u0447\u0442\u043e \u043d\u0430\u0447\u0430\u0442\u044c \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043b\u0435\u0433\u043a\u043e, \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044f \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0432 Visual Studio \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0442\u0435\u0441\u0442\u043e\u0432 \u0434\u043b\u044f C++ \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0438 \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a Boost.Test, Google.Test, \u0438\u043b\u0438 CppUTest, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 mock-\u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a Google.Mock, \u0438\u043b\u0438 Turtle. \u0414\u0430 \u0438 \u043d\u0435 \u0432\u0441\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u043e\u0434\u0443\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432. \u041d\u043e, \u0442\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0447\u0435\u0440\u0435\u0437 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u043c\u0435\u0442\u043d\u043e \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u0432 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043a\u043e\u0434\u0430, \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0442 \u0435\u0433\u043e \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0438 \u043f\u0440\u0438\u0434\u0430\u044e\u0442 \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a, \u043a\u0430\u043a \u0431\u044b\u043b\u043e \u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e.<\/p>\n<p>  \u041f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0430 \u0443 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u0435\u0439 \u044f \u043c\u043e\u0433\u0443 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0442\u043e\u0440\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0432 \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u043c \u0441\u0442\u0438\u043b\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u043f\u0443\u043d\u043a\u0442\u043e\u0432 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<h4> \u0420\u0435\u0441\u0443\u0440\u0441\u044b<\/h4>\n<p>  \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d \u0432\u0435\u0441\u044c \u043a\u043e\u0434 \u0432 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">Interpreter.h<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">#pragma once; #include &lt;vector&gt; #include &lt;wchar.h&gt; #include &lt;algorithm&gt; #include &lt;functional&gt; #include &lt;map&gt; #include &lt;memory&gt;  namespace Interpreter {  enum class Operator : wchar_t {     Plus = L'+',     Minus = L'-',     Mul = L'*',     Div = L'\/',     LParen = L'(',     RParen = L')', };  inline std::wstring ToString(const Operator &op) {     return{ static_cast&lt;wchar_t&gt;(op) }; }  struct TokenVisitor {     virtual void VisitNumber(double) {}      virtual void VisitOperator(Operator) {}  protected:     ~TokenVisitor() {} };  class Token {     struct TokenConcept {         virtual ~TokenConcept() {}          virtual void Accept(TokenVisitor &) const = 0;          virtual std::wstring ToString() const = 0;          virtual bool Equals(const TokenConcept &other) const = 0;          virtual bool EqualsToNumber(double) const {             return false;         }          virtual bool EqualsToOperator(Operator) const {             return false;         }          virtual double ToNumber() const {             throw std::logic_error(&quot;Invalid token type&quot;);         }          virtual Operator ToOperator() const {             throw std::logic_error(&quot;Invalid token type&quot;);         }     };      struct NumberToken : TokenConcept {         NumberToken(double val) : m_number(val) {}          void Accept(TokenVisitor &visitor) const override {             visitor.VisitNumber(m_number);         }          std::wstring ToString() const override {             return std::to_wstring(m_number);         }          bool EqualsToNumber(double value) const override {             return value == m_number;         }          bool Equals(const TokenConcept &other) const {             return other.EqualsToNumber(m_number);         }          double ToNumber() const override {             return m_number;         }      private:         double m_number;     };      struct OperatorToken : TokenConcept {         OperatorToken(Operator val) : m_operator(val) {}          void Accept(TokenVisitor &visitor) const override {             visitor.VisitOperator(m_operator);         }          std::wstring ToString() const override {             return Interpreter::ToString(m_operator);         }          bool EqualsToOperator(Operator value) const  override {             return value == m_operator;         }          bool Equals(const TokenConcept &other) const {             return other.EqualsToOperator(m_operator);         }          Operator ToOperator() const override {             return m_operator;         }      private:         Operator m_operator;     };  public:     Token(Operator val) : m_concept(std::make_shared&lt;OperatorToken&gt;(val)) {}      Token(double val) : m_concept(std::make_shared&lt;NumberToken&gt;(val)) {}      void Accept(TokenVisitor &visitor) const {         m_concept-&gt;Accept(visitor);     }      operator Operator() const {         return m_concept-&gt;ToOperator();     }      operator double() const {         return m_concept-&gt;ToNumber();     }      friend inline bool operator==(const Token &left, const Token &right) {         return left.m_concept-&gt;Equals(*right.m_concept);     }      friend inline std::wstring ToString(const Token &token) {         return token.m_concept-&gt;ToString();     }  private:     std::shared_ptr&lt;const TokenConcept&gt; m_concept; };  typedef std::vector&lt;Token&gt; Tokens;   namespace Lexer {  namespace Detail {  class Tokenizer { public:     Tokenizer(const std::wstring &expr) : m_current(expr.c_str()) {}      void Tokenize() {         while(!EndOfExperssion()) {             if(IsNumber()) {                 ScanNumber();             }             else if(IsOperator()) {                 ScanOperator();             }             else {                 MoveNext();             }         }     }      const Tokens &Result() const {         return m_result;     }  private:     bool EndOfExperssion() const {         return *m_current == L'\\0';     }      bool IsNumber() const {         return iswdigit(*m_current) != 0;     }      void ScanNumber() {         wchar_t *end = nullptr;         m_result.push_back(wcstod(m_current, &end));         m_current = end;     }      bool IsOperator() const {         auto all = { Operator::Plus, Operator::Minus, Operator::Mul, Operator::Div, Operator::LParen, Operator::RParen };         return std::any_of(all.begin(), all.end(), [this](Operator o) {return *m_current == static_cast&lt;wchar_t&gt;(o); });     }      void ScanOperator() {         m_result.push_back(static_cast&lt;Operator&gt;(*m_current));         MoveNext();     }      void MoveNext() {         ++m_current;     }      const wchar_t *m_current;     Tokens m_result; };  } \/\/ namespace Detail  inline Tokens Tokenize(const std::wstring &expr) {     Detail::Tokenizer tokenizer(expr);     tokenizer.Tokenize();     return tokenizer.Result(); }  } \/\/ namespace Lexer   namespace Parser {  inline int PrecedenceOf(Operator op) {     return (op == Operator::Mul || op == Operator::Div) ? 1 : 0; }  namespace Detail {  class ShuntingYardParser : TokenVisitor { public:     void Parse(const Tokens &tokens) {         for(const Token &token : tokens) {             token.Accept(*this);         }         PopToOutputUntil([this]() {return StackHasNoOperators(); });     }      const Tokens &Result() const {         return m_output;     }  private:     void VisitOperator(Operator op) override {         switch(op) {             case Operator::LParen:                 PushCurrentToStack(op);                 break;             case Operator::RParen:                 PopToOutputUntil([this]() { return LeftParenOnTop(); });                 PopLeftParen();                 break;             default:                 PopToOutputUntil([&]() { return LeftParenOnTop() || OperatorWithLessPrecedenceOnTop(op); });                 PushCurrentToStack(op);                 break;         }     }      void VisitNumber(double number) override {         m_output.emplace_back(number);     }      bool StackHasNoOperators() const {         if(m_stack.back() == Token(Operator::LParen)) {             throw std::logic_error(&quot;Closing paren not found.&quot;);         }         return false;     }      void PushCurrentToStack(Operator op) {         return m_stack.emplace_back(op);     }      void PopLeftParen() {         if(m_stack.empty() || m_stack.back() != Operator::LParen) {             throw std::logic_error(&quot;Opening paren not found.&quot;);         }         m_stack.pop_back();     }      bool OperatorWithLessPrecedenceOnTop(Operator op) const {         return PrecedenceOf(m_stack.back()) &lt; PrecedenceOf(op);     }      bool LeftParenOnTop() const {         return static_cast&lt;Operator&gt;(m_stack.back()) == Operator::LParen;     }      template&lt;class T&gt;     void PopToOutputUntil(T whenToEnd) {         while(!m_stack.empty() && !whenToEnd()) {             m_output.push_back(m_stack.back());             m_stack.pop_back();         }     }      Tokens m_output, m_stack; };  } \/\/ namespace Detail  inline Tokens Parse(const Tokens &tokens) {     Detail::ShuntingYardParser parser;     parser.Parse(tokens);     return parser.Result(); }  } \/\/ namespace Parser   namespace Evaluator {  namespace Detail {  class StackEvaluator : TokenVisitor { public:     void Evaluate(const Tokens &tokens) {         for(const Token &token : tokens) {             token.Accept(*this);         }     }      double Result() const {         return m_stack.empty() ? 0 : m_stack.back();     }  private:     void VisitOperator(Operator op) override {         double second = PopOperand();         double first = PopOperand();         m_stack.push_back(BinaryFunctionFor(op)(first, second));     }      void VisitNumber(double number) override {         m_stack.push_back(number);     }      double PopOperand() {         double back = m_stack.back();         m_stack.pop_back();         return back;     }      static const std::function&lt;double(double, double)&gt; &BinaryFunctionFor(Operator op) {         static const std::map&lt;Operator, std::function&lt;double(double, double)&gt;&gt; functions{                 { Operator::Plus, std::plus&lt;double&gt;() },                 { Operator::Minus, std::minus&lt;double&gt;() },                 { Operator::Mul, std::multiplies&lt;double&gt;() },                 { Operator::Div, std::divides&lt;double&gt;() },         };         auto found = functions.find(op);         if(found == functions.cend()) {             throw std::logic_error(&quot;Operator not found.&quot;);         }         return found-&gt;second;     }      std::vector&lt;double&gt; m_stack; };  } \/\/ namespace Detail  inline double Evaluate(const Tokens &tokens) {     Detail::StackEvaluator evaluator;     evaluator.Evaluate(tokens);     return evaluator.Result(); }  } \/\/ namespace Evaluator   inline double InterpreteExperssion(const std::wstring &expression) {     return Evaluator::Evaluate(Parser::Parse(Lexer::Tokenize(expression))); }  } \/\/ namespace Interpreter <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">InterpreterTests.cpp<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">#include &quot;stdafx.h&quot; #include &quot;CppUnitTest.h&quot; #include &quot;Interpreter.h&quot; #pragma warning(disable: 4505)  namespace InterpreterTests { using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace Interpreter; using namespace std;  namespace AssertRange {  template&lt;class T, class ActualRange&gt; static void AreEqual(initializer_list&lt;T&gt; expect, const ActualRange &actual) {     auto actualIter = begin(actual);     auto expectIter = begin(expect);      Assert::AreEqual(distance(expectIter, end(expect)), distance(actualIter, end(actual)), L&quot;Size differs.&quot;);      for(; expectIter != end(expect) && actualIter != end(actual); ++expectIter, ++actualIter) {         auto message = L&quot;Mismatch in position &quot; + to_wstring(distance(begin(expect), expectIter));         Assert::AreEqual&lt;T&gt;(*expectIter, *actualIter, message.c_str());     } }  } \/\/ namespace AssertRange  static const Token plus(Operator::Plus), minus(Operator::Minus); static const Token mul(Operator::Mul), div(Operator::Div); static const Token pLeft(Operator::LParen), pRight(Operator::RParen); static const Token _1(1), _2(2), _3(3), _4(4), _5(5);   TEST_CLASS(LexerTests) { public:     TEST_METHOD(Should_return_empty_token_list_when_put_empty_expression) {         Tokens tokens = Lexer::Tokenize(L&quot;&quot;);         Assert::IsTrue(tokens.empty());     }      TEST_METHOD(Should_tokenize_single_plus_operator) {         Tokens tokens = Lexer::Tokenize(L&quot;+&quot;);         AssertRange::AreEqual({ plus }, tokens);     }      TEST_METHOD(Should_tokenize_single_digit) {         Tokens tokens = Lexer::Tokenize(L&quot;1&quot;);         AssertRange::AreEqual({ _1 }, tokens);     }      TEST_METHOD(Should_tokenize_floating_point_number) {         Tokens tokens = Lexer::Tokenize(L&quot;12.34&quot;);         AssertRange::AreEqual({ 12.34 }, tokens);     }      TEST_METHOD(Should_tokenize_plus_and_number) {         Tokens tokens = Lexer::Tokenize(L&quot;+12.34&quot;);         AssertRange::AreEqual({ plus, Token(12.34) }, tokens);     }      TEST_METHOD(Should_skip_spaces) {         Tokens tokens = Lexer::Tokenize(L&quot; 1 +  12.34  &quot;);         AssertRange::AreEqual({ _1, plus, Token(12.34) }, tokens);     }      TEST_METHOD(Should_tokenize_complex_experssion) {         Tokens tokens = Lexer::Tokenize(L&quot;1+2*3\/(4-5)&quot;);         AssertRange::AreEqual({ _1, plus, _2, mul, _3, div, pLeft, _4, minus, _5, pRight }, tokens);     } };   TEST_CLASS(TokenTests) { public:     TEST_METHOD(Should_check_for_equality_operator_tokens) {         Assert::AreEqual(minus, minus);         Assert::AreNotEqual(minus, plus);         Assert::AreNotEqual(minus, _1);     }      TEST_METHOD(Should_check_for_equality_number_tokens) {         Assert::AreEqual(_1, _1);         Assert::AreNotEqual(_1, _2);         Assert::AreNotEqual(_1, minus);     }      TEST_METHOD(Should_get_operator_code_from_operator_token) {         Token token(Operator::Plus);         Assert::AreEqual&lt;Operator&gt;(Operator::Plus, token);     }      TEST_METHOD(Should_get_number_value_from_number_token) {         Token token(1.23);         Assert::AreEqual&lt;double&gt;(1.23, token);     } };   TEST_CLASS(ParserTests) { public:     TEST_METHOD(Should_return_empty_list_when_put_empty_list) {         Tokens tokens = Parser::Parse({});         Assert::IsTrue(tokens.empty());     }      TEST_METHOD(Should_parse_single_number) {         Tokens tokens = Parser::Parse({ _1 });         AssertRange::AreEqual({ _1 }, tokens);     }      TEST_METHOD(Should_parse_num_plus_num) {         Tokens tokens = Parser::Parse({ _1, plus, _2 });         AssertRange::AreEqual({ _1, _2, plus }, tokens);     }      TEST_METHOD(Should_parse_two_additions) {         Tokens tokens = Parser::Parse({ _1, plus, _2, plus, _3 });         AssertRange::AreEqual({ _1, _2, plus, _3, plus }, tokens);     }      TEST_METHOD(Should_get_same_precedence_for_operator_pairs) {         Assert::AreEqual(Parser::PrecedenceOf(Operator::Plus), Parser::PrecedenceOf(Operator::Minus));         Assert::AreEqual(Parser::PrecedenceOf(Operator::Mul), Parser::PrecedenceOf(Operator::Div));     }      TEST_METHOD(Should_get_greater_precedence_for_multiplicative_operators) {         Assert::IsTrue(Parser::PrecedenceOf(Operator::Mul) &gt; Parser::PrecedenceOf(Operator::Plus));     }      TEST_METHOD(Should_parse_add_and_mul) {         Tokens tokens = Parser::Parse({ _1, plus, _2, mul, _3 });         AssertRange::AreEqual({ _1, _2, _3, mul, plus }, tokens);     }      TEST_METHOD(Should_parse_complex_experssion) {         Tokens tokens = Parser::Parse({ _1, plus, _2, div, _3, minus, _4, mul, _5 });         AssertRange::AreEqual({ _1, _2, _3, div, plus, _4, _5, mul, minus }, tokens);     }      TEST_METHOD(Should_skip_parens_around_number) {         Tokens tokens = Parser::Parse({ pLeft, _1, pRight });         AssertRange::AreEqual({ _1 }, tokens);     }      TEST_METHOD(Should_parse_expression_with_parens_in_beginning) {         Tokens tokens = Parser::Parse({ pLeft, _1, plus, _2, pRight, mul, _3 });         AssertRange::AreEqual({ _1, _2, plus, _3, mul }, tokens);     }      TEST_METHOD(Should_throw_when_opening_paren_not_found) {         Assert::ExpectException&lt;std::logic_error&gt;([]() {Parser::Parse({ _1, pRight }); });     }      TEST_METHOD(Should_throw_when_closing_paren_not_found) {         Assert::ExpectException&lt;std::logic_error&gt;([]() {Parser::Parse({ pLeft, _1 }); });     }      TEST_METHOD(Should_parse_complex_experssion_with_paren) {         \/\/ (1+2)*(3\/(4-5)) = 1 2 + 3 4 5 - \/ *         Tokens tokens = Parser::Parse({ pLeft, _1, plus, _2, pRight, mul, pLeft, _3, div, pLeft, _4, minus, _5, pRight, pRight });         AssertRange::AreEqual({ _1, _2, plus, _3, _4, _5, minus, div, mul }, tokens);     } };   TEST_CLASS(EvaluatorTests) { public:     TEST_METHOD(Should_return_zero_when_evaluate_empty_list) {         double result = Evaluator::Evaluate({});         Assert::AreEqual(0.0, result);     }      TEST_METHOD(Should_return_number_when_evaluate_list_with_number) {         double result = Evaluator::Evaluate({ _1 });         Assert::AreEqual(1.0, result);     }      TEST_METHOD(Should_eval_expression_with_one_operator) {         double result = Evaluator::Evaluate({ _1, _2, plus });         Assert::AreEqual(3.0, result);     }      TEST_METHOD(Should_eval_expression_with_one_multiplication) {         double result = Evaluator::Evaluate({ _2, _3, mul });         Assert::AreEqual(6.0, result);     }      TEST_METHOD(Should_eval_expression_with_one_subtraction) {         double result = Evaluator::Evaluate({ _2, _3, minus });         Assert::AreEqual(-1.0, result);     }      TEST_METHOD(Should_eval_expression_with_one_division) {         double result = Evaluator::Evaluate({ _5, _2, div });         Assert::AreEqual(2.5, result);     }      TEST_METHOD(Should_eval_complex_expression) {         \/\/ (4+1)*2\/(4\/(3-1)) = 4 1 + 2 * 4 3 1 - \/ \/  = 5         double result = Evaluator::Evaluate({ _4, _1, plus, _2, mul, _4, _3, _1, minus, div, div });         Assert::AreEqual(5.0, result);     } };   TEST_CLASS(InterpreterIntegrationTests) { public:     TEST_METHOD(Should_interprete_empty_experssion) {         double result = Interpreter::InterpreteExperssion(L&quot;  &quot;);         Assert::AreEqual(0.0, result);     }      TEST_METHOD(Should_interprete_experssion) {         double result = Interpreter::InterpreteExperssion(L&quot;1+2&quot;);         Assert::AreEqual(3.0, result);     } };  } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <a href=\"https:\/\/github.com\/Unril\/InterpreterTDD\">\u041a\u043e\u0434 \u043a \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0430 GitHub<\/a>. \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043c\u043c\u0438\u0442\u043e\u0432 \u0438 \u0438\u0445 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0442\u0435\u0441\u0442\u0430\u043c \u0438 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430\u043c, \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u043c \u0432\u044b\u0448\u0435.<\/p>\n<p>  \u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043e\u0447\u043d\u043e\u0439 \u0441\u0442\u0430\u043d\u0446\u0438\u0438 \u043d\u0430 <a href=\"http:\/\/wcipeg.com\/wiki\/Shunting_yard_algorithm\"> PEGWiki<\/a>.<\/p>\n<p>  \u0421\u043e\u0432\u0435\u0442\u0443\u044e \u043a \u043f\u0440\u043e\u0447\u0442\u0435\u043d\u0438\u044e \u043a\u043d\u0438\u0433\u0443 Jeff Langr. Modern C++ Programming with Test-Driven Development. \u2014 The Pragmatic Programmers, 2013.      \t<\/p>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/232097\/\"> http:\/\/habrahabr.ru\/post\/232097\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\">     \t\u0412 <a href=\"http:\/\/habrahabr.ru\/post\/231657\/\">\u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0431\u044b\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043b\u0435\u043a\u0441\u0435\u0440<\/a>, \u0430 \u0432\u043e <a href=\"http:\/\/habrahabr.ru\/post\/232081\/\">\u0432\u0442\u043e\u0440\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u2014 \u043f\u0430\u0440\u0441\u0435\u0440<\/a>. \u0414\u0430\u043b\u0435\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044f \u0438 \u0444\u0430\u0441\u0430\u0434\u0430 \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u0432\u0441\u0435\u0433\u043e \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0443\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<h4> \u0412\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c<\/h4>\n<p>  \u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c\u0443. \u0412\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u043f\u043e\u0441\u0442\u0444\u0438\u043a\u0441\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u044c \u0434\u0432\u0443\u043c\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438: \u0447\u0435\u0440\u0435\u0437 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e, \u043d\u0435\u044f\u0432\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0441\u0442\u0435\u043a \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430, \u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u044f\u0432\u043d\u044b\u0439 \u0441\u0442\u0435\u043a. \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0432\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442. \u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u044f\u0432\u043d\u043e\u0433\u043e \u0441\u0442\u0435\u043a\u0430 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<ul>\n<li> \u0415\u0441\u043b\u0438 \u043d\u0430 \u0432\u0445\u043e\u0434 \u043f\u043e\u0434\u0430\u043d \u043e\u043f\u0435\u0440\u0430\u043d\u0434, \u043e\u043d \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0432\u0435\u0440\u0448\u0438\u043d\u0443 \u0441\u0442\u0435\u043a\u0430. <\/li>\n<li> \u0415\u0441\u043b\u0438 \u043d\u0430 \u0432\u0445\u043e\u0434 \u043f\u043e\u0434\u0430\u043d \u0437\u043d\u0430\u043a \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438, \u0442\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0434 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439, \u0438\u0437\u0432\u043b\u0435\u0447\u0451\u043d\u043d\u044b\u0445 \u0438\u0437 \u0441\u0442\u0435\u043a\u0430, \u0432\u0437\u044f\u0442\u044b\u0445 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043b\u0430\u0434\u0451\u0442\u0441\u044f \u043d\u0430 \u0432\u0435\u0440\u0448\u0438\u043d\u0443 \u0441\u0442\u0435\u043a\u0430. <\/li>\n<li> \u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043b\u0435\u0436\u0438\u0442 \u043d\u0430 \u0432\u0435\u0440\u0448\u0438\u043d\u0435 \u0441\u0442\u0435\u043a\u0430. <\/li>\n<\/ul>\n<p>  \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u043c:<\/p>\n<ul>\n<li> \u0415\u0441\u043b\u0438 \u043d\u0430 \u0432\u0445\u043e\u0434\u0435 \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u043f\u0438\u0441\u043e\u043a, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c 0. <\/li>\n<li> \u0415\u0441\u043b\u0438 \u043d\u0430 \u0432\u0445\u043e\u0434\u0435 \u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u043e\u0434\u043d\u0438\u043c \u0447\u0438\u0441\u043b\u043e\u043c, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u044d\u0442\u043e \u0447\u0438\u0441\u043b\u043e. <\/li>\n<li> \u0415\u0441\u043b\u0438 \u043d\u0430 \u0432\u0445\u043e\u0434\u0435 [1 2 +], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c 3. <\/li>\n<\/ul>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u0442\u0435\u0441\u0442.<\/p>\n<pre><code class=\"cpp\">TEST_CLASS(EvaluatorTests) { public:     TEST_METHOD(Should_return_zero_when_evaluate_empty_list) {         double result = Evaluator::Evaluate({});         Assert::AreEqual(0.0, result);     } }; <\/code><\/pre>\n<p>  <\/p>\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-232097","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/232097","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=232097"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/232097\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=232097"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=232097"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=232097"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}