{"id":350424,"date":"2023-07-18T15:02:55","date_gmt":"2023-07-18T15:02:55","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=350424"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=350424","title":{"rendered":"<span>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u0432 IntelliJ \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ANTLR<\/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>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f IntelliJ \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 %lang_name% \u0441 \u043d\u0443\u043b\u044f. \u041a\u0440\u043e\u043c\u0435 <a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/custom-language-support.html\" rel=\"noopener noreferrer nofollow\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a> \u0438 <a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/custom-language-support-tutorial.html\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b\u0430<\/a> \u043e\u0442 JetBrains \u0432 \u0441\u0435\u0442\u0438 \u0435\u0441\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0441\u0442\u0430\u0442\u0435\u0439 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432. \u041d\u0430 \u0425\u0430\u0431\u0440\u0435 \u0442\u043e\u0436\u0435 \u0435\u0441\u0442\u044c <a href=\"https:\/\/habr.com\/ru\/articles\/653183\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0430\u0440\u0430<\/a> \u0432\u0435\u0441\u044c\u043c\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0445 <a href=\"https:\/\/habr.com\/ru\/articles\/653667\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u0435\u0439<\/a> \u043e\u0442 <a class=\"mention\" href=\"\/users\/pyltsinm\">@pyltsinm<\/a>. \u0424\u043e\u043a\u0443\u0441 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <a href=\"https:\/\/www.antlr.org\/\" rel=\"noopener noreferrer nofollow\">ANTLR<\/a> \u0438 \u043c\u043e\u0451\u043c \u043e\u043f\u044b\u0442\u0435 \u0432 \u044d\u0442\u043e\u043c \u043d\u0435\u043b\u0451\u0433\u043a\u043e\u043c \u0434\u0435\u043b\u0435.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0431\u0443\u0434\u0435\u0442 <a href=\"https:\/\/plugins.jetbrains.com\/plugin\/21826-webcalm-javascript-and-css\" rel=\"noopener noreferrer nofollow\">WebCalm<\/a> &#8212; \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f IntelliJ \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 JavaScript \u0438 CSS, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0441\u0434\u0435\u043b\u0430\u043b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ANTLR.<\/p>\n<h3>\u041f\u043e\u0447\u0435\u043c\u0443 ANTLR<\/h3>\n<p>\u0414\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u0432 IntelliJ \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 <a href=\"https:\/\/github.com\/JetBrains\/Grammar-Kit\" rel=\"noopener noreferrer nofollow\">Grammar-Kit<\/a> &#8212; \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438 \u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043f\u043e \u043d\u0435\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u0434\u043b\u044f IntelliJ \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u044f\u0437\u044b\u043a\u0430. \u0414\u043b\u044f \u043b\u0435\u043a\u0441\u0435\u0440\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/jflex.de\/\" rel=\"noopener noreferrer nofollow\">JFlex<\/a>, \u0430 \u043f\u0430\u0440\u0441\u0435\u0440 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e <code>*.bnf<\/code> \u0444\u0430\u0439\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0443 \u0432 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A0%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F_%D1%84%D0%BE%D1%80%D0%BC%D0%B0_%D0%91%D1%8D%D0%BA%D1%83%D1%81%D0%B0_%E2%80%94_%D0%9D%D0%B0%D1%83%D1%80%D0%B0\" rel=\"noopener noreferrer nofollow\">\u0420\u0411\u041d\u0424<\/a> \u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0441 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430\u043c\u0438.<\/p>\n<p>\u0414\u043b\u044f \u0442\u0435\u0445 \u043a\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u0435\u0442, <a href=\"https:\/\/ru.wikipedia.org\/wiki\/ANTLR\" rel=\"noopener noreferrer nofollow\">ANTLR<\/a> &#8212; \u044d\u0442\u043e, \u0433\u0440\u0443\u0431\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u043f\u0430\u0440\u0441\u0435\u0440\u043e\u0432. \u041d\u0430 \u0432\u0445\u043e\u0434\u0435 &#8212; \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0430 \u0432 \u0444\u043e\u0440\u043c\u0435 \u0420\u0411\u041d\u0424, \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 &#8212; \u043b\u0435\u043a\u0441\u0435\u0440 \u0438 \u043f\u0430\u0440\u0441\u0435\u0440 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430. \u0414\u043b\u044f ANTLR \u0438\u043c\u0435\u0435\u0442\u0441\u044f <a href=\"https:\/\/github.com\/antlr\/grammars-v4\/\" rel=\"noopener noreferrer nofollow\">\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a<\/a> \u0434\u043b\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0444\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432. \u041a\u043e\u0434 \u0435\u0433\u043e \u043e\u0442\u043a\u0440\u044b\u0442, \u0430 \u0441\u0430\u043c \u043e\u043d \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u0435\u043d \u0438 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0435\u0439 BSD-3.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0434\u043b\u044f \u044f\u0437\u044b\u043a\u0430, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c, \u0443\u0436\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0433\u043e\u0442\u043e\u0432\u0430\u044f ANTLR-\u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0430, \u0430 \u0432\u044b \u043d\u0435 \u0433\u043e\u0440\u0438\u0442\u0435 \u0436\u0435\u043b\u0430\u043d\u0438\u0435\u043c \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0435\u0451 \u043f\u043e\u0434 Grammar-Kit, \u0442\u043e \u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043f\u043e\u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0435\u0451 \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. \u0412 \u044d\u0442\u043e\u043c \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 <a href=\"https:\/\/github.com\/antlr\/antlr4-intellij-adaptor\" rel=\"noopener noreferrer nofollow\">antlr4-intellij-adaptor<\/a> &#8212; \u0430\u0434\u0430\u043f\u0442\u0435\u0440 ANTLR \u0434\u043b\u044f IntelliJ, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u044c \u0438\u0437 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f. \u042d\u0442\u043e \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043e\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u0435\u043b\u0435\u0439 ANTLR \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u043e\u0432 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043b\u0435\u043a\u0441\u0435\u0440\u043e\u0432 \u0438 \u043f\u0430\u0440\u0441\u0435\u0440\u043e\u0432 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 ANTLR \u0432 IntelliJ.<\/p>\n<h2>\u0411\u0430\u0437\u0430<\/h2>\n<p>\u0414\u0443\u043c\u0430\u044e, \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043b\u0438\u0448\u043d\u0438\u043c \u043a\u0440\u0430\u0442\u043a\u043e \u043f\u0440\u043e\u0431\u0435\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u044f\u0437\u044b\u043a\u0430 \u0432 InetlliJ.<\/p>\n<p>\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0432\u0441\u0451, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0441 \u043b\u0435\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0430 (\u0442\u043e\u043a\u0435\u043d\u0438\u0437\u0430\u0446\u0438\u0438). \u0417\u0430 \u044d\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043a\u043b\u0430\u0441\u0441 <a href=\"https:\/\/github.com\/JetBrains\/intellij-community\/blob\/master\/platform\/core-api\/src\/com\/intellij\/lexer\/Lexer.java\" rel=\"noopener noreferrer nofollow\">Lexer<\/a>. \u041e\u043d \u0432\u044b\u0434\u0430\u0451\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0442\u043e\u043a\u0435\u043d\u043e\u0432. \u041a\u0430\u0436\u0434\u044b\u0439 \u0442\u043e\u043a\u0435\u043d \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439 \u0442\u0438\u043f &#8212; <a href=\"https:\/\/github.com\/JetBrains\/intellij-community\/blob\/master\/platform\/core-api\/src\/com\/intellij\/psi\/tree\/IElementType.java\" rel=\"noopener noreferrer nofollow\">IElementType<\/a>. \u041f\u0440\u0438\u0447\u0451\u043c \u043b\u0435\u043a\u0441\u0435\u0440\u0430 \u0443\u0436\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0443 \u0434\u043b\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u044f\u0437\u044b\u043a\u0430 &#8212; \u0437\u0430 \u044d\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 <a href=\"https:\/\/github.com\/JetBrains\/intellij-community\/blob\/master\/platform\/editor-ui-api\/src\/com\/intellij\/openapi\/fileTypes\/SyntaxHighlighter.java\" rel=\"noopener noreferrer nofollow\">SyntaxHighlighter<\/a>.<\/p>\n<p>\u0417\u0430 \u043f\u0430\u0440\u0441\u0438\u043d\u0433 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 <a href=\"https:\/\/github.com\/JetBrains\/intellij-community\/blob\/master\/platform\/core-api\/src\/com\/intellij\/lang\/PsiParser.java\" rel=\"noopener noreferrer nofollow\">PsiParser<\/a>. \u041d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043e\u043d \u0434\u0430\u0451\u0442 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%90%D0%B1%D1%81%D1%82%D1%80%D0%B0%D0%BA%D1%82%D0%BD%D0%BE%D0%B5_%D1%81%D0%B8%D0%BD%D1%82%D0%B0%D0%BA%D1%81%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE\" rel=\"noopener noreferrer nofollow\">AST<\/a> &#8212; \u0434\u0435\u0440\u0435\u0432\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0438\u0437 <a href=\"https:\/\/github.com\/JetBrains\/intellij-community\/blob\/master\/platform\/core-api\/src\/com\/intellij\/lang\/ASTNode.java\" rel=\"noopener noreferrer nofollow\">ASTNode<\/a>. \u041a\u0430\u0436\u0434\u044b\u0439 \u0443\u0437\u0435\u043b \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439 \u0442\u0438\u043f (IElementType). \u041d\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0438 \u0441\u0430\u043c\u0430 IntelliJ \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e (\u043d\u043e \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430) \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 AST \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e &#8212; \u0432\u0441\u0451 \u044d\u0442\u043e \u0434\u043e\u0431\u0440\u043e \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0437\u0430 <a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/psi.html\" rel=\"noopener noreferrer nofollow\">Program Structure Interface<\/a> \u0438\u043b\u0438 \u0441\u043e\u043a\u0440\u0430\u0449\u0451\u043d\u043d\u043e PSI. PSI &#8212; \u043a\u043b\u0430\u0441\u0441\u044b \u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043b\u043e\u0433\u0438\u043a\u0443 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u043c \u044f\u0437\u044b\u043a\u0430 &#8212; \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c, \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c, \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 \u0438 \u0442.\u0434. <\/p>\n<p>\u0422\u0438\u043f\u0438\u0447\u043d\u043e\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u0432 IntelliJ \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<ol>\n<li>\n<p>\u041e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043b\u0435\u043a\u0441\u0435\u0440 \u0438 \u043f\u0430\u0440\u0441\u0435\u0440 \u0432\u043e <code>*.flex<\/code> \u0438 <code>*.bnf<\/code> \u0444\u0430\u0439\u043b\u0430\u0445 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e.<\/p>\n<\/li>\n<li>\n<p>\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043b\u0435\u043a\u0441\u0435\u0440, \u043f\u0430\u0440\u0441\u0435\u0440 \u0438, \u0447\u0442\u043e \u0441\u0430\u043c\u043e\u0435 \u0433\u043b\u0430\u0432\u043d\u043e\u0435, PSI \u043a\u043b\u0430\u0441\u0441\u044b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u043c \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438. \u0412\u0440\u0443\u0447\u043d\u0443\u044e \u0438\u0437 IDE \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/plugins.jetbrains.com\/plugin\/6606-grammar-kit\" rel=\"noopener noreferrer nofollow\">Grammar-Kit<\/a> \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0434\u043b\u044f IntelliJ \u0438\u043b\u0438 \u0438\u0437 Gradle \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/github.com\/JetBrains\/gradle-grammar-kit-plugin\" rel=\"noopener noreferrer nofollow\">gradle-grammar-kit-plugin<\/a>.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u043e\u0431\u0432\u044f\u0437\u043a\u0443 \u0447\u0442\u043e\u0431 \u0432\u0441\u0451 \u044d\u0442\u043e \u0437\u0430\u0432\u0435\u043b\u043e\u0441\u044c.<\/p>\n<\/li>\n<\/ol>\n<h2>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 ANTLR<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c ANTLR-\u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0443 \u0432 IntelliJ.<\/p>\n<h4>\u0413\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0430<\/h4>\n<p>\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0441 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438. \u0418\u0449\u0435\u043c \u043d\u0443\u0436\u043d\u0443\u044e \u043d\u0430\u043c <a href=\"https:\/\/github.com\/antlr\/grammars-v4\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0440\u0435\u0434\u0438 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445<\/a>. \u0412 \u043c\u043e\u0451\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e <a href=\"https:\/\/github.com\/antlr\/grammars-v4\/tree\/master\/javascript\/javascript\" rel=\"noopener noreferrer nofollow\">javascript<\/a> \u0438 <a href=\"https:\/\/github.com\/antlr\/grammars-v4\/tree\/master\/css3\" rel=\"noopener noreferrer nofollow\">css3<\/a> \u0434\u043b\u044f JavaScript \u0438 CSS \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e. \u0422\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b. \u0414\u043b\u044f JavaScript \u044d\u0442\u043e <a href=\"https:\/\/github.com\/antlr\/grammars-v4\/blob\/master\/javascript\/javascript\/Java\/JavaScriptLexerBase.java\" rel=\"noopener noreferrer nofollow\">JavaScriptLexerBase<\/a> \u0438 <a href=\"https:\/\/github.com\/antlr\/grammars-v4\/blob\/master\/javascript\/javascript\/Java\/JavaScriptParserBase.java\" rel=\"noopener noreferrer nofollow\">JavaScriptParserBase<\/a>.<\/p>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438 \u0434\u043b\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u043d\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0438 \u0432\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0451 \u0441 \u043d\u0443\u043b\u044f. \u0412 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044f \u0431\u044b \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043b \u043f\u043e\u0434\u0443\u043c\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u0430 \u043b\u0438 \u043e\u043d\u0430 \u0433\u0434\u0435-\u0442\u043e \u0435\u0449\u0451 \u043a\u0440\u043e\u043c\u0435 IntelliJ. \u0415\u0441\u043b\u0438 \u043d\u0435\u0442, \u0442\u043e \u043b\u0443\u0447\u0448\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0443 \u0434\u043b\u044f Grammar-Kit, \u0442.\u043a. \u044d\u0442\u043e\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0437\u0430\u0442\u043e\u0447\u0435\u043d \u0434\u043b\u044f IntelliJ \u0438 \u0434\u0430\u0451\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 (\u043e \u043d\u0438\u0445 \u043f\u043e\u0437\u0436\u0435).<\/p>\n<h4>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 ANTLR \u0432 Gradle<\/h4>\n<p>\u041a\u0443\u0441\u043e\u0447\u0435\u043a <code>build.gradle.kts<\/code> \u0438\u0437 <a href=\"https:\/\/github.com\/ris58h\/WebCalm\/blob\/master\/build.gradle.kts\" rel=\"noopener noreferrer nofollow\">WebCalm<\/a>:<\/p>\n<pre><code class=\"kotlin\">\/\/ ...  plugins {     \/\/ ...     id(\"antlr\") }  \/\/ ...  val antlrVersion = \"4.12.0\"  dependencies {     implementation(\"org.antlr:antlr4-intellij-adaptor:0.1\") {         constraints {             implementation(\"org.antlr\", \"antlr4-runtime\", antlrVersion) {                 because(\"Old runtime leads to 'Could not deserialize ATN' error.\")             }         }     }     antlr(\"org.antlr\", \"antlr4\", antlrVersion) {         \/\/ Not required for 'generateGrammarSource' task.         exclude(\"com.ibm.icu\", \"icu4j\")         exclude(\"org.abego.treelayout\", \"org.abego.treelayout.core\")     } } \/\/TODO: a hack to exclude antlr4 dependencies from the resulting distribution zip. See https:\/\/github.com\/gradle\/gradle\/issues\/820 configurations[JavaPlugin.API_CONFIGURATION_NAME].let { apiConfiguration ->     apiConfiguration.setExtendsFrom(apiConfiguration.extendsFrom.filter { it.name != \"antlr\" }) }  \/\/ ...<\/code><\/pre>\n<p>\u0421\u043f\u0435\u0440\u0432\u0430 \u0432 <code>plugins<\/code> \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c <code>antlr<\/code> \u043f\u043b\u0430\u0433\u0438\u043d. \u0412 <code>dependencies<\/code> \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0432\u0435\u0440\u0441\u0438\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 (ANLTR \u0438 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u0430) \u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438. \u041d\u0430\u043f\u043e\u0441\u043b\u0435\u0434\u043e\u043a \u0432\u0442\u044b\u043a\u0430\u0435\u043c \u0445\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u043e\u0439\u0442\u0438 <a href=\"https:\/\/github.com\/gradle\/gradle\/issues\/820\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443<\/a> \u0441 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0432\u0441\u0435\u0433\u043e <code>antlr<\/code> \u0432 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c <code>generateGrammarSource<\/code> Gradle-\u0437\u0430\u0434\u0430\u0447\u0430 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043b\u0435\u043a\u0441\u0435\u0440\u0430 \u0438 \u043f\u0430\u0440\u0441\u0435\u0440\u0430 (\u0434\u043b\u044f ANTLR, \u043d\u043e \u043d\u0435 \u0434\u043b\u044f IntelliJ). \u041f\u043e-\u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, ANTLR-\u043f\u043b\u0430\u0433\u0438\u043d \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438 \u0432 <code>src\/main\/antlr<\/code>, \u043d\u043e \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e <a href=\"https:\/\/docs.gradle.org\/current\/dsl\/org.gradle.api.plugins.antlr.AntlrTask.html\" rel=\"noopener noreferrer nofollow\">\u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c<\/a>.<\/p>\n<h4>\u041b\u0435\u043a\u0441\u0435\u0440<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043b\u0435\u043a\u0441\u0435\u0440\u0430 \u0438\u0437 ANTLR-\u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u043b\u0435\u043a\u0441\u0435\u0440\u0430 \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043e\u0442 <code>org.antlr.v4.runtime.Lexer<\/code>. \u0427\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u0435\u0433\u043e \u0432 <code>com.intellij.lexer.Lexer<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 IntelliJ, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 <code>org.antlr.intellij.adaptor.lexer.ANTLRLexerAdaptor<\/code>. \u0412\u0440\u043e\u0434\u0435 \u0432\u0441\u0451 \u043f\u0440\u043e\u0441\u0442\u043e, \u043d\u043e \u0435\u0441\u043b\u0438 \u043a\u043e\u0434 \u043d\u0430 \u0432\u0430\u0448\u0435\u043c \u044f\u0437\u044b\u043a\u0435 \u0432\u0441\u0442\u0440\u043e\u0435\u043d \u0432 \u043a\u043e\u0434 \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u043c (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, JavaScript \u0438 CSS \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0432 HTML), \u0442\u043e, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0432\u044b \u0441\u0442\u043e\u043b\u043a\u043d\u0451\u0442\u0435\u0441\u044c \u0441 <a href=\"https:\/\/github.com\/antlr\/antlr4-intellij-adaptor\/issues\/31\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439<\/a> <code>java.lang.IndexOutOfBoundsException<\/code>. \u0427\u0442\u043e \u0436, \u043f\u0438\u0448\u0435\u043c <a href=\"https:\/\/github.com\/ris58h\/WebCalm\/blob\/master\/src\/main\/kotlin\/ris58h\/webcalm\/antlr\/FixedANTLRLexerAdaptor.kt\" rel=\"noopener noreferrer nofollow\">\u043a\u043e\u0441\u0442\u044b\u043b\u044c<\/a>:<\/p>\n<pre><code class=\"kotlin\">open class FixedANTLRLexerAdaptor(language: Language, lexer: Lexer) : ANTLRLexerAdaptor(language, lexer) {     \/\/ TODO: it's a hack to prevent IndexOutOfBounds exception. See https:\/\/github.com\/antlr\/antlr4-intellij-adaptor\/issues\/31     override fun toLexerState(state: Int): ANTLRLexerState {         if (state == 0) {             return initialState         }         return super.toLexerState(state)     } }<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0442\u043e\u043a\u0435\u043d\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u0442\u044c \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043d\u0438\u043c\u0438, \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0438\u0445 \u0438\u043c\u0435\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 IElementType. \u0414\u043b\u044f \u0438\u0445 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c <code>org.antlr.intellij.adaptor.lexer.PSIElementTypeFactory#defineLanguageIElementTypes<\/code> \u0441 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438. \u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f &#8212; <code>org.antlr.intellij.adaptor.lexer.PSIElementTypeFactory#getTokenIElementTypes<\/code>. \u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 <a href=\"https:\/\/github.com\/ris58h\/WebCalm\/blob\/master\/src\/main\/kotlin\/ris58h\/webcalm\/javascript\/psi\/JavaScriptTypes.kt\" rel=\"noopener noreferrer nofollow\">WebCalm<\/a>:<\/p>\n<pre><code class=\"kotlin\">object JavaScriptTypes {     init {         PSIElementTypeFactory.defineLanguageIElementTypes(             JavaScriptLanguage, JavaScriptLexer.tokenNames, JavaScriptParser.ruleNames         )     }      val FILE = IFileElementType(JavaScriptLanguage)      private val TOKENS = PSIElementTypeFactory.getTokenIElementTypes(JavaScriptLanguage)     val UNEXPECTED_CHARACTER = TOKENS[JavaScriptLexer.UnexpectedCharacter]!!     val WS = TOKENS[JavaScriptLexer.WhiteSpaces]!!     val EOL = TOKENS[JavaScriptLexer.LineTerminator]!!     val LINE_COMMENT = TOKENS[JavaScriptLexer.SingleLineComment]!!     val MULTILINE_COMMENT = TOKENS[JavaScriptLexer.MultiLineComment]!!     val STRING = TOKENS[JavaScriptLexer.StringLiteral]!!     \/\/ ... }<\/code><\/pre>\n<p>Grammar-Kit \u0436\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u0451 \u044d\u0442\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 &#8212; \u044d\u0442\u043e \u0435\u0433\u043e \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u043f\u0435\u0440\u0435\u0434 ANTLR-\u0430\u0434\u0430\u043f\u0442\u0435\u0440\u043e\u043c.<\/p>\n<h4>\u041f\u0430\u0440\u0441\u0435\u0440<\/h4>\n<p>\u0414\u043b\u044f \u043f\u0430\u0440\u0441\u0435\u0440\u0430 \u0442\u043e\u0436\u0435 \u0435\u0441\u0442\u044c \u0430\u0434\u0430\u043f\u0442\u0435\u0440 &#8212; <code>org.antlr.intellij.adaptor.parser.ANTLRParserAdaptor<\/code>. \u041e\u043d \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 AST, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 IntelliJ, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0430\u0440\u0441\u0435\u0440\u0430 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e ANTLR. \u0412\u043d\u0443\u0442\u0440\u0438 \u0430\u0434\u0430\u043f\u0442\u0435\u0440 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 <code>org.antlr.v4.runtime.tree.ParseTree<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u044b\u0434\u0430\u0451\u0442 \u043f\u0430\u0440\u0441\u0435\u0440 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 ANTLR, \u0432 <code>com.intellij.lang.ASTNode<\/code>. \u0414\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>org.antlr.intellij.adaptor.parser.ANTLRParseTreeToPSIConverter<\/code>. \u042d\u0442\u043e \u0442\u0430 \u0442\u043e\u0447\u043a\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u0433\u0434\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0435 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e.<\/p>\n<h4>\u041c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f AST<\/h4>\n<p>\u0412 ANTLR-\u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0435 \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A4%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0\" rel=\"noopener noreferrer nofollow\">\u043d\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0430<\/a> \u0438\u043b\u0438 \u0432\u044b\u0431\u043e\u0440\u0430 \u0438\u0437 \u043d\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432. \u0422\u0430\u043a\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0443\u0434\u043b\u0438\u043d\u044f\u044e\u0442 \u0432\u0435\u0442\u043a\u0438 \u0434\u0435\u0440\u0435\u0432\u0430, \u043d\u043e \u043d\u0435 \u043d\u0435\u0441\u0443\u0442 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u044b:<\/p>\n<pre><code>declaration     : variableStatement     | classDeclaration     | functionDeclaration     ;<\/code><\/pre>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430, \u043d\u043e \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0441\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u0438 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u043a\u0438\u043d\u0443\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438 \u0432 AST \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/github.com\/ris58h\/WebCalm\/blob\/master\/src\/main\/kotlin\/ris58h\/webcalm\/antlr\/CustomParseTreeToPsiConverter.kt\" rel=\"noopener noreferrer nofollow\">\u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0435\u0440\u0430<\/a>:<\/p>\n<pre><code class=\"kotlin\">class CustomParseTreeToPsiConverter(language: Language, parser: Parser, builder: PsiBuilder) : ANTLRParseTreeToPSIConverter(language, parser, builder) {     private var rulesToDrop: Set&lt;Int> = emptySet()     \/\/ ...      override fun exitEveryRule(ctx: ParserRuleContext) {         ProgressIndicatorProvider.checkCanceled()         val ruleIndex = ctx.ruleIndex         if (rulesToDrop.contains(ruleIndex)) {             val marker = markers.pop()             marker.drop()         } else {             \/\/ ...         }     }      \/\/ ... }<\/code><\/pre>\n<p>\u0415\u0449\u0451 \u0432 ANTLR-\u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0435 \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043c\u0435\u0447\u0430\u0442\u044c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u044b \u0432\u044b\u0431\u043e\u0440\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u043a:<\/p>\n<pre><code>anonymousFunction     : Async? Function_ '*'? '(' formalParameterList? ')' functionBody    # AnonymousFunctionDecl     | Async? arrowFunctionParameters '=>' arrowFunctionBody              # ArrowFunction     ;<\/code><\/pre>\n<p><code>AnonymousFunctionDecl<\/code> \u0438 <code>ArrowFunction<\/code> \u043a\u0430\u043a \u0440\u0430\u0437 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0442\u0430\u043a\u0438\u043c\u0438 \u043c\u0435\u0442\u043a\u0430\u043c\u0438. \u041e\u043d\u0438 \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u044e\u0442 \u043d\u043e\u0432\u043e\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0441 \u0442\u0430\u043a\u0438\u043c \u0436\u0435 \u0438\u043c\u0435\u043d\u0435\u043c \u0432\u044b \u0443\u0436\u0435 \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442\u0435. <a href=\"https:\/\/github.com\/antlr\/antlr4\/issues\/4357\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/a> \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0440\u0438 \u043e\u0431\u0445\u043e\u0434\u0435 \u0434\u0435\u0440\u0435\u0432\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0438\u0437 ANTLR, \u043d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u044d\u0442\u0438\u043c \u043c\u0435\u0442\u043a\u0430\u043c. \u0427\u0442\u043e \u0436, \u043d\u0430\u043c \u043d\u0435 \u043f\u043e\u043c\u0435\u0448\u0430\u0435\u0442 \u043b\u0438\u0448\u043d\u0438\u0439 \u043a\u043e\u0441\u0442\u044b\u043b\u044c:<\/p>\n<pre><code class=\"kotlin\">private fun label(ctx: ParserRuleContext): String? {     val javaClass = ctx.javaClass     val isLabeled = javaClass.superclass.canonicalName != \"org.antlr.v4.runtime.ParserRuleContext\"     return if (isLabeled) {         javaClass.simpleName.removeSuffix(\"Context\")     } else null }<\/code><\/pre>\n<p>\u0412 \u043a\u043e\u0434\u0435 \u0432\u044b\u0448\u0435 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0442\u043a\u0438 \u0438\u0437 \u0438\u043c\u0435\u043d\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0430.<\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043c\u0435\u0442\u043a\u0438 \u043a \u043d\u0430\u0448\u0435\u043c\u0443 <a href=\"https:\/\/github.com\/ris58h\/WebCalm\/blob\/master\/src\/main\/kotlin\/ris58h\/webcalm\/antlr\/CustomParseTreeToPsiConverter.kt\" rel=\"noopener noreferrer nofollow\">\u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0435\u0440\u0443<\/a>:<\/p>\n<pre><code class=\"kotlin\">class CustomParseTreeToPsiConverter(language: Language, parser: Parser, builder: PsiBuilder) : ANTLRParseTreeToPSIConverter(language, parser, builder) {     private var rulesToDrop: Set&lt;Int> = emptySet()     private var labeledRules: Map&lt;String, IElementType> = emptyMap()      override fun exitEveryRule(ctx: ParserRuleContext) {         ProgressIndicatorProvider.checkCanceled()         val ruleIndex = ctx.ruleIndex         if (rulesToDrop.contains(ruleIndex)) {             val marker = markers.pop()             marker.drop()         } else {             val marker = markers.pop()             val label = label(ctx)             val ruleIElementType = labeledRules[label] ?: getRuleElementTypes()[ctx.ruleIndex]             marker.done(ruleIElementType)         }     }      fun withRulesToDrop(rulesToDrop: Set&lt;Int>): CustomParseTreeToPsiConverter {         this.rulesToDrop = rulesToDrop         return this     }      fun withLabeledRules(labeledRuleElements: Map&lt;String, IElementType>): CustomParseTreeToPsiConverter {         this.labeledRules = labeledRuleElements         return this     }      private fun label(ctx: ParserRuleContext): String? {         val javaClass = ctx.javaClass         val isLabeled = javaClass.superclass.canonicalName != \"org.antlr.v4.runtime.ParserRuleContext\"         return if (isLabeled) {             javaClass.simpleName.removeSuffix(\"Context\")         } else null     } }<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/github.com\/ris58h\/WebCalm\/blob\/master\/src\/main\/kotlin\/ris58h\/webcalm\/javascript\/JavaScriptParser.kt\" rel=\"noopener noreferrer nofollow\">JavaScriptParser<\/a>.<\/p>\n<h4>PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b<\/h4>\n<p>\u0418 \u0442\u0430\u043a, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0430\u0440\u0441\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0430\u0451\u0442 \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 <code>com.intellij.lang.ASTNode<\/code>. \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0448\u0430\u0433 &#8212; \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u044d\u0442\u043e \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0438\u0437 PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. \u0417\u0430 \u044d\u0442\u043e \u0432 IntelliJ \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 <code>com.intellij.lang.ParserDefinition#createElement<\/code>. \u042d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434, \u043e\u0431\u044b\u0447\u043d\u043e \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u0444\u0430\u0431\u0440\u0438\u043a\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 Grammar-Kit, \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u043d\u043e \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0451 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0440\u0443\u0447\u043a\u0430\u043c\u0438. \u041f\u0440\u0438\u043c\u0435\u0440 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/github.com\/ris58h\/WebCalm\/blob\/master\/src\/main\/kotlin\/ris58h\/webcalm\/javascript\/psi\/JavaScriptTypes.kt\" rel=\"noopener noreferrer nofollow\">JavaScriptTypes$Factory<\/a>:<\/p>\n<pre><code class=\"kotlin\">object JavaScriptTypes {     init {         PSIElementTypeFactory.defineLanguageIElementTypes(             JavaScriptLanguage, JavaScriptLexer.tokenNames, JavaScriptParser.ruleNames         )     }      \/\/ ...      object Factory {         \/\/ ...          private val RULES = PSIElementTypeFactory.getRuleIElementTypes(JavaScriptLanguage)         private val IDENTIFIER = RULES[JavaScriptParser.RULE_identifier]         private val IDENTIFIER_NAME = RULES[JavaScriptParser.RULE_identifierName]         private val LITERAL = RULES[JavaScriptParser.RULE_literal]         private val FUNCTION_DECLARATION = RULES[JavaScriptParser.RULE_functionDeclaration]         \/\/ ...          fun createElement(node: ASTNode): PsiElement {             return when (node.elementType) {                 IDENTIFIER -> JavaScriptIdentifier(node)                 IDENTIFIER_NAME -> JavaScriptIdentifierName(node)                 LITERAL -> JavaScriptLiteral(node)                 FUNCTION_DECLARATION -> JavaScriptFunctionDeclaration(node)                 \/\/ ...                 else -> ASTWrapperPsiElement(node)             }         }          \/\/ ...     } }<\/code><\/pre>\n<p>\u0412 \u043a\u043e\u0434\u0435 \u0432\u044b\u0448\u0435 \u043f\u043e IElementType \u0443\u0437\u043b\u0430 \u0434\u0435\u0440\u0435\u0432\u0430 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442. \u041a\u043b\u0430\u0441\u0441\u044b PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0442\u043e\u0436\u0435 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0440\u0443\u0447\u043a\u0430\u043c\u0438, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 Grammar-Kit, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0445 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0441\u0430\u043c.<\/p>\n<h3>\u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0438\u0448\u043a\u0438<\/h3>\n<p>\u041b\u0435\u043a\u0441\u0435\u0440 \u0438 \u043f\u0430\u0440\u0441\u0435\u0440 \u0433\u043e\u0442\u043e\u0432\u044b (\u0441\u043f\u0430\u0441\u0438\u0431\u043e ANTLR \u0437\u0430 \u044d\u0442\u043e) \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0438\u0448\u0435\u043a: \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0430 \u043a\u043e\u0434\u0430, \u0441\u0432\u0451\u0440\u0442\u043a\u0430 \u043a\u043e\u0434\u0430, \u043f\u043e\u0438\u0441\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0439, \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0442.\u043f. \u0411\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 <a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/custom-language-support.html\" rel=\"noopener noreferrer nofollow\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a> \u0438 <a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/custom-language-support-tutorial.html\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b\u0435<\/a>. \u041d\u0435 \u0441\u0442\u0435\u0441\u043d\u044f\u0439\u0442\u0435\u0441\u044c \u043f\u043e\u0434\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0447\u0442\u043e-\u0442\u043e \u0432 <a href=\"https:\/\/github.com\/ris58h\/WebCalm\/\" rel=\"noopener noreferrer nofollow\">WebCalm<\/a> \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u0430\u0445 \u043d\u0430 GitHub.<\/p>\n<h3>\u041f\u043b\u044e\u0441\u044b \u0438 \u043c\u0438\u043d\u0443\u0441\u044b<\/h3>\n<p>\u041f\u043b\u044e\u0441\u044b:<\/p>\n<ul>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0441\u043e\u043a\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u041c\u0438\u043d\u0443\u0441\u044b:<\/p>\n<ul>\n<li>\n<p>\u0413\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438 \u043d\u0435 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b. \u042f \u0441\u043e\u0437\u0434\u0430\u043b <a href=\"https:\/\/github.com\/antlr\/grammars-v4\/issues?q=is%3Aissue+author%3Aris58h\" rel=\"noopener noreferrer nofollow\">\u0431\u043e\u043b\u0435\u0435 15 issue<\/a> \u043d\u0430 GitHub \u0434\u043b\u044f JavaScript \u0438 CSS \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a. \u0411\u043b\u0430\u0433\u043e, \u0440\u0435\u0431\u044f\u0442\u0430 \u0438\u0437 ANTLR \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0448\u0443\u0441\u0442\u0440\u043e \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0442 <a href=\"https:\/\/github.com\/antlr\/grammars-v4\/issues?q=is%3Aissue+author%3Aris58h\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0430\u0432\u043a\u0438<\/a>.<\/p>\n<\/li>\n<li>\n<p>ANTLR-\u0430\u0434\u0430\u043f\u0442\u0435\u0440 \u0432\u0441\u0451 \u0435\u0449\u0451 \u0438\u043c\u0435\u0435\u0442 \u0432\u0435\u0440\u0441\u0438\u044e <code>0.1<\/code>, \u0438 \u0432 \u043d\u0451\u043c \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0442\u0441\u044f <a href=\"https:\/\/github.com\/antlr\/antlr4-intellij-adaptor\/issues?q=is%3Aissue+author%3Aris58h\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043e\u0431\u0445\u043e\u0434\u0438\u0442\u044c \u0445\u0430\u043a\u0430\u043c\u0438. \u0412\u0441\u0451 \u0436\u0435, \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0432\u0435\u0441\u044c\u043c\u0430 \u043d\u0438\u0448\u0435\u0432\u044b\u0439.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043c\u043d\u043e\u0433\u043e \u0447\u0435\u0433\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0440\u0443\u0447\u043a\u0430\u043c\u0438, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a Grammar-Kit \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438. \u0415\u0441\u0442\u044c \u0434\u0430\u0436\u0435 <a href=\"https:\/\/youtrack.jetbrains.com\/issue\/IDEA-248773\" rel=\"noopener noreferrer nofollow\">\u0437\u0430\u043f\u0440\u043e\u0441<\/a> \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f ANTLR \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a \u0432 Grammar-Kit, \u043d\u043e \u043d\u0435 \u0434\u0443\u043c\u0430\u044e \u0447\u0442\u043e \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u0451\u043d.<\/p>\n<\/li>\n<li>\n<p>\u0412 ANTLR \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0444\u0438\u0448\u043a\u0438 Grammar-Kit. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u044f \u0442\u0430\u043a \u0438 \u043d\u0435 \u043d\u0430\u0448\u0451\u043b \u0441\u043f\u043e\u0441\u043e\u0431 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u043b\u0435 \u043e\u0448\u0438\u0431\u043e\u043a. \u0412 Grammar-Kit \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0447\u0443\u0442\u044c \u043b\u0438 \u043d\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0412\u044b\u0432\u043e\u0434\u044b<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u0430\u044f ANTLR-\u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0430 \u0434\u043b\u044f \u044f\u0437\u044b\u043a\u0430, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 IntelliJ, \u0442\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0435\u0441\u044c\u043c\u0430 \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ANTLR-\u0430\u0434\u0430\u043f\u0442\u0435\u0440\u0430.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0439 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438 \u043d\u0435\u0442, \u0438 \u043e\u043d\u0430 \u043d\u0435 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u0433\u0434\u0435-\u0442\u043e \u0435\u0449\u0451, \u0442\u043e \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Grammar-Kit \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0443 \u0434\u043b\u044f \u043d\u0435\u0433\u043e.<\/p>\n<h3>\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/h3>\n<ul>\n<li>\n<p><a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/custom-language-support.html\" rel=\"noopener noreferrer nofollow\">\u041e\u0444\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438<\/a>\u044f \u0438 <a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/custom-language-support-tutorial.html\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b<\/a> \u043e\u0442 JetBrains \u043f\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u044f\u0437\u044b\u043a\u043e\u0432\u044b\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/antlr\/grammars-v4\/\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/antlr\/grammars-v4\/<\/a> &#8212; \u043d\u0430\u0431\u043e\u0440 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a \u0434\u043b\u044f ANTLR.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/antlr\/antlr4-intellij-adaptor\/\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/antlr\/antlr4-intellij-adaptor\/<\/a> &#8212; ANTLR-\u0430\u0434\u0430\u043f\u0442\u0435\u0440 \u0434\u043b\u044f IntelliJ.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/ris58h\/WebCalm\/\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/ris58h\/WebCalm\/<\/a> &#8212; \u043c\u043e\u0439 \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 JavaScript \u0438 CSS \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0445 ANTLR.<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<p> <!----> <!----><\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/748622\/\"> https:\/\/habr.com\/ru\/articles\/748622\/<\/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>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f IntelliJ \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 %lang_name% \u0441 \u043d\u0443\u043b\u044f. \u041a\u0440\u043e\u043c\u0435 <a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/custom-language-support.html\" rel=\"noopener noreferrer nofollow\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a> \u0438 <a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/custom-language-support-tutorial.html\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b\u0430<\/a> \u043e\u0442 JetBrains \u0432 \u0441\u0435\u0442\u0438 \u0435\u0441\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0441\u0442\u0430\u0442\u0435\u0439 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432. \u041d\u0430 \u0425\u0430\u0431\u0440\u0435 \u0442\u043e\u0436\u0435 \u0435\u0441\u0442\u044c <a href=\"https:\/\/habr.com\/ru\/articles\/653183\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0430\u0440\u0430<\/a> \u0432\u0435\u0441\u044c\u043c\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0445 <a href=\"https:\/\/habr.com\/ru\/articles\/653667\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u0435\u0439<\/a> \u043e\u0442 <a class=\"mention\" href=\"\/users\/pyltsinm\">@pyltsinm<\/a>. \u0424\u043e\u043a\u0443\u0441 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <a href=\"https:\/\/www.antlr.org\/\" rel=\"noopener noreferrer nofollow\">ANTLR<\/a> \u0438 \u043c\u043e\u0451\u043c \u043e\u043f\u044b\u0442\u0435 \u0432 \u044d\u0442\u043e\u043c \u043d\u0435\u043b\u0451\u0433\u043a\u043e\u043c \u0434\u0435\u043b\u0435.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0431\u0443\u0434\u0435\u0442 <a href=\"https:\/\/plugins.jetbrains.com\/plugin\/21826-webcalm-javascript-and-css\" rel=\"noopener noreferrer nofollow\">WebCalm<\/a> &#8212; \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f IntelliJ \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 JavaScript \u0438 CSS, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0441\u0434\u0435\u043b\u0430\u043b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ANTLR.<\/p>\n<h3>\u041f\u043e\u0447\u0435\u043c\u0443 ANTLR<\/h3>\n<p>\u0414\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u0432 IntelliJ \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 <a href=\"https:\/\/github.com\/JetBrains\/Grammar-Kit\" rel=\"noopener noreferrer nofollow\">Grammar-Kit<\/a> &#8212; \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438 \u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043f\u043e \u043d\u0435\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u0434\u043b\u044f IntelliJ \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u044f\u0437\u044b\u043a\u0430. \u0414\u043b\u044f \u043b\u0435\u043a\u0441\u0435\u0440\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/jflex.de\/\" rel=\"noopener noreferrer nofollow\">JFlex<\/a>, \u0430 \u043f\u0430\u0440\u0441\u0435\u0440 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e <code>*.bnf<\/code> \u0444\u0430\u0439\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0443 \u0432 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A0%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F_%D1%84%D0%BE%D1%80%D0%BC%D0%B0_%D0%91%D1%8D%D0%BA%D1%83%D1%81%D0%B0_%E2%80%94_%D0%9D%D0%B0%D1%83%D1%80%D0%B0\" rel=\"noopener noreferrer nofollow\">\u0420\u0411\u041d\u0424<\/a> \u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0441 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430\u043c\u0438.<\/p>\n<p>\u0414\u043b\u044f \u0442\u0435\u0445 \u043a\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u0435\u0442, <a href=\"https:\/\/ru.wikipedia.org\/wiki\/ANTLR\" rel=\"noopener noreferrer nofollow\">ANTLR<\/a> &#8212; \u044d\u0442\u043e, \u0433\u0440\u0443\u0431\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u043f\u0430\u0440\u0441\u0435\u0440\u043e\u0432. \u041d\u0430 \u0432\u0445\u043e\u0434\u0435 &#8212; \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0430 \u0432 \u0444\u043e\u0440\u043c\u0435 \u0420\u0411\u041d\u0424, \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 &#8212; \u043b\u0435\u043a\u0441\u0435\u0440 \u0438 \u043f\u0430\u0440\u0441\u0435\u0440 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430. \u0414\u043b\u044f ANTLR \u0438\u043c\u0435\u0435\u0442\u0441\u044f <a href=\"https:\/\/github.com\/antlr\/grammars-v4\/\" rel=\"noopener noreferrer nofollow\">\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a<\/a> \u0434\u043b\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0444\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432. \u041a\u043e\u0434 \u0435\u0433\u043e \u043e\u0442\u043a\u0440\u044b\u0442, \u0430 \u0441\u0430\u043c \u043e\u043d \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u0435\u043d \u0438 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0435\u0439 BSD-3.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0434\u043b\u044f \u044f\u0437\u044b\u043a\u0430, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c, \u0443\u0436\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0433\u043e\u0442\u043e\u0432\u0430\u044f ANTLR-\u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0430, \u0430 \u0432\u044b \u043d\u0435 \u0433\u043e\u0440\u0438\u0442\u0435 \u0436\u0435\u043b\u0430\u043d\u0438\u0435\u043c \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0435\u0451 \u043f\u043e\u0434 Grammar-Kit, \u0442\u043e \u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043f\u043e\u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0435\u0451 \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. \u0412 \u044d\u0442\u043e\u043c \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 <a href=\"https:\/\/github.com\/antlr\/antlr4-intellij-adaptor\" rel=\"noopener noreferrer nofollow\">antlr4-intellij-adaptor<\/a> &#8212; \u0430\u0434\u0430\u043f\u0442\u0435\u0440 ANTLR \u0434\u043b\u044f IntelliJ, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u044c \u0438\u0437 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f. \u042d\u0442\u043e \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043e\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u0435\u043b\u0435\u0439 ANTLR \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u043e\u0432 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043b\u0435\u043a\u0441\u0435\u0440\u043e\u0432 \u0438 \u043f\u0430\u0440\u0441\u0435\u0440\u043e\u0432 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 ANTLR \u0432 IntelliJ.<\/p>\n<h2>\u0411\u0430\u0437\u0430<\/h2>\n<p>\u0414\u0443\u043c\u0430\u044e, \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043b\u0438\u0448\u043d\u0438\u043c \u043a\u0440\u0430\u0442\u043a\u043e \u043f\u0440\u043e\u0431\u0435\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u044f\u0437\u044b\u043a\u0430 \u0432 InetlliJ.<\/p>\n<p>\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0432\u0441\u0451, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0441 \u043b\u0435\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0430 (\u0442\u043e\u043a\u0435\u043d\u0438\u0437\u0430\u0446\u0438\u0438). \u0417\u0430 \u044d\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043a\u043b\u0430\u0441\u0441 <a href=\"https:\/\/github.com\/JetBrains\/intellij-community\/blob\/master\/platform\/core-api\/src\/com\/intellij\/lexer\/Lexer.java\" rel=\"noopener noreferrer nofollow\">Lexer<\/a>. \u041e\u043d \u0432\u044b\u0434\u0430\u0451\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0442\u043e\u043a\u0435\u043d\u043e\u0432. \u041a\u0430\u0436\u0434\u044b\u0439 \u0442\u043e\u043a\u0435\u043d \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439 \u0442\u0438\u043f &#8212; <a href=\"https:\/\/github.com\/JetBrains\/intellij-community\/blob\/master\/platform\/core-api\/src\/com\/intellij\/psi\/tree\/IElementType.java\" rel=\"noopener noreferrer nofollow\">IElementType<\/a>. \u041f\u0440\u0438\u0447\u0451\u043c \u043b\u0435\u043a\u0441\u0435\u0440\u0430 \u0443\u0436\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0443 \u0434\u043b\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u044f\u0437\u044b\u043a\u0430 &#8212; \u0437\u0430 \u044d\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 <a href=\"https:\/\/github.com\/JetBrains\/intellij-community\/blob\/master\/platform\/editor-ui-api\/src\/com\/intellij\/openapi\/fileTypes\/SyntaxHighlighter.java\" rel=\"noopener noreferrer nofollow\">SyntaxHighlighter<\/a>.<\/p>\n<p>\u0417\u0430 \u043f\u0430\u0440\u0441\u0438\u043d\u0433 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 <a href=\"https:\/\/github.com\/JetBrains\/intellij-community\/blob\/master\/platform\/core-api\/src\/com\/intellij\/lang\/PsiParser.java\" rel=\"noopener noreferrer nofollow\">PsiParser<\/a>. \u041d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043e\u043d \u0434\u0430\u0451\u0442 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%90%D0%B1%D1%81%D1%82%D1%80%D0%B0%D0%BA%D1%82%D0%BD%D0%BE%D0%B5_%D1%81%D0%B8%D0%BD%D1%82%D0%B0%D0%BA%D1%81%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE\" rel=\"noopener noreferrer nofollow\">AST<\/a> &#8212; \u0434\u0435\u0440\u0435\u0432\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0438\u0437 <a href=\"https:\/\/github.com\/JetBrains\/intellij-community\/blob\/master\/platform\/core-api\/src\/com\/intellij\/lang\/ASTNode.java\" rel=\"noopener noreferrer nofollow\">ASTNode<\/a>. \u041a\u0430\u0436\u0434\u044b\u0439 \u0443\u0437\u0435\u043b \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439 \u0442\u0438\u043f (IElementType). \u041d\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0438 \u0441\u0430\u043c\u0430 IntelliJ \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e (\u043d\u043e \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430) \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 AST \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e &#8212; \u0432\u0441\u0451 \u044d\u0442\u043e \u0434\u043e\u0431\u0440\u043e \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0437\u0430 <a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/psi.html\" rel=\"noopener noreferrer nofollow\">Program Structure Interface<\/a> \u0438\u043b\u0438 \u0441\u043e\u043a\u0440\u0430\u0449\u0451\u043d\u043d\u043e PSI. PSI &#8212; \u043a\u043b\u0430\u0441\u0441\u044b \u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043b\u043e\u0433\u0438\u043a\u0443 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u043c \u044f\u0437\u044b\u043a\u0430 &#8212; \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c, \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c, \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 \u0438 \u0442.\u0434. <\/p>\n<p>\u0422\u0438\u043f\u0438\u0447\u043d\u043e\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u0432 IntelliJ \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<ol>\n<li>\n<p>\u041e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043b\u0435\u043a\u0441\u0435\u0440 \u0438 \u043f\u0430\u0440\u0441\u0435\u0440 \u0432\u043e <code>*.flex<\/code> \u0438 <code>*.bnf<\/code> \u0444\u0430\u0439\u043b\u0430\u0445 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e.<\/p>\n<\/li>\n<li>\n<p>\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043b\u0435\u043a\u0441\u0435\u0440, \u043f\u0430\u0440\u0441\u0435\u0440 \u0438, \u0447\u0442\u043e \u0441\u0430\u043c\u043e\u0435 \u0433\u043b\u0430\u0432\u043d\u043e\u0435, PSI \u043a\u043b\u0430\u0441\u0441\u044b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u043c \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438. \u0412\u0440\u0443\u0447\u043d\u0443\u044e \u0438\u0437 IDE \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/plugins.jetbrains.com\/plugin\/6606-grammar-kit\" rel=\"noopener noreferrer nofollow\">Grammar-Kit<\/a> \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0434\u043b\u044f IntelliJ \u0438\u043b\u0438 \u0438\u0437 Gradle \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/github.com\/JetBrains\/gradle-grammar-kit-plugin\" rel=\"noopener noreferrer nofollow\">gradle-grammar-kit-plugin<\/a>.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u043e\u0431\u0432\u044f\u0437\u043a\u0443 \u0447\u0442\u043e\u0431 \u0432\u0441\u0451 \u044d\u0442\u043e \u0437\u0430\u0432\u0435\u043b\u043e\u0441\u044c.<\/p>\n<\/li>\n<\/ol>\n<h2>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 ANTLR<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c ANTLR-\u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0443 \u0432 IntelliJ.<\/p>\n<h4>\u0413\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0430<\/h4>\n<p>\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0441 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438. \u0418\u0449\u0435\u043c \u043d\u0443\u0436\u043d\u0443\u044e \u043d\u0430\u043c <a href=\"https:\/\/github.com\/antlr\/grammars-v4\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0440\u0435\u0434\u0438 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445<\/a>. \u0412 \u043c\u043e\u0451\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e <a href=\"https:\/\/github.com\/antlr\/grammars-v4\/tree\/master\/javascript\/javascript\" rel=\"noopener noreferrer nofollow\">javascript<\/a> \u0438 <a href=\"https:\/\/github.com\/antlr\/grammars-v4\/tree\/master\/css3\" rel=\"noopener noreferrer nofollow\">css3<\/a> \u0434\u043b\u044f JavaScript \u0438 CSS \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e. \u0422\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b. \u0414\u043b\u044f JavaScript \u044d\u0442\u043e <a href=\"https:\/\/github.com\/antlr\/grammars-v4\/blob\/master\/javascript\/javascript\/Java\/JavaScriptLexerBase.java\" rel=\"noopener noreferrer nofollow\">JavaScriptLexerBase<\/a> \u0438 <a href=\"https:\/\/github.com\/antlr\/grammars-v4\/blob\/master\/javascript\/javascript\/Java\/JavaScriptParserBase.java\" rel=\"noopener noreferrer nofollow\">JavaScriptParserBase<\/a>.<\/p>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438 \u0434\u043b\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u043d\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0438 \u0432\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0451 \u0441 \u043d\u0443\u043b\u044f. \u0412 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044f \u0431\u044b \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043b \u043f\u043e\u0434\u0443\u043c\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u0430 \u043b\u0438 \u043e\u043d\u0430 \u0433\u0434\u0435-\u0442\u043e \u0435\u0449\u0451 \u043a\u0440\u043e\u043c\u0435 IntelliJ. \u0415\u0441\u043b\u0438 \u043d\u0435\u0442, \u0442\u043e \u043b\u0443\u0447\u0448\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0443 \u0434\u043b\u044f Grammar-Kit, \u0442.\u043a. \u044d\u0442\u043e\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0437\u0430\u0442\u043e\u0447\u0435\u043d \u0434\u043b\u044f IntelliJ \u0438 \u0434\u0430\u0451\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 (\u043e \u043d\u0438\u0445 \u043f\u043e\u0437\u0436\u0435).<\/p>\n<h4>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 ANTLR \u0432 Gradle<\/h4>\n<p>\u041a\u0443\u0441\u043e\u0447\u0435\u043a <code>build.gradle.kts<\/code> \u0438\u0437 <a href=\"https:\/\/github.com\/ris58h\/WebCalm\/blob\/master\/build.gradle.kts\" rel=\"noopener noreferrer nofollow\">WebCalm<\/a>:<\/p>\n<pre><code class=\"kotlin\">\/\/ ...  plugins {     \/\/ ...     id(\"antlr\") }  \/\/ ...  val antlrVersion = \"4.12.0\"  dependencies {     implementation(\"org.antlr:antlr4-intellij-adaptor:0.1\") {         constraints {             implementation(\"org.antlr\", \"antlr4-runtime\", antlrVersion) {                 because(\"Old runtime leads to 'Could not deserialize ATN' error.\")             }         }     }     antlr(\"org.antlr\", \"antlr4\", antlrVersion) {         \/\/ Not required for 'generateGrammarSource' task.         exclude(\"com.ibm.icu\", \"icu4j\")         exclude(\"org.abego.treelayout\", \"org.abego.treelayout.core\")     } } \/\/TODO: a hack to exclude antlr4 dependencies from the resulting distribution zip. See https:\/\/github.com\/gradle\/gradle\/issues\/820 configurations[JavaPlugin.API_CONFIGURATION_NAME].let { apiConfiguration ->     apiConfiguration.setExtendsFrom(apiConfiguration.extendsFrom.filter { it.name != \"antlr\" }) }  \/\/ ...<\/code><\/pre>\n<p>\u0421\u043f\u0435\u0440\u0432\u0430 \u0432 <code>plugins<\/code> \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c <code>antlr<\/code> \u043f\u043b\u0430\u0433\u0438\u043d. \u0412 <code>dependencies<\/code> \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0432\u0435\u0440\u0441\u0438\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 (ANLTR \u0438 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u0430) \u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438. \u041d\u0430\u043f\u043e\u0441\u043b\u0435\u0434\u043e\u043a \u0432\u0442\u044b\u043a\u0430\u0435\u043c \u0445\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u043e\u0439\u0442\u0438 <a href=\"https:\/\/github.com\/gradle\/gradle\/issues\/820\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443<\/a> \u0441 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0432\u0441\u0435\u0433\u043e <code>antlr<\/code> \u0432 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c <code>generateGrammarSource<\/code> Gradle-\u0437\u0430\u0434\u0430\u0447\u0430 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043b\u0435\u043a\u0441\u0435\u0440\u0430 \u0438 \u043f\u0430\u0440\u0441\u0435\u0440\u0430 (\u0434\u043b\u044f ANTLR, \u043d\u043e \u043d\u0435 \u0434\u043b\u044f IntelliJ). \u041f\u043e-\u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, ANTLR-\u043f\u043b\u0430\u0433\u0438\u043d \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438 \u0432 <code>src\/main\/antlr<\/code>, \u043d\u043e \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e <a href=\"https:\/\/docs.gradle.org\/current\/dsl\/org.gradle.api.plugins.antlr.AntlrTask.html\" rel=\"noopener noreferrer nofollow\">\u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c<\/a>.<\/p>\n<h4>\u041b\u0435\u043a\u0441\u0435\u0440<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043b\u0435\u043a\u0441\u0435\u0440\u0430 \u0438\u0437 ANTLR-\u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u043b\u0435\u043a\u0441\u0435\u0440\u0430 \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043e\u0442 <code>org.antlr.v4.runtime.Lexer<\/code>. \u0427\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u0435\u0433\u043e \u0432 <code>com.intellij.lexer.Lexer<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 IntelliJ, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 <code>org.antlr.intellij.adaptor.lexer.ANTLRLexerAdaptor<\/code>. \u0412\u0440\u043e\u0434\u0435 \u0432\u0441\u0451 \u043f\u0440\u043e\u0441\u0442\u043e, \u043d\u043e \u0435\u0441\u043b\u0438 \u043a\u043e\u0434 \u043d\u0430 \u0432\u0430\u0448\u0435\u043c \u044f\u0437\u044b\u043a\u0435 \u0432\u0441\u0442\u0440\u043e\u0435\u043d \u0432 \u043a\u043e\u0434 \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u043c (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, JavaScript \u0438 CSS \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0432 HTML), \u0442\u043e, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0432\u044b \u0441\u0442\u043e\u043b\u043a\u043d\u0451\u0442\u0435\u0441\u044c \u0441 <a href=\"https:\/\/github.com\/antlr\/antlr4-intellij-adaptor\/issues\/31\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439<\/a> <code>java.lang.IndexOutOfBoundsException<\/code>. \u0427\u0442\u043e \u0436, \u043f\u0438\u0448\u0435\u043c <a href=\"https:\/\/github.com\/ris58h\/WebCalm\/blob\/master\/src\/main\/kotlin\/ris58h\/webcalm\/antlr\/FixedANTLRLexerAdaptor.kt\" rel=\"noopener noreferrer nofollow\">\u043a\u043e\u0441\u0442\u044b\u043b\u044c<\/a>:<\/p>\n<pre><code class=\"kotlin\">open class FixedANTLRLexerAdaptor(language: Language, lexer: Lexer) : ANTLRLexerAdaptor(language, lexer) {     \/\/ TODO: it's a hack to prevent IndexOutOfBounds exception. See https:\/\/github.com\/antlr\/antlr4-intellij-adaptor\/issues\/31     override fun toLexerState(state: Int): ANTLRLexerState {         if (state == 0) {             return initialState         }         return super.toLexerState(state)     } }<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0442\u043e\u043a\u0435\u043d\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u0442\u044c \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043d\u0438\u043c\u0438, \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0438\u0445 \u0438\u043c\u0435\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 IElementType. \u0414\u043b\u044f \u0438\u0445 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c <code>org.antlr.intellij.adaptor.lexer.PSIElementTypeFactory#defineLanguageIElementTypes<\/code> \u0441 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438. \u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f &#8212; <code>org.antlr.intellij.adaptor.lexer.PSIElementTypeFactory#getTokenIElementTypes<\/code>. \u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 <a href=\"https:\/\/github.com\/ris58h\/WebCalm\/blob\/master\/src\/main\/kotlin\/ris58h\/webcalm\/javascript\/psi\/JavaScriptTypes.kt\" rel=\"noopener noreferrer nofollow\">WebCalm<\/a>:<\/p>\n<pre><code class=\"kotlin\">object JavaScriptTypes {     init {         PSIElementTypeFactory.defineLanguageIElementTypes(             JavaScriptLanguage, JavaScriptLexer.tokenNames, JavaScriptParser.ruleNames         )     }      val FILE = IFileElementType(JavaScriptLanguage)      private val TOKENS = PSIElementTypeFactory.getTokenIElementTypes(JavaScriptLanguage)     val UNEXPECTED_CHARACTER = TOKENS[JavaScriptLexer.UnexpectedCharacter]!!     val WS = TOKENS[JavaScriptLexer.WhiteSpaces]!!     val EOL = TOKENS[JavaScriptLexer.LineTerminator]!!     val LINE_COMMENT = TOKENS[JavaScriptLexer.SingleLineComment]!!     val MULTILINE_COMMENT = TOKENS[JavaScriptLexer.MultiLineComment]!!     val STRING = TOKENS[JavaScriptLexer.StringLiteral]!!     \/\/ ... }<\/code><\/pre>\n<p>Grammar-Kit \u0436\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u0451 \u044d\u0442\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 &#8212; \u044d\u0442\u043e \u0435\u0433\u043e \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u043f\u0435\u0440\u0435\u0434 ANTLR-\u0430\u0434\u0430\u043f\u0442\u0435\u0440\u043e\u043c.<\/p>\n<h4>\u041f\u0430\u0440\u0441\u0435\u0440<\/h4>\n<p>\u0414\u043b\u044f \u043f\u0430\u0440\u0441\u0435\u0440\u0430 \u0442\u043e\u0436\u0435 \u0435\u0441\u0442\u044c \u0430\u0434\u0430\u043f\u0442\u0435\u0440 &#8212; <code>org.antlr.intellij.adaptor.parser.ANTLRParserAdaptor<\/code>. \u041e\u043d \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 AST, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 IntelliJ, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0430\u0440\u0441\u0435\u0440\u0430 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e ANTLR. \u0412\u043d\u0443\u0442\u0440\u0438 \u0430\u0434\u0430\u043f\u0442\u0435\u0440 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 <code>org.antlr.v4.runtime.tree.ParseTree<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u044b\u0434\u0430\u0451\u0442 \u043f\u0430\u0440\u0441\u0435\u0440 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 ANTLR, \u0432 <code>com.intellij.lang.ASTNode<\/code>. \u0414\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>org.antlr.intellij.adaptor.parser.ANTLRParseTreeToPSIConverter<\/code>. \u042d\u0442\u043e \u0442\u0430 \u0442\u043e\u0447\u043a\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u0433\u0434\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0435 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e.<\/p>\n<h4>\u041c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f AST<\/h4>\n<p>\u0412 ANTLR-\u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0435 \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A4%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0\" rel=\"noopener noreferrer nofollow\">\u043d\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0430<\/a> \u0438\u043b\u0438 \u0432\u044b\u0431\u043e\u0440\u0430 \u0438\u0437 \u043d\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432. \u0422\u0430\u043a\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0443\u0434\u043b\u0438\u043d\u044f\u044e\u0442 \u0432\u0435\u0442\u043a\u0438 \u0434\u0435\u0440\u0435\u0432\u0430, \u043d\u043e \u043d\u0435 \u043d\u0435\u0441\u0443\u0442 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u044b:<\/p>\n<pre><code>declaration     : variableStatement     | classDeclaration     | functionDeclaration     ;<\/code><\/pre>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430, \u043d\u043e \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0441\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u0438 \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u043a\u0438\u043d\u0443\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438 \u0432 AST \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/github.com\/ris58h\/WebCalm\/blob\/master\/src\/main\/kotlin\/ris58h\/webcalm\/antlr\/CustomParseTreeToPsiConverter.kt\" rel=\"noopener noreferrer nofollow\">\u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0435\u0440\u0430<\/a>:<\/p>\n<pre><code class=\"kotlin\">class CustomParseTreeToPsiConverter(language: Language, parser: Parser, builder: PsiBuilder) : ANTLRParseTreeToPSIConverter(language, parser, builder) {     private var rulesToDrop: Set&lt;Int> = emptySet()     \/\/ ...      override fun exitEveryRule(ctx: ParserRuleContext) {         ProgressIndicatorProvider.checkCanceled()         val ruleIndex = ctx.ruleIndex         if (rulesToDrop.contains(ruleIndex)) {             val marker = markers.pop()             marker.drop()         } else {             \/\/ ...         }     }      \/\/ ... }<\/code><\/pre>\n<p>\u0415\u0449\u0451 \u0432 ANTLR-\u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0435 \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043c\u0435\u0447\u0430\u0442\u044c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u044b \u0432\u044b\u0431\u043e\u0440\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u043a:<\/p>\n<pre><code>anonymousFunction     : Async? Function_ '*'? '(' formalParameterList? ')' functionBody    # AnonymousFunctionDecl     | Async? arrowFunctionParameters '=>' arrowFunctionBody              # ArrowFunction     ;<\/code><\/pre>\n<p><code>AnonymousFunctionDecl<\/code> \u0438 <code>ArrowFunction<\/code> \u043a\u0430\u043a \u0440\u0430\u0437 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0442\u0430\u043a\u0438\u043c\u0438 \u043c\u0435\u0442\u043a\u0430\u043c\u0438. \u041e\u043d\u0438 \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u044e\u0442 \u043d\u043e\u0432\u043e\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0441 \u0442\u0430\u043a\u0438\u043c \u0436\u0435 \u0438\u043c\u0435\u043d\u0435\u043c \u0432\u044b \u0443\u0436\u0435 \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442\u0435. <a href=\"https:\/\/github.com\/antlr\/antlr4\/issues\/4357\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/a> \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0440\u0438 \u043e\u0431\u0445\u043e\u0434\u0435 \u0434\u0435\u0440\u0435\u0432\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0438\u0437 ANTLR, \u043d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u044d\u0442\u0438\u043c \u043c\u0435\u0442\u043a\u0430\u043c. \u0427\u0442\u043e \u0436, \u043d\u0430\u043c \u043d\u0435 \u043f\u043e\u043c\u0435\u0448\u0430\u0435\u0442 \u043b\u0438\u0448\u043d\u0438\u0439 \u043a\u043e\u0441\u0442\u044b\u043b\u044c:<\/p>\n<pre><code class=\"kotlin\">private fun label(ctx: ParserRuleContext): String? {     val javaClass = ctx.javaClass     val isLabeled = javaClass.superclass.canonicalName != \"org.antlr.v4.runtime.ParserRuleContext\"     return if (isLabeled) {         javaClass.simpleName.removeSuffix(\"Context\")     } else null }<\/code><\/pre>\n<p>\u0412 \u043a\u043e\u0434\u0435 \u0432\u044b\u0448\u0435 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0442\u043a\u0438 \u0438\u0437 \u0438\u043c\u0435\u043d\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0430.<\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043c\u0435\u0442\u043a\u0438 \u043a \u043d\u0430\u0448\u0435\u043c\u0443 <a href=\"https:\/\/github.com\/ris58h\/WebCalm\/blob\/master\/src\/main\/kotlin\/ris58h\/webcalm\/antlr\/CustomParseTreeToPsiConverter.kt\" rel=\"noopener noreferrer nofollow\">\u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0435\u0440\u0443<\/a>:<\/p>\n<pre><code class=\"kotlin\">class CustomParseTreeToPsiConverter(language: Language, parser: Parser, builder: PsiBuilder) : ANTLRParseTreeToPSIConverter(language, parser, builder) {     private var rulesToDrop: Set&lt;Int> = emptySet()     private var labeledRules: Map&lt;String, IElementType> = emptyMap()      override fun exitEveryRule(ctx: ParserRuleContext) {         ProgressIndicatorProvider.checkCanceled()         val ruleIndex = ctx.ruleIndex         if (rulesToDrop.contains(ruleIndex)) {             val marker = markers.pop()<\/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-350424","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/350424","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=350424"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/350424\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=350424"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=350424"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=350424"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}