{"id":458754,"date":"2025-05-06T03:08:35","date_gmt":"2025-05-06T03:08:35","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=458754"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=458754","title":{"rendered":"<span>\u041a\u0430\u043a \u044f \u043f\u0438\u0441\u0430\u043b\u0430 DSL<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0417\u0434\u0440\u0430\u0432\u0441\u0442\u0432\u0443\u0439\u0442\u0435. \u042f \u0443\u0447\u0443\u0441\u044c \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c \u043a\u0443\u0440\u0441\u0435 \u0431\u0430\u043a\u0430\u043b\u0430\u0432\u0440\u0438\u0430\u0442\u0430 \u0438 \u0443\u0436\u0435 \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0441\u044f\u0446 \u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c \u0431\u0443\u0434\u0443 \u0437\u0430\u0449\u0438\u0449\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0432\u044b\u043f\u0443\u0441\u043a\u043d\u0443\u044e \u043a\u0432\u0430\u043b\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 (\u0438\u043b\u0438 \u0436\u0435 \u0434\u0438\u043f\u043b\u043e\u043c\u043d\u0443\u044e). \u041c\u043d\u0435 \u0437\u0430\u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u043e \u043d\u0435\u0451 \u0437\u0434\u0435\u0441\u044c, \u0447\u0435\u043c \u044f \u0441\u0435\u0439\u0447\u0430\u0441 \u0438 \u0437\u0430\u0439\u043c\u0443\u0441\u044c.<\/p>\n<p>\u041c\u0435\u043d\u044f \u0434\u0430\u0432\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u044f\u0437\u044b\u043a\u043e\u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f &#8212; \u043b\u0435\u043a\u0441\u0435\u0440\u044b, \u043f\u0430\u0440\u0441\u0435\u0440\u044b, \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u044b, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u044b \u0438 \u0432\u0441\u044f\u043a\u043e\u0435 \u0442\u0430\u043a\u043e\u0435. \u041d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0442, \u0447\u0442\u043e \u0443\u0436\u0435 \u0432 \u043a\u043e\u043d\u0446\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u0443\u0440\u0441\u0430 \u044f \u0440\u0435\u0448\u0438\u043b\u0430, \u0447\u0442\u043e \u0432 \u043a\u043e\u043d\u0446\u0435 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443 \u0437\u0430\u0449\u0438\u0449\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439 \u044f\u0437\u044b\u043a \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0423\u0432\u044b, \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0434\u0435\u043b\u043e\u043c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u043c, \u0438\u0437-\u0437\u0430 \u0447\u0435\u0433\u043e \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0438\u0441\u043a\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0442\u0435\u043c\u0443. \u041f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043d\u0430 \u0442\u0440\u0435\u0442\u044c\u0435\u043c \u043a\u0443\u0440\u0441\u0435 \u043c\u044b \u0438\u0437\u0443\u0447\u0430\u043b\u0438 \u0432 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442\u0435 Kotlin, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u0441\u0442\u0440\u043e \u0437\u0430\u043f\u0430\u043b \u043c\u043d\u0435 \u0432 \u0434\u0443\u0448\u0443 \u0438 \u0441\u0442\u0430\u043b \u043c\u043e\u0438\u043c \u043b\u044e\u0431\u0438\u043c\u0446\u0435\u043c (\u043f\u043e\u0441\u043b\u0435 Lua). \u041c\u043d\u0435 \u0437\u0430\u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0434\u0438\u043f\u043b\u043e\u043c\u043d\u0443\u044e \u0438\u043c\u0435\u043d\u043d\u043e \u043d\u0430 \u043d\u0451\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0441\u0442\u0430\u043b\u0430 \u0434\u0443\u043c\u0430\u0442\u044c, \u0447\u0442\u043e \u0431\u044b \u0442\u0430\u043a\u043e\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c. \u0422\u0430\u043a \u043a\u0430\u043a \u043c\u0435\u043d\u044f \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043b \u0433\u0435\u0439\u043c\u0434\u0435\u0432, \u044f \u043f\u043e\u0434\u0443\u043c\u0430\u043b\u0430: &#171;\u041f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0434\u0432\u0438\u0436\u043e\u043a \u0434\u043b\u044f \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0445 \u043a\u0432\u0435\u0441\u0442\u043e\u0432 \u043a\u0430\u043a \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0443 Ren&#8217;Py?&#187;. \u041f\u043e\u0434\u0443\u043c\u0430\u043b\u0430 \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0434\u0432\u0438\u0436\u043e\u043a. \u0423\u0432\u044b, \u0432 \u043d\u0451\u043c \u043d\u0435 \u0431\u044b\u043b\u043e \u043d\u0430\u0443\u0447\u043d\u043e\u0439 \u043d\u043e\u0432\u0438\u0437\u043d\u044b, \u0434\u0430 \u0438 \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u0434 \u043d\u0435\u0433\u043e \u0431\u044b\u043b\u043e \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u043e, \u043d\u0443 \u0445\u043e\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0430 \u043e\u043f\u044b\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u044f\u0437\u044b\u0447\u043a\u043e\u0432, \u043a\u043e\u0433\u0434\u0430 \u0434\u0430\u043b\u0430 \u0436\u0438\u0437\u043d\u044c \u0441\u0432\u043e\u0435\u043c\u0443 Av, \u043f\u0440\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0438\u0441\u0430\u043b\u0430 \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<p>\u0412 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442\u0435 \u043c\u043d\u0435 \u0441\u043a\u0430\u0437\u0430\u043b\u0438, \u0447\u0442\u043e \u043f\u043e\u0434\u043e\u0431\u043d\u0430\u044f \u0442\u0435\u043c\u0430 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0437\u0430\u0449\u0438\u0442\u044b, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u044f \u0441\u043d\u043e\u0432\u0430 \u0437\u0430\u0434\u0443\u043c\u0430\u043b\u0430\u0441\u044c, \u0447\u0442\u043e \u0431\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c. \u0412\u0441\u043f\u043e\u043c\u043d\u0438\u043b\u0430, \u0447\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043d\u0435\u043f\u043b\u043e\u0445\u043e \u0437\u043d\u0430\u043a\u043e\u043c\u0430 \u0441 ANTLR, \u0438 \u0440\u0435\u0448\u0438\u043b\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c DSL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043b ANTLR, \u0432 AST Kotlin. \u042d\u0442\u0430 \u043c\u044b\u0441\u043b\u044c \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u043e, \u043d\u043e \u043c\u043d\u0435 \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u0442\u0430\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u0432\u043e \u0447\u0442\u043e \u043e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f. \u041a\u0430\u043a \u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 DSL, \u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0435, \u0437\u0430\u0447\u0435\u043c? \u041a\u0430\u043a \u044f \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u043b\u0430 \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u0432\u043a\u0430\u0444\u0435\u0434\u0440\u043e\u0439, \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u043a\u043e\u0434\u043e\u0432\u044b\u0435 \u0431\u0430\u0437\u044b \u0441 \u0440\u0430\u0437\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432 \u043d\u0430 \u043e\u0434\u0438\u043d &#8212; \u043c\u043e\u0439 \u043b\u044e\u0431\u0438\u043c\u044b\u0439 \u041a\u043e\u0442\u043b\u0438\u043d. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u044d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u0440\u043e\u0432 \u043d\u043e\u0432\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0440\u0430\u043d\u0442\u0430\u0439\u043c, \u0430 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 JVM, \u0432\u0435\u0434\u044c \u041a\u043e\u0442\u043b\u0438\u043d \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u043d\u0451\u043c.<\/p>\n<p>\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0442\u0435\u043c\u0430 \u043c\u043e\u0435\u0439 \u0434\u0438\u043f\u043b\u043e\u043c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u0430\u043a: &#171;DSL ASTra \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0442\u0440\u0430\u043d\u0441\u043f\u0430\u0439\u043b\u0435\u0440\u043e\u0432 \u0438\u0437 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 ANTLR, \u0432 AST Kotlin&#187;. \u041f\u043e\u0447\u0435\u043c\u0443 ASTra? \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e [AS]T [Tra]nspiler. \u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043c\u043e\u0439 DSL \u0438 \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u043e\u0437\u044c\u043c\u0443 \u0442\u0440\u0430\u043d\u0441\u043f\u0430\u0439\u043b\u0435\u0440 <code>STLC =&gt; Kotlin<\/code>.<\/p>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0434\u0432\u0443\u0445 \u0447\u0430\u0441\u0442\u0435\u0439:<\/p>\n<ul>\n<li>\n<p>\u042f\u0434\u0440\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0442\u0440\u0430\u043d\u0441\u043f\u0430\u0439\u043b\u0435\u0440\u044b<\/p>\n<\/li>\n<li>\n<p>\u041e\u043a\u043e\u043b\u043e \u0442\u0440\u0451\u0445 \u0441\u043e\u0442\u0435\u043d \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 AST Kotlin \u0432\u0435\u0440\u0441\u0438\u0438 1.9.22<\/p>\n<\/li>\n<\/ul>\n<p>\u042f\u0434\u0440\u043e \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432:<\/p>\n<ul>\n<li>\n<p>TranspilationRule<\/p>\n<\/li>\n<li>\n<p>RuleBuilder<\/p>\n<\/li>\n<li>\n<p>RuleHolder<\/p>\n<\/li>\n<li>\n<p>RuleHolderBuilder<\/p>\n<\/li>\n<li>\n<p>RuleVisitor<\/p>\n<\/li>\n<li>\n<p>DefaultRule<\/p>\n<\/li>\n<li>\n<p>RuleLogger<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6be\/b32\/92a\/6beb3292a46b4129013be0ad25c66b42.png\" alt=\"\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u044f\u0434\u0440\u0430 DSL\" title=\"\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u044f\u0434\u0440\u0430 DSL\" width=\"2092\" height=\"2130\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/6be\/b32\/92a\/6beb3292a46b4129013be0ad25c66b42.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6be\/b32\/92a\/6beb3292a46b4129013be0ad25c66b42.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u044f\u0434\u0440\u0430 DSL<\/figcaption><\/div>\n<\/figure>\n<p><code>TranspilationRule&lt;P, A&gt;<\/code> &#8212; \u044d\u0442\u043e \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0442\u0440\u0430\u043d\u0441\u043f\u0438\u043b\u044f\u0446\u0438\u0438. \u041c\u044b \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0443 <code>P:ParseTree<\/code> \u0438 <code>A:KotlinAst<\/code>  \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439, \u0447\u0442\u043e\u0431\u044b \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c RuleVisitor \u043c\u043e\u0433 \u0438\u0441\u043a\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0434\u0435\u0440\u0435\u0432\u043e \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u0432 AST.<\/p>\n<p>\u041a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0438\u043b\u0434\u0435\u0440\u0430 TranspilationRule:<\/p>\n<pre><code class=\"kotlin\">val rX = rule&lt;XContext, KSimpleIdentifier&gt;(\"x\") {     from(XContext::class)     how {ctx: XContext -&gt;         ctx.ID().text.id     } }<\/code><\/pre>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0438\u043f\u043e\u0432\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0438 rule, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u043d\u0438 \u0432\u044b\u0432\u0435\u0434\u0443\u0442\u0441\u044f \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u0435\u0437 \u0432\u0441\u044f\u043a\u0438\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c, \u043d\u043e \u044f \u043e\u0431\u044b\u0447\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e \u0438\u0445 \u0432\u0435\u0437\u0434\u0435. \u0424\u0443\u043d\u043a\u0446\u0438\u044f rule \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 type-safe builder, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u044d\u0442\u0430\u043f\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u043e.<\/p>\n<p>XContent &#8212; \u044d\u0442\u043e \u043a\u043b\u0430\u0441\u0441, \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 ANTLR, KSimpleIdentifier &#8212; \u043a\u043b\u0430\u0441\u0441, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0432 AST Kotlin. \u0424\u0443\u043d\u043a\u0446\u0438\u044f how \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e XContent \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f KSimpleIdentifier. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0435\u0449\u0451 howCtx, \u0433\u0434\u0435 ctx \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0440\u0435\u0441\u0438\u0432\u0435\u0440\u043e\u043c, \u0438 howFixed, \u0433\u0434\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0442\u043e\u0440\u0430 \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u0441\u0430\u043c\u0430 how \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0439, \u0437\u0430 \u0441\u0447\u0451\u0442 \u0447\u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0435\u0431\u044f \u0436\u0435 \u0431\u0435\u0437 \u043f\u043e\u0438\u0441\u043a\u0430 \u0441\u0440\u0435\u0434\u0438 \u043f\u0440\u0430\u0432\u0438\u043b. \u041c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043d\u0435 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u043c\u044f \u0441\u0440\u0430\u0437\u0443, \u0430 \u0432\u044b\u0437\u0432\u0430\u0442\u044c <code>name(\"name\")<\/code> \u0432\u043d\u0443\u0442\u0440\u0438 <code>rule {}<\/code>, \u043d\u043e \u043c\u043d\u0435 \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u043c\u044f.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u0441\u043b\u043e\u0436\u043d\u0435\u0435:<\/p>\n<pre><code class=\"kotlin\">val rConditional = rule(\"conditional\") {     from(ConditionalContext::class)     how {ctx: ConditionalContext -&gt;         val tToExp = lookup&lt;TContext, KExpression&gt;()         ?: error(\"ASTra doesn't know how to get KExpression from T\")         tToExp(ctx.pred).ifElse(             tToExp(ctx.if_true).block,             tToExp(ctx.if_false).block         )     } }<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0443\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0432\u044b\u0437\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 lookup. \u042d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0449\u0435\u043c \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0441 \u0442\u0430\u043a\u043e\u0439 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u043e\u0439, \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044f\u0441\u044c \u0435\u0433\u043e \u0438\u043c\u0435\u043d\u0435\u043c \u0438 \u043d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u044f\u0441\u044c \u043a \u043d\u0435\u043c\u0443 \u0445\u0430\u0440\u0434\u043a\u043e\u0434\u043d\u043e.<\/p>\n<p>\u041f\u043e \u0444\u0430\u043a\u0442\u0443 \u0432\u0435\u0441\u044c DSL \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u0430\u0432\u0438\u043b, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0445, \u043a\u0430\u043a \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0430 \u043d\u0435\u043a\u043e\u0435\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0435 \u041a\u043e\u0442\u043b\u0438\u043d\u0430. \u0415\u0441\u0442\u044c, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043d\u043e \u0432 \u0446\u0435\u043b\u043e\u043c \u044d\u0442\u043e \u0432\u0441\u0451. \u0420\u0430\u0437\u0432\u0435 \u0447\u0442\u043e \u0441\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434 \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438 \u043f\u043e\u0441\u043b\u0435, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435 defaultRule, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f, \u0435\u0441\u043b\u0438 \u0434\u043b\u044f \u0443\u0437\u043b\u0430 \u0434\u0435\u0440\u0435\u0432\u0430 \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0439\u0434\u0435\u043d\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u043e.<\/p>\n<p>\u0412\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440 defaultRule:<\/p>\n<pre><code class=\"kotlin\">default {     println(\"default for $it\")     \"TODO\".id() }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0442\u0440\u0430\u043d\u0441\u043f\u0430\u0439\u043b\u0435\u0440\u0430 STLC =&gt; Kotlin \u0446\u0435\u043b\u0438\u043a\u043e\u043c<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">val stlcRuleHolder=rules&lt;StlcLexer,StlcParser&gt; {     default {         println(\"default for ${it::class.simpleName}\")         \"TODO\".id()     }      val rX=         rule(\"x\") {             from(XContext::class)             how {ctx:XContext-&gt; ctx.ID().text.id}         }      val rVariable=         rule(\"variable\") {             from(VariableContext::class)             how {ctx:VariableContext-&gt; rX(ctx.x())}         }      val rTrue=         rule(\"true\") {             from(Constant_trueContext::class)             how {true.ast}         }      val rFalse=         rule(\"false\") {             from(Constant_falseContext::class)             how {false.ast}         }      val rParenthesis=         rule(\"parenthesis\") {             from(ParenthesisContext::class)             how {ctx:ParenthesisContext-&gt;                 val tToExp=lookup&lt;TContext,KExpression&gt;()                            ?: error(\"ASTra doesn't know how to get KExpression from Parenthesis\")                 tToExp(ctx.t()).paren             }         }      val rConditional=         rule(\"conditional\") {             from(ConditionalContext::class)             how {ctx:ConditionalContext-&gt;                 val tToExp=lookup&lt;TContext,KExpression&gt;()                            ?: error(\"ASTra doesn't know how to get KExpression from T\")                 tToExp(ctx.pred).ifElse(                     tToExp(ctx.if_true).block,                     tToExp(ctx.if_false).block                 )             }         }      val rT=         rule(\"t\") {             from(TContext::class)             how {ctx:TContext-&gt;                 when(ctx)                 {                     is VariableContext-&gt;rVariable(ctx)                     is AbstractionContext-&gt;                         lookup&lt;AbstractionContext,KFunctionLiteral&gt;()?.invoke(ctx)                         ?: error(\"ASTra doesn't know how to get KLambdaLiteral from Abstraction\")                      is ApplicationContext-&gt;                         lookup&lt;ApplicationContext,KExpression&gt;()?.invoke(ctx)                         ?: error(\"ASTra doesn't know how to get KExpression from ApplicationContext\")                      is Constant_trueContext-&gt;rTrue(ctx)                     is Constant_falseContext-&gt;rFalse(ctx)                     is ConditionalContext-&gt;rConditional(ctx)                     is ParenthesisContext-&gt;rParenthesis(ctx)                     else-&gt;error(\"ASTra doesn't know how to get KExpression from ${ctx::class.simpleName}\")                 }             }         }      val rApplication=         rule&lt;ApplicationContext,KExpression&gt;(\"application\") {             from(ApplicationContext::class)             how {ctx-&gt;                 val exp=ctx.t(1)                 ctx.t(0).let(rT)(rT(exp))             }         }      val rType=         rule(\"type\") {             from(TypeContext::class)             howFixed {rType-&gt;                 {ctx:TypeContext-&gt;                     val boolify={name:String-&gt;                         if(name==\"Bool\") \"Boolean\" else name                     }                     when(ctx)                     {                         is Flat_typeContext-&gt;boolify(ctx.ID().text).type                          is Abstraction_typeContext-&gt;                             boolify(ctx.ID().text).type                                 .functionTypeParameters                                 .leadsTo(rType(ctx.type()))                                 .type                          else-&gt;error(\"ASTra doesn't know how to get other KType from ${ctx::class.simpleName}\")                     }                 }             }         }      val rAbstraction=         rule&lt;AbstractionContext,KLambdaLiteral&gt;(\"abstraction\") {             from(AbstractionContext::class)             how {ctx-&gt;                 rX(ctx.x()).variableDecl(rType(ctx.type()))                     .lambdaParams                     .literal(rT(ctx.t()).stat)             }         } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u0443\u043c\u0430\u044e, \u0441 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u044c\u044e \u0432\u0441\u0451 \u0431\u043e\u043b\u0435\u0435-\u043c\u0435\u043d\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u043f\u0435\u0440\u0435\u0445\u043e\u0436\u0443 \u043a\u043e \u0432\u0442\u043e\u0440\u043e\u0439. IDEA \u0433\u043e\u0432\u043e\u0440\u0438\u0442, \u0447\u0442\u043e \u0443 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 KotlinAst 282 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430. \u042f \u043d\u0435 \u0431\u0443\u0434\u0443 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u0445 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0430 \u043f\u043e\u0432\u0435\u0440\u044e \u0435\u0439.<\/p>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443 \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u043e\u0432? \u042f \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043b\u0430 <a href=\"https:\/\/kotlinlang.org\/docs\/reference\/grammar.html\" rel=\"noopener noreferrer nofollow\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0435<\/a> \u0438 \u0443\u043f\u0440\u043e\u0449\u0430\u043b\u0430 \u0435\u0451 \u0442\u0430\u043c, \u0433\u0434\u0435 \u044d\u0442\u043e \u0431\u044b\u043b\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u043e \u0432 \u0446\u0435\u043b\u043e\u043c \u043c\u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0451 \u0446\u0435\u043b\u0438\u043a\u043e\u043c, \u043a\u0440\u043e\u043c\u0435 \u043b\u0438\u0448\u043d\u0438\u0445 \u0447\u0430\u0441\u0442\u0435\u0439.<\/p>\n<p>\u041a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e, \u043d\u0430\u0447\u043d\u0443 \u0441 &#171;Hello, world!&#187;:<\/p>\n<pre><code class=\"kotlin\">\"println\".id(\"Hello, world!\".ast)<\/code><\/pre>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0437\u0434\u0435\u0441\u044c <code>println<\/code> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c, \u0430 <code>\"Hello, world!\"<\/code> &#8212; \u0441\u0442\u0440\u043e\u043a\u043e\u0439 \u0432 AST. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 invoke \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c <code>println.id<\/code> \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0447\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e.<\/p>\n<pre><code class=\"kotlin\">val x = \"x\".id<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u0441\u043b\u0430\u043b\u0438\u0441\u044c \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e &#171;x&#187;.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u0441\u043b\u043e\u0436\u043d\u0435\u0435:<\/p>\n<pre><code class=\"kotlin\">val exp: KBinaryExpression = 1.ast + 2.ast <\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438\u043c\u0435\u0435\u0442 \u0442\u0438\u043f KBinaryExpression, \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044e\u0449\u0438\u0439 \u0432 \u0441\u0435\u0431\u0435 KAdditiveExpression \u0438 KMultiplicativeExpression. \u041f\u0443\u0442\u0451\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u0442\u0444\u0438\u043a\u0441\u0430 ast \u043a \u043b\u0438\u0442\u0435\u0440\u0430\u043b\u0443 \u0446\u0435\u043b\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u043c\u044b \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0435\u0433\u043e \u0432 KIntegerLiteral.<\/p>\n<pre><code class=\"kotlin\">\"obj\"[\"prop\".id]<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0431\u0435\u0440\u0451\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e &#171;prop&#187; \u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 &#171;obj&#187;.<\/p>\n<pre><code class=\"kotlin\">val declaration = kval(\"x\", 10.ast)<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430. \u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u043e\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u0435\u043e\u0431\u044b\u0447\u0430\u0439\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043b\u043d\u0430\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044f:<\/p>\n<pre><code class=\"kotlin\">val declaration1 = kval(\"x\") {     +Lateinit \/\/ import EMemberModifier.Lateinit     +Override \/\/ import EMemberModifier.Override     isVar     +10.ast }  \/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u0440\u0430\u0432\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u044b  val declaration2 = kval(\"x\") {     mods(Lateinit, Override)     isVal(false)     expr(10.ast) }<\/code><\/pre>\n<p>\u041d\u043e \u044d\u0442\u043e \u043b\u0430\u0434\u043d\u043e, \u0432\u0441\u0451 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e. \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u043e\u0437\u044c\u043c\u0443 \u043f\u0440\u044f\u043c \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043a\u0443\u0441\u043e\u043a \u043a\u043e\u0434\u0430 \u0438 \u043f\u043e\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043e\u043d \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0430 \u041a\u043e\u0442\u043b\u0438\u043d\u0435 \u0438 \u043c\u043e\u0451\u043c DSL.<\/p>\n<details class=\"spoiler\">\n<summary>\u041e\u0440\u0438\u0433\u0438\u043d\u0430\u043b<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">abstract class Character(val name: String, var health: Int) {     abstract fun attack(target: Character)      fun isAlive(): Boolean = health &gt; 0      open fun takeDamage(amount: Int)     {         health -= amount         println(\"$name \u043f\u043e\u043b\u0443\u0447\u0438\u043b $amount \u0443\u0440\u043e\u043d\u0430. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c $health HP.\");         if (health &lt;= 0) println(\"$name \u043f\u0430\u043b \u0432 \u0431\u043e\u044e...\")     } }  abstract class Hero(     name: String,     health: Int,     val power: Int ):Character(name, health) {     override fun attack(target: Character)     {         println(\"$name \u0430\u0442\u0430\u043a\u0443\u0435\u0442 ${target.name}!\")         target.takeDamage(power)     } }  class Monster(     name: String,     health: Int,     val damage: Int ):Character(name, health) {     override fun attack(target: Character)     {         println(\"$name \u043a\u0443\u0441\u0430\u0435\u0442 ${target.name}!\")         target.takeDamage(damage);     } }  fun main() {     val hero = Hero(\"\u0410\u043b\u0438\u0441\u0430\", 100, 20)     val goblin = Monster(\"\u0413\u043e\u0431\u043b\u0438\u043d\", 100, 20)     println(\"\u2694\ufe0f \u0411\u0438\u0442\u0432\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f!\")     while(hero.isAlive()&amp;&amp;goblin.isAlive())     {         hero.attack(goblin)         if(goblin.isAlive()) goblin.attack(hero)         println()     }     println(\"\ud83c\udfc1 \u0411\u0438\u0442\u0432\u0430 \u043e\u043a\u043e\u043d\u0447\u0435\u043d\u0430!\") }<\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041d\u0430 DSL<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">kotlinFile {     +kclass(\"Character\",EInheritanceModifier.Abstract) {         primaryConstructor {             \"name\" ofType \"String\"             \"health\" init {                 isVar                 type(\"Int\")             }         }         classBody {             function(\"attack\") {                 +EInheritanceModifier.Abstract                 \"target\" ofType \"Character\"             }             function(\"isAlive\") {                 type(\"Boolean\".type)                 exprBody(\"health\".id greater 0.ast)             }             function(\"takeDamage\") {                 +EInheritanceModifier.Open                 \"amount\" ofType \"Int\"                 blockBody {                     +\"health\".id.subAssign(\"amount\".id)                     +\"println\".id(                         stringLiteral {                             ref(\"name\")                             text(\" \u043f\u043e\u043b\u0443\u0447\u0438\u043b \")                             ref(\"amount\")                             text(\" \u0443\u0440\u043e\u043d\u0430. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \")                             ref(\"health\")                             text(\" HP.\")                         }                     )                     +\"health\".id                         .lessEq(0.ast)                         .ifTrue(\"println\".id(\"\\$name \u043f\u0430\u043b \u0432 \u0431\u043e\u044e...\".ast).stat)                 }             }         }     }      +kclass(\"Hero\",EInheritanceModifier.Abstract) {         primaryConstructor {             \"name\" init {                 notMine \/\/ isn't val\/var, just sends to parent constructor                 type(\"String\")             }             \"health\" init {                 notMine                 type(\"Int\")             }             \"power\" ofType \"Int\"         }         delegationSpecifiers {             \"Character\".id.simpleUserType.userType constructorInvocation                     listOf(\"name\".id.valueArg, \"health\".id.valueArg)         }         classBody {             function(\"attack\") {                 +Override                 \"target\" ofType \"Character\"                 blockBody {                     +\"println\".id(                         stringLiteral {                             ref(\"name\")                             text(\" \u0430\u0442\u0430\u043a\u0443\u0435\u0442 \")                             expr(\"target\".id[\"name\".id])                             text(\"!\")                         }                     )                     +\"target\"[\"takeDamage\".id](\"power\".id)                 }             }         }     }      +kclass(\"Monster\") {         primaryConstructor {             \"name\" init {                 notMine                 type(\"String\")             }             \"health\" init {                 notMine                 type(\"Int\")             }             \"damage\" ofType \"Int\"         }         delegationSpecifiers {             \"Character\".id.simpleUserType.userType constructorInvocation                     listOf(\"name\".id.valueArg, \"health\".id.valueArg)         }         classBody {             function(\"attack\") {                 +Override                 \"target\" ofType \"Character\"                 blockBody {                     +\"println\".id(                         stringLiteral {                             ref(\"name\")                             text(\" \u043a\u0443\u0441\u0430\u0435\u0442 \")                             expr(\"target\".id[\"name\".id])                             text(\"!\")                         }                     )                     +\"target\"[\"takeDamage\".id](\"damage\".id)                 }             }         }     }      +kfun(\"main\") {         blockBody {             +kval(\"hero\", \"Hero\".id(\"\u0410\u043b\u0438\u0441\u0430\".ast, 100.ast, 20.ast))             +kval(\"goblin\", \"Monster\".id(\"\u0413\u043e\u0431\u043b\u0438\u043d\".ast, 100.ast, 20.ast))              +\"println\".id(\"\u2694\ufe0f \u0411\u0438\u0442\u0432\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f!\".ast)              +(\"hero\"[\"isAlive\".id]() and \"goblin\"[\"isAlive\".id]()).kwhile {                 +\"hero\"[\"attack\".id](\"goblin\".id)                 +\"goblin\"[\"isAlive\".id]().ifTrue(                     \"goblin\"[\"attack\".id](\"hero\".id).stat                 )                 +\"println\".id()             }              +\"println\".id(\"\ud83c\udfc1 \u0411\u0438\u0442\u0432\u0430 \u043e\u043a\u043e\u043d\u0447\u0435\u043d\u0430!\".ast)         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0427\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442? \u041c\u044b \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 Character, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u044e\u0442\u0441\u044f \u043a\u043b\u0430\u0441\u0441\u044b Hero \u0438 Monster. \u041e\u0431\u0430 \u0443\u043c\u0435\u044e\u0442 \u0434\u0440\u0430\u0442\u044c\u0441\u044f \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0440\u043e\u043d. \u041d\u0438\u0436\u0435 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 main \u043c\u044b \u0437\u0430\u0433\u043e\u043d\u044f\u0435\u043c \u0438\u0445 \u043d\u0430 \u0430\u0440\u0435\u043d\u0443 \u0438 \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0434\u0440\u0430\u0442\u044c\u0441\u044f \u043d\u0435 \u043d\u0430 \u0436\u0438\u0437\u043d\u044c, \u0430 \u043d\u0430 \u0441\u043c\u0435\u0440\u0442\u044c. \u041a\u043e\u0434 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0440\u0430\u0431\u043e\u0447\u0438\u0439, \u0435\u0441\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043a\u0442\u043e \u0438\u0437 \u043d\u0438\u0445 \u0432\u044b\u0436\u0438\u0432\u0435\u0442, \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0432 IDE \u0438\u043b\u0438 \u0432 <a href=\"https:\/\/pl.kotl.in\/E9Jt1TrX4?theme=darcula\" rel=\"noopener noreferrer nofollow\">\u043e\u043d\u043b\u0430\u0439\u043d-\u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0435<\/a>.<\/p>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u044f \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e type-safe builders \u0438 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0439-\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0447\u0435\u043c\u0443 \u0443 \u043c\u0435\u043d\u044f \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u0430\u044f \u0438 \u0443\u0434\u043e\u0431\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c.<\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 when \u0442\u043e\u0436\u0435 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0434\u043e\u0431\u043d\u043e:<\/p>\n<pre><code class=\"kotlin\">kwhen(\"x\".id) {     \"Int\".type caseIs \"Int\".ast     \"String\".type caseIs \"String\".ast     \"Unknown\".ast.stat.caseElse }<\/code><\/pre>\n<p>\u0421\u0442\u043e\u0438\u0442 \u0442\u0430\u043a\u0436\u0435 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0435\u0433\u043e AST \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u044f \u0441\u043e\u0437\u0434\u0430\u043b\u0430 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Emitter&lt;E&gt;, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u044d\u043c\u0438\u0442\u0442\u0435\u0440, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438 KotlinEmitter, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0435\u0441\u0442\u044c \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435.<\/p>\n<p>\u0427\u0435\u043c \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 kastree, kotlinx.ast, kotlinpoet? \u0422\u0435\u043c, \u0447\u0442\u043e \u0443 \u043c\u0435\u043d\u044f \u0438\u043c\u0435\u043d\u043d\u043e DSL \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 AST, \u043e\u043d \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u0438\u0437\u0430\u0442\u043e\u0440\u0430, \u043a\u0430\u043a kotlinpoet, \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c AST \u0431\u043e\u043b\u0435\u0435 \u043b\u0430\u043a\u043e\u043d\u0438\u0447\u043d\u043e \u0438 \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u043e \u0437\u0430 \u0441\u0447\u0451\u0442 \u0443\u0434\u043e\u0431\u043d\u044b\u0445 \u0431\u0438\u043b\u0434\u0435\u0440\u043e\u0432 \u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432-\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439. \u041f\u043b\u044e\u0441 \u043e\u043d \u0441\u043e\u0437\u0434\u0430\u043d \u043c\u043d\u043e\u0439 \u0434\u043b\u044f \u0434\u0438\u043f\u043b\u043e\u043c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b, \u0434\u0430.<\/p>\n<p>\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0435\u0441\u043b\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u043d\u0435 \u0445\u0432\u0430\u0442\u0438\u043b\u043e, \u043f\u0438\u0448\u0438\u0442\u0435 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u0438\u043b\u0438 \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438, \u0442\u0430\u043c \u043a\u0430\u043a \u0440\u0430\u0437 \u0435\u0449\u0451 \u0435\u0441\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u0440\u0430\u043d\u0441\u043f\u0430\u0439\u043b\u0435\u0440\u0430 <code>Lisp =&gt; Kotlin<\/code>, \u0433\u0434\u0435 \u0438\u0433\u0440\u0443\u0448\u0435\u0447\u043d\u044b\u0439 \u041b\u0438\u0441\u043f \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u041a\u043e\u0442\u043b\u0438\u043d \u043f\u043e \u0449\u0435\u043b\u0447\u043a\u0443 \u043f\u0430\u043b\u044c\u0446\u0430. \u041f\u0440\u043e\u0448\u0443 \u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0437\u0430 \u043d\u0435\u0431\u0440\u0435\u0436\u043d\u043e \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434, \u044f \u0437\u0430\u0439\u043c\u0443\u0441\u044c \u0438\u043c, \u043a\u043e\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u0440\u0435\u043c\u044f.<\/p>\n<p>P. S. Av \u0438\u0437 \u043c\u043e\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u0435\u0440\u0435\u0431\u0440\u0430\u043b\u0441\u044f \u0432 <a href=\"https:\/\/github.com\/Fancryer\/Av\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439<\/a> \u043d\u0430 \u0413\u0438\u0442\u0445\u0430\u0431\u0435, \u043c\u043e\u0436\u0435\u0442\u0435 \u0442\u043e\u0436\u0435 \u0433\u043b\u044f\u043d\u0443\u0442\u044c.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/905766\/\"> https:\/\/habr.com\/ru\/articles\/905766\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0417\u0434\u0440\u0430\u0432\u0441\u0442\u0432\u0443\u0439\u0442\u0435. \u042f \u0443\u0447\u0443\u0441\u044c \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c \u043a\u0443\u0440\u0441\u0435 \u0431\u0430\u043a\u0430\u043b\u0430\u0432\u0440\u0438\u0430\u0442\u0430 \u0438 \u0443\u0436\u0435 \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0441\u044f\u0446 \u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c \u0431\u0443\u0434\u0443 \u0437\u0430\u0449\u0438\u0449\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0432\u044b\u043f\u0443\u0441\u043a\u043d\u0443\u044e \u043a\u0432\u0430\u043b\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 (\u0438\u043b\u0438 \u0436\u0435 \u0434\u0438\u043f\u043b\u043e\u043c\u043d\u0443\u044e). \u041c\u043d\u0435 \u0437\u0430\u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u043e \u043d\u0435\u0451 \u0437\u0434\u0435\u0441\u044c, \u0447\u0435\u043c \u044f \u0441\u0435\u0439\u0447\u0430\u0441 \u0438 \u0437\u0430\u0439\u043c\u0443\u0441\u044c.<\/p>\n<p>\u041c\u0435\u043d\u044f \u0434\u0430\u0432\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u044f\u0437\u044b\u043a\u043e\u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f &#8212; \u043b\u0435\u043a\u0441\u0435\u0440\u044b, \u043f\u0430\u0440\u0441\u0435\u0440\u044b, \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u044b, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u044b \u0438 \u0432\u0441\u044f\u043a\u043e\u0435 \u0442\u0430\u043a\u043e\u0435. \u041d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0442, \u0447\u0442\u043e \u0443\u0436\u0435 \u0432 \u043a\u043e\u043d\u0446\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u0443\u0440\u0441\u0430 \u044f \u0440\u0435\u0448\u0438\u043b\u0430, \u0447\u0442\u043e \u0432 \u043a\u043e\u043d\u0446\u0435 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443 \u0437\u0430\u0449\u0438\u0449\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439 \u044f\u0437\u044b\u043a \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0423\u0432\u044b, \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0434\u0435\u043b\u043e\u043c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u043c, \u0438\u0437-\u0437\u0430 \u0447\u0435\u0433\u043e \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0438\u0441\u043a\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0442\u0435\u043c\u0443. \u041f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043d\u0430 \u0442\u0440\u0435\u0442\u044c\u0435\u043c \u043a\u0443\u0440\u0441\u0435 \u043c\u044b \u0438\u0437\u0443\u0447\u0430\u043b\u0438 \u0432 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442\u0435 Kotlin, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u0441\u0442\u0440\u043e \u0437\u0430\u043f\u0430\u043b \u043c\u043d\u0435 \u0432 \u0434\u0443\u0448\u0443 \u0438 \u0441\u0442\u0430\u043b \u043c\u043e\u0438\u043c \u043b\u044e\u0431\u0438\u043c\u0446\u0435\u043c (\u043f\u043e\u0441\u043b\u0435 Lua). \u041c\u043d\u0435 \u0437\u0430\u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0434\u0438\u043f\u043b\u043e\u043c\u043d\u0443\u044e \u0438\u043c\u0435\u043d\u043d\u043e \u043d\u0430 \u043d\u0451\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0441\u0442\u0430\u043b\u0430 \u0434\u0443\u043c\u0430\u0442\u044c, \u0447\u0442\u043e \u0431\u044b \u0442\u0430\u043a\u043e\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c. \u0422\u0430\u043a \u043a\u0430\u043a \u043c\u0435\u043d\u044f \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043b \u0433\u0435\u0439\u043c\u0434\u0435\u0432, \u044f \u043f\u043e\u0434\u0443\u043c\u0430\u043b\u0430: &#171;\u041f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0434\u0432\u0438\u0436\u043e\u043a \u0434\u043b\u044f \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0445 \u043a\u0432\u0435\u0441\u0442\u043e\u0432 \u043a\u0430\u043a \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0443 Ren&#8217;Py?&#187;. \u041f\u043e\u0434\u0443\u043c\u0430\u043b\u0430 \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0434\u0432\u0438\u0436\u043e\u043a. \u0423\u0432\u044b, \u0432 \u043d\u0451\u043c \u043d\u0435 \u0431\u044b\u043b\u043e \u043d\u0430\u0443\u0447\u043d\u043e\u0439 \u043d\u043e\u0432\u0438\u0437\u043d\u044b, \u0434\u0430 \u0438 \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u0434 \u043d\u0435\u0433\u043e \u0431\u044b\u043b\u043e \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u043e, \u043d\u0443 \u0445\u043e\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0430 \u043e\u043f\u044b\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u044f\u0437\u044b\u0447\u043a\u043e\u0432, \u043a\u043e\u0433\u0434\u0430 \u0434\u0430\u043b\u0430 \u0436\u0438\u0437\u043d\u044c \u0441\u0432\u043e\u0435\u043c\u0443 Av, \u043f\u0440\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0438\u0441\u0430\u043b\u0430 \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<p>\u0412 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442\u0435 \u043c\u043d\u0435 \u0441\u043a\u0430\u0437\u0430\u043b\u0438, \u0447\u0442\u043e \u043f\u043e\u0434\u043e\u0431\u043d\u0430\u044f \u0442\u0435\u043c\u0430 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0437\u0430\u0449\u0438\u0442\u044b, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u044f \u0441\u043d\u043e\u0432\u0430 \u0437\u0430\u0434\u0443\u043c\u0430\u043b\u0430\u0441\u044c, \u0447\u0442\u043e \u0431\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c. \u0412\u0441\u043f\u043e\u043c\u043d\u0438\u043b\u0430, \u0447\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043d\u0435\u043f\u043b\u043e\u0445\u043e \u0437\u043d\u0430\u043a\u043e\u043c\u0430 \u0441 ANTLR, \u0438 \u0440\u0435\u0448\u0438\u043b\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c DSL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043b ANTLR, \u0432 AST Kotlin. \u042d\u0442\u0430 \u043c\u044b\u0441\u043b\u044c \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u043e, \u043d\u043e \u043c\u043d\u0435 \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u0442\u0430\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u0432\u043e \u0447\u0442\u043e \u043e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f. \u041a\u0430\u043a \u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 DSL, \u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0435, \u0437\u0430\u0447\u0435\u043c? \u041a\u0430\u043a \u044f \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u043b\u0430 \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u0432\u043a\u0430\u0444\u0435\u0434\u0440\u043e\u0439, \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u043a\u043e\u0434\u043e\u0432\u044b\u0435 \u0431\u0430\u0437\u044b \u0441 \u0440\u0430\u0437\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432 \u043d\u0430 \u043e\u0434\u0438\u043d &#8212; \u043c\u043e\u0439 \u043b\u044e\u0431\u0438\u043c\u044b\u0439 \u041a\u043e\u0442\u043b\u0438\u043d. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u044d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u0440\u043e\u0432 \u043d\u043e\u0432\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0440\u0430\u043d\u0442\u0430\u0439\u043c, \u0430 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 JVM, \u0432\u0435\u0434\u044c \u041a\u043e\u0442\u043b\u0438\u043d \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u043d\u0451\u043c.<\/p>\n<p>\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0442\u0435\u043c\u0430 \u043c\u043e\u0435\u0439 \u0434\u0438\u043f\u043b\u043e\u043c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u0430\u043a: &#171;DSL ASTra \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0442\u0440\u0430\u043d\u0441\u043f\u0430\u0439\u043b\u0435\u0440\u043e\u0432 \u0438\u0437 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 ANTLR, \u0432 AST Kotlin&#187;. \u041f\u043e\u0447\u0435\u043c\u0443 ASTra? \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e [AS]T [Tra]nspiler. \u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043c\u043e\u0439 DSL \u0438 \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u043e\u0437\u044c\u043c\u0443 \u0442\u0440\u0430\u043d\u0441\u043f\u0430\u0439\u043b\u0435\u0440 <code>STLC =&gt; Kotlin<\/code>.<\/p>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0434\u0432\u0443\u0445 \u0447\u0430\u0441\u0442\u0435\u0439:<\/p>\n<ul>\n<li>\n<p>\u042f\u0434\u0440\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0442\u0440\u0430\u043d\u0441\u043f\u0430\u0439\u043b\u0435\u0440\u044b<\/p>\n<\/li>\n<li>\n<p>\u041e\u043a\u043e\u043b\u043e \u0442\u0440\u0451\u0445 \u0441\u043e\u0442\u0435\u043d \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 AST Kotlin \u0432\u0435\u0440\u0441\u0438\u0438 1.9.22<\/p>\n<\/li>\n<\/ul>\n<p>\u042f\u0434\u0440\u043e \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432:<\/p>\n<ul>\n<li>\n<p>TranspilationRule<\/p>\n<\/li>\n<li>\n<p>RuleBuilder<\/p>\n<\/li>\n<li>\n<p>RuleHolder<\/p>\n<\/li>\n<li>\n<p>RuleHolderBuilder<\/p>\n<\/li>\n<li>\n<p>RuleVisitor<\/p>\n<\/li>\n<li>\n<p>DefaultRule<\/p>\n<\/li>\n<li>\n<p>RuleLogger<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\">\n<div><figcaption>\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u044f\u0434\u0440\u0430 DSL<\/figcaption><\/div>\n<\/figure>\n<p><code>TranspilationRule&lt;P, A&gt;<\/code> &#8212; \u044d\u0442\u043e \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0442\u0440\u0430\u043d\u0441\u043f\u0438\u043b\u044f\u0446\u0438\u0438. \u041c\u044b \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0443 <code>P:ParseTree<\/code> \u0438 <code>A:KotlinAst<\/code>  \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439, \u0447\u0442\u043e\u0431\u044b \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c RuleVisitor \u043c\u043e\u0433 \u0438\u0441\u043a\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0434\u0435\u0440\u0435\u0432\u043e \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u0432 AST.<\/p>\n<p>\u041a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0438\u043b\u0434\u0435\u0440\u0430 TranspilationRule:<\/p>\n<pre><code class=\"kotlin\">val rX = rule&lt;XContext, KSimpleIdentifier&gt;(\"x\") {     from(XContext::class)     how {ctx: XContext -&gt;         ctx.ID().text.id     } }<\/code><\/pre>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0438\u043f\u043e\u0432\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0438 rule, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u043d\u0438 \u0432\u044b\u0432\u0435\u0434\u0443\u0442\u0441\u044f \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u0435\u0437 \u0432\u0441\u044f\u043a\u0438\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c, \u043d\u043e \u044f \u043e\u0431\u044b\u0447\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e \u0438\u0445 \u0432\u0435\u0437\u0434\u0435. \u0424\u0443\u043d\u043a\u0446\u0438\u044f rule \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 type-safe builder, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u044d\u0442\u0430\u043f\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u043e.<\/p>\n<p>XContent &#8212; \u044d\u0442\u043e \u043a\u043b\u0430\u0441\u0441, \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 ANTLR, KSimpleIdentifier &#8212; \u043a\u043b\u0430\u0441\u0441, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0432 AST Kotlin. \u0424\u0443\u043d\u043a\u0446\u0438\u044f how \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e XContent \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f KSimpleIdentifier. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0435\u0449\u0451 howCtx, \u0433\u0434\u0435 ctx \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0440\u0435\u0441\u0438\u0432\u0435\u0440\u043e\u043c, \u0438 howFixed, \u0433\u0434\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0442\u043e\u0440\u0430 \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u0441\u0430\u043c\u0430 how \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0439, \u0437\u0430 \u0441\u0447\u0451\u0442 \u0447\u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0435\u0431\u044f \u0436\u0435 \u0431\u0435\u0437 \u043f\u043e\u0438\u0441\u043a\u0430 \u0441\u0440\u0435\u0434\u0438 \u043f\u0440\u0430\u0432\u0438\u043b. \u041c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043d\u0435 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u043c\u044f \u0441\u0440\u0430\u0437\u0443, \u0430 \u0432\u044b\u0437\u0432\u0430\u0442\u044c <code>name(\"name\")<\/code> \u0432\u043d\u0443\u0442\u0440\u0438 <code>rule {}<\/code>, \u043d\u043e \u043c\u043d\u0435 \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u043c\u044f.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u0441\u043b\u043e\u0436\u043d\u0435\u0435:<\/p>\n<pre><code class=\"kotlin\">val rConditional = rule(\"conditional\") {     from(ConditionalContext::class)     how {ctx: ConditionalContext -&gt;         val tToExp = lookup&lt;TContext, KExpression&gt;()         ?: error(\"ASTra doesn't know how to get KExpression from T\")         tToExp(ctx.pred).ifElse(             tToExp(ctx.if_true).block,             tToExp(ctx.if_false).block         )     } }<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0443\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0432\u044b\u0437\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 lookup. \u042d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0449\u0435\u043c \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0441 \u0442\u0430\u043a\u043e\u0439 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u043e\u0439, \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044f\u0441\u044c \u0435\u0433\u043e \u0438\u043c\u0435\u043d\u0435\u043c \u0438 \u043d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u044f\u0441\u044c \u043a \u043d\u0435\u043c\u0443 \u0445\u0430\u0440\u0434\u043a\u043e\u0434\u043d\u043e.<\/p>\n<p>\u041f\u043e \u0444\u0430\u043a\u0442\u0443 \u0432\u0435\u0441\u044c DSL \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u0430\u0432\u0438\u043b, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0445, \u043a\u0430\u043a \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0430 \u043d\u0435\u043a\u043e\u0435\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0435 \u041a\u043e\u0442\u043b\u0438\u043d\u0430. \u0415\u0441\u0442\u044c, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043d\u043e \u0432 \u0446\u0435\u043b\u043e\u043c \u044d\u0442\u043e \u0432\u0441\u0451. \u0420\u0430\u0437\u0432\u0435 \u0447\u0442\u043e \u0441\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434 \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438 \u043f\u043e\u0441\u043b\u0435, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435 defaultRule, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f, \u0435\u0441\u043b\u0438 \u0434\u043b\u044f \u0443\u0437\u043b\u0430 \u0434\u0435\u0440\u0435\u0432\u0430 \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0439\u0434\u0435\u043d\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u043e.<\/p>\n<p>\u0412\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440 defaultRule:<\/p>\n<pre><code class=\"kotlin\">default {     println(\"default for $it\")     \"TODO\".id() }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0442\u0440\u0430\u043d\u0441\u043f\u0430\u0439\u043b\u0435\u0440\u0430 STLC =&gt; Kotlin \u0446\u0435\u043b\u0438\u043a\u043e\u043c<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">val stlcRuleHolder=rules&lt;StlcLexer,StlcParser&gt; {     default {         println(\"default for ${it::class.simpleName}\")         \"TODO\".id()     }      val rX=         rule(\"x\") {             from(XContext::class)             how {ctx:XContext-&gt; ctx.ID().text.id}         }      val rVariable=         rule(\"variable\") {             from(VariableContext::class)             how {ctx:VariableContext-&gt; rX(ctx.x())}         }      val rTrue=         rule(\"true\") {             from(Constant_trueContext::class)             how {true.ast}         }      val rFalse=         rule(\"false\") {             from(Constant_falseContext::class)             how {false.ast}         }      val rParenthesis=         rule(\"parenthesis\") {             from(ParenthesisContext::class)             how {ctx:ParenthesisContext-&gt;                 val tToExp=lookup&lt;TContext,KExpression&gt;()                            ?: error(\"ASTra doesn't know how to get KExpression from Parenthesis\")                 tToExp(ctx.t()).paren             }         }      val rConditional=         rule(\"conditional\") {             from(ConditionalContext::class)             how {ctx:ConditionalContext-&gt;                 val tToExp=lookup&lt;TContext,KExpression&gt;()                            ?: error(\"ASTra doesn't know how to get KExpression from T\")                 tToExp(ctx.pred).ifElse(                     tToExp(ctx.if_true).block,                     tToExp(ctx.if_false).block                 )             }         }      val rT=         rule(\"t\") {             from(TContext::class)             how {ctx:TContext-&gt;                 when(ctx)                 {                     is VariableContext-&gt;rVariable(ctx)                     is AbstractionContext-&gt;                         lookup&lt;AbstractionContext,KFunctionLiteral&gt;()?.invoke(ctx)                         ?: error(\"ASTra doesn't know how to get KLambdaLiteral from Abstraction\")                      is ApplicationContext-&gt;                         lookup&lt;ApplicationContext,KExpression&gt;()?.invoke(ctx)                         ?: error(\"ASTra doesn't know how to get KExpression from ApplicationContext\")                      is Constant_trueContext-&gt;rTrue(ctx)                     is Constant_falseContext-&gt;rFalse(ctx)                     is ConditionalContext-&gt;rConditional(ctx)                     is ParenthesisContext-&gt;rParenthesis(ctx)                     else-&gt;error(\"ASTra doesn't know how to get KExpression from ${ctx::class.simpleName}\")                 }             }         }      val rApplication=         rule&lt;ApplicationContext,KExpression&gt;(\"application\") {             from(ApplicationContext::class)             how {ctx-&gt;                 val exp=ctx.t(1)                 ctx.t(0).let(rT)(rT(exp))             }         }      val rType=         rule(\"type\") {             from(TypeContext::class)             howFixed {rType-&gt;                 {ctx:TypeContext-&gt;                     val boolify={name:String-&gt;                         if(name==\"Bool\") \"Boolean\" else name                     }                     when(ctx)                     {                         is Flat_typeContext-&gt;boolify(ctx.ID().text).type                          is Abstraction_typeContext-&gt;                             boolify(ctx.ID().text).type                                 .functionTypeParameters                                 .leadsTo(rType(ctx.type()))                                 .type                          else-&gt;error(\"ASTra doesn't know how to get other KType from ${ctx::class.simpleName}\")                     }                 }             }         }      val rAbstraction=         rule&lt;AbstractionContext,KLambdaLiteral&gt;(\"abstraction\") {             from(AbstractionContext::class)             how {ctx-&gt;                 rX(ctx.x()).variableDecl(rType(ctx.type()))                     .lambdaParams                     .literal(rT(ctx.t()).stat)             }         } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u0443\u043c\u0430\u044e, \u0441 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u044c\u044e \u0432\u0441\u0451 \u0431\u043e\u043b\u0435\u0435-\u043c\u0435\u043d\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u043f\u0435\u0440\u0435\u0445\u043e\u0436\u0443 \u043a\u043e \u0432\u0442\u043e\u0440\u043e\u0439. IDEA \u0433\u043e\u0432\u043e\u0440\u0438\u0442, \u0447\u0442\u043e \u0443 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 KotlinAst 282 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430. \u042f \u043d\u0435 \u0431\u0443\u0434\u0443 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u0445 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0430 \u043f\u043e\u0432\u0435\u0440\u044e \u0435\u0439.<\/p>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443 \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u043e\u0432? \u042f \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043b\u0430 <a href=\"https:\/\/kotlinlang.org\/docs\/reference\/grammar.html\" rel=\"noopener noreferrer nofollow\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0435<\/a> \u0438 \u0443\u043f\u0440\u043e\u0449\u0430\u043b\u0430 \u0435\u0451 \u0442\u0430\u043c, \u0433\u0434\u0435 \u044d\u0442\u043e \u0431\u044b\u043b\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u043e \u0432 \u0446\u0435\u043b\u043e\u043c \u043c\u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0451 \u0446\u0435\u043b\u0438\u043a\u043e\u043c, \u043a\u0440\u043e\u043c\u0435 \u043b\u0438\u0448\u043d\u0438\u0445 \u0447\u0430\u0441\u0442\u0435\u0439.<\/p>\n<p>\u041a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e, \u043d\u0430\u0447\u043d\u0443 \u0441 &#171;Hello, world!&#187;:<\/p>\n<pre><code class=\"kotlin\">\"println\".id(\"Hello, world!\".ast)<\/code><\/pre>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0437\u0434\u0435\u0441\u044c <code>println<\/code> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c, \u0430 <code>\"Hello, world!\"<\/code> &#8212; \u0441\u0442\u0440\u043e\u043a\u043e\u0439 \u0432 AST. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 invoke \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c <code>println.id<\/code> \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0447\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e.<\/p>\n<pre><code class=\"kotlin\">val x = \"x\".id<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u0441\u043b\u0430\u043b\u0438\u0441\u044c \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e &#171;x&#187;.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u0441\u043b\u043e\u0436\u043d\u0435\u0435:<\/p>\n<pre><code class=\"kotlin\">val exp: KBinaryExpression = 1.ast + 2.ast <\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438\u043c\u0435\u0435\u0442 \u0442\u0438\u043f KBinaryExpression, \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044e\u0449\u0438\u0439 \u0432 \u0441\u0435\u0431\u0435 KAdditiveExpression \u0438 KMultiplicativeExpression. \u041f\u0443\u0442\u0451\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u0442\u0444\u0438\u043a\u0441\u0430 ast \u043a \u043b\u0438\u0442\u0435\u0440\u0430\u043b\u0443 \u0446\u0435\u043b\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u043c\u044b \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0435\u0433\u043e \u0432 KIntegerLiteral.<\/p>\n<pre><code class=\"kotlin\">\"obj\"[\"prop\".id]<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0431\u0435\u0440\u0451\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e &#171;prop&#187; \u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 &#171;obj&#187;.<\/p>\n<pre><code class=\"kotlin\">val declaration = kval(\"x\", 10.ast)<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430. \u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u043e\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u0435\u043e\u0431\u044b\u0447\u0430\u0439\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043b\u043d\u0430\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044f:<\/p>\n<pre><code class=\"kotlin\">val declaration1 = kval(\"x\") { <\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-458754","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/458754","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=458754"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/458754\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=458754"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=458754"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=458754"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}