{"id":232081,"date":"2014-08-04T17:38:03","date_gmt":"2014-08-04T13:38:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=232081"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=232081","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 2<\/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>. \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 \u043f\u0430\u0440\u0441\u0435\u0440\u0430.<\/p>\n<h4> \u041f\u0430\u0440\u0441\u0435\u0440<\/h4>\n<p>  \u041f\u0430\u0440\u0441\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u043f\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0443 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043e\u0447\u043d\u043e\u0439 \u0441\u0442\u0430\u043d\u0446\u0438\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442 \u0438 \u043d\u0435 \u043d\u0443\u0436\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438. \u0421\u0430\u043c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0442\u0430\u043a\u043e\u0432:<\/p>\n<p>  \u0412 \u043d\u0430\u0447\u0430\u043b\u0435 \u0434\u0430\u044e\u0442\u0441\u044f \u043f\u0443\u0441\u0442\u043e\u0439 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0438 \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u0442\u0435\u043a. \u041d\u0430\u0447\u043d\u0451\u043c \u0447\u0438\u0442\u0430\u0442\u044c \u0442\u043e\u043a\u0435\u043d\u044b \u0438\u0437 \u0432\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430 \u043f\u043e \u043e\u0447\u0435\u0440\u0435\u0434\u0438.<\/p>\n<ul>\n<li> \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u0447\u0438\u0441\u043b\u043e, \u0442\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a. <\/li>\n<li> \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043b\u0435\u0432\u043e \u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440, \u0442\u043e \u0432\u044b\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d\u044b \u0438\u0437 \u0441\u0442\u0435\u043a\u0430 \u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 \u043e\u043d \u043d\u0435 \u043e\u043f\u0443\u0441\u0442\u0435\u0435\u0442, \u043b\u0438\u0431\u043e \u043d\u0435 \u0435\u0433\u043e \u0432\u0435\u0440\u0448\u0438\u043d\u0435 \u043d\u0435 \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u0442\u0441\u044f \u0441\u043a\u043e\u0431\u043a\u0430, \u0438\u043b\u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u0441 \u0431\u043e\u043b\u0435\u0435 \u043d\u0438\u0437\u043a\u0438\u043c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c. <\/li>\n<li> \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u0441\u043a\u043e\u0431\u043a\u0430, \u0442\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0435\u0451 \u0432 \u0441\u0442\u0435\u043a. <\/li>\n<li> \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u0441\u043a\u043e\u0431\u043a\u0430, \u0442\u043e \u0432\u044b\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d\u044b \u0438\u0437 \u0441\u0442\u0435\u043a\u0430 \u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0434\u043e \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u0439 \u0441\u043a\u043e\u0431\u043a\u0438. \u0412\u044b\u0442\u043e\u043b\u043a\u043d\u0443\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0443\u044e \u0441\u043a\u043e\u0431\u043a\u0443 \u0438\u0437 \u0441\u0442\u0435\u043a\u0430, \u043d\u043e \u043d\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0435\u0451 \u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a. \u0415\u0441\u043b\u0438 \u0441\u0442\u0435\u043a \u043e\u043f\u0443\u0441\u0442\u0435\u043b, \u0438 \u0441\u043a\u043e\u0431\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430, \u0442\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443. <\/li>\n<\/ul>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0446\u0430 \u0432\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430, \u0432\u044b\u0442\u043e\u043b\u043a\u043d\u0443\u0442\u044c \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u0432 \u0441\u0442\u0435\u043a\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a. \u0415\u0441\u043b\u0438 \u0432 \u043d\u0451\u043c \u043d\u0430\u0439\u0434\u0435\u043d\u043e \u0447\u0442\u043e-\u043b\u0438\u0431\u043e \u043a\u0440\u043e\u043c\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432, \u0442\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443.<\/p>\n<p>  \u041f\u0440\u0438\u043a\u0438\u043d\u0435\u043c, \u043a\u0430\u043a\u0438\u0435 \u0442\u0435\u0441\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430.<\/p>\n<ul>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043f\u0443\u0441\u0442\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u043f\u0438\u0441\u043e\u043a. <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0441\u043f\u0438\u0441\u043a\u0430 \u0441 \u043e\u0434\u043d\u0438\u043c \u0447\u0438\u0441\u043b\u043e\u043c, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u044d\u0442\u0438\u043c \u0447\u0438\u0441\u043b\u043e\u043c. <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [1 + 2], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f [1 2 +]. <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [1 + 2 + 3], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f [1 2 + 3 +], \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 + \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0435\u0432\u043e \u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0442\u0438\u0432\u043d\u044b\u043c. <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [1 * 2 + 3], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f [1 2 * 3 +]. <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [1 + 2 * 3], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f [1 2 3 * +], \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 * \u0438\u043c\u0435\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0438\u0439 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442. <\/li>\n<\/ul>\n<p>  \u0421\u043e \u0441\u043a\u043e\u0431\u043a\u0430\u043c\u0438 \u0438 \u043e\u0448\u0438\u0431\u043a\u0430\u043c\u0438 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f \u043f\u043e\u0437\u0434\u043d\u0435\u0435. \u0418\u0442\u0430\u043a, \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u0442\u0435\u0441\u0442 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430.<\/p>\n<pre><code class=\"cpp\">TEST_CLASS(ParserTests) { public:     TEST_METHOD(Should_return_empty_list_when_put_empty_list) {         Tokens tokens = Parser::Parse({});         Assert::IsTrue(tokens.empty());     } }; <\/code><\/pre>\n<p>  <a name=\"habracut\"><\/a><br \/>  \u041a\u0430\u043a \u0438 \u0432 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437, \u043f\u0430\u0440\u0441\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u0431\u043e\u0439 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0432 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435 \u0438\u043c\u0451\u043d <code>Parser<\/code>.<\/p>\n<pre><code class=\"cpp\">namespace Parser { inline Tokens Parse(const Tokens &) { throw std::exception(); } } \/\/ namespace Parser <\/code><\/pre>\n<p>  \u0417\u0430\u0441\u0442\u0430\u0432\u0438\u043c \u0442\u0435\u0441\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0432 ({} \u2192 nil). <\/p>\n<pre><code class=\"cpp\">inline Tokens Parse(const Tokens &) {     return{}; } <\/code><\/pre>\n<p>  \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0442\u0435\u0441\u0442 \u043f\u043e\u0447\u0442\u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u0435\u043d \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443.<\/p>\n<pre><code class=\"cpp\">    TEST_METHOD(Should_parse_single_number) {         Tokens tokens = Parser::Parse({ Token(1) });         AssertRange::AreEqual({ Token(1) }, tokens);     } <\/code><\/pre>\n<p>  \u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0432 (constant \u2192 scalar) \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f \u0438 \u0441 \u043d\u0438\u043c.<\/p>\n<pre><code class=\"cpp\">inline Tokens Parse(const Tokens &tokens) {     return tokens; } <\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li> <s>\u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043f\u0443\u0441\u0442\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u043f\u0438\u0441\u043e\u043a. <\/s> <\/li>\n<li> <s>\u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0441\u043f\u0438\u0441\u043a\u0430 \u0441 \u043e\u0434\u043d\u0438\u043c \u0447\u0438\u0441\u043b\u043e\u043c, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u044d\u0442\u0438\u043c \u0447\u0438\u0441\u043b\u043e\u043c. <\/s> <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [1 + 2], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f [1 2 +]. <\/li>\n<li> \u2026 <\/li>\n<\/ul>\n<p>  \u0414\u0430\u043b\u044c\u0448\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u043a\u0435\u043d\u043e\u0432.<\/p>\n<pre><code class=\"cpp\">    TEST_METHOD(Should_parse_num_plus_num) {         Tokens tokens = Parser::Parse({ Token(1), Token(Operator::Plus), Token(2) });         AssertRange::AreEqual({ Token(1), Token(2), Token(Operator::Plus) }, tokens);     } <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043b\u0435\u0433\u043a\u0430 \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>Parse<\/code> \u043d\u0435 \u043d\u0430\u0440\u0443\u0448\u0430\u044f \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0442\u0435\u0441\u0442\u044b. <\/p>\n<pre><code class=\"cpp\">inline Tokens Parse(const Tokens &tokens) {     Tokens output;     for(const Token &token : tokens) {         output.push_back(token);     }     return output; } <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043b\u0435\u0433\u043a\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u0435\u043a \u0434\u043b\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0438 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0442\u0435\u0441\u0442.<\/p>\n<pre><code class=\"cpp\">inline Tokens Parse(const Tokens &tokens) {     Tokens output;     Tokens stack;     for(const Token &token : tokens) {         if(token.Type() == TokenType::Number) {             output.push_back(token);         }         else {             stack.push_back(token);         }     }     std::copy(stack.crbegin(), stack.crend(), std::back_inserter(output));     return output; } <\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li> <s>\u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [1 + 2], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f [1 2 +]. <\/s> <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [1 + 2 + 3], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f [1 2 + 3 +], \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 + \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0435\u0432\u043e \u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0442\u0438\u0432\u043d\u044b\u043c. <\/li>\n<li> \u2026 <\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"cpp\">    TEST_METHOD(Should_parse_two_additions) {         Tokens tokens = Parser::Parse({ Token(1), Token(Operator::Plus), Token(2), Token(Operator::Plus), Token(3) });         AssertRange::AreEqual({ Token(1), Token(2), Token(Operator::Plus), Token(3), Token(Operator::Plus) }, tokens);     } <\/code><\/pre>\n<p>  \u0422\u0435\u0441\u0442 \u043d\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442, \u0442\u0430\u043a \u043a\u0430\u043a \u0432\u0441\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0446\u0435 \u0441\u043f\u0438\u0441\u043a\u0430. \u0411\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u043a\u0438\u0434\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0451 \u0438\u0437 \u0441\u0442\u0435\u043a\u0430 \u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430.<\/p>\n<pre><code class=\"cpp\">inline Tokens Parse(const Tokens &tokens) {     Tokens output, stack;     auto popAll = [&]() { while(!stack.empty()) {         output.push_back(stack.back());         stack.pop_back();     }};     for(const Token &token : tokens) {         if(token.Type() == TokenType::Operator) {             popAll();             stack.push_back(token);             continue;         }         output.push_back(token);     }     popAll();     return output; } <\/code><\/pre>\n<p>  \u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f \u0441 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0442\u0435\u0441\u0442 \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0432 \u043d\u0435\u0451 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430.<\/p>\n<ul>\n<li> <s>\u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [1 + 2 + 3], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f [1 2 + 3 +], \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 + \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0435\u0432\u043e \u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0442\u0438\u0432\u043d\u044b\u043c. <\/s> <\/li>\n<li> \u041f\u0430\u0440\u044b \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 +- \u0438 *\/ \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u043c\u0435\u0442\u044c \u0440\u0430\u0432\u043d\u044b\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u044b. <\/li>\n<li> \u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 + \u0438 \u2014 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043c\u0435\u043d\u044c\u0448\u0435, \u0447\u0435\u043c \u0443 * \u0438 \/<\/li>\n<li> \u2026 <\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"cpp\">    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));     } <\/code><\/pre>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0435\u0442\u043e\u0434 PrecedenceOf \u0432 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u0438\u043c\u0451\u043d Parser \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c ({} \u2192 nil).<\/p>\n<pre><code class=\"cpp\">inline int PrecedenceOf(Operator) { return 0; } <\/code><\/pre>\n<p>  \u0422\u0435\u0441\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442, \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443.<\/p>\n<pre><code class=\"cpp\">    TEST_METHOD(Should_get_greater_precedence_for_multiplicative_operators) {         Assert::IsTrue(Parser::PrecedenceOf(Operator::Mul) &gt; Parser::PrecedenceOf(Operator::Plus));     } <\/code><\/pre>\n<p>  \u041f\u0440\u0438\u043c\u0435\u043d\u0438\u043c (unconditional \u2192 if).<\/p>\n<pre><code class=\"cpp\">inline int PrecedenceOf(Operator op) {     return (op == Operator::Mul || op == Operator::Div) ? 1 : 0; } <\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li> <s>\u041f\u0430\u0440\u044b \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 +- \u0438 *\/ \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u043c\u0435\u0442\u044c \u0440\u0430\u0432\u043d\u044b\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u044b. <\/s> <\/li>\n<li> <s>\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 + \u0438 \u2014 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043c\u0435\u043d\u044c\u0448\u0435, \u0447\u0435\u043c \u0443 * \u0438 \/<\/s> <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [1 * 2 + 3], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f [1 2 * 3 +]. <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [1 + 2 * 3], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f [1 2 3 * +], \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 * \u0438\u043c\u0435\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0438\u0439 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442. <\/li>\n<\/ul>\n<p>  \u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0442\u0435\u0441\u0442\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u043c.<\/p>\n<pre><code class=\"cpp\">    TEST_METHOD(Should_parse_add_and_mul) {         Tokens tokens = Parser::Parse({ Token(1), Token(Operator::Plus), Token(2), Token(Operator::Mul), Token(3) });         AssertRange::AreEqual({ Token(1), Token(2), Token(3), Token(Operator::Mul), Token(Operator::Plus) }, tokens);     } <\/code><\/pre>\n<p>  \u041e\u043d \u043d\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0430\u0440\u0441\u0435\u0440 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0442\u044c \u0438\u0437 \u0441\u0442\u0435\u043a\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0441 \u043c\u0435\u043d\u044c\u0448\u0438\u043c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043b\u044f\u043c\u0431\u0434\u0443, \u0432\u044b\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u044e\u0449\u0443\u044e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0438\u0437 \u0441\u0442\u0435\u043a\u0430, \u043f\u0440\u0435\u0434\u0438\u043a\u0430\u0442, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0438\u0439, \u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f.<\/p>\n<pre><code class=\"cpp\">inline Tokens Parse(const Tokens &tokens) {     Tokens output, stack;     auto popToOutput = [&output, &stack](auto whenToEnd) {         while(!stack.empty() && !whenToEnd(stack.back())) {             output.push_back(stack.back());             stack.pop_back();         }};     for(const Token &current : tokens) {         if(current.Type() == TokenType::Operator) {             popToOutput([&](Operator top) { return PrecedenceOf(top) &lt; PrecedenceOf(current); });             stack.push_back(current);             continue;         }         output.push_back(current);     }     popToOutput([](auto) { return false; });     return output; } <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0442\u0435\u0441\u0442, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0435\u0433\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u0438\u0432. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u0438.<\/p>\n<pre><code class=\"cpp\">    TEST_METHOD(Should_parse_complex_experssion) {         \/\/ 1 + 2 \/ 3 - 4 * 5 = 1 2 3 \/ + 4 5 * -         Tokens tokens = Parser::Parse({             Token(1), Token(Operator::Plus), Token(2), Token(Operator::Div), Token(3),             Token(Operator::Minus), Token(4), Token(Operator::Mul), Token(5)         });         AssertRange::AreEqual({             Token(1), Token(2), Token(3), Token(Operator::Div), Token(Operator::Plus),             Token(4), Token(5), Token(Operator::Mul), Token(Operator::Minus)         }, tokens);     } <\/code><\/pre>\n<p>  \u041e\u043d \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442. \u041f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u0435\u0437 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u0430\u043a\u043e\u0433\u043e-\u043b\u0438\u0431\u043e \u043a\u043e\u0434\u0430, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u043c\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u043e\u0439, \u043d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0442\u044b \u043d\u0435 \u0443\u0432\u0435\u0440\u0435\u043d \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e. \u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>Parse<\/code>, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u0430\u044f \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u043c \u0441\u0442\u0438\u043b\u0435, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043a\u043e\u0440\u043e\u0442\u043a\u0430 \u0438 \u043b\u0430\u043a\u043e\u043d\u0438\u0447\u043d\u0430, \u043d\u043e \u043f\u043b\u043e\u0445\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u0430. \u041a\u0430\u043a \u0438 \u0432 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437, \u0432\u044b\u0434\u0435\u043b\u0438\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0432 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u0438\u043c\u0451\u043d <code>Detail<\/code> \u0438 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0451\u043c \u0432 \u043d\u0435\u0433\u043e \u0432\u0441\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043f\u0430\u0440\u0441\u0435\u0440\u0430, \u043e\u0441\u0442\u0430\u0432\u0438\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>Parse<\/code> \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0444\u0430\u0441\u0430\u0434\u0430. \u041f\u0440\u043e\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043b\u0435\u0433\u043a\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u043e\u044f\u0442\u044c\u0441\u044f \u0447\u0442\u043e-\u043b\u0438\u0431\u043e \u0441\u043b\u043e\u043c\u0430\u0442\u044c.<\/p>\n<pre><code class=\"cpp\">inline Tokens Parse(const Tokens &tokens) {     Detail::ShuntingYardParser parser(tokens);     parser.Parse();     return parser.Result(); } <\/code><\/pre>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043b\u0430\u0441\u0441 Detail::ShuntingYardParser<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">namespace Detail {  class ShuntingYardParser { public:     ShuntingYardParser(const Tokens &tokens) : m_current(tokens.cbegin()), m_end(tokens.cend()) {}      void Parse() {         for(; m_current != m_end; ++m_current) {             ParseCurrentToken();         }         PopToOutputUntil(StackIsEmpty);     }      const Tokens &Result() const { return m_output; }  private:     static bool StackIsEmpty() { return false; }      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;);         }     }      void ParseOperator() {         PopToOutputUntil([this]() { return PrecedenceOf(m_stack.back()) &lt; PrecedenceOf(*m_current); });         m_stack.push_back(*m_current);     }      void ParseNumber() {         m_output.push_back(*m_current);     }      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::const_iterator m_current;     Tokens::const_iterator m_end;     Tokens m_output;     Tokens m_stack; };  } \/\/ namespace Detail <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0441\u043a\u043e\u0431\u043e\u043a. \u0421\u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u0435\u0441\u0442\u043e\u0432, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<ul>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [(1)], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f [1]. <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [(1 + 2) * 3], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f [1 2 + 3 *]. <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [1)], \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435. <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [(1], \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435. <\/li>\n<\/ul>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u0442\u0435\u0441\u0442.<\/p>\n<pre><code class=\"cpp\">    TEST_METHOD(Should_skip_paren_around_number) {         Tokens tokens = Parser::Parse({ Token(Operator::LParen), Token(1), Token(Operator::RParen) });         AssertRange::AreEqual({ Token(1) }, tokens);     } <\/code><\/pre>\n<p>  \u0422\u0430\u043a \u043a\u0430\u043a \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u044b \u043d\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u043c \u0441\u043a\u043e\u0431\u043a\u0438 \u043e\u0442 \u0434\u0440\u0443\u0433\u0438\u0445 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432, \u0442\u043e \u043e\u043d \u043d\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442. \u0412\u043d\u0435\u0441\u0451\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 (unconditional \u2192 if) \u0432 \u043c\u0435\u0442\u043e\u0434 <code>ParseOperator<\/code>.<\/p>\n<pre><code class=\"cpp\">    void ParseOperator() {         const Operator currOp = *m_current;         switch(currOp) {             case Operator::LParen:                 break;             case Operator::RParen:                 break;             default:                 PopToOutputUntil([&]() { return PrecedenceOf(m_stack.back()) &lt; PrecedenceOf(currOp); });                 m_stack.push_back(*m_current);                 break;         }     } <\/code><\/pre>\n<p>  \u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0442\u0435\u0441\u0442, \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0442\u0435\u0441\u0442\u043e\u0432. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0434\u043b\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0447\u0438\u0441\u0435\u043b. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u0434\u0430 \u0432 \u0442\u0435\u0441\u0442\u0430\u0445.<\/p>\n<pre><code class=\"cpp\">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); <\/code><\/pre>\n<p>  \u0412 \u0438\u0442\u043e\u0433\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0442\u0435\u0441\u0442 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u0435\u0435 \u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0435.<\/p>\n<pre><code class=\"cpp\">    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);     } <\/code><\/pre>\n<p>  \u0418\u0437\u043c\u0435\u043d\u0438\u043c \u043c\u0435\u0442\u043e\u0434 <code>ParseOperator<\/code> \u043a\u043b\u0430\u0441\u0441\u0430 <code>ShuntingYardParser<\/code> \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u043b \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u043c\u0443 \u0432\u044b\u0448\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0443.<\/p>\n<pre><code class=\"cpp\">    void ParseOperator() {         switch(*m_current) {             case Operator::LParen:                 m_stack.push_back(*m_current);                 break;             case Operator::RParen:                 PopToOutputUntil([this]() { return LeftParenOnTop(); });                 m_stack.pop_back();                 break;             default:                 PopToOutputUntil([this]() { return LeftParenOnTop() || OperatorWithLessPrecedenceOnTop(); });                 m_stack.push_back(*m_current);                 break;         }     }      bool OperatorWithLessPrecedenceOnTop() const {         return PrecedenceOf(m_stack.back()) &lt; PrecedenceOf(*m_current);     }      bool LeftParenOnTop() const {         return static_cast&lt;Operator&gt;(m_stack.back()) == Operator::LParen;     } <\/code><\/pre>\n<p>  \u0423 \u043d\u0430\u0441 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043a\u0430\u043a\u0430\u044f-\u043b\u0438\u0431\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0445 \u0441\u043a\u043e\u0431\u043e\u043a \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u043c. \u0414\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439, \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <code>Assert<\/code> \u0435\u0441\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 <code>ExpectException<\/code>, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0439 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0442\u0438\u043f \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e.<\/p>\n<pre><code class=\"cpp\">    TEST_METHOD(Should_throw_when_opening_paren_not_found) {         Assert::ExpectException&lt;std::logic_error&gt;([]() {Parser::Parse({ _1, pRight }); });     } <\/code><\/pre>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0441\u043a\u043e\u0431\u043a\u0438 \u043f\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u0439 \u0441\u043a\u043e\u0431\u043a\u0438.<\/p>\n<pre><code class=\"cpp\">            \u2026             case Operator::RParen:                 PopToOutputUntil([this]() { return LeftParenOnTop(); });                 if(m_stack.empty() || m_stack.back() != Operator::LParen) {                     throw std::logic_error(&quot;Opening paren not found.&quot;);                 }                 m_stack.pop_back();                 break; <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0442\u0435\u0441\u0442 \u043d\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u0439 \u0441\u043a\u043e\u0431\u043a\u0438.<\/p>\n<pre><code class=\"cpp\">    TEST_METHOD(Should_throw_when_closing_paren_not_found) {         Assert::ExpectException&lt;std::logic_error&gt;([]() {Parser::Parse({ pLeft, _1 }); });     } <\/code><\/pre>\n<p>  \u0414\u0430\u043d\u043d\u0443\u044e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u043e \u043d\u0430\u043b\u0438\u0447\u0438\u044e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0441\u043a\u043e\u0431\u043a\u0438 \u0432 \u0441\u0442\u0435\u043a\u0438 \u043d\u0430 \u043a\u043e\u043d\u0435\u0446 \u0440\u0430\u0437\u0431\u043e\u0440\u0430.<\/p>\n<pre><code class=\"cpp\">    void Parse() {         for(; m_current != m_end; ++m_current) {             ParseCurrentToken();         }         PopToOutputUntil([this]() {             if(m_stack.back() == Token(Operator::LParen)) {                 throw std::logic_error(&quot;Closing paren not found.&quot;);             }             return false;         });     } <\/code><\/pre>\n<p>  \u0418\u0442\u0430\u043a, \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u044b \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a\u043e\u0434 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <code>ShuntingYardParser<\/code> \u0432 \u043f\u043e\u0440\u044f\u0434\u043e\u043a.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043b\u0430\u0441\u0441 ShuntingYardParser \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 ShuntingYardParser { public:     ShuntingYardParser(const Tokens &tokens) : m_current(tokens.cbegin()), m_end(tokens.cend()) {}      void Parse() {         for(; m_current != m_end; ++m_current) {             ParseCurrentToken();         }         PopToOutputUntil([this]() {return StackHasNoOperators(); });     }      const Tokens &Result() const { return m_output; }  private:     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;);         }     }      bool StackHasNoOperators() const {         if(m_stack.back() == Token(Operator::LParen)) {             throw std::logic_error(&quot;Closing paren not found.&quot;);         }         return false;     }      void ParseOperator() {         switch(*m_current) {             case Operator::LParen:                 PushCurrentToStack();                 break;             case Operator::RParen:                 PopToOutputUntil([this]() { return LeftParenOnTop(); });                 PopLeftParen();                 break;             default:                 PopToOutputUntil([this]() { return LeftParenOnTop() || OperatorWithLessPrecedenceOnTop(); });                 PushCurrentToStack();                 break;         }     }      void PushCurrentToStack() {         return m_stack.push_back(*m_current);     }      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() const {         return PrecedenceOf(m_stack.back()) &lt; PrecedenceOf(*m_current);     }      bool LeftParenOnTop() const {         return static_cast&lt;Operator&gt;(m_stack.back()) == Operator::LParen;     }      void ParseNumber() {         m_output.push_back(*m_current);     }      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::const_iterator m_current, m_end;     Tokens m_output, m_stack; }; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0414\u043b\u044f \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0435\u0441\u0442 \u043d\u0430 \u0440\u0430\u0437\u0431\u043e\u0440 \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_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);     } <\/code><\/pre>\n<p>  \u041e\u043d \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442, \u0447\u0442\u043e \u0438 \u0431\u044b\u043b\u043e \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e.<\/p>\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. \u041e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044e \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043a\u043e\u043c\u043c\u0438\u0442 \u00abParserTests Should_parse_complex_experssion_with_paren\u00bb.<\/p>\n<p>  \u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0447\u0430\u0441\u0442\u0438 \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.      \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\/232081\/\"> http:\/\/habrahabr.ru\/post\/232081\/<\/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>. \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 \u043f\u0430\u0440\u0441\u0435\u0440\u0430.<\/p>\n<h4> \u041f\u0430\u0440\u0441\u0435\u0440<\/h4>\n<p>  \u041f\u0430\u0440\u0441\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u043f\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0443 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043e\u0447\u043d\u043e\u0439 \u0441\u0442\u0430\u043d\u0446\u0438\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442 \u0438 \u043d\u0435 \u043d\u0443\u0436\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0438. \u0421\u0430\u043c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0442\u0430\u043a\u043e\u0432:<\/p>\n<p>  \u0412 \u043d\u0430\u0447\u0430\u043b\u0435 \u0434\u0430\u044e\u0442\u0441\u044f \u043f\u0443\u0441\u0442\u043e\u0439 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0438 \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u0442\u0435\u043a. \u041d\u0430\u0447\u043d\u0451\u043c \u0447\u0438\u0442\u0430\u0442\u044c \u0442\u043e\u043a\u0435\u043d\u044b \u0438\u0437 \u0432\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430 \u043f\u043e \u043e\u0447\u0435\u0440\u0435\u0434\u0438.<\/p>\n<ul>\n<li> \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u0447\u0438\u0441\u043b\u043e, \u0442\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a. <\/li>\n<li> \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043b\u0435\u0432\u043e \u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440, \u0442\u043e \u0432\u044b\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d\u044b \u0438\u0437 \u0441\u0442\u0435\u043a\u0430 \u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 \u043e\u043d \u043d\u0435 \u043e\u043f\u0443\u0441\u0442\u0435\u0435\u0442, \u043b\u0438\u0431\u043e \u043d\u0435 \u0435\u0433\u043e \u0432\u0435\u0440\u0448\u0438\u043d\u0435 \u043d\u0435 \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u0442\u0441\u044f \u0441\u043a\u043e\u0431\u043a\u0430, \u0438\u043b\u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u0441 \u0431\u043e\u043b\u0435\u0435 \u043d\u0438\u0437\u043a\u0438\u043c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c. <\/li>\n<li> \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u0441\u043a\u043e\u0431\u043a\u0430, \u0442\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0435\u0451 \u0432 \u0441\u0442\u0435\u043a. <\/li>\n<li> \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u0441\u043a\u043e\u0431\u043a\u0430, \u0442\u043e \u0432\u044b\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d\u044b \u0438\u0437 \u0441\u0442\u0435\u043a\u0430 \u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0434\u043e \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u0439 \u0441\u043a\u043e\u0431\u043a\u0438. \u0412\u044b\u0442\u043e\u043b\u043a\u043d\u0443\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0443\u044e \u0441\u043a\u043e\u0431\u043a\u0443 \u0438\u0437 \u0441\u0442\u0435\u043a\u0430, \u043d\u043e \u043d\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0435\u0451 \u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a. \u0415\u0441\u043b\u0438 \u0441\u0442\u0435\u043a \u043e\u043f\u0443\u0441\u0442\u0435\u043b, \u0438 \u0441\u043a\u043e\u0431\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430, \u0442\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443. <\/li>\n<\/ul>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0446\u0430 \u0432\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430, \u0432\u044b\u0442\u043e\u043b\u043a\u043d\u0443\u0442\u044c \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u0432 \u0441\u0442\u0435\u043a\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a. \u0415\u0441\u043b\u0438 \u0432 \u043d\u0451\u043c \u043d\u0430\u0439\u0434\u0435\u043d\u043e \u0447\u0442\u043e-\u043b\u0438\u0431\u043e \u043a\u0440\u043e\u043c\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432, \u0442\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443.<\/p>\n<p>  \u041f\u0440\u0438\u043a\u0438\u043d\u0435\u043c, \u043a\u0430\u043a\u0438\u0435 \u0442\u0435\u0441\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430.<\/p>\n<ul>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043f\u0443\u0441\u0442\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u043f\u0438\u0441\u043e\u043a. <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0441\u043f\u0438\u0441\u043a\u0430 \u0441 \u043e\u0434\u043d\u0438\u043c \u0447\u0438\u0441\u043b\u043e\u043c, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u044d\u0442\u0438\u043c \u0447\u0438\u0441\u043b\u043e\u043c. <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [1 + 2], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f [1 2 +]. <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [1 + 2 + 3], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f [1 2 + 3 +], \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 + \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0435\u0432\u043e \u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0442\u0438\u0432\u043d\u044b\u043c. <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [1 * 2 + 3], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f [1 2 * 3 +]. <\/li>\n<li> \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 [1 + 2 * 3], \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f [1 2 3 * +], \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 * \u0438\u043c\u0435\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0438\u0439 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442. <\/li>\n<\/ul>\n<p>  \u0421\u043e \u0441\u043a\u043e\u0431\u043a\u0430\u043c\u0438 \u0438 \u043e\u0448\u0438\u0431\u043a\u0430\u043c\u0438 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f \u043f\u043e\u0437\u0434\u043d\u0435\u0435. \u0418\u0442\u0430\u043a, \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u0442\u0435\u0441\u0442 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430.<\/p>\n<pre><code class=\"cpp\">TEST_CLASS(ParserTests) { public:     TEST_METHOD(Should_return_empty_list_when_put_empty_list) {         Tokens tokens = Parser::Parse({});         Assert::IsTrue(tokens.empty());     } }; <\/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-232081","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/232081","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=232081"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/232081\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=232081"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=232081"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=232081"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}