{"id":288033,"date":"2018-08-16T14:21:29","date_gmt":"2018-08-16T10:21:29","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=288033"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=288033","title":{"rendered":"\u0428\u0430\u0431\u043b\u043e\u043d\u044b \u0442\u0440\u0435\u0442\u044c\u0435\u0433\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0430, \u0438\u043b\u0438 \u043a\u0430\u043a \u044f \u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043b Jinja2 \u043d\u0430 C++"},"content":{"rendered":"\n<div data-io-article-url=\"https:\/\/habr.com\/post\/416581\/\" class=\"post__text post__text-html js-mediator-article\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/c81\/fe0\/548\/c81fe0548837b911b9569cdf49d90ca2.jpg\" alt=\"Jinja2 logo\" align=\"left\">\u041f\u043e\u0434 \u00ab\u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438\u00bb \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 C++ \u043e\u0431\u044b\u0447\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f \u0432\u043f\u043e\u043b\u043d\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u044f\u0437\u044b\u043a\u043e\u0432\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438. \u0415\u0441\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043e\u0434\u043d\u043e\u0442\u0438\u043f\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c. \u0415\u0441\u043b\u0438 \u0443 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0438\u0437 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0441\u0430\u043c \u043f\u043e \u0441\u0435\u0431\u0435 \u0448\u0430\u0431\u043b\u043e\u043d, \u0442\u043e \u044d\u0442\u043e \u0443\u0436\u0435, \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0442 \u043e\u043d\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u0432\u043e\u0438\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432. \u041d\u043e \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0438 \u0438\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0438 \u043f\u0440\u043e\u0449\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442? \u041c\u043d\u043e\u0433\u043e \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430?<\/p>\n<p>  \u041b\u044e\u0431\u0438\u0442\u0435\u043b\u044f\u043c Python \u0430 \u0442\u0430\u043a\u0436\u0435 HTML-\u0432\u0451\u0440\u0441\u0442\u043a\u0438 \u0437\u043d\u0430\u043a\u043e\u043c\u043e \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e (\u0434\u0432\u0438\u0436\u043e\u043a, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430) \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u043c\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c <b>Jinja2<\/b>. \u041d\u0430 \u0432\u0445\u043e\u0434 \u044d\u0442\u043e\u0442 \u0434\u0432\u0438\u0436\u043e\u043a \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0444\u0430\u0439\u043b-\u0448\u0430\u0431\u043b\u043e\u043d, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0442\u0435\u043a\u0441\u0442 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u0448\u0430\u043d \u0441 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u043c\u0438 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f\u043c\u0438, \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0447\u0438\u0441\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0432\u0441\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0437\u0430\u043c\u0435\u043d\u0435\u043d\u044b \u0442\u0435\u043a\u0441\u0442\u043e\u043c \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u0437\u0432\u043d\u0435 (\u0438\u043b\u0438 \u0438\u0437\u043d\u0443\u0442\u0440\u0438) \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438. \u0413\u0440\u0443\u0431\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u044d\u0442\u043e \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435 ASP-\u0441\u0442\u0440\u0430\u043d\u0438\u0446 (\u0438\u043b\u0438 C++-\u043f\u0440\u0435\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430), \u0442\u043e\u043b\u044c\u043a\u043e \u044f\u0437\u044b\u043a \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438 \u0434\u0440\u0443\u0433\u043e\u0439.<\/p>\n<p>  \u0414\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u0432\u0438\u0436\u043a\u0430 \u0431\u044b\u043b\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f Python. \u0422\u0435\u043f\u0435\u0440\u044c \u0436\u0435 \u043e\u043d\u0430 \u0435\u0441\u0442\u044c \u0438 \u0434\u043b\u044f C++. \u041e \u0442\u043e\u043c, \u043a\u0430\u043a \u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u0442\u0430\u043a \u0432\u044b\u0448\u043b\u043e, \u0438 \u043f\u043e\u0439\u0434\u0451\u0442 \u0440\u0435\u0447\u044c \u0432 \u0441\u0442\u0430\u0442\u044c\u0435.<br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<h2>\u0417\u0430\u0447\u0435\u043c \u044f \u0432\u043e\u043e\u0431\u0449\u0435 \u0437\u0430 \u044d\u0442\u043e \u0432\u0437\u044f\u043b\u0441\u044f<\/h2>\n<p>  \u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u0430 \u0437\u0430\u0447\u0435\u043c? \u0412\u0435\u0434\u044c \u0435\u0441\u0442\u044c \u0436\u0435 Python, \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u2014 \u043e\u0442\u043b\u0438\u0447\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u043a\u0443\u0447\u0430 \u0444\u0438\u0447\u0435\u0439, \u0446\u0435\u043b\u044c\u043d\u0430\u044f \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043d\u0430 \u044f\u0437\u044b\u043a. \u0411\u0435\u0440\u0438 \u0438 \u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0441\u044f! \u041d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f Python \u2014 \u043c\u043e\u0436\u043d\u043e \u0432\u0437\u044f\u0442\u044c <a href=\"https:\/\/github.com\/hughperkins\/Jinja2CppLight\">Jinja2CppLight<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/github.com\/pantor\/inja\">inja<\/a>, \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u044b\u0435 \u043f\u043e\u0440\u0442\u044b Jinja2 \u043d\u0430 C++. \u041c\u043e\u0436\u043d\u043e, \u0432 \u043a\u043e\u043d\u0446\u0435 \u043a\u043e\u043d\u0446\u043e\u0432, \u0432\u0437\u044f\u0442\u044c C++-\u043f\u043e\u0440\u0442 {{<a href=\"https:\/\/github.com\/no1msd\/mstch\">Mustache<\/a>}}. \u0414\u044c\u044f\u0432\u043e\u043b, \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e, \u0432 \u0434\u0435\u0442\u0430\u043b\u044f\u0445. \u0412\u043e\u0442 \u043c\u043d\u0435, \u0441\u043a\u0430\u0436\u0435\u043c, \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u043b\u0430\u0441\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432 \u043e\u0442 Jinja2 \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 extends, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u044b\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u044b (\u0430 \u0435\u0449\u0451 \u043c\u0430\u043a\u0440\u043e\u0441\u044b \u0438 include, \u043d\u043e \u044d\u0442\u043e \u043f\u043e\u0442\u043e\u043c). \u0418 \u043d\u0438 \u043e\u0434\u043d\u0430 \u0438\u0437 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u044b\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439 \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442. \u041c\u043e\u0433 \u043b\u0438 \u044f \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c \u0431\u0435\u0437 \u0432\u0441\u0435\u0433\u043e \u044d\u0442\u043e\u0433\u043e? \u0422\u043e\u0436\u0435 \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u0432\u043e\u043f\u0440\u043e\u0441. \u0421\u0443\u0434\u0438\u0442\u0435 \u0441\u0430\u043c\u0438. \u0415\u0441\u0442\u044c \u0443 \u043c\u0435\u043d\u044f <a href=\"https:\/\/github.com\/flexferrum\/autoprogrammer\">\u043f\u0440\u043e\u0435\u043a\u0442<\/a>, \u0446\u0435\u043b\u044c \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 C++-to-C++ \u0430\u0432\u0442\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430 boilerplate-\u043a\u043e\u0434\u0430. \u042d\u0442\u043e\u0442 \u0430\u0432\u0442\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434, \u0441\u043a\u0430\u0436\u0435\u043c, \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430\u043c\u0438 \u0438\u043b\u0438 enum&#8217;\u0430\u043c\u0438 \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043d\u0430 \u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438\/\u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043b\u0438, \u0441\u043a\u0430\u0436\u0435\u043c, \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 enum&#8217;\u043e\u0432 \u0432 \u0441\u0442\u0440\u043e\u043a\u0438 (\u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e). \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u044d\u0442\u043e\u0439 \u0443\u0442\u0438\u043b\u0438\u0442\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043b\u0443\u0448\u0430\u0442\u044c \u0432 \u043c\u043e\u0438\u0445 \u0434\u043e\u043a\u043b\u0430\u0434\u0430\u0445 <a href=\"https:\/\/www.youtube.com\/watch?v=aPTyatTI42k&amp;t=2s&amp;list=FLFa8PRsAQn2sSOHuGPIQXMA&amp;index=6\">\u0437\u0434\u0435\u0441\u044c<\/a> (eng) \u0438\u043b\u0438 <a href=\"https:\/\/youtu.be\/ZeZqU3Kkvcw?t=10m30s\">\u0437\u0434\u0435\u0441\u044c<\/a> (\u0440\u0443\u0441).<\/p>\n<p>  \u0422\u0430\u043a \u0432\u043e\u0442, \u0442\u0438\u043f\u043e\u0432\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430, \u0440\u0435\u0448\u0430\u0435\u043c\u0430\u044f \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0434 \u0443\u0442\u0438\u043b\u0438\u0442\u043e\u0439 \u2014 \u044d\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432, \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c \u0448\u0430\u043f\u043a\u0430 (\u0441 ifdef&#8217;\u0430\u043c\u0438 \u0438 include&#8217;\u0430\u043c\u0438), \u0442\u0435\u043b\u043e \u0441 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c \u0438 \u043f\u043e\u0434\u0432\u0430\u043b. \u041f\u0440\u0438\u0447\u0451\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u2014 \u044d\u0442\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0446\u0438\u0438, \u0440\u0430\u0441\u043f\u0438\u0445\u0430\u043d\u043d\u044b\u0435 \u043f\u043e namespace&#8217;\u0430\u043c. \u0412 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u043d\u0430 C++ \u043a\u043e\u0434 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a (\u0438 \u044d\u0442\u043e \u0435\u0449\u0451 \u043d\u0435 \u0432\u0441\u0451):<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041c\u043d\u043e\u0433\u043e C++-\u043a\u043e\u0434\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">void Enum2StringGenerator::WriteHeaderContent(CppSourceStream &amp;hdrOs) {     std::vector&lt;reflection::EnumInfoPtr&gt; enums;     WriteNamespaceContents(hdrOs, m_namespaces.GetRootNamespace(), [this, &amp;enums](CppSourceStream &amp;os, reflection::NamespaceInfoPtr ns) {         for (auto&amp; enumInfo : ns-&gt;enums)         {             WriteEnumToStringConversion(os, enumInfo);             WriteEnumFromStringConversion(os, enumInfo);             enums.push_back(enumInfo);         }     });      hdrOs &lt;&lt; \"\\n\\n\";      {         out::BracedStreamScope flNs(\"\\nnamespace flex_lib\", \"\\n\\n\", 0);         hdrOs &lt;&lt; out::new_line(1) &lt;&lt; flNs;          for (reflection::EnumInfoPtr enumInfo : enums)         {             auto scopedParams = MakeScopedParams(hdrOs, enumInfo);                      {                 hdrOs &lt;&lt; out::new_line(1) &lt;&lt; \"template&lt;&gt;\";                 out::BracedStreamScope body(\"inline const char* Enum2String($enumFullQualifiedName$ e)\", \"\\n\");                 hdrOs &lt;&lt; out::new_line(1) &lt;&lt; body;                 hdrOs &lt;&lt; out::new_line(1) &lt;&lt; \"return $namespaceQual$::$enumName$ToString(e);\";             }             {                 hdrOs &lt;&lt; out::new_line(1) &lt;&lt; \"template&lt;&gt;\";                 out::BracedStreamScope body(\"inline $enumFullQualifiedName$ String2Enum&lt;$enumFullQualifiedName$&gt;(const char* itemName)\", \"\\n\");                 hdrOs &lt;&lt; out::new_line(1) &lt;&lt; body;                 hdrOs &lt;&lt; out::new_line(1) &lt;&lt; \"return $namespaceQual$::StringTo$enumName$(itemName);\";             }         }             }     {         out::BracedStreamScope flNs(\"\\nnamespace std\", \"\\n\\n\", 0);         hdrOs &lt;&lt; out::new_line(1) &lt;&lt; flNs;          for (reflection::EnumInfoPtr enumInfo : enums)         {             auto scopedParams = MakeScopedParams(hdrOs, enumInfo);              out::BracedStreamScope body(\"inline std::string to_string($enumFullQualifiedName$ e)\", \"\\n\");             hdrOs &lt;&lt; out::new_line(1) &lt;&lt; body;             hdrOs &lt;&lt; out::new_line(1) &lt;&lt; \"return $namespaceQual$::$enumName$ToString(e);\";         }     } }  \/\/ Enum item to string conversion writer void Enum2StringGenerator::WriteEnumToStringConversion(CppSourceStream &amp;hdrOs, const reflection::EnumInfoPtr &amp;enumDescr) {     auto scopedParams = MakeScopedParams(hdrOs, enumDescr);      out::BracedStreamScope fnScope(\"inline const char* $enumName$ToString($enumScopedName$ e)\", \"\\n\");     hdrOs &lt;&lt; out::new_line(1) &lt;&lt; fnScope;     {         out::BracedStreamScope switchScope(\"switch (e)\", \"\\n\");         hdrOs &lt;&lt; out::new_line(1) &lt;&lt; switchScope;         out::OutParams innerParams;         for (auto&amp; i : enumDescr-&gt;items)         {             innerParams[\"itemName\"] = i.itemName;             hdrOs &lt;&lt; out::with_params(innerParams)                   &lt;&lt; out::new_line(-1) &lt;&lt; \"case $prefix$$itemName$:\"                   &lt;&lt; out::new_line(1) &lt;&lt; \"return \\\"$itemName$\\\";\";         }     }     hdrOs &lt;&lt; out::new_line(1) &lt;&lt; \"return \\\"Unknown Item\\\";\"; }  \/\/ String to enum conversion writer void Enum2StringGenerator::WriteEnumFromStringConversion(CppSourceStream &amp;hdrOs, const reflection::EnumInfoPtr &amp;enumDescr) {     auto params = MakeScopedParams(hdrOs, enumDescr);      out::BracedStreamScope fnScope(\"inline $enumScopedName$ StringTo$enumName$(const char* itemName)\", \"\\n\");     hdrOs &lt;&lt; out::new_line(1) &lt;&lt; fnScope;     {         out::BracedStreamScope itemsScope(\"static std::pair&lt;const char*, $enumScopedName$&gt; items[] = \", \";\\n\");         hdrOs &lt;&lt; out::new_line(1) &lt;&lt; itemsScope;          out::OutParams&amp; innerParams = params.GetParams();         auto items = enumDescr-&gt;items;         std::sort(begin(items), end(items), [](auto&amp; i1, auto&amp; i2) {return i1.itemName &lt; i2.itemName;});         for (auto&amp; i : items)         {             innerParams[\"itemName\"] = i.itemName;             hdrOs &lt;&lt; out::with_params(innerParams) &lt;&lt; out::new_line(1) &lt;&lt; \"{\\\"$itemName$\\\", $prefix$$itemName$},\";         }     }      hdrOs &lt;&lt; out::with_params(params.GetParams()) &lt;&lt; R\"(      $enumScopedName$ result;      if (!flex_lib::detail::String2Enum(itemName, items, result))          flex_lib::bad_enum_name::Throw(itemName, \"$enumName$\");      return result;)\"; }<\/code><\/pre>\n<p>  <a href=\"https:\/\/github.com\/flexferrum\/autoprogrammer\/blob\/1d246b809f916b0aa06388b985b17cc6f6b9e842\/src\/generators\/enum2string_generator.cpp#L88\">\u041e\u0442\u0441\u044e\u0434\u0430<\/a>.  <\/div>\n<\/div>\n<p>  \u041f\u0440\u0438\u0447\u0451\u043c \u043a\u043e\u0434 \u044d\u0442\u043e\u0442 \u043c\u0430\u043b\u043e \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0442 \u0444\u0430\u0439\u043b\u0430 \u043a \u0444\u0430\u0439\u043b\u0443. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c clang-format. \u041d\u043e \u044d\u0442\u043e \u043d\u0435 \u043e\u0442\u043c\u0435\u043d\u044f\u0435\u0442 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u0440\u0443\u0447\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u043e \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430.<br \/>  \u0418 \u0432\u043e\u0442 \u0432 \u043e\u0434\u0438\u043d \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u044f \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u0436\u0438\u0437\u043d\u044c \u0441\u0435\u0431\u0435 \u043d\u0430\u0434\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0442\u044c. \u0412\u0430\u0440\u0438\u0430\u043d\u0442 \u0441 \u043f\u0440\u0438\u043a\u0440\u0443\u0447\u0438\u0432\u0430\u043d\u0438\u0435\u043c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u044f \u043d\u0435 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u043b \u0438\u0437-\u0437\u0430 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430. \u0410 \u0432\u043e\u0442 \u043d\u0430\u0439\u0442\u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0434\u0432\u0438\u0436\u043e\u043a \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u2014 \u0430 \u043f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u0438 \u043d\u0435\u0442? \u041f\u043e\u043b\u0435\u0437 \u0438\u0441\u043a\u0430\u0442\u044c, \u043d\u0430\u0448\u0451\u043b, \u043f\u043e\u0442\u043e\u043c \u043d\u0430\u0448\u0451\u043b \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u043d\u0430 Jinja2 \u0438 \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u044d\u0442\u043e \u2014 \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u043e, \u0447\u0442\u043e \u043c\u043d\u0435 \u043d\u0430\u0434\u043e. \u0418\u0431\u043e \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u044d\u0442\u043e\u0439 \u0441\u043f\u0435\u043a\u043e\u0439 \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b\u0438 \u0431\u044b \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cpp\">{% extends \"header_skeleton.j2tpl\" %} {% block generator_headers %}  #include &lt;flex_lib\/stringized_enum.h&gt;  #include &lt;algorithm&gt;  #include &lt;utility&gt; {% endblock %}  {% block namespaced_decls %}{{super()}}{% endblock %}  {% block namespace_content %} {% for enum in ns.enums | sort(attribute=\"name\") %} {% set enumName = enum.name %} {% set scopeSpec = enum.scopeSpecifier %} {% set scopedName = scopeSpec ~ ('::' if scopeSpec) ~ enumName %} {% set prefix = (scopedName + '::') if not enumInfo.isScoped else (scopedName ~ '::' ~ scopeSpec ~ ('::' if scopeSpec)) %}  inline const char* {{enumName}}ToString({{scopedName}} e) {     switch (e)     { {% for itemName in enum.items | map(attribute=\"itemName\") | sort%}     case {{prefix}}{{itemName}}:         return \"{{itemName}}\"; {% endfor %}     }     return \"Unknown Item\"; }  inline {{scopedName}} StringTo{{enumName}}(const char* itemName) {     static std::pair&lt;const char*, {{scopedName}}&gt; items[] = { {% for itemName in enum.items | map(attribute=\"itemName\") | sort %}         {\"{{itemName}}\", {{prefix}}{{itemName}} } {{',' if not loop.last }} {% endfor %}     };      {{scopedName}} result;     if (!flex_lib::detail::String2Enum(itemName, items, result))          flex_lib::bad_enum_name::Throw(itemName, \"{{enumName}}\");      return result; } {% endfor %}{% endblock %}  {% block global_decls %} {% for ns in [rootNamespace] recursive %} {% for enum in ns.enums %}  template&lt;&gt; inline const char* flex_lib::Enum2String({{enum.fullQualifiedName}} e) {     return {{enum.namespaceQualifier}}::{{enum.name}}ToString(e); }  template&lt;&gt; inline {{enum.fullQualifiedName}} flex_lib::String2Enum&lt;{{enum.fullQualifiedName}}&gt;(const char* itemName) {     return {{enum.namespaceQualifier}}::StringTo{{enum.name}}(itemName); }  inline std::string to_string({{enum.fullQualifiedName}} e) {     return {{enum.namespaceQualifier}}::{{enum.name}}ToString(e); } {% endfor %} {{loop(ns.namespaces)}} {% endfor %} {% endblock %}<\/code><\/pre>\n<p>  <a href=\"https:\/\/github.com\/flexferrum\/autoprogrammer\/blob\/938f456e0d4049d825d888a2dd5cbc95eede81d3\/src\/generators\/enum2string_generator.cpp#L74\">\u041e\u0442\u0441\u044e\u0434\u0430<\/a>.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/c98\/7d6\/5da\/c987d65da32b047a4eb3d2b7630fb99c.jpg\" alt=\"image\" align=\"right\" width=\"50%\">\u0411\u044b\u043b\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: \u043d\u0438 \u043e\u0434\u0438\u043d \u0438\u0437 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0445 \u043c\u043d\u043e\u044e \u0434\u0432\u0438\u0436\u043a\u043e\u0432 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u043b \u0432\u0441\u0435\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 \u043d\u0443\u0436\u043d\u044b\u0445 \u043c\u043d\u0435 \u0444\u0438\u0447\u0435\u0439. \u041d\u0443 \u0438, \u0440\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u043c\u0435\u043b \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 <a href=\"http:\/\/lurkmore.to\/%D0%A4%D0%B0%D1%82%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D0%BD%D0%B5%D0%B4%D0%BE%D1%81%D1%82%D0%B0%D1%82%D0%BE%D0%BA\">\u0444\u0430\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u043a<\/a>. \u042f \u043f\u043e\u0434\u0443\u043c\u0430\u043b \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438 \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u0435\u0449\u0451 \u043e\u0442 \u043e\u0434\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u043c\u0438\u0440\u0443 \u0441\u0438\u043b\u044c\u043d\u043e \u0445\u0443\u0436\u0435 \u043d\u0435 \u0441\u0442\u0430\u043d\u0435\u0442. \u0422\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u0447\u0442\u043e, \u043f\u043e \u043f\u0440\u0438\u043a\u0438\u0434\u043a\u0430\u043c, \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0431\u044b\u043b\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u0442\u043e \u0447\u0442\u043e\u0431\u044b \u0441\u0438\u043b\u044c\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u043e. \u0412\u0435\u0434\u044c \u0442\u0435\u043f\u0435\u0440\u044c \u0432 C++ \u0435\u0441\u0442\u044c regexp&#8217;\u044b!<br \/>  \u0418 \u0442\u0430\u043a \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043f\u0440\u043e\u0435\u043a\u0442 <a href=\"https:\/\/github.com\/flexferrum\/Jinja2Cpp\">Jinja2Cpp<\/a>. \u041d\u0430 \u0441\u0447\u0451\u0442 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e (\u0441\u043e\u0432\u0441\u0435\u043c \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e) \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u044f \u043f\u043e\u0447\u0442\u0438 \u0443\u0433\u0430\u0434\u0430\u043b. \u0412 \u0446\u0435\u043b\u043e\u043c \u0436\u0435 \u2014 \u043f\u0440\u043e\u043c\u0430\u0445\u043d\u0443\u043b\u0441\u044f \u0430\u043a\u043a\u0443\u0440\u0430\u0442 \u043d\u0430 \u043a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442 \u041f\u0438 \u0432 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0435: \u043d\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u0441\u0435\u0433\u043e \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u043c\u043d\u0435 \u0443\u0448\u043b\u043e \u0447\u0443\u0442\u044c \u043c\u0435\u043d\u044c\u0448\u0435 \u0442\u0440\u0451\u0445 \u043c\u0435\u0441\u044f\u0446\u0435\u0432. \u041d\u043e \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0451 \u0431\u044b\u043b\u043e \u0434\u043e\u043f\u0438\u0441\u0430\u043d\u043e, \u0434\u043e\u043f\u0438\u043b\u0435\u043d\u043e \u0438 \u0432\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u0432 \u201c\u0410\u0432\u0442\u043e\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u201d \u2014 \u044f \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u0441\u0442\u0430\u0440\u0430\u043b\u0441\u044f \u043d\u0435 \u0437\u0440\u044f. \u0424\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u043f\u043e \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u0434\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0430 \u043c\u043e\u0449\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432\u044b\u0439 \u044f\u0437\u044b\u043a \u0441\u043e\u0432\u043c\u0435\u0449\u0451\u043d\u043d\u044b\u0439 \u0441 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438, \u0447\u0442\u043e \u043e\u0442\u043a\u0440\u044b\u043b\u043e \u043f\u0435\u0440\u0435\u0434 \u043d\u0435\u0439 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043d\u043e\u0432\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u044f.<\/p>\n<p>  NB: \u0423 \u043c\u0435\u043d\u044f \u0431\u044b\u043b\u0430 \u043c\u044b\u0441\u043b\u044c \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u0442\u044c Python (\u0438\u043b\u0438 Lua). \u041d\u043e \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u0438\u0437 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0445 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432\u044b\u0445 \u0434\u0432\u0438\u0436\u043a\u043e\u0432 \u043d\u0435 \u0440\u0435\u0448\u0430\u0435\u0442 \u00ab\u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438\u00bb \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u043f\u043e \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0442\u0435\u043a\u0441\u0442\u0430 \u0438\u0437 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432. \u0422\u043e \u0435\u0441\u0442\u044c \u043a Python \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043f\u0440\u0438\u043a\u0440\u0443\u0447\u0438\u0432\u0430\u0442\u044c \u0442\u0443 \u0436\u0435 Jinja2, \u0430 \u0434\u043b\u044f Lua \u0438\u0441\u043a\u0430\u0442\u044c \u0447\u0442\u043e-\u0442\u043e \u0441\u0432\u043e\u0451. \u0417\u0430\u0447\u0435\u043c \u043c\u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u044d\u0442\u043e \u043b\u0438\u0448\u043d\u0435\u0435 \u0437\u0432\u0435\u043d\u043e?<\/p>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0430\u0440\u0441\u0435\u0440\u0430<\/h2>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/d32\/570\/463\/d325704634011d586894096d9e09b20f.png\" alt=\"image\" align=\"left\" width=\"60%\">\u0418\u0434\u0435\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b Jinja2-\u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430. \u0415\u0441\u043b\u0438 \u0432 \u0442\u0435\u043a\u0441\u0442\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0447\u0442\u043e-\u0442\u043e, \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u043e\u0435 \u0432 \u043f\u0430\u0440\u0443 &#171;{{&#187; \/ &#171;}}&#187; \u2014 \u0442\u043e \u044d\u0442\u043e \u00ab\u0447\u0442\u043e-\u0442\u043e\u00bb \u2014 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u043e, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u043e \u0432 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u0432\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u0432 \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442. \u0412\u043d\u0443\u0442\u0440\u0438 \u043f\u0430\u0440\u044b &#171;{%&#187; \/ &#171;%}&#187; \u2014 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0442\u0438\u043f\u0430 for, if, set \u0438 \u0442. \u043f. \u041d\u0443 \u0430 \u0432 &#171;{#&#187; \/ &#171;#}&#187; \u2014 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438. \u0418\u0437\u0443\u0447\u0438\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e Jinja2CppLight, \u044f \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043d\u0430\u0439\u0442\u0438 \u0432 \u0442\u0435\u043a\u0441\u0442\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0432\u0441\u0435 \u044d\u0442\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u2014 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u0430\u0447\u043d\u0430\u044f \u0438\u0434\u0435\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0432\u043e\u043e\u0440\u0443\u0436\u0438\u043b\u0441\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u044b\u043c regexp&#8217;\u043e\u043c: ((\\{\\{)|(\\}\\})|(\\{%)|(%\\})|(\\{#)|(#\\})|(\\n)), \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u043e\u0431\u0438\u043b \u0442\u0435\u043a\u0441\u0442 \u043d\u0430 \u043d\u0443\u0436\u043d\u044b\u0435 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b. \u0418 \u043d\u0430\u0437\u0432\u0430\u043b \u044d\u0442\u043e \u0433\u0440\u0443\u0431\u043e\u0439 \u0444\u0430\u0437\u043e\u0439 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430. \u041d\u0430 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0438\u0434\u0435\u044f \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430 \u0441\u0432\u043e\u044e \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c (\u0434\u0430, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0438 \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442), \u043d\u043e, \u043f\u043e-\u0445\u043e\u0440\u043e\u0448\u0435\u043c\u0443, \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0435\u0451 \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u0442\u044c, \u0442\u0430\u043a \u043a\u0430\u043a \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0430 \u0442\u0435\u043a\u0441\u0442 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0435\u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f: \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u0440 &#171;{{&#187; \u0438 &#171;}}&#187; \u0432 \u0442\u0435\u043a\u0441\u0442\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u00ab\u0432 \u043b\u043e\u0431\u00bb.<\/p>\n<p>  \u0412\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0444\u0430\u0437\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e \u043f\u0430\u0440\u0441\u0438\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e, \u0447\u0442\u043e \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u00ab\u0441\u043a\u043e\u0431\u043e\u043a\u00bb. \u0418 \u0432\u043e\u0442 \u0442\u0443\u0442 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u043e\u0432\u043e\u0437\u0438\u0442\u044c\u0441\u044f. \u0427\u0442\u043e \u0432 inja, \u0447\u0442\u043e \u0432 Jinja2CppLight, \u043f\u0430\u0440\u0441\u0435\u0440 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439. \u0412 \u043f\u0435\u0440\u0432\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u2014 \u043d\u0430 \u0442\u0435\u0445 \u0436\u0435 regexp&#8217;\u0430\u0445, \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u2014 \u0440\u0443\u043a\u043e\u043f\u0438\u0441\u043d\u044b\u0439, \u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0449\u0438\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438. \u041e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432, \u0442\u0435\u0441\u0442\u0435\u0440\u043e\u0432, \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u043a\u0438 \u0438\u043b\u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0430\u043c \u0440\u0435\u0447\u0438 \u0434\u0430\u0436\u0435 \u043d\u0435 \u0438\u0434\u0451\u0442. \u0410 \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u0438\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 Jinja2 \u043c\u043d\u0435 \u0438 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0441\u0435\u0433\u043e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0443 \u043c\u0435\u043d\u044f \u043d\u0435 \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0432\u044b\u0445\u043e\u0434\u0430, \u043a\u0430\u043a \u043d\u0430\u043f\u0435\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 LL(1)-\u043f\u0430\u0440\u0441\u0435\u0440 (\u043c\u0435\u0441\u0442\u0430\u043c\u0438 \u2014 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e-\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0439), \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0443. \u041b\u0435\u0442 \u0434\u0435\u0441\u044f\u0442\u044c-\u043f\u044f\u0442\u043d\u0430\u0434\u0446\u0430\u0442\u044c \u043d\u0430\u0437\u0430\u0434 \u044f \u0431\u044b, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0432\u0437\u044f\u043b \u0431\u044b \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e Bison \u0438\u043b\u0438 ANTLR \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u0431\u044b \u043f\u0430\u0440\u0441\u0435\u0440 \u0441 \u0438\u0445 \u043f\u043e\u043c\u043e\u0449\u044c\u044e. \u041b\u0435\u0442 \u0441\u0435\u043c\u044c \u0431\u044b \u043d\u0430\u0437\u0430\u0434 \u044f \u0431\u044b \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b Boost.Spirit. \u0421\u0435\u0439\u0447\u0430\u0441 \u0436\u0435 \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u043d\u0443\u0436\u043d\u044b\u0439 \u043c\u043d\u0435 \u043f\u0430\u0440\u0441\u0435\u0440, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u0441\u043f\u0443\u0441\u043a\u0430, \u0431\u0435\u0437 \u043f\u043e\u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043b\u0438\u0448\u043d\u0438\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0438 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438, \u043a\u0430\u043a \u044d\u0442\u043e \u0441\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0431\u044b \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0443\u0442\u0438\u043b\u0438\u0442 \u0438\u043b\u0438 Boost.Spirit. \u041d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043f\u0430\u0440\u0441\u0435\u0440\u0430 \u044f \u043f\u043e\u043b\u0443\u0447\u0430\u044e AST (\u0434\u043b\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0438\u043b\u0438 \u0434\u043b\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432), \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u0448\u0430\u0431\u043b\u043e\u043d, \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u0440\u0438\u043c\u0435\u0440 \u043b\u043e\u0433\u0438\u043a\u0438 \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">ExpressionEvaluatorPtr&lt;FullExpressionEvaluator&gt; ExpressionParser::ParseFullExpression(LexScanner &amp;lexer, bool includeIfPart) {     ExpressionEvaluatorPtr&lt;FullExpressionEvaluator&gt; result;     LexScanner::StateSaver saver(lexer);      ExpressionEvaluatorPtr&lt;FullExpressionEvaluator&gt; evaluator = std::make_shared&lt;FullExpressionEvaluator&gt;();     auto value = ParseLogicalOr(lexer);     if (!value)         return result;      evaluator-&gt;SetExpression(value);     ExpressionEvaluatorPtr&lt;ExpressionFilter&gt; filter;     if (lexer.PeekNextToken() == '|')     {         lexer.EatToken();         filter = ParseFilterExpression(lexer);         if (!filter)             return result;         evaluator-&gt;SetFilter(filter);     }      ExpressionEvaluatorPtr&lt;IfExpression&gt; ifExpr;     if (lexer.PeekNextToken() == Token::If)     {         if (includeIfPart)         {             lexer.EatToken();             ifExpr = ParseIfExpression(lexer);             if (!ifExpr)                 return result;             evaluator-&gt;SetTester(ifExpr);         }     }      saver.Commit();      return evaluator; }  ExpressionEvaluatorPtr&lt;Expression&gt; ExpressionParser::ParseLogicalOr(LexScanner&amp; lexer) {     auto left = ParseLogicalAnd(lexer);     if (!left)         return ExpressionEvaluatorPtr&lt;Expression&gt;();      if (lexer.NextToken() != Token::LogicalOr)     {         lexer.ReturnToken();         return left;     }     auto right = ParseLogicalOr(lexer);     if (!right)         return ExpressionEvaluatorPtr&lt;Expression&gt;();      return std::make_shared&lt;BinaryExpression&gt;(BinaryExpression::LogicalOr, left, right); }  ExpressionEvaluatorPtr&lt;Expression&gt; ExpressionParser::ParseLogicalAnd(LexScanner&amp; lexer) {     auto left = ParseLogicalCompare(lexer);     if (!left)         return ExpressionEvaluatorPtr&lt;Expression&gt;();      if (lexer.NextToken() != Token::LogicalAnd)     {         lexer.ReturnToken();         return left;     }     auto right = ParseLogicalAnd(lexer);     if (!right)         return ExpressionEvaluatorPtr&lt;Expression&gt;();      return std::make_shared&lt;BinaryExpression&gt;(BinaryExpression::LogicalAnd, left, right); }  ExpressionEvaluatorPtr&lt;Expression&gt; ExpressionParser::ParseLogicalCompare(LexScanner&amp; lexer) {     auto left = ParseStringConcat(lexer);     if (!left)         return ExpressionEvaluatorPtr&lt;Expression&gt;();      auto tok = lexer.NextToken();     BinaryExpression::Operation operation;     switch (tok.type)     {     case Token::Equal:         operation = BinaryExpression::LogicalEq;         break;     case Token::NotEqual:         operation = BinaryExpression::LogicalNe;         break;     case '&lt;':         operation = BinaryExpression::LogicalLt;         break;     case '&gt;':         operation = BinaryExpression::LogicalGt;         break;     case Token::GreaterEqual:         operation = BinaryExpression::LogicalGe;         break;     case Token::LessEqual:         operation = BinaryExpression::LogicalLe;         break;     case Token::In:         operation = BinaryExpression::In;         break;     case Token::Is:     {         Token nextTok = lexer.NextToken();         if (nextTok != Token::Identifier)             return ExpressionEvaluatorPtr&lt;Expression&gt;();          std::string name = AsString(nextTok.value);         bool valid = true;         CallParams params;          if (lexer.NextToken() == '(')             params = ParseCallParams(lexer, valid);         else             lexer.ReturnToken();          if (!valid)             return ExpressionEvaluatorPtr&lt;Expression&gt;();          return std::make_shared&lt;IsExpression&gt;(left, std::move(name), std::move(params));     }     default:         lexer.ReturnToken();         return left;     }      auto right = ParseStringConcat(lexer);     if (!right)         return ExpressionEvaluatorPtr&lt;Expression&gt;();      return std::make_shared&lt;BinaryExpression&gt;(operation, left, right); }<\/code><\/pre>\n<p>  <a href=\"https:\/\/github.com\/flexferrum\/Jinja2Cpp\/blob\/4854abfcf619c735a33f23a3f9c89cd2b24abeeb\/src\/expression_parser.cpp#L24\">\u041e\u0442\u0441\u044e\u0434\u0430<\/a>.  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0424\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 AST-\u0434\u0435\u0440\u0435\u0432\u0430 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">class ExpressionFilter; class IfExpression;  class FullExpressionEvaluator : public ExpressionEvaluatorBase { public:     void SetExpression(ExpressionEvaluatorPtr&lt;Expression&gt; expr)     {         m_expression = expr;     }     void SetFilter(ExpressionEvaluatorPtr&lt;ExpressionFilter&gt; expr)     {         m_filter = expr;     }     void SetTester(ExpressionEvaluatorPtr&lt;IfExpression&gt; expr)     {         m_tester = expr;     }     InternalValue Evaluate(RenderContext&amp; values) override;     void Render(OutStream &amp;stream, RenderContext &amp;values) override; private:     ExpressionEvaluatorPtr&lt;Expression&gt; m_expression;     ExpressionEvaluatorPtr&lt;ExpressionFilter&gt; m_filter;     ExpressionEvaluatorPtr&lt;IfExpression&gt; m_tester; };  class ValueRefExpression : public Expression { public:     ValueRefExpression(std::string valueName)         : m_valueName(valueName)     {     }     InternalValue Evaluate(RenderContext&amp; values) override; private:     std::string m_valueName; };  class SubscriptExpression : public Expression { public:     SubscriptExpression(ExpressionEvaluatorPtr&lt;Expression&gt; value, ExpressionEvaluatorPtr&lt;Expression&gt; subscriptExpr)         : m_value(value)         , m_subscriptExpr(subscriptExpr)     {     }     InternalValue Evaluate(RenderContext&amp; values) override; private:     ExpressionEvaluatorPtr&lt;Expression&gt; m_value;     ExpressionEvaluatorPtr&lt;Expression&gt; m_subscriptExpr; };  class ConstantExpression : public Expression { public:     ConstantExpression(InternalValue constant)         : m_constant(constant)     {}     InternalValue Evaluate(RenderContext&amp;) override     {         return m_constant;     } private:     InternalValue m_constant; };  class TupleCreator : public Expression { public:     TupleCreator(std::vector&lt;ExpressionEvaluatorPtr&lt;&gt;&gt; exprs)         : m_exprs(std::move(exprs))     {     }      InternalValue Evaluate(RenderContext&amp;) override;  private:     std::vector&lt;ExpressionEvaluatorPtr&lt;&gt;&gt; m_exprs; };<\/code><\/pre>\n<p>  <a href=\"https:\/\/github.com\/flexferrum\/Jinja2Cpp\/blob\/4854abfcf619c735a33f23a3f9c89cd2b24abeeb\/src\/expression_evaluator.h#L62\">\u041e\u0442\u0441\u044e\u0434\u0430<\/a>.  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 AST-\u0434\u0435\u0440\u0435\u0432\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">struct Statement : public RendererBase { };  template&lt;typename T = Statement&gt; using StatementPtr = std::shared_ptr&lt;T&gt;;  template&lt;typename CharT&gt; class TemplateImpl;  class ForStatement : public Statement { public:     ForStatement(std::vector&lt;std::string&gt; vars, ExpressionEvaluatorPtr&lt;&gt; expr, ExpressionEvaluatorPtr&lt;&gt; ifExpr, bool isRecursive)         : m_vars(std::move(vars))         , m_value(expr)         , m_ifExpr(ifExpr)         , m_isRecursive(isRecursive)     {     }      void SetMainBody(RendererPtr renderer)     {         m_mainBody = renderer;     }      void SetElseBody(RendererPtr renderer)     {         m_elseBody = renderer;     }      void Render(OutStream&amp; os, RenderContext&amp; values) override;      private:     void RenderLoop(const InternalValue&amp; val, OutStream&amp; os, RenderContext&amp; values);  private:     std::vector&lt;std::string&gt; m_vars;     ExpressionEvaluatorPtr&lt;&gt; m_value;     ExpressionEvaluatorPtr&lt;&gt; m_ifExpr;     bool m_isRecursive;     RendererPtr m_mainBody;     RendererPtr m_elseBody; };  class ElseBranchStatement;  class IfStatement : public Statement { public:     IfStatement(ExpressionEvaluatorPtr&lt;&gt; expr)         : m_expr(expr)     {     }      void SetMainBody(RendererPtr renderer)     {         m_mainBody = renderer;     }      void AddElseBranch(StatementPtr&lt;ElseBranchStatement&gt; branch)     {         m_elseBranches.push_back(branch);     }      void Render(OutStream&amp; os, RenderContext&amp; values) override;  private:     ExpressionEvaluatorPtr&lt;&gt; m_expr;     RendererPtr m_mainBody;     std::vector&lt;StatementPtr&lt;ElseBranchStatement&gt;&gt; m_elseBranches; };   class ElseBranchStatement : public Statement { public:     ElseBranchStatement(ExpressionEvaluatorPtr&lt;&gt; expr)         : m_expr(expr)     {     }      bool ShouldRender(RenderContext&amp; values) const;     void SetMainBody(RendererPtr renderer)     {         m_mainBody = renderer;     }     void Render(OutStream&amp; os, RenderContext&amp; values) override;  private:     ExpressionEvaluatorPtr&lt;&gt; m_expr;     RendererPtr m_mainBody; }; <\/code><\/pre>\n<p>  <a href=\"https:\/\/github.com\/flexferrum\/Jinja2Cpp\/blob\/4854abfcf619c735a33f23a3f9c89cd2b24abeeb\/src\/statements.h#L12\">\u041e\u0442\u0441\u044e\u0434\u0430<\/a>.  <\/div>\n<\/div>\n<p>  \u0423\u0437\u043b\u044b AST \u0438\u043c\u0435\u044e\u0442 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u043a \u0442\u0435\u043a\u0441\u0442\u0443 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0438 \u0435\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d\u044b thread-safe. \u041d\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u0432 \u0447\u0430\u0441\u0442\u0438, \u043a\u0430\u0441\u0430\u044e\u0449\u0435\u0439\u0441\u044f \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430.<br \/>  \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430\u0439\u0437\u0435\u0440\u0430 \u044f \u0432\u044b\u0431\u0440\u0430\u043b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 <a href=\"https:\/\/github.com\/ArashPartow\/lexertk\">lexertk<\/a>. \u041e\u043d\u0430 \u0438\u043c\u0435\u0435\u0442 \u043d\u0443\u0436\u043d\u0443\u044e \u043c\u043d\u0435 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u044e \u0438 header-only. \u041f\u0440\u0438\u0448\u043b\u043e\u0441\u044c, \u043f\u0440\u0430\u0432\u0434\u0430, \u043e\u0442\u0440\u0435\u0437\u0430\u0442\u044c \u043e\u0442 \u043d\u0435\u0451 \u0432\u0441\u0435 \u043d\u0430\u0432\u043e\u0440\u043e\u0442\u044b \u043f\u043e \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u0443 \u0431\u0430\u043b\u0430\u043d\u0441\u0430 \u0441\u043a\u043e\u0431\u043e\u043a \u0438 \u043f\u0440\u043e\u0447\u0435\u0435 \u0438 \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0442\u043e\u043a\u0435\u043d\u0430\u0439\u0437\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 (\u043f\u043e\u0441\u043b\u0435 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0440\u0438\u0445\u0442\u043e\u0432\u043a\u0438 \u043d\u0430\u043f\u0438\u043b\u044c\u043d\u0438\u043a\u043e\u043c) \u043d\u0430\u0443\u0447\u0438\u043b\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0441 char, \u043d\u043e \u0438 \u0441 wchar_t-\u0441\u0438\u043c\u0432\u043e\u043b\u0430\u043c\u0438. \u0421\u0432\u0435\u0440\u0445\u0443 \u044d\u0442\u043e\u0442 \u0442\u043e\u043a\u0435\u043d\u0430\u0439\u0437\u0435\u0440 \u0431\u044b\u043b \u043c\u043d\u043e\u044e \u043e\u0431\u0451\u0440\u043d\u0443\u0442 \u0435\u0449\u0451 \u043e\u0434\u043d\u0438\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0438\u043c \u0442\u0440\u0438 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0438: \u0430) \u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u0443\u0435\u0442 \u043a\u043e\u0434 \u043f\u0430\u0440\u0441\u0435\u0440\u0430 \u043e\u0442 \u0442\u0438\u043f\u0430 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0432\u0435\u0434\u0451\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430, \u0431) \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0451\u0442 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430, \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0435 \u0434\u043b\u044f Jinja2 \u0438 \u0432) \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u043e\u0442\u043e\u043a\u043e\u043c \u0442\u043e\u043a\u0435\u043d\u043e\u0432:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">LexScanner<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">class LexScanner { public:     struct State     {         Lexer::TokensList::const_iterator m_begin;         Lexer::TokensList::const_iterator m_end;         Lexer::TokensList::const_iterator m_cur;     };      struct StateSaver     {         StateSaver(LexScanner&amp; scanner)             : m_state(scanner.m_state)             , m_scanner(scanner)         {         }          ~StateSaver()         {             if (!m_commited)                 m_scanner.m_state = m_state;         }          void Commit()         {             m_commited = true;         }          State m_state;         LexScanner&amp; m_scanner;         bool m_commited = false;     };      LexScanner(const Lexer&amp; lexer)     {         m_state.m_begin = lexer.GetTokens().begin();         m_state.m_end = lexer.GetTokens().end();         Reset();     }      void Reset()     {         m_state.m_cur = m_state.m_begin;     }      auto GetState() const     {         return m_state;     }      void RestoreState(const State&amp; state)     {         m_state = state;     }      const Token&amp; NextToken()     {         if (m_state.m_cur == m_state.m_end)             return EofToken();          return *m_state.m_cur ++;     }      void EatToken()     {         if (m_state.m_cur != m_state.m_end)             ++ m_state.m_cur;     }      void ReturnToken()     {         if (m_state.m_cur != m_state.m_begin)             -- m_state.m_cur;     }      const Token&amp; PeekNextToken() const     {         if (m_state.m_cur == m_state.m_end)             return EofToken();          return *m_state.m_cur;     }      bool EatIfEqual(char type, Token* tok = nullptr)     {         return EatIfEqual(static_cast&lt;Token::Type&gt;(type), tok);     }      bool EatIfEqual(Token::Type type, Token* tok = nullptr)     {         if (m_state.m_cur == m_state.m_end)         {             if(type == Token::Type::Eof &amp;&amp; tok)                 *tok = EofToken();              return type == Token::Type::Eof;         }          if (m_state.m_cur-&gt;type == type)         {             if (tok)                 *tok = *m_state.m_cur;             ++ m_state.m_cur;             return true;         }          return false;     }  private:     State m_state;     static const Token&amp; EofToken()     {         static Token eof;         eof.type = Token::Eof;         return eof;     } };<\/code><\/pre>\n<p>  <a href=\"https:\/\/github.com\/flexferrum\/Jinja2Cpp\/blob\/4854abfcf619c735a33f23a3f9c89cd2b24abeeb\/src\/lexer.h#L146\">\u041e\u0442\u0441\u044e\u0434\u0430<\/a>.  <\/div>\n<\/div>\n<p>  \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0434\u0432\u0438\u0436\u043e\u043a \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u0430\u043a \u0441 char, \u0442\u0430\u043a \u0438 \u0441 wchar_t-\u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438, \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u0434 \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u043e\u0442 \u0442\u0438\u043f\u0430 \u0441\u0438\u043c\u0432\u043e\u043b\u0430 \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442. \u041d\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u2014 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435, \u043f\u043e\u0441\u0432\u044f\u0449\u0451\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\u043c \u0441 \u0442\u0438\u043f\u043e\u043c \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432.<\/p>\n<p>  \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u043e\u0432\u043e\u0437\u0438\u0442\u044c\u0441\u044f \u0441 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u043c\u0438 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f\u043c\u0438. \u0412 Jinja2 \u043c\u043d\u043e\u0433\u0438\u0435 \u0438\u0437 \u043d\u0438\u0445 \u2014 \u043f\u0430\u0440\u043d\u044b\u0435. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, for\/endfor, if\/endif, block\/endblock \u0438 \u0442. \u043f. \u041a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u0430\u0440\u044b \u0438\u0434\u0451\u0442 \u0432 \u0441\u0432\u043e\u0438\u0445 \u00ab\u0441\u043a\u043e\u0431\u043a\u0430\u0445\u00bb, \u0430 \u043c\u0435\u0436\u0434\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u0443\u0447\u0430 \u0432\u0441\u0435\u0433\u043e: \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0442\u0435\u043a\u0441\u0442, \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0435 \u0431\u043b\u043e\u043a\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u0442\u0435\u043a\u0430, \u043a \u0442\u0435\u043a\u0443\u0449\u0435\u043c\u0443 \u0432\u0435\u0440\u0445\u043d\u0435\u043c\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u00ab\u0446\u0435\u043f\u043b\u044f\u044e\u0442\u0441\u044f\u00bb \u0432\u0441\u0435 \u0432\u043d\u043e\u0432\u044c \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438. \u041f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u044d\u0442\u043e\u0433\u043e \u0436\u0435 \u0441\u0442\u0435\u043a\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0440\u0430\u0437\u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438 \u0442\u0438\u043f\u0430 if-for-endif-endfor. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0432\u0441\u0435\u0433\u043e \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u0434 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f \u043d\u0435 \u0442\u0430\u043a\u043e\u0439 \u00ab\u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u044b\u0439\u00bb \u043a\u0430\u043a, \u0441\u043a\u0430\u0436\u0435\u043c, \u0443 Jinja2CppLight (\u0438\u043b\u0438 inja), \u0433\u0434\u0435 \u0432\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u2014 \u0432 \u043e\u0434\u043d\u043e\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0435 (\u0438\u043b\u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435). \u041d\u043e \u043b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u0438, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0430 \u0432 \u043a\u043e\u0434\u0435 \u0432\u0438\u0434\u043d\u044b \u0431\u043e\u043b\u0435\u0435 \u044f\u0432\u043d\u043e, \u0447\u0442\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0435\u0433\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435. \u041f\u043e \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043c\u0435\u0440\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u043a \u044d\u0442\u043e\u043c\u0443 \u044f \u0441\u0442\u0440\u0435\u043c\u0438\u043b\u0441\u044f. \u041c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0438\u043b\u0438 \u043e\u0431\u044a\u0451\u043c \u043a\u043e\u0434\u0430 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f, \u0437\u043d\u0430\u0447\u0438\u0442 \u043d\u0430\u0434\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0433\u043e \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u043c.<\/p>\n<p>  \u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0440\u0435\u0447\u044c \u043f\u043e\u0439\u0434\u0451\u0442 \u043f\u0440\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432, \u0430 \u043f\u043e\u043a\u0430 \u2014 \u0441\u0441\u044b\u043b\u043a\u0438:<\/p>\n<p>  \u0421\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f Jinja2: <a href=\"http:\/\/jinja.pocoo.org\/docs\/2.10\/templates\/\">http:\/\/jinja.pocoo.org\/docs\/2.10\/templates\/<\/a><\/p>\n<p>  \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f Jinja2Cpp: <a href=\"https:\/\/github.com\/flexferrum\/Jinja2Cpp\">https:\/\/github.com\/flexferrum\/Jinja2Cpp<\/a><\/p>\n<p>  \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f Jinja2CppLight: <a href=\"https:\/\/github.com\/hughperkins\/Jinja2CppLight\">https:\/\/github.com\/hughperkins\/Jinja2CppLight<\/a><\/p>\n<p>  \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f inja: <a href=\"https:\/\/github.com\/pantor\/inja\">https:\/\/github.com\/pantor\/inja<\/a><\/p>\n<p>  \u0423\u0442\u0438\u043b\u0438\u0442\u0430 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u0434\u0430 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 Jinja2: <a href=\"https:\/\/github.com\/flexferrum\/autoprogrammer\/tree\/jinja2cpp_refactor\">https:\/\/github.com\/flexferrum\/autoprogrammer\/tree\/jinja2cpp_refactor<\/a><\/div>\n<p>        <script class=\"js-mediator-script\">!function(e){function t(t,n){if(!(n in e)){for(var r,a=e.document,i=a.scripts,o=i.length;o--;)if(-1!==i[o].src.indexOf(t)){r=i[o];break}if(!r){r=a.createElement(\"script\"),r.type=\"text\/javascript\",r.async=!0,r.defer=!0,r.src=t,r.charset=\"UTF-8\";var d=function(){var e=a.getElementsByTagName(\"script\")[0];e.parentNode.insertBefore(r,e)};\"[object Opera]\"==e.opera?a.addEventListener?a.addEventListener(\"DOMContentLoaded\",d,!1):e.attachEvent(\"onload\",d):d()}}}t(\"\/\/mediator.mail.ru\/script\/2820404\/\",\"_mediator\")}(window);<\/script>     <br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/post\/416581\/\"> https:\/\/habr.com\/post\/416581\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div data-io-article-url=\"https:\/\/habr.com\/post\/416581\/\" class=\"post__text post__text-html js-mediator-article\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/c81\/fe0\/548\/c81fe0548837b911b9569cdf49d90ca2.jpg\" alt=\"Jinja2 logo\" align=\"left\">\u041f\u043e\u0434 \u00ab\u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438\u00bb \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 C++ \u043e\u0431\u044b\u0447\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f \u0432\u043f\u043e\u043b\u043d\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u044f\u0437\u044b\u043a\u043e\u0432\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438. \u0415\u0441\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043e\u0434\u043d\u043e\u0442\u0438\u043f\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c. \u0415\u0441\u043b\u0438 \u0443 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0438\u0437 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0441\u0430\u043c \u043f\u043e \u0441\u0435\u0431\u0435 \u0448\u0430\u0431\u043b\u043e\u043d, \u0442\u043e \u044d\u0442\u043e \u0443\u0436\u0435, \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0442 \u043e\u043d\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u0432\u043e\u0438\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432. \u041d\u043e \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0438 \u0438\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0438 \u043f\u0440\u043e\u0449\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442? \u041c\u043d\u043e\u0433\u043e \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430?<\/p>\n<p>  \u041b\u044e\u0431\u0438\u0442\u0435\u043b\u044f\u043c Python \u0430 \u0442\u0430\u043a\u0436\u0435 HTML-\u0432\u0451\u0440\u0441\u0442\u043a\u0438 \u0437\u043d\u0430\u043a\u043e\u043c\u043e \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e (\u0434\u0432\u0438\u0436\u043e\u043a, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430) \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u043c\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c <b>Jinja2<\/b>. \u041d\u0430 \u0432\u0445\u043e\u0434 \u044d\u0442\u043e\u0442 \u0434\u0432\u0438\u0436\u043e\u043a \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0444\u0430\u0439\u043b-\u0448\u0430\u0431\u043b\u043e\u043d, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0442\u0435\u043a\u0441\u0442 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u0448\u0430\u043d \u0441 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u043c\u0438 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f\u043c\u0438, \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0447\u0438\u0441\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0432\u0441\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0437\u0430\u043c\u0435\u043d\u0435\u043d\u044b \u0442\u0435\u043a\u0441\u0442\u043e\u043c \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u0437\u0432\u043d\u0435 (\u0438\u043b\u0438 \u0438\u0437\u043d\u0443\u0442\u0440\u0438) \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438. \u0413\u0440\u0443\u0431\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u044d\u0442\u043e \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435 ASP-\u0441\u0442\u0440\u0430\u043d\u0438\u0446 (\u0438\u043b\u0438 C++-\u043f\u0440\u0435\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430), \u0442\u043e\u043b\u044c\u043a\u043e \u044f\u0437\u044b\u043a \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438 \u0434\u0440\u0443\u0433\u043e\u0439.<\/p>\n<p>  \u0414\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u0432\u0438\u0436\u043a\u0430 \u0431\u044b\u043b\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f Python. \u0422\u0435\u043f\u0435\u0440\u044c \u0436\u0435 \u043e\u043d\u0430 \u0435\u0441\u0442\u044c \u0438 \u0434\u043b\u044f C++. \u041e \u0442\u043e\u043c, \u043a\u0430\u043a \u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u0442\u0430\u043a \u0432\u044b\u0448\u043b\u043e, \u0438 \u043f\u043e\u0439\u0434\u0451\u0442 \u0440\u0435\u0447\u044c \u0432 \u0441\u0442\u0430\u0442\u044c\u0435.  <\/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-288033","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/288033","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=288033"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/288033\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=288033"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=288033"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=288033"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}