{"id":191252,"date":"2013-08-25T09:20:03","date_gmt":"2013-08-25T05:20:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=191252"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=191252","title":{"rendered":"<span class=\"post_title\">\u0420\u0430\u0437\u0431\u043e\u0440 \u043a\u043e\u0434\u0430 \u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0434\u0435\u0440\u0435\u0432\u044c\u0435\u0432 \u0441 PLY. \u041e\u0441\u043d\u043e\u0432\u044b<\/span>"},"content":{"rendered":"<div class=\"content html_format\">   \t<img decoding=\"async\" align=\"left\" src=\"http:\/\/habrastorage.org\/storage2\/178\/82c\/79e\/17882c79e4443998a0e1020819cc3d3b.png\"\/>  <\/p>\n<h2>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 PLY?<\/h2>\n<p>  <a href=\"http:\/\/www.dabeaz.com\/ply\/ply.html\">PLY<\/a> \u2014 \u044d\u0442\u043e \u0430\u0431\u0431\u0440\u0435\u0432\u0438\u0430\u0442\u0443\u0440\u0430 \u0438\u0437 \u043f\u0435\u0440\u0432\u044b\u0445 \u0431\u0443\u043a\u0432 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f: <strong>P<\/strong>ython <strong>L<\/strong>ex-<strong>Y<\/strong>acc.<br \/>  \u0424\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u044d\u0442\u043e \u043f\u043e\u0440\u0442 \u0443\u0442\u0438\u043b\u0438\u0442 lex \u0438 yacc \u043d\u0430 python \u0432 \u043a\u0440\u0430\u0441\u0438\u0432\u043e\u0439 \u043e\u0431\u0435\u0440\u0442\u043a\u0435.<br \/>  \u0420\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 ply \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u0438 \u043f\u043e\u0440\u043e\u0433 \u0432\u0445\u043e\u0434\u0430 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0443\u043b\u0435\u0432\u043e\u0439.<br \/>  \u041d\u0430\u043f\u0438\u0441\u0430\u043d \u043e\u043d \u043d\u0430 \u0447\u0438\u0441\u0442\u043e\u043c \u043f\u0438\u0442\u043e\u043d\u0435 \u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f <a href=\"http:\/\/ru.wikipedia.org\/wiki\/LALR%281%29\">LALR(1) \u043f\u0430\u0440\u0441\u0435\u0440<\/a>, \u043d\u043e \u043a\u043e\u043c\u0443 \u044d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e?<br \/>  \u042f \u043f\u043e \u043d\u0430\u0442\u0443\u0440\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u043a (\u043a\u0430\u043a \u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0432\u043e \u0438\u0437 \u0432\u0430\u0441) \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0448\u043b\u0438 \u0432 \u0431\u043e\u0439!<\/p>\n<h2>\u0427\u0442\u043e \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c?<\/h2>\n<p>  <a href=\"http:\/\/www.dabeaz.com\/ply\/example.html\">\u041d\u0430 \u0441\u0430\u0439\u0442\u0435 \u0435\u0441\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440<\/a> \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0433\u043e \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c\u0441\u044f \u043d\u0435 \u0431\u0443\u0434\u0435\u043c. \u0410 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0447\u0442\u043e-\u0442\u043e \u043d\u0430\u0432\u0440\u043e\u0434\u0435 \u043f\u0430\u0440\u0441\u0435\u0440\u0430 \u043e\u0447\u0435\u043d\u044c \u043e\u0447\u0435\u043d\u044c \u0443\u0437\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 PHP \ud83d\ude42<br \/>  \u041d\u0430\u0448\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e \u0434\u043b\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430:<\/p>\n<pre><code class=\"php\">&lt;?php $val = 5; $result = substr( &quot;foobar&quot;, 2*(7-$val) ); echo &quot;\u044d\u0442\u043e \u043d\u0430\u0448 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442: $result&quot;; <\/code><\/pre>\n<p>  \u041f\u0440\u0438\u043c\u0435\u0440 \u043e\u0447\u0435\u043d\u044c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439 \u0438 \u0432\u0437\u044f\u0442 \u0441 \u043f\u043e\u0442\u043e\u043b\u043a\u0430. \u041d\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0434\u0435\u0440\u0435\u0432\u043e \u043a\u043e\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0438 \u043f\u043e\u0445\u043e\u0434\u0443 \u043c\u044b \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c PLY \u043a\u0430\u043a state.<\/p>\n<p>  <a name=\"habracut\"><\/a><\/p>\n<h4>Lex<\/h4>\n<p>  <a href=\"http:\/\/ru.wikipedia.org\/wiki\/Lex\">Lex<\/a> \u2014 \u044d\u0442\u043e \u0448\u0442\u0443\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u0442 \u0442\u0435\u043a\u0441\u0442 \u043d\u0430 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u044f\u0437\u044b\u043a\u0430. \u041d\u0443 \u0438\u043b\u0438 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u0443\u0435\u0442 \u0442\u0435\u043a\u0441\u0442 \u0432 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b. \u041a\u0430\u043a-\u0442\u043e \u0442\u0430\u043a.<\/p>\n<p>  \u0427\u0442\u043e \u043c\u044b \u0437\u0434\u0435\u0441\u044c \u0432\u0438\u0434\u0438\u043c, \u043a\u0440\u043e\u043c\u0435 \u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430? \u0412\u0438\u0434\u0438\u043c \u0442\u043e\u043a\u0435\u043d\u044b (\u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b):<br \/>  PHP_START \u2014 &#8216;&lt;?php&#8217;<br \/>  PHP_VAR \u2014 &#8216;$result&#8217;<br \/>  PHP_EQUAL \u2014 &#8216;=&#8217;<br \/>  PHP_NAME \u2014 &#8216;substr&#8217;<br \/>  PHP_OPEN \u2014 &#8216;(&#8216;<br \/>  PHP_STRING \u2014 \u00abfoobar\u00bb, &#8216;\u044d\u0442\u043e \u043d\u0430\u0448 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442: $result&#8217;<br \/>  PHP_NUM \u2014 &#8216;2&#8217;, &#8216;7&#8217;<br \/>  PHP_CLOSE \u2014 &#8216;)&#8217; <br \/>  PHP_ECHO \u2014 \u00abecho\u00bb<br \/>  PHP_COLON \u2014 &#8216;;&#8217;<br \/>  PHP_COMA \u2014 &#8216;,&#8217;<br \/>  PHP_PLUSMINUS \u2014 &#8216;-&#8216;<br \/>  PHP_DIVMUL \u2014 &#8216;*&#8217;<\/p>\n<p>  \u0414\u043b\u044f \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u0442\u0435\u043a\u0441\u0442\u0430 \u043d\u0430 \u0442\u043e\u043a\u0435\u043d\u044b \u0432 PLY \u0438\u043c\u0435\u0435\u0442\u0441\u044f <i>ply.lex<\/i>. \u0418 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043e\u043d \u0441 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u043c\u0438 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u043c\u0438.<br \/>  \u0410 \u0435\u0449\u0435 \u043e\u043d \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u0438\u0434\u0438\u0440\u0447\u0438\u0432\u044b\u0439 \u043a \u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043c\u044b \u043f\u0438\u0448\u0435\u043c \u0432 \u043a\u043e\u0434\u0435. \u041e\u043d \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c tokens.<br \/>  \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u044d\u0442\u043e\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u043c\u044b \u043e\u0431\u044f\u0437\u0430\u043d\u044b \u0438\u043c\u0435\u0442\u044c \u0432 \u043a\u043e\u0434\u0435 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0443 \u0438\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0441 \u0438\u043c\u0435\u043d\u0435\u043c t_\u042d\u041b\u0415\u041c\u0415\u041d\u0422.<br \/>  \u041f\u043e\u0447\u0435\u043c\u0443 \u043e\u043d \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u0438\u0434\u0438\u0440\u0447\u0438\u0432\u044b\u0439? \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043b\u0438\u0448\u044c \u0435\u0434\u0438\u043d\u043e\u0436\u0434\u044b \u043f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0444\u0430\u0439\u043b lextab.py, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u0432 \u0438 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0438. \u041f\u0440\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043e\u043d \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0438 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0433\u043e \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u0443\u0436\u0435 \u043d\u0435 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0437\u0430\u043d\u043e\u0432\u043e, \u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435.<br \/>  \u041d\u0430\u0437\u0430\u0434 \u043a \u043a\u043e\u0434\u0443.<br \/>  \u0415\u0441\u043b\u0438 \u0431\u044b \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 PHP \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u043b\u0441\u044f \u0442\u0440\u0438\u043d\u0430\u0434\u0446\u0430\u0442\u044c\u044e \u0432\u044b\u0448\u0435 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0442\u043e\u043a\u0435\u043d\u0430\u043c\u0438, \u0442\u043e \u043c\u044b \u0431\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<pre><code class=\"python\"># coding=utf8 import ply.lex as lex  # \u0431\u0435\u0437 \u044d\u0442\u043e\u0439 \u0448\u0442\u0443\u043a\u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0441\u044a\u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u043c\u0430\u0441\u0441\u0438\u0432 \u0448\u0430\u0440\u0438\u0442\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u043b\u0435\u043a\u0441\u0435\u0440\u043e\u043c \u0438 \u043f\u0430\u0440\u0441\u0435\u0440\u043e\u043c \u0438 \u043a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 tokens = (     'PHPSTART', 'PHPVAR', 'PHPEQUAL', 'PHPFUNC',     'PHPSTRING', 'PHPECHO', 'PHPCOLON', 'PHPCOMA',     'PHPOPEN', 'PHPCLOSE', 'PHPNUM', 'PLUSMINUS', 'DIVMUL' )  # \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0443 \u0434\u043b\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0433\u043e \u0438\u0434\u0435\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 ident = r'[a-z]\\w*'  # \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430 \u0438\u0437 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0432\u0438\u0434\u0430 t_\u0418\u041c\u042f\u0422\u041e\u041a\u0415\u041d\u0410 = \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0430 t_PHPSTART = r'\\&lt;\\?php' t_PHPVAR = r'\\$'+ident # \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e, \u043f\u0440\u0430\u0432\u0434\u0430? t_PHPEQUAL = r'\\=' t_PHPFUNC = ident t_PHPSTRING = r'&quot;(\\\\.|[^&quot;])*&quot;' t_PHPECHO = r'echo' t_PHPCOLON = r';' t_PHPCOMA = r',' t_PHPOPEN = r'\\(' t_PHPCLOSE = r'\\)' t_PHPNUM = r'\\d+' t_PLUSMINUS = r'\\+|\\-' t_DIVMUL = r'\/|\\*'  # \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u0435\u0437\u043d\u0430\u0447\u0430\u0449\u0438\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b. \u041d\u0430\u043c \u0432\u0435\u0434\u044c \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e $var=$value \u0438\u043b\u0438 $var&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;$value t_ignore = ' \\r\\n\\t\\f'  # \u0430 \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0438. \u041a\u0441\u0442\u0430\u0442\u0438 \u0437\u0430\u043c\u0435\u0442\u044c\u0442\u0435 \u0444\u043e\u0440\u043c\u0430\u0442 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 def t_error(t):     print &quot;Illegal character '%s'&quot; % t.value[0]     t.lexer.skip(1)  lexer = lex.lex(reflags=re.UNICODE | re.DOTALL)  data = ''' &lt;?php $result = substr(&quot;foobar&quot;, &quot;bar&quot;); echo $result; '''  lexer.input(data)  while True:     tok = lexer.token() # \u0447\u0438\u0442\u0430\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d     if not tok: break      # \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438\u0441\u044c \u043f\u0435\u0447\u0435\u043d\u044c\u043a\u0438     print tok <\/code><\/pre>\n<p>  \u0412 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0445 \u043a \u043a\u043e\u0434\u0443 \u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u043b \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0442\u0430\u043c \u0442\u0432\u043e\u0440\u0438\u0442\u0441\u044f. \u0417\u0430\u043c\u0435\u0447\u0443 \u043b\u0438\u0448\u044c, \u0447\u0442\u043e \u0432\u043c\u0435\u0441\u0442\u043e \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043e\u043a, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0438\u0445 \u0442\u043e\u043a\u0435\u043d, <a href=\"http:\/\/www.dabeaz.com\/ply\/ply.html#ply_nn6\">\u043c\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/a> \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0443\u0442 \u044d\u0442\u0438 \u0436\u0435 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0438, \u043d\u043e \u043a\u0440\u043e\u043c\u0435 \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0442\u0443\u0434\u0430 \u0432\u043f\u0438\u0441\u0430\u0442\u044c \u0447\u0442\u043e-\u0442\u043e \u0435\u0449\u0435 \u0441\u0432\u043e\u0435. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"python\">def t_PHPVAR(t):     r'\\$[a-zA-Z]\\w*'     print '\u0423\u0440\u0440\u0430, \u043c\u044b \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e ' + t.value # value - \u044d\u0442\u043e \u0442\u043e \u0447\u0442\u043e \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u043e\u0439     return t <\/code><\/pre>\n<p>  \u041a\u0441\u0442\u0430\u0442\u0438 \u0432\u044b\u0432\u043e\u0434 \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u0447\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u0432\u044b\u0448\u0435 \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u0438\u043c:<\/p>\n<pre>LexToken(PHPSTART,'&lt;?php',1,1) LexToken(PHPVAR,'$val',1,7) LexToken(PHPEQUAL,'=',1,12) LexToken(PHPNUM,'5',1,14) LexToken(PHPCOLON,';',1,15) LexToken(PHPVAR,'$result',1,17) LexToken(PHPEQUAL,'=',1,25) LexToken(PHPFUNC,'substr',1,27) LexToken(PHPOPEN,'(',1,33) LexToken(PHPSTRING,'&quot;foobar&quot;',1,35) LexToken(PHPCOMA,',',1,43) LexToken(PHPNUM,'2',1,45) LexToken(DIVMUL,'*',1,46) LexToken(PHPOPEN,'(',1,47) LexToken(PHPNUM,'7',1,48) LexToken(PLUSMINUS,'-',1,49) LexToken(PHPVAR,'$val',1,50) LexToken(PHPCLOSE,')',1,54) LexToken(PHPCLOSE,')',1,56) LexToken(PHPCOLON,';',1,57) LexToken(PHPFUNC,'echo',1,59) LexToken(PHPSTRING,'&quot;\\xd1\\x8d\\xd1\\x82\\xd0\\xbe \\xd0\\xbd\\xd0\\xb0\\xd1\\x88 \\xd1\\x80\\xd0\\xb5\\xd0\\xb7\\xd1\\x83\\xd0\\xbb\\xd1\\x8c\\xd1\\x82\\xd0\\xb0\\xd1\\x82: $result&quot;',1,64) LexToken(PHPCOLON,';',1,107) <\/pre>\n<p>  \u0427\u0438\u0441\u043b\u0430 \u0432 \u043a\u043e\u043d\u0446\u0435 \u2014 \u044d\u0442\u043e \u043d\u043e\u043c\u0435\u0440 \u0441\u0442\u0440\u043e\u043a\u0438 \u0438 \u043d\u043e\u043c\u0435\u0440 \u0441\u0438\u043c\u0432\u043e\u043b\u0430. \u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u043d\u043e\u043c\u0435\u0440 \u0441\u0442\u0440\u043e\u043a\u0438 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f. \u0415\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u043c\u0435\u043d\u044f\u0442\u044c \u0441\u0430\u043c\u0438\u043c. \u041a\u0430\u043a? \u041f\u0440\u0438 \u043f\u0440\u043e\u0445\u043e\u0434\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 \u0441 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u043c \u043d\u0430 \u043d\u043e\u0432\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0443\u0431\u0435\u0440\u0435\u043c \u0441\u0438\u043c\u0432\u043e\u043b \u043d\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u0438\u0437 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c\u044b\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e t_newline:<\/p>\n<pre><code class=\"python\">t_ignore = ' \\r\\t\\f'  def t_newline(t):     r'\\n+'     t.lexer.lineno += len(t.value) <\/code><\/pre>\n<p>  \u0412\u043e\u0442 \u0442\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<pre> LexToken(PHPSTART,'&lt;?php',2,1) LexToken(PHPVAR,'$val',3,7) LexToken(PHPEQUAL,'=',3,12) LexToken(PHPNUM,'5',3,14) LexToken(PHPCOLON,';',3,15) LexToken(PHPVAR,'$result',4,17) LexToken(PHPEQUAL,'=',4,25) LexToken(PHPFUNC,'substr',4,27) LexToken(PHPOPEN,'(',4,33) LexToken(PHPSTRING,'&quot;foobar&quot;',4,35) LexToken(PHPCOMA,',',4,43) LexToken(PHPNUM,'2',4,45) LexToken(DIVMUL,'*',4,46) LexToken(PHPOPEN,'(',4,47) LexToken(PHPNUM,'7',4,48) LexToken(PLUSMINUS,'-',4,49) LexToken(PHPVAR,'$val',4,50) LexToken(PHPCLOSE,')',4,54) LexToken(PHPCLOSE,')',4,56) LexToken(PHPCOLON,';',4,57) LexToken(PHPFUNC,'echo',5,59) LexToken(PHPSTRING,'&quot;\\xd1\\x8d\\xd1\\x82\\xd0\\xbe \\xd0\\xbd\\xd0\\xb0\\xd1\\x88 \\xd1\\x80\\xd0\\xb5\\xd0\\xb7\\xd1\\x83\\xd0\\xbb\\xd1\\x8c\\xd1\\x82\\xd0\\xb0\\xd1\\x82: $result&quot;',5,64) LexToken(PHPCOLON,';',5,107) <\/pre>\n<p>  \u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u043e \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e. \u041d\u0430\u0448\u0430 \u0441\u0442\u0440\u043e\u043a\u0430 \u00ab\u044d\u0442\u043e \u043d\u0430\u0448 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442: $result\u00bb \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043b\u0435\u043a\u0441\u0435\u0440\u043e\u043c \u043a\u0430\u043a \u0435\u0441\u0442\u044c. \u0410 \u043a\u0430\u043a \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0435\u0451 \u0431\u0443\u0434\u0435\u043c? \u0421\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043b\u0435\u043a\u0441\u0435\u0440? \u041d\u0435\u0430. \u0412 PLY (\u0434\u0430 \u0438 \u0432 \u0441\u0438\u0448\u043d\u043e\u043c lex) \u0435\u0441\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0442\u0430\u043a\u043e\u0439 \u0448\u0442\u0443\u043a\u0438 \u043a\u0430\u043a state. <a href=\"http:\/\/www.dabeaz.com\/ply\/ply.html#ply_nn21\">State<\/a> \u2014 \u044d\u0442\u043e \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u043b\u043a\u0430 \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u0442\u0438\u043f \u0442\u043e\u043a\u0435\u043d\u043e\u0432. \u0412\u043e\u0442 \u044d\u0442\u043e \u043c\u044b \u0438 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c.<\/p>\n<h6>State<\/h6>\n<p>  \u0418\u0442\u0430\u043a, \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 state \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0435\u0433\u043e \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c:<\/p>\n<pre><code class=\"python\">states = (    ('string','exclusive'), ) <\/code><\/pre>\n<p>  &#8216;string&#8217; \u2014 \u044d\u0442\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u0430 exclusive \u2014 \u044d\u0442\u043e \u0442\u0438\u043f. \u0412\u043e\u043e\u0431\u0449\u0435, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0434\u0432\u0430 \u0442\u0438\u043f\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439: exclusive \u0438 inclusive. Exclusive \u2014 \u043e\u0431\u0449\u0438\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u043d\u0435 \u0432\u0438\u0434\u043d\u043e (\u043e\u0431\u0449\u0438\u0435, \u044d\u0442\u043e \u0442\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043f\u0438\u0441\u0430\u043b\u0438 \u0434\u043e \u044d\u0442\u043e\u0433\u043e, \u043e\u043d\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 INITIAL). Inclusive \u2014 \u0432\u0438\u0434\u043d\u044b \u043e\u0431\u0449\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u044b \u0438 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a \u043d\u0438\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435.<br \/>  \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430\u0448\u0435\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u043d\u0430\u043c \u043d\u0435 \u043d\u0443\u0436\u043d\u044b \u0434\u0440\u0443\u0433\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u044b, \u0442\u0430\u043a \u043a\u0430\u043a \u0432\u043d\u0443\u0442\u0440\u0438 \u0443 \u043d\u0430\u0441 \u0442\u0430\u043c \u0432\u0441\u0435 \u043f\u043e \u0434\u0440\u0443\u0433\u043e\u043c\u0443. \u0412\u043f\u0440\u043e\u0447\u0435\u043c \u043f\u0430\u0440\u043e\u0447\u043a\u0443 \u043c\u044b \u043f\u043e\u0437\u0430\u0438\u043c\u0441\u0442\u0432\u0443\u0435\u043c. \u041d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0442\u043e\u043a\u0435\u043d PHPVAR, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0443 \u043d\u0430\u0441 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e \u0438 \u0441\u043d\u0430\u0440\u0443\u0436\u0438 \u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0442\u0440\u043e\u043a\u0438, \u0438 \u043d\u0443\u0436\u0435\u043d \u0431\u0443\u0434\u0435\u0442 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0442\u043e\u043a\u0435\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u043f\u043e\u0445\u043e\u0434\u0443 \u043d\u0438\u0436\u0435.<br \/>  \u0427\u0442\u043e\u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u043e\u0431\u0449\u0438\u043c \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0442\u044c \u0435\u043c\u0443 \u043f\u0440\u0435\u0444\u0438\u043a\u0441 ANY_, \u043d\u0443 \u0430 \u0447\u0442\u043e\u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u0432\u0438\u0434\u0438\u043c\u044b\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043a\u0430\u043a\u043e\u0433\u043e-\u0442\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u2014 &lt;\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435&gt;_. \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0435 \u0442\u043e\u043a\u0435\u043d\u044b.<\/p>\n<pre><code class=\"python\"># \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430 \u0438\u0437 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0432\u0438\u0434\u0430 t_\u0418\u041c\u042f\u0422\u041e\u041a\u0415\u041d\u0410 = \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0430 t_PHPSTART = r'\\&lt;\\?php' t_ANY_PHPVAR = r'\\$'+ident # \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e, \u043f\u0440\u0430\u0432\u0434\u0430? t_PHPEQUAL = r'\\=' t_PHPFUNC = ident t_PHPECHO = r'echo' t_PHPCOLON = r';' t_PHPCOMA = r',' t_PHPOPEN = r'\\(' t_PHPCLOSE = r'\\)' t_PHPNUM = r'\\d+' t_PLUSMINUS = r'\\+|\\-' t_DIVMUL = r'\/|\\*'  # \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0438 \u0442\u043e\u043a\u0435\u043d PHPSTRING \u0438 \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0438\u0437 \u043d\u0435\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0435\u0433\u043e \u0432\u043e \u0432\u0441\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f def t_ANY_PHPSTRING(t): # \u043d\u0443\u0436\u0435\u043d \u0432 \u043e\u0431\u043e\u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u0445, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0434\u0432\u043e\u0439\u043d\u044b\u0435 \u043a\u0430\u0432\u044b\u0447\u043a\u0438 \u043c\u0430\u0442\u0447\u0430\u0442\u0441\u044f \u0438 \u0442\u0430\u043c \u0438 \u0442\u0430\u043c.     r'&quot;'     if t.lexer.current_state() == 'string':         t.lexer.begin('INITIAL') # \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435     else:         t.lexer.begin('string') # \u043f\u0430\u0440\u0441\u0438\u043c \u0441\u0442\u0440\u043e\u043a\u0443     return t  t_string_STR = r'(\\\\.|[^$&quot;])+' # \u043f\u0430\u0440\u0441\u0438\u043c \u043f\u043e\u043a\u0430 \u043d\u0435 \u0434\u043e\u0439\u0434\u0435\u043c \u0434\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0438\u043b\u0438 \u0434\u043e \u043a\u0430\u0432\u044b\u0447\u043a\u0438, \u043f\u043e\u043f\u0443\u0442\u043d\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u044d\u043a\u0440\u0430\u043d\u043a\u0438  # \u0433\u043e\u0432\u043e\u0440\u0438\u043c \u0447\u0442\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c t_string_ignore = '' # \u044d\u0442\u043e \u043a\u0441\u0442\u0430\u0442\u0438 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f, \u0431\u0435\u0437 \u043d\u0435\u0451 \u043d\u0435\u043b\u044c\u0437\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 state  # \u043d\u0443 \u0438 \u043a\u0443\u0434\u0430 \u0436\u0435 \u043c\u044b \u0431\u0435\u0437 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0448\u0438\u0431\u043e\u043a def t_string_error(t):     print &quot;Illegal character '%s'&quot; % t.value[0]     t.lexer.skip(1) <\/code><\/pre>\n<p>  \u041a\u0441\u0442\u0430\u0442\u0438, \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438 \u044d\u0442\u043e: <i>LexToken(PHPFUNC,&#8217;echo&#8217;,5,59)<\/i>?<br \/>  PLY \u043f\u0435\u0440\u0435\u0434 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0441\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043f\u043e \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u043d\u0438\u044e \u0438 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 \u043f\u043e\u0431\u0435\u0436\u0434\u0430\u0435\u0442 \u0434\u043b\u0438\u043d\u043d\u0435\u0439\u0448\u0435\u0435. \u0412\u043e\u0442 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 echo \u0438 \u043d\u0435 \u043f\u0430\u0440\u0441\u0438\u0442\u0441\u044f \u043a\u0430\u043a PHPECHO. \u041a\u0430\u043a \u044d\u0442\u043e \u043e\u0431\u043e\u0439\u0442\u0438? \u041b\u0435\u0433\u043a\u043e. \u041f\u0440\u043e\u0441\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0442\u0438\u043f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438.<br \/>  \u0412\u043e\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"python\">@TOKEN(ident) def t_PHPFUNC(t):     if t.value.lower() == 'echo':         t.type = 'PHPECHO'     return t <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c echo \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043d\u0443\u0436\u043d\u043e. \u041a\u0441\u0442\u0430\u0442\u0438 \u043e \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u0435 <a href=\"http:\/\/www.dabeaz.com\/ply\/ply.html#ply_nn14\"><a href=\"http:\/\/habrahabr.ru\/users\/token\/\" class=\"user_link\">TOKEN<\/a><\/a>: \u0432\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0438\u0441\u0430\u0442\u044c \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0443 \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0442\u0435\u043b\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0435\u0451 \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043a \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043a\u0430\u043a \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440. \u0427\u0442\u043e \u043c\u044b \u0438 \u0441\u0434\u0435\u043b\u0430\u043b\u0438.<\/p>\n<p>  \u0412\u043e\u0442. \u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0440\u043e\u0434\u0435 \u0432\u0441\u0435. \u0414\u0430 \u043d\u0435 \u0432\u0441\u0435.<br \/>  \u041d\u0435\u043f\u043b\u043e\u0445\u043e \u0431\u044b \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438.<br \/>  \u0427\u0442\u043e \u0436\u0435, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0449\u0435 \u043e\u0434\u043d\u0443 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0432 \u043b\u0435\u043a\u0441\u0435\u0440:<\/p>\n<pre><code class=\"python\">def t_comment(t):     r'(\/\\*(.|\\n)*?\\*\/)|(\/\/.*)'     pass <\/code><\/pre>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u043e\u043b\u043d\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043b\u0435\u043a\u0441\u0435\u0440\u0430 (lexer.py)<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"python\"># coding=utf8 import ply.lex as lex from ply.lex import TOKEN import re  states = (    ('string','exclusive'), )  # \u0431\u0435\u0437 \u044d\u0442\u043e\u0439 \u0448\u0442\u0443\u043a\u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0441\u044a\u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u043c\u0430\u0441\u0441\u0438\u0432 \u0448\u0430\u0440\u0438\u0442\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u043b\u0435\u043a\u0441\u0435\u0440\u043e\u043c \u0438 \u043f\u0430\u0440\u0441\u0435\u0440\u043e\u043c \u0438 \u043a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 tokens = (     'PHPSTART', 'PHPVAR', 'PHPEQUAL', 'PHPFUNC',     'PHPSTRING', 'PHPECHO', 'PHPCOLON', 'PHPCOMA',     'PHPOPEN', 'PHPCLOSE', 'PHPNUM', 'PLUSMINUS', 'DIVMUL',     'STR' )  # \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0443 \u0434\u043b\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0433\u043e \u0438\u0434\u0435\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 ident = r'[a-z]\\w*'  # \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430 \u0438\u0437 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0432\u0438\u0434\u0430 t_\u0418\u041c\u042f\u0422\u041e\u041a\u0415\u041d\u0410 = \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0430 t_PHPSTART = r'\\&lt;\\?php' t_ANY_PHPVAR = r'\\$'+ident # \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e, \u043f\u0440\u0430\u0432\u0434\u0430? t_PHPEQUAL = r'\\=' t_PHPCOLON = r';' t_PHPCOMA = r',' t_PHPOPEN = r'\\(' t_PHPCLOSE = r'\\)' t_PHPNUM = r'\\d+' t_PLUSMINUS = r'\\+|\\-' t_DIVMUL = r'\/|\\*'  @TOKEN(ident) def t_PHPFUNC(t):     if t.value.lower() == 'echo':         t.type = 'PHPECHO'     return t  # \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 def t_comment(t):     r'(\/\\*(.|\\n)*?\\*\/)|(\/\/.*)'     pass  # \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0438 \u0442\u043e\u043a\u0435\u043d PHPSTRING \u0438 \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0438\u0437 \u043d\u0435\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0435\u0433\u043e \u0432\u043e \u0432\u0441\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f def t_ANY_PHPSTRING(t): # \u043d\u0443\u0436\u0435\u043d \u0432 \u043e\u0431\u043e\u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u0445, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0434\u0432\u043e\u0439\u043d\u044b\u0435 \u043a\u0430\u0432\u044b\u0447\u043a\u0438 \u043c\u0430\u0442\u0447\u0430\u0442\u0441\u044f \u0438 \u0442\u0430\u043c \u0438 \u0442\u0430\u043c.     r'&quot;'     if t.lexer.current_state() == 'string':         t.lexer.begin('INITIAL') # \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435     else:         t.lexer.begin('string') # \u043f\u0430\u0440\u0441\u0438\u043c \u0441\u0442\u0440\u043e\u043a\u0443     return t  t_string_STR = r'(\\\\.|[^$&quot;])+' # \u043f\u0430\u0440\u0441\u0438\u043c \u043f\u043e\u043a\u0430 \u043d\u0435 \u0434\u043e\u0439\u0434\u0435\u043c \u0434\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0438\u043b\u0438 \u0434\u043e \u043a\u0430\u0432\u044b\u0447\u043a\u0438, \u043f\u043e\u043f\u0443\u0442\u043d\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u044d\u043a\u0440\u0430\u043d\u043a\u0438  # \u0433\u043e\u0432\u043e\u0440\u0438\u043c \u0447\u0442\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c t_string_ignore = '' # \u044d\u0442\u043e \u043a\u0441\u0442\u0430\u0442\u0438 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f, \u0431\u0435\u0437 \u043d\u0435\u0451 \u043d\u0435\u043b\u044c\u0437\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 state  # \u043d\u0443 \u0438 \u043a\u0443\u0434\u0430 \u0436\u0435 \u043c\u044b \u0431\u0435\u0437 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0448\u0438\u0431\u043e\u043a def t_string_error(t):     print &quot;Illegal character '%s'&quot; % t.value[0]     t.lexer.skip(1)  # \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u0435\u0437\u043d\u0430\u0447\u0430\u0449\u0438\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b. \u041d\u0430\u043c \u0432\u0435\u0434\u044c \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e $var=$value \u0438\u043b\u0438 $var&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;$value t_ignore = ' \\r\\t\\f'  def t_newline(t):     r'\\n+'     t.lexer.lineno += len(t.value)  # \u0430 \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0438. \u041a\u0441\u0442\u0430\u0442\u0438 \u0437\u0430\u043c\u0435\u0442\u044c\u0442\u0435 \u0444\u043e\u0440\u043c\u0430\u0442 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 def t_error(t):     print &quot;Illegal character '%s'&quot; % t.value[0]     t.lexer.skip(1)  lexer = lex.lex(reflags=re.UNICODE | re.DOTALL | re.IGNORECASE)  if __name__==&quot;__main__&quot;:     data = ''' &lt;?php $val = 5; $result = substr( &quot;foobar&quot;, 2*(7-$val) ); echo &quot;\u044d\u0442\u043e \u043d\u0430\u0448 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442: $result&quot;;     '''      lexer.input(data)      while True:         tok = lexer.token() # \u0447\u0438\u0442\u0430\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d         if not tok: break      # \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438\u0441\u044c \u043f\u0435\u0447\u0435\u043d\u044c\u043a\u0438         print tok <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0412\u043e\u0442 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043f\u0430\u0440\u0441\u0435\u0440\u0443 (parser.py).<\/p>\n<h4>Yacc<\/h4>\n<p>  Yacc \u2014 \u044d\u0442\u043e \u0448\u0442\u0443\u043a\u0430 (\u043f\u0430\u0440\u0441\u0435\u0440), \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d\u044b \u0438 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f (\u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0443). \u041f\u043e\u0445\u043e\u0434\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e \u0438\u043b\u0438 \u0436\u0435 \u0441\u0440\u0430\u0437\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 (\u043a\u0430\u043a \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0441 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u043d\u0430 \u0441\u0430\u0439\u0442\u0435).<br \/>  \u0412 PLY \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043a\u043b\u0430\u0441\u0441 <i>ply.yacc<\/i>.<br \/>  \u041e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0433\u0440\u0430\u043c\u0430\u0442\u0438\u043a\u0443 \u0432 ply \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u0438 \u044d\u0442\u043e \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u0436\u0435 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0430\u0441\u043b\u0430\u0436\u0434\u0435\u043d\u0438\u0435. \u0414\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0443 \u043d\u0430\u0441 \u0441\u043d\u043e\u0432\u0430 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 p_\u0438\u043c\u044f\u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0433\u0434\u0435 \u0432 doc-\u0441\u0442\u0440\u043e\u043a\u0430\u0445 \u043c\u044b \u0438 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u044d\u0442\u0443 \u0441\u0430\u043c\u0443\u044e \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0443.<br \/>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u0443\u044e \u0433\u0440\u0430\u043c\u043c\u0430\u0442\u0438\u043a\u0443 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0441 php:<\/p>\n<pre> php -&gt; [PHPSTART phpbody]? phpbody -&gt; [phpline phpcolons]* phpcolons -&gt; [ PHPCOLON ]+ phpline -&gt; assign | func | [PHPECHO args] assign -&gt; PHPVAR PHPEQUAL expr expr -&gt; [fact | expr PLUSMINUS fact] fact -&gt; [term | fact DIVMUL term] term -&gt; [arg | PHPOPEN expr PHPCLOSE] func -&gt; PHPFUNC PHPOPEN args PHPCLOSE args -&gt; [ expr [PHPCOMA expr]* ]? arg -&gt; string | phpvar | PHPNUM | func string -&gt; PHPSTRING str PHPSTRING str -&gt; [STR | str phpvar]? phpvar -&gt; PHPVAR <\/pre>\n<p>  \u0422\u0435\u043a\u0441\u0442\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0443\u0436\u0435 \u043c\u043d\u043e\u0433\u043e, \u0438 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0435\u0449\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0447\u0435\u043d\u044c \u0434\u043e\u043b\u0433\u043e. \u041d\u043e \u0434\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u043e\u0441\u043d\u043e\u0432 ply.yacc \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u043f\u0440\u0438\u043c\u0435\u0440. \u0410 \u0434\u0430\u043b\u044c\u0448\u0435 \u044f \u0443\u0436\u0435 \u0432\u044b\u043b\u043e\u0436\u0443 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a \u043f\u0430\u0440\u0441\u0435\u0440\u0430.<\/p>\n<p>  \u0418\u0442\u0430\u043a, \u0432\u044b\u0434\u0440\u0430\u043d\u043d\u044b\u0439 \u043a\u0443\u0441\u043e\u043a \u0438\u0437 \u043f\u0430\u0440\u0441\u0435\u0440\u0430:<\/p>\n<pre><code class=\"python\">def p_str(p):     '''str :            | STR            | str phpvar'''     if len(p) == 1:         p[0] = Node('str', [''])     elif len(p) == 2:         p[0] = Node('str', [p[1]])     else:         p[0] = p[1].add_parts([p[2]]) <\/code><\/pre>\n<p>  \u041f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443. \u041f\u0430\u0440\u0441\u0438\u043d\u0433 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0432\u0435\u0440\u0445\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u043c p_&lt;\u0444\u0443\u043d\u043a\u0446\u0438\u044f&gt;. \u0422.\u0435. \u0443 \u043c\u0435\u043d\u044f \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u0435\u0440\u0432\u043e\u0439 \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0435 \u0441\u0442\u043e\u0438\u0442 p_php, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0430\u0440\u0441\u0435\u0440 \u043d\u0430\u0447\u043d\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0438\u043c\u0435\u043d\u043d\u043e \u0441 \u043d\u0435\u0451 (\u0441\u0432\u0435\u0440\u0445\u0443 \u0432\u043d\u0438\u0437). \u041f\u0430\u0440\u0441\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u043c\u0438 \u0432 doc-\u0441\u0442\u0440\u043e\u043a\u0430\u0445, \u0438 \u043f\u043e\u0441\u043b\u0435 \u0438\u0445 \u043c\u0430\u0442\u0447\u0438\u043d\u0433\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0441 \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u043c\u0438 \u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e p. \u0412 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 p \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430. \u041f\u0440\u0438\u0447\u0435\u043c \u043f\u043e\u0441\u043b\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0437\u0430\u0441\u0443\u043d\u0443\u0442\u044c \u043d\u0430\u0448\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0432 p[0]. \u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 p[1], \u044d\u0442\u043e \u043f\u0440\u0430\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043d\u0430\u0448\u0438\u0445 \u043f\u0440\u0430\u0432\u0438\u043b \u2014 \u043e\u0442\u043c\u0430\u0442\u0447\u0435\u043d\u043d\u044b\u0435 \u0442\u043e\u043a\u0435\u043d\u044b \u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430.<\/p>\n<pre><code class=\"python\">    '''str :            | STR            | str phpvar''' <\/code><\/pre>\n<p>  \u041f\u043e \u0441\u0443\u0442\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0432\u044b\u0448\u0435 \u2014 \u044d\u0442\u043e \u0441\u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 (\u0441\u043b\u0438\u0442\u043e\u0435) \u043f\u0440\u0430\u0432\u0438\u043b\u043e. &#8216;|&#8217; \u043a\u0430\u043a \u043d\u0435\u0441\u043b\u043e\u0436\u043d\u043e \u0434\u043e\u0433\u0430\u0434\u0430\u0442\u044c\u0441\u044f \u2014 \u044d\u0442\u043e \u0418\u041b\u0418, \u043d\u0443 \u0438\u043b\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0442\u043e\u043a\u0435\u043d\u0430.<br \/>  \u041c\u0435\u0436\u0434\u0443 \u0434\u0432\u043e\u0435\u0442\u043e\u0447\u0438\u0435\u043c \u0438 \u043b\u0435\u0432\u043e\u0439\/\u043f\u0440\u0430\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u044c\u044e \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u0435\u043d \u043f\u0440\u043e\u0431\u0435\u043b. \u0422\u0430\u043a \u043b\u044e\u0431\u0438\u0442 ply. \u0415\u0441\u043b\u0438 \u043f\u0440\u0430\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u043e\u0439, \u0442\u043e \u043f\u043e\u0441\u043b\u0435 \u0434\u0432\u043e\u0435\u0442\u043e\u0447\u0438\u044f \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u0438\u0448\u0435\u043c. \u0422\u043e\u043a\u0435\u043d\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0431\u0443\u043a\u0432\u0430\u043c\u0438, \u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u043c\u0438, \u0431\u0435\u0437 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u0430 p_. \u0422.\u0435. \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0432\u044b\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 p_str \u0438 p_phpvar.<\/p>\n<p>  \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u043c\u044b \u0438\u043c\u0435\u0435\u043c &quot;&quot; (\u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443), \u0442\u043e \u0432 p \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u2014 p[0], \u043f\u0440\u0438\u0447\u0435\u043c \u043e\u043d\u043e \u043d\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u043d\u043e \u0438 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0435\u0433\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c.<br \/>  \u0415\u0441\u043b\u0438 \u0443 \u043d\u0430\u0441 \u0441\u0442\u0440\u043e\u043a\u0430 \u00ab\u043f\u0440\u0438\u0432\u0435\u0442 $vasya \u043f\u0443\u043f\u043a\u0438\u043d\u00bb, \u0442\u043e \u044d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0441\u044f \u0442\u0440\u0438 \u0440\u0430\u0437\u0430. \u041f\u0435\u0440\u0432\u044b\u0439 \u0440\u0430\u0437 \u0434\u043b\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f STR, \u0438 \u043c\u044b \u0432\u0435\u0440\u043d\u0435\u043c \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 p[0], \u0432\u0442\u043e\u0440\u043e\u0439 \u0440\u0430\u0437 \u0434\u043b\u044f $vasya, \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u044d\u0442\u043e \u043a \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e (p[1] \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043d\u043e\u0434\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0432\u0435\u0440\u043d\u0443\u043b\u0438 \u0432 p[0] \u043d\u0430 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438), \u0430 \u0442\u0440\u0435\u0442\u0438\u0439 \u0440\u0430\u0437 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0430 \u0432\u044b\u0445\u043e\u0434 \u00ab\u043f\u0443\u043f\u043a\u0438\u043d\u00bb. \u041d\u0430\u0432\u0435\u0440\u043d\u043e\u0435 \u044f \u0441\u0443\u043c\u0431\u0443\u0440\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u043b, \u043d\u043e \u044d\u0442\u043e \u043d\u0430\u0434\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0442\u0440\u043e\u0433\u0430\u0442\u044c. \u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0441\u0440\u0435\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u0438\u0433\u0440\u0430\u0442\u044c\u0441\u044f \ud83d\ude42<\/p>\n<p>  \u041a\u0441\u0442\u0430\u0442\u0438, \u0438\u043d\u043e\u0433\u0434\u0430 \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u0435\u043d \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430\u043c\u0438 (\u0442\u0430\u0444\u0442\u043e\u043b\u043e\u0433\u0438\u044f, \u043f\u0440\u043e\u0441\u0442\u0438\u0442\u0435):<\/p>\n<pre><code class=\"python\">def p_str_empty(p):     '''str :'''     p[0] = Node('str', [''])   def p_str_raw(p):     '''str : STR'''     p[0] = Node('str', [p[1]])  def p_str_var(p):     '''str : str phpvar'''     p[0] = p[1].add_parts([p[2]]) <\/code><\/pre>\n<p>  \u041e\u043d \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u0435\u043d \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0443 \u043a\u043e\u0434\u0430. \u041f\u0440\u043e\u0441\u0442\u043e \u0444\u043b\u043e\u043c\u0430\u0441\u0442\u0435\u0440\u044b \u0434\u0440\u0443\u0433\u0438\u0435. \u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u043c\u0435\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f (\u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0442\u044c \u0438\u0445 \u043d\u0430\u0434\u043e \u0432 \u043f\u0438\u0442\u043e\u043d\u0435), \u043d\u043e \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u044b \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u044b\u0435 (str), \u0447\u0442\u043e \u0438 \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 ply \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0432\u043c\u0435\u0441\u0442\u0435 \u043a\u0430\u043a \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0430.<\/p>\n<p>  \u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0434\u0435\u0440\u0435\u0432\u0430 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u0438 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441:<\/p>\n<pre><code class=\"python\">class Node:     def parts_str(self):         st = []         for part in self.parts:             st.append( str( part ) )         return &quot;\\n&quot;.join(st)      def __repr__(self):         return self.type + &quot;:\\n\\t&quot; + self.parts_str().replace(&quot;\\n&quot;, &quot;\\n\\t&quot;)      def add_parts(self, parts):         self.parts += parts         return self      def __init__(self, type, parts):         self.type = type         self.parts = parts <\/code><\/pre>\n<p>  \u041e\u043d \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0438 \u0445\u0440\u0430\u043d\u0438\u0442 \u0432\u0441\u0435 \u043d\u0443\u0436\u043d\u043e\u0435, \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u0443\u0435\u0442 \u0432\u044b\u0432\u043e\u0434, \u0447\u0442\u043e \u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e \u043f\u0440\u0438 \u043e\u0442\u043b\u0430\u0434\u043a\u0435.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0430\u0440\u0441\u0435\u0440\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"python\"># coding=utf8  from lexer import tokens import ply.yacc as yacc  class Node:     def parts_str(self):         st = []         for part in self.parts:             st.append( str( part ) )         return &quot;\\n&quot;.join(st)      def __repr__(self):         return self.type + &quot;:\\n\\t&quot; + self.parts_str().replace(&quot;\\n&quot;, &quot;\\n\\t&quot;)      def add_parts(self, parts):         self.parts += parts         return self      def __init__(self, type, parts):         self.type = type         self.parts = parts  def p_php(p):     '''php :            | PHPSTART phpbody'''     if len(p) == 1:         p[0] = None     else:         p[0] = p[2]  def p_phpbody(p):     '''phpbody :                | phpbody phpline phpcolons'''     if len(p) &gt; 1:         if p[1] is None:             p[1] = Node('body', [])         p[0] = p[1].add_parts([p[2]])     else:         p[0] = Node('body', [])  def p_phpcolons(p):     '''phpcolons : PHPCOLON                  | phpcolons PHPCOLON'''  def p_phpline(p):     '''phpline : assign                | func                | PHPECHO args'''     if len(p) == 2:         p[0] = p[1]     else:         p[0] = Node('echo', [p[2]])  def p_assign(p):     '''assign : PHPVAR PHPEQUAL expr'''     p[0] = Node('assign', [p[1], p[3]])  def p_expr(p):     '''expr : fact             | expr PLUSMINUS fact'''     if len(p) == 2:         p[0] = p[1]     else:         p[0] = Node(p[2], [p[1], p[3]])  def p_fact(p):     '''fact : term             | fact DIVMUL term'''     if len(p) == 2:         p[0] = p[1]     else:         p[0] = Node(p[2], [p[1], p[3]])  def p_term(p):     '''term : arg             | PHPOPEN expr PHPCLOSE'''     if len(p) == 2:         p[0] = p[1]     else:         p[0] = p[2]  def p_func(p):     '''func : PHPFUNC PHPOPEN args PHPCLOSE'''     p[0] = Node('func', [p[1], p[3]])  def p_args(p):     '''args :             | expr             | args PHPCOMA expr'''     if len(p) == 1:         p[0] = Node('args', [])     elif len(p) == 2:         p[0] = Node('args', [p[1]])     else:         p[0] = p[1].add_parts([p[3]])  def p_arg(p):     '''arg : string            | phpvar            | PHPNUM            | func'''     p[0] = Node('arg', [p[1]])  def p_phpvar(p):     '''phpvar : PHPVAR'''     p[0] = Node('var', [p[1]])  def p_string(p):     '''string : PHPSTRING str PHPSTRING'''     p[0] = p[2]  def p_str(p):     '''str :            | STR            | str phpvar'''     if len(p) == 1:         p[0] = Node('str', [''])     elif len(p) == 2:         p[0] = Node('str', [p[1]])     else:         p[0] = p[1].add_parts([p[2]])  def p_error(p):     print 'Unexpected token:', p  parser = yacc.yacc()  def build_tree(code):     return parser.parse(code) <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0444\u0430\u0439\u043b\u0438\u043a, \u043e\u0442\u043a\u0443\u0434\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0432\u0441\u0435<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"python\"># coding=utf8  from parser import build_tree  data = ''' &lt;?php $val = 5; $result = substr( &quot;foobar&quot;, 2*(7-$val) ); \/* comment *\/ echo &quot;\u044d\u0442\u043e \u043d\u0430\u0448 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442: &quot;, $result; '''  result = build_tree(data) print result <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0412\u044b\u0432\u043e\u0434 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0434\u0435\u0440\u0435\u0432\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre> line: \tassign: \t\t$val \t\targ: \t\t\t5 \tassign: \t\t$result \t\targ: \t\t\tfunc: \t\t\t\tsubstr \t\t\t\targs: \t\t\t\t\targ: \t\t\t\t\t\tstr: \t\t\t\t\t\t\tfoobar \t\t\t\t\t*: \t\t\t\t\t\targ: \t\t\t\t\t\t\t2 \t\t\t\t\t\t-: \t\t\t\t\t\t\targ: \t\t\t\t\t\t\t\t7 \t\t\t\t\t\t\targ: \t\t\t\t\t\t\t\tvar: \t\t\t\t\t\t\t\t\t$val \techo: \t\targs: \t\t\targ: \t\t\t\tstr: \t\t\t\t\t\u044d\u0442\u043e \u043d\u0430\u0448 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:  \t\t\targ: \t\t\t\tvar: \t\t\t\t\t$result <\/pre>\n<p>  <\/div>\n<\/div>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>  \u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0437\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u044f \u0438\u043b\u0438 \u043f\u043e\u0436\u0435\u043b\u0430\u043d\u0438\u044f, \u0441 \u0443\u0434\u043e\u0432\u043e\u043b\u044c\u0441\u0442\u0432\u0438\u0435\u043c \u0434\u043e\u043f\u0438\u0448\u0443\/\u0438\u0437\u043c\u0435\u043d\u044e \u043f\u043e\u0441\u0442.<\/p>\n<p>  <a href=\"https:\/\/github.com\/dyatlov\/habr-ply-microphp\">\u041a\u043e\u0434 \u0441\u0442\u0430\u0442\u044c\u0438 \u0437\u0434\u0435\u0441\u044c<\/a><\/p>\n<p>  \u041d\u0443 \u0438 \u0435\u0441\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0441 \u0447\u0435\u0433\u043e \u044f \u0432\u0434\u0440\u0443\u0433 \u043f\u0440\u043e ply \u0440\u0435\u0448\u0438\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u2014 <a href=\"https:\/\/github.com\/dyatlov\/Pyfox\">pyfox<\/a>. \u0414\u0435\u043b\u0430\u044e \u043f\u043e\u0442\u0438\u0445\u043e\u043d\u0435\u0447\u044c\u043a\u0443 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 css \u043d\u0430 python. \u0412\u0435\u0440\u043d\u0435\u0435 \u043f\u0430\u0440\u0441\u0435\u0440 css \u043d\u0430\u043f\u0438\u0441\u0430\u043d, \u043d\u043e \u0432\u043e\u0442 \u043f\u0440\u043e\u0433\u0443\u043b\u043a\u0430 \u043f\u043e dom \u0435\u0449\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 (\u043d\u0435 \u0432\u0441\u0435 \u043f\u0441\u0435\u0432\u0434\u043e\u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442). \u0421\u0435\u0439\u0447\u0430\u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 nth-child. \u041d\u0435 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 css \u0430 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043c\u0430\u0442\u0447\u0438\u043d\u0433\u0430 \u2014 \u0432 dom \u043d\u0435\u0442\u0443 \u0442\u0430\u043a\u043e\u0433\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043a\u0430\u043a \u043d\u043e\u043c\u0435\u0440 \u0441\u0440\u0435\u0434\u0438 \u0441\u043e\u0441\u0435\u0434\u0435\u0439, \u0430 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0441\u043e\u0441\u0435\u0434\u0435\u0439 \u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f. \u0412\u0438\u0434\u0438\u043c\u043e \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f HTMLParser \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u041c\u043e\u0436\u0435\u0442 \u043a\u0442\u043e \u0440\u0435\u0448\u0438\u0442 \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u0441\u044c\u044f \u043a\u043e \u043c\u043d\u0435? \u0412\u0441\u0435\u0445 welcome \ud83d\ude42    \t<\/p>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/191252\/\"> http:\/\/habrahabr.ru\/post\/191252\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\">   \t<img decoding=\"async\" align=\"left\" src=\"http:\/\/habrastorage.org\/storage2\/178\/82c\/79e\/17882c79e4443998a0e1020819cc3d3b.png\"\/>  <\/p>\n<h2>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 PLY?<\/h2>\n<p>  <a href=\"http:\/\/www.dabeaz.com\/ply\/ply.html\">PLY<\/a> \u2014 \u044d\u0442\u043e \u0430\u0431\u0431\u0440\u0435\u0432\u0438\u0430\u0442\u0443\u0440\u0430 \u0438\u0437 \u043f\u0435\u0440\u0432\u044b\u0445 \u0431\u0443\u043a\u0432 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f: <strong>P<\/strong>ython <strong>L<\/strong>ex-<strong>Y<\/strong>acc.<br \/>  \u0424\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u044d\u0442\u043e \u043f\u043e\u0440\u0442 \u0443\u0442\u0438\u043b\u0438\u0442 lex \u0438 yacc \u043d\u0430 python \u0432 \u043a\u0440\u0430\u0441\u0438\u0432\u043e\u0439 \u043e\u0431\u0435\u0440\u0442\u043a\u0435.<br \/>  \u0420\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 ply \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u0438 \u043f\u043e\u0440\u043e\u0433 \u0432\u0445\u043e\u0434\u0430 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0443\u043b\u0435\u0432\u043e\u0439.<br \/>  \u041d\u0430\u043f\u0438\u0441\u0430\u043d \u043e\u043d \u043d\u0430 \u0447\u0438\u0441\u0442\u043e\u043c \u043f\u0438\u0442\u043e\u043d\u0435 \u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f <a href=\"http:\/\/ru.wikipedia.org\/wiki\/LALR%281%29\">LALR(1) \u043f\u0430\u0440\u0441\u0435\u0440<\/a>, \u043d\u043e \u043a\u043e\u043c\u0443 \u044d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e?<br \/>  \u042f \u043f\u043e \u043d\u0430\u0442\u0443\u0440\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u043a (\u043a\u0430\u043a \u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0432\u043e \u0438\u0437 \u0432\u0430\u0441) \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0448\u043b\u0438 \u0432 \u0431\u043e\u0439!<\/p>\n<h2>\u0427\u0442\u043e \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c?<\/h2>\n<p>  <a href=\"http:\/\/www.dabeaz.com\/ply\/example.html\">\u041d\u0430 \u0441\u0430\u0439\u0442\u0435 \u0435\u0441\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440<\/a> \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0433\u043e \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c\u0441\u044f \u043d\u0435 \u0431\u0443\u0434\u0435\u043c. \u0410 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0447\u0442\u043e-\u0442\u043e \u043d\u0430\u0432\u0440\u043e\u0434\u0435 \u043f\u0430\u0440\u0441\u0435\u0440\u0430 \u043e\u0447\u0435\u043d\u044c \u043e\u0447\u0435\u043d\u044c \u0443\u0437\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 PHP \ud83d\ude42<br \/>  \u041d\u0430\u0448\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e \u0434\u043b\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430:<\/p>\n<pre><code class=\"php\">&lt;?php $val = 5; $result = substr( &quot;foobar&quot;, 2*(7-$val) ); echo &quot;\u044d\u0442\u043e \u043d\u0430\u0448 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442: $result&quot;; <\/code><\/pre>\n<p>  \u041f\u0440\u0438\u043c\u0435\u0440 \u043e\u0447\u0435\u043d\u044c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439 \u0438 \u0432\u0437\u044f\u0442 \u0441 \u043f\u043e\u0442\u043e\u043b\u043a\u0430. \u041d\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0434\u0435\u0440\u0435\u0432\u043e \u043a\u043e\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0438 \u043f\u043e\u0445\u043e\u0434\u0443 \u043c\u044b \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c PLY \u043a\u0430\u043a state.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-191252","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/191252","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=191252"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/191252\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=191252"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=191252"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=191252"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}