{"id":324380,"date":"2021-06-04T21:00:23","date_gmt":"2021-06-04T21:00:23","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=324380"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=324380","title":{"rendered":"\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u0442\u0435\u043a\u043e\u0432\u043e\u0439 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u044b \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430 \u043f\u043e\u0434 \u043d\u0435\u0451 (\u0447\u0430\u0441\u0442\u044c II)"},"content":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c01\/072\/90f\/c0107290fc347f1f18e310880c43d6b4.jpg\" width=\"760\" height=\"427\"><figcaption><\/figcaption><\/figure>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/560356\/\" rel=\"noopener noreferrer nofollow\">\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u0442\u0435\u043a\u043e\u0432\u043e\u0439 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u044b \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430 \u043f\u043e\u0434 \u043d\u0435\u0451 (\u0447\u0430\u0441\u0442\u044c I)<\/a> \u0441\u0434\u0435\u043b\u0430\u043b \u0441\u0432\u043e\u044e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0440\u043d\u0443\u044e \u0441\u0442\u0435\u043a\u043e\u0432\u0443\u044e \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u043c\u0430\u0448\u0438\u043d\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0443\u043c\u0435\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e \u0441\u0442\u0435\u043a\u043e\u043c, \u0434\u0435\u043b\u0430\u0442\u044c \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u043a\u0443 \u0441 \u0446\u0435\u043b\u044b\u043c\u0438 \u0447\u0438\u0441\u043b\u0430\u043c\u0438 \u0441\u043e \u0437\u043d\u0430\u043a\u043e\u043c, \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u044b \u0438 \u0432\u044b\u0437\u043e\u0432\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0441 \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u043e\u043c. \u041d\u043e \u0442\u0430\u043a \u043a\u0430\u043a \u0446\u0435\u043b\u044c\u044e \u0431\u044b\u043b\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u043c\u0430\u0448\u0438\u043d\u0443, \u043d\u043e \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 C \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430, \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0435 \u0448\u0430\u0433\u0438 \u0432 \u0441\u0442\u043e\u0440\u043e\u043d\u0443 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438. \u041e\u043f\u044b\u0442\u0430 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e. \u0411\u0443\u0434\u0443 \u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0440\u0430\u0437\u0443\u043c\u0435\u043d\u0438\u044e.<\/p>\n<p>\u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u043f\u0435\u0440\u0432\u044b\u0445 \u044d\u0442\u0430\u043f\u043e\u0432 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437 (parsing) \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043d\u0430\u0448\u0435\u0433\u043e &#171;C \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430&#187; (\u043a\u0441\u0442\u0430\u0442\u0438, \u043d\u0430\u0434\u043e \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u0442\u044c \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043d \u0441\u0442\u0430\u043d\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 \u0444\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u043c). \u0417\u0430\u0434\u0430\u0447\u0430 \u043f\u0440\u043e\u0441\u0442\u0430\u044f &#8212; &#171;\u043d\u0430\u0440\u0443\u0431\u0438\u0442\u044c&#187; \u043c\u0430\u0441\u0441\u0438\u0432 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 (\u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434) \u043d\u0430 \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437\u0431\u043e\u0440 \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u043d\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u043b\u0438 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043f\u0435\u0440\u0432\u044b\u0439 \u0448\u0430\u0433 &#8212; \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0442\u0438\u043f\u0430\u043c\u0438 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 (\u0438\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u043e \u0431\u0443\u0434\u0435\u043c \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 C), \u0441\u0438\u043c\u0432\u043e\u043b\u0430\u043c\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u0434\u0435\u043b\u044f\u0442\u044c \u0442\u043e\u043a\u0435\u043d\u044b \u0434\u0440\u0443\u0433 \u043e\u0442 \u0434\u0440\u0443\u0433\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 (\u0442\u0438\u043f, \u0442\u0435\u043a\u0441\u0442 \u0442\u043e\u043a\u0435\u043d\u0430, \u0434\u043b\u0438\u043d\u0430, \u0441\u0442\u0440\u043e\u043a\u0430 \u0438 \u0441\u0442\u043e\u043b\u0431\u0435\u0446 \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c \u043a\u043e\u0434\u0435). <\/p>\n<pre><code class=\"cpp\">\tconstexpr char* BLANKS = \"\\x20\\n\\t\"; \tconstexpr char* DELIMETERS = \",;{}[]()=&gt;&lt;+-*\/&amp;|~^!.\";  \tenum class TokenType { \t\tNONE = 0, UNKNOWN, IDENTIFIER, \t\tCONST_CHAR, CONST_INTEGER, CONST_REAL, CONST_STRING, \t\tCOMMA, MEMBER_ACCESS, EOS,  \t\tOP_BRACES, CL_BRACES, OP_BRACKETS, CL_BRACKETS, OP_PARENTHESES, CL_PARENTHESES, \t\tBYTE, SHORT, INT, LONG, CHAR, FLOAT, DOUBLE, STRING, IF, ELSE, WHILE, RETURN, \t\tASSIGN, EQUAL, NOT_EQUAL, GREATER, GR_EQUAL, LESS, LS_EQUAL, \t\tPLUS, MINUS, MULTIPLY, DIVIDE, AND, OR, XOR, NOT, SHL, SHR, \t\tLOGIC_AND, LOGIC_OR, LOGIC_NOT \t};  \ttypedef struct { \t\tTokenType type;           \t\tchar* text;               \t\tWORD length;              \t\tWORD row;                 \t\tWORD col;                 \t} Token; <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0440\u0430\u0437\u0431\u043e\u0440\u0430, \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0435\u0442 <strong>parseToTokens<\/strong>(char*). \u0422\u0443\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439: \u0438\u0434\u0435\u043c \u0434\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044f (<strong>BLANKS<\/strong> \u0438 <strong>DELIMETERS<\/strong>), \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043d\u0430\u0447\u0430\u043b\u043e \u0438 \u043a\u043e\u043d\u0435\u0446 \u0442\u043e\u043a\u0435\u043d\u0430, \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u0432\u0435\u043a\u0442\u043e\u0440 (\u0441\u043f\u0438\u0441\u043e\u043a) \u0442\u043e\u043a\u0435\u043d\u043e\u0432. \u041e\u0441\u043e\u0431\u044b\u0435 \u0441\u043b\u0443\u0447\u0430\u0438 \u0440\u0430\u0437\u0431\u043e\u0440\u0430 &#8212; \u044d\u0442\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c \u0446\u0435\u043b\u044b\u0435 \u0447\u0438\u0441\u043b\u0430 \u043e\u0442 \u0432\u0435\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445, \u0432\u0435\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0447\u0438\u0441\u043b\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, &#171;<strong>315.0<\/strong>&#171;) \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c \u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0447\u043b\u0435\u043d\u0430\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b\/\u043e\u0431\u044a\u0435\u043a\u0442\u0430 (&#171;<strong>obj10.field1<\/strong>&#171;), \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 \u043e\u0442 \u0434\u0440\u0443\u0433\u0438\u0445 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432.<\/p>\n<pre><code class=\"cpp\"> void VMParser::parseToTokens(const char* sourceCode) {  \tTokenType isNumber = TokenType::UNKNOWN; \tbool insideString = false;                                         \/\/ inside string flag \tbool isReal = false;                                               \/\/ is real number flag \tsize_t length;                                                     \/\/ token length variable  \tchar nextChar;                                                     \/\/ next char variable \tbool blank, delimeter;                                             \/\/ blank &amp; delimeter char flags  \ttokens-&gt;clear();                                                   \/\/ clear tokens vector \trowCounter = 1;                                                    \/\/ reset current row counter \trowPointer = (char*)sourceCode;                                    \/\/ set current row pointer to beginning  \tchar* cursor = (char*)sourceCode;                                  \/\/ set cursor to source beginning  \tchar* start = cursor;                                              \/\/ start new token from cursor \tchar value = *cursor;                                              \/\/ read first char from cursor  \twhile (value != NULL) {                                            \/\/ while not end of string \t\tblank = isBlank(value);                                          \/\/ is blank char found? \t\tdelimeter = isDelimeter(value);                                  \/\/ is delimeter found? \t\tlength = cursor - start;                                         \/\/ measure token length \t\t     \/\/ Diffirentiate real numbers from member access operator '.' \t\tisNumber = identifyNumber(start, length - 1);                    \/\/ Try to get integer part of real number \t\tisReal = (value=='.' &amp;&amp; isNumber==TokenType::CONST_INTEGER);     \/\/ Is current token is real number  \t\tif ((blank || delimeter) &amp;&amp; !insideString &amp;&amp; !isReal) {          \/\/ if there is token separator                    \t\t\tif (length &gt; 0) pushToken(start, length);                      \/\/ if length &gt; 0 push token to vector \t\t\tif (value == '\\n') {                                           \/\/ if '\\n' found  \t\t\t\trowCounter++;                                                \/\/ increment row counter \t\t\t\trowPointer = cursor + 1;                                     \/\/ set row beginning pointer \t\t\t} \t\t\tnextChar = *(cursor + 1);                                      \/\/ get next char after cursor \t\t\tif (!blank &amp;&amp; isDelimeter(nextChar)) {                         \/\/ if next char is also delimeter \t\t\t\tif (pushToken(cursor, 2) == TokenType::UNKNOWN)              \/\/ try to push double char delimeter token \t\t\t\t\tpushToken(cursor, 1);                                      \/\/ if not pushed - its single char delimeter \t\t\t\telse cursor++;                                               \/\/ if double delimeter, increment cursor \t\t\t} else pushToken(cursor, 1);                                   \/\/ else push single char delimeter \t\t\tstart = cursor + 1;                                            \/\/ calculate next token start pointer \t\t} \t\telse if (value == '\"') insideString = !insideString;             \/\/ if '\"' char - flip insideString flag  \t\telse if (insideString &amp;&amp; value == '\\n') {                        \/\/ if '\\n' found inside string \t\t\t\/\/ TODO warn about parsing error \t\t} \t\tcursor++;                                                        \/\/ increment cursor pointer \t\tvalue = *cursor;                                                 \/\/ read next char \t}  \tlength = cursor - start;                                           \/\/ if there is a last token \tif (length &gt; 0) pushToken(start, length);                          \/\/ push last token to vector  } <\/code><\/pre>\n<p>\u041d\u0430\u0440\u044f\u0434\u0443 \u0441 \u043c\u0435\u0442\u043e\u0434\u043e\u043c parseToTokens, \u043f\u043e\u043c\u043e\u0433\u0430\u0442\u044c \u0432 \u0440\u0430\u0437\u0431\u043e\u0440\u0435 \u0438 \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043d\u0430\u043c \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0438\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u0438 \u0438 \u0442\u0438\u043f \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430. \u041f\u043b\u044e\u0441 \u043c\u0435\u0442\u043e\u0434 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u0432 \u0432\u0435\u043a\u0442\u043e\u0440. <\/p>\n<pre><code class=\"cpp\">class VMParser { \tpublic: \t\tVMParser(); \t\t~VMParser(); \t\tvoid parseToTokens(const char* sourceCode); \t\tToken getToken(size_t index); \t\tsize_t getTokenCount(); \t   private: \t\tvector&lt;Token&gt;* tokens; \t\tWORD rowCounter; \t\tchar* rowPointer;    \t\tbool isBlank(char value); \t\tbool isDelimeter(char value); \t\tTokenType pushToken(char* text, size_t length); \t\tTokenType getTokenType(char* text, size_t length); \t\tTokenType identifyNumber(char* text, size_t length); \t\tTokenType identifyKeyword(char* text, size_t length); \t};<\/code><\/pre>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043a\u043b\u0430\u0441\u0441 VMParser <strong><em>\u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 C \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430<\/em><\/strong> (\u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0431\u0435\u0441\u0441\u043c\u044b\u0441\u043b\u0435\u043d\u043d\u044b\u0439, \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0440\u0430\u0437\u0431\u043e\u0440\u0430):<\/p>\n<pre><code class=\"cpp\">int main() {     printf (\"Wow!\");     float a = 365.0 * 10 - 10.0 \/ 2 + 3; \t\twhile (1 != 2) { \t\t    abc.v1 = 'x'; \t\t} \t\tif (a &gt;= b) return a &amp;&amp; b; else a || b;  };<\/code><\/pre>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u0435\u0440\u0435\u0447\u0435\u043d\u044c \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ba5\/0f8\/e56\/ba50f8e56b0cbc2b06ddef28b72a62fb.jpg\" alt=\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 C \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430\" title=\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 C \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430\" width=\"1119\" height=\"891\"><figcaption>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 C \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430<\/figcaption><\/figure>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043f\u0430\u0440\u0441\u0435\u0440. \u0422\u0435\u043f\u0435\u0440\u044c \u0435\u0433\u043e \u043d\u0430\u0434\u043e \u043a\u0430\u043a-\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u044c \u0440\u0430\u0437\u0431\u043e\u0440 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044e \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u044b.<\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0441 \u0446\u0435\u043b\u044b\u043c\u0438 \u0447\u0438\u0441\u043b\u0430\u043c\u0438 (\u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 &#171;*&#187; \u0438 &#171;\/&#187; \u043d\u0430\u0434 &#171;+&#187; \u0438 &#171;-&#187; \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f), \u0431\u0435\u0437 \u0441\u043a\u043e\u0431\u043e\u043a, \u0443\u043d\u0430\u0440\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0432\u0430\u0436\u043d\u044b\u0445 \u0432\u0435\u0449\u0435\u0439, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043e\u0448\u0438\u0431\u043e\u043a. \u0420\u0430\u0437\u0431\u043e\u0440 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0432\u043e\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cpp\">void VMCompiler::parseExpression(size_t startIndex, VMImage* destImage) { \tToken tkn; \tcurrentToken = startIndex; \tparseTerm(destImage); \ttkn = parser-&gt;getToken(currentToken); \twhile (tkn.type==TokenType::PLUS || tkn.type==TokenType::MINUS) { \t\t  currentToken++; \t\t  parseTerm(destImage); \t\t  if (tkn.type==TokenType::PLUS) destImage-&gt;emit(OP_ADD); else destImage-&gt;emit(OP_SUB); \t\t  tkn = parser-&gt;getToken(currentToken); \t} }   void VMCompiler::parseTerm(VMImage* destImage) { \tToken tkn; \tparseFactor(destImage); \tcurrentToken++; \ttkn = parser-&gt;getToken(currentToken); \twhile (tkn.type == TokenType::MULTIPLY || tkn.type == TokenType::DIVIDE) { \t\t  currentToken++; \t\t  parseFactor(destImage); \t\t  if (tkn.type == TokenType::MULTIPLY) destImage-&gt;emit(OP_MUL); else destImage-&gt;emit(OP_DIV); \t\t  currentToken++; \t\t  tkn = parser-&gt;getToken(currentToken); \t} }   void VMCompiler::parseFactor(VMImage* destImage) { \tToken tkn = parser-&gt;getToken(currentToken); \tchar buffer[32]; \tstrncpy(buffer, tkn.text, tkn.length); \tbuffer[tkn.length] = 0; \tdestImage-&gt;emit(OP_CONST, atoi(buffer)); }<\/code><\/pre>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u043a\u043e\u0440\u043c\u0438\u0442\u044c \u044d\u0442\u043e\u043c\u0443 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0443 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 &#171;3+5<em>*6+2*<\/em>3+15\/5&#8243;, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0441 \u0432\u044b\u0432\u043e\u0434\u043e\u043c \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0438 \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u043c\u0430\u0448\u0438\u043d\u0443. \u041e\u0436\u0438\u0434\u0430\u0435\u043c, \u0447\u0442\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0441\u0442\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0432\u0435\u0440\u0448\u0438\u043d\u0435 \u0441\u0442\u0435\u043a\u0430 &#8212; 42.<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3c2\/453\/71d\/3c245371d8ccab5429b042adf37ffefc.png\" width=\"442\" height=\"261\"><figcaption><\/figcaption><\/figure>\n<p>\u0423\u0440\u0430! \u041f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c! \u041f\u0435\u0440\u0432\u044b\u0435 \u0448\u0430\u0433\u0438 \u0432 \u0441\u0442\u043e\u0440\u043e\u043d\u0443 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430 \u0441\u0434\u0435\u043b\u0430\u043d\u044b.<\/p>\n<\/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=\"https:\/\/habr.com\/ru\/post\/560986\/\"> https:\/\/habr.com\/ru\/post\/560986\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/560356\/\" rel=\"noopener noreferrer nofollow\">\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u0442\u0435\u043a\u043e\u0432\u043e\u0439 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u044b \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430 \u043f\u043e\u0434 \u043d\u0435\u0451 (\u0447\u0430\u0441\u0442\u044c I)<\/a> \u0441\u0434\u0435\u043b\u0430\u043b \u0441\u0432\u043e\u044e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0440\u043d\u0443\u044e \u0441\u0442\u0435\u043a\u043e\u0432\u0443\u044e \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u043c\u0430\u0448\u0438\u043d\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0443\u043c\u0435\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e \u0441\u0442\u0435\u043a\u043e\u043c, \u0434\u0435\u043b\u0430\u0442\u044c \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u043a\u0443 \u0441 \u0446\u0435\u043b\u044b\u043c\u0438 \u0447\u0438\u0441\u043b\u0430\u043c\u0438 \u0441\u043e \u0437\u043d\u0430\u043a\u043e\u043c, \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u044b \u0438 \u0432\u044b\u0437\u043e\u0432\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0441 \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u043e\u043c. \u041d\u043e \u0442\u0430\u043a \u043a\u0430\u043a \u0446\u0435\u043b\u044c\u044e \u0431\u044b\u043b\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u043c\u0430\u0448\u0438\u043d\u0443, \u043d\u043e \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 C \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430, \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0435 \u0448\u0430\u0433\u0438 \u0432 \u0441\u0442\u043e\u0440\u043e\u043d\u0443 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438. \u041e\u043f\u044b\u0442\u0430 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e. \u0411\u0443\u0434\u0443 \u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0440\u0430\u0437\u0443\u043c\u0435\u043d\u0438\u044e.<\/p>\n<p>\u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u043f\u0435\u0440\u0432\u044b\u0445 \u044d\u0442\u0430\u043f\u043e\u0432 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437 (parsing) \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043d\u0430\u0448\u0435\u0433\u043e &#171;C \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430&#187; (\u043a\u0441\u0442\u0430\u0442\u0438, \u043d\u0430\u0434\u043e \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u0442\u044c \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043d \u0441\u0442\u0430\u043d\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 \u0444\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u043c). \u0417\u0430\u0434\u0430\u0447\u0430 \u043f\u0440\u043e\u0441\u0442\u0430\u044f &#8212; &#171;\u043d\u0430\u0440\u0443\u0431\u0438\u0442\u044c&#187; \u043c\u0430\u0441\u0441\u0438\u0432 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 (\u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434) \u043d\u0430 \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437\u0431\u043e\u0440 \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u043d\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u043b\u0438 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043f\u0435\u0440\u0432\u044b\u0439 \u0448\u0430\u0433 &#8212; \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0442\u0438\u043f\u0430\u043c\u0438 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 (\u0438\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u043e \u0431\u0443\u0434\u0435\u043c \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 C), \u0441\u0438\u043c\u0432\u043e\u043b\u0430\u043c\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u0434\u0435\u043b\u044f\u0442\u044c \u0442\u043e\u043a\u0435\u043d\u044b \u0434\u0440\u0443\u0433 \u043e\u0442 \u0434\u0440\u0443\u0433\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 (\u0442\u0438\u043f, \u0442\u0435\u043a\u0441\u0442 \u0442\u043e\u043a\u0435\u043d\u0430, \u0434\u043b\u0438\u043d\u0430, \u0441\u0442\u0440\u043e\u043a\u0430 \u0438 \u0441\u0442\u043e\u043b\u0431\u0435\u0446 \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c \u043a\u043e\u0434\u0435). <\/p>\n<pre><code class=\"cpp\">\tconstexpr char* BLANKS = \"\\x20\\n\\t\"; \tconstexpr char* DELIMETERS = \",;{}[]()=&gt;&lt;+-*\/&amp;|~^!.\";  \tenum class TokenType { \t\tNONE = 0, UNKNOWN, IDENTIFIER, \t\tCONST_CHAR, CONST_INTEGER, CONST_REAL, CONST_STRING, \t\tCOMMA, MEMBER_ACCESS, EOS,  \t\tOP_BRACES, CL_BRACES, OP_BRACKETS, CL_BRACKETS, OP_PARENTHESES, CL_PARENTHESES, \t\tBYTE, SHORT, INT, LONG, CHAR, FLOAT, DOUBLE, STRING, IF, ELSE, WHILE, RETURN, \t\tASSIGN, EQUAL, NOT_EQUAL, GREATER, GR_EQUAL, LESS, LS_EQUAL, \t\tPLUS, MINUS, MULTIPLY, DIVIDE, AND, OR, XOR, NOT, SHL, SHR, \t\tLOGIC_AND, LOGIC_OR, LOGIC_NOT \t};  \ttypedef struct { \t\tTokenType type;           \t\tchar* text;               \t\tWORD length;              \t\tWORD row;                 \t\tWORD col;                 \t} Token; <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0440\u0430\u0437\u0431\u043e\u0440\u0430, \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0435\u0442 <strong>parseToTokens<\/strong>(char*). \u0422\u0443\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439: \u0438\u0434\u0435\u043c \u0434\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044f (<strong>BLANKS<\/strong> \u0438 <strong>DELIMETERS<\/strong>), \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043d\u0430\u0447\u0430\u043b\u043e \u0438 \u043a\u043e\u043d\u0435\u0446 \u0442\u043e\u043a\u0435\u043d\u0430, \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u0432\u0435\u043a\u0442\u043e\u0440 (\u0441\u043f\u0438\u0441\u043e\u043a) \u0442\u043e\u043a\u0435\u043d\u043e\u0432. \u041e\u0441\u043e\u0431\u044b\u0435 \u0441\u043b\u0443\u0447\u0430\u0438 \u0440\u0430\u0437\u0431\u043e\u0440\u0430 &#8212; \u044d\u0442\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c \u0446\u0435\u043b\u044b\u0435 \u0447\u0438\u0441\u043b\u0430 \u043e\u0442 \u0432\u0435\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445, \u0432\u0435\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0447\u0438\u0441\u043b\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, &#171;<strong>315.0<\/strong>&#171;) \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c \u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0447\u043b\u0435\u043d\u0430\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b\/\u043e\u0431\u044a\u0435\u043a\u0442\u0430 (&#171;<strong>obj10.field1<\/strong>&#171;), \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 \u043e\u0442 \u0434\u0440\u0443\u0433\u0438\u0445 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432.<\/p>\n<pre><code class=\"cpp\"> void VMParser::parseToTokens(const char* sourceCode) {  \tTokenType isNumber = TokenType::UNKNOWN; \tbool insideString = false;                                         \/\/ inside string flag \tbool isReal = false;                                               \/\/ is real number flag \tsize_t length;                                                     \/\/ token length variable  \tchar nextChar;                                                     \/\/ next char variable \tbool blank, delimeter;                                             \/\/ blank &amp; delimeter char flags  \ttokens-&gt;clear();                                                   \/\/ clear tokens vector \trowCounter = 1;                                                    \/\/ reset current row counter \trowPointer = (char*)sourceCode;                                    \/\/ set current row pointer to beginning  \tchar* cursor = (char*)sourceCode;                                  \/\/ set cursor to source beginning  \tchar* start = cursor;                                              \/\/ start new token from cursor \tchar value = *cursor;                                              \/\/ read first char from cursor  \twhile (value != NULL) {                                            \/\/ while not end of string \t\tblank = isBlank(value);                                          \/\/ is blank char found? \t\tdelimeter = isDelimeter(value);                                  \/\/ is delimeter found? \t\tlength = cursor - start;                                         \/\/ measure token length \t\t     \/\/ Diffirentiate real numbers from member access operator '.' \t\tisNumber = identifyNumber(start, length - 1);                    \/\/ Try to get integer part of real number \t\tisReal = (value=='.' &amp;&amp; isNumber==TokenType::CONST_INTEGER);     \/\/ Is current token is real number  \t\tif ((blank || delimeter) &amp;&amp; !insideString &amp;&amp; !isReal) {          \/\/ if there is token separator                    \t\t\tif (length &gt; 0) pushToken(start, length);                      \/\/ if length &gt; 0 push token to vector \t\t\tif (value == '\\n') {                                           \/\/ if '\\n' found  \t\t\t\trowCounter++;                                                \/\/ increment row counter \t\t\t\trowPointer = cursor + 1;                                     \/\/ set row beginning pointer \t\t\t} \t\t\tnextChar = *(cursor + 1);                                      \/\/ get next char after cursor \t\t\tif (!blank &amp;&amp; isDelimeter(nextChar)) {                         \/\/ if next char is also delimeter \t\t\t\tif (pushToken(cursor, 2) == TokenType::UNKNOWN)              \/\/ try to push double char delimeter token \t\t\t\t\tpushToken(cursor, 1);                                      \/\/ if not pushed - its single char delimeter \t\t\t\telse cursor++;                                               \/\/ if double delimeter, increment cursor \t\t\t} else pushToken(cursor, 1);                                   \/\/ else push single char delimeter \t\t\tstart = cursor + 1;                                            \/\/ calculate next token start pointer \t\t} \t\telse if (value == '\"') insideString = !insideString;             \/\/ if '\"' char - flip insideString flag  \t\telse if (insideString &amp;&amp; value == '\\n') {                        \/\/ if '\\n' found inside string \t\t\t\/\/ TODO warn about parsing error \t\t} \t\tcursor++;                                                        \/\/ increment cursor pointer \t\tvalue = *cursor;                                                 \/\/ read next char \t}  \tlength = cursor - start;                                           \/\/ if there is a last token \tif (length &gt; 0) pushToken(start, length);                          \/\/ push last token to vector  } <\/code><\/pre>\n<p>\u041d\u0430\u0440\u044f\u0434\u0443 \u0441 \u043c\u0435\u0442\u043e\u0434\u043e\u043c parseToTokens, \u043f\u043e\u043c\u043e\u0433\u0430\u0442\u044c \u0432 \u0440\u0430\u0437\u0431\u043e\u0440\u0435 \u0438 \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043d\u0430\u043c \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0438\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u0438 \u0438 \u0442\u0438\u043f \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430. \u041f\u043b\u044e\u0441 \u043c\u0435\u0442\u043e\u0434 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u0432 \u0432\u0435\u043a\u0442\u043e\u0440. <\/p>\n<pre><code class=\"cpp\">class VMParser { \tpublic: \t\tVMParser(); \t\t~VMParser(); \t\tvoid parseToTokens(const char* sourceCode); \t\tToken getToken(size_t index); \t\tsize_t getTokenCount(); \t   private: \t\tvector&lt;Token&gt;* tokens; \t\tWORD rowCounter; \t\tchar* rowPointer;    \t\tbool isBlank(char value); \t\tbool isDelimeter(char value); \t\tTokenType pushToken(char* text, size_t length); \t\tTokenType getTokenType(char* text, size_t length); \t\tTokenType identifyNumber(char* text, size_t length); \t\tTokenType identifyKeyword(char* text, size_t length); \t};<\/code><\/pre>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043a\u043b\u0430\u0441\u0441 VMParser <strong><em>\u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 C \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430<\/em><\/strong> (\u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0431\u0435\u0441\u0441\u043c\u044b\u0441\u043b\u0435\u043d\u043d\u044b\u0439, \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0440\u0430\u0437\u0431\u043e\u0440\u0430):<\/p>\n<pre><code class=\"cpp\">int main() {     printf (\"Wow!\");     float a = 365.0 * 10 - 10.0 \/ 2 + 3; \t\twhile (1 != 2) { \t\t    abc.v1 = 'x'; \t\t} \t\tif (a &gt;= b) return a &amp;&amp; b; else a || b;  };<\/code><\/pre>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u0435\u0440\u0435\u0447\u0435\u043d\u044c \u043a\u043b\u0430\u0441\u0441\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0442\u043e\u043a\u0435\u043d\u043e\u0432:<\/p>\n<figure class=\"full-width\"><figcaption>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 C \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430<\/figcaption><\/figure>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043f\u0430\u0440\u0441\u0435\u0440. \u0422\u0435\u043f\u0435\u0440\u044c \u0435\u0433\u043e \u043d\u0430\u0434\u043e \u043a\u0430\u043a-\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u044c \u0440\u0430\u0437\u0431\u043e\u0440 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044e \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u044b.<\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0441 \u0446\u0435\u043b\u044b\u043c\u0438 \u0447\u0438\u0441\u043b\u0430\u043c\u0438 (\u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 &#171;*&#187; \u0438 &#171;\/&#187; \u043d\u0430\u0434 &#171;+&#187; \u0438 &#171;-&#187; \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f), \u0431\u0435\u0437 \u0441\u043a\u043e\u0431\u043e\u043a, \u0443\u043d\u0430\u0440\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0432\u0430\u0436\u043d\u044b\u0445 \u0432\u0435\u0449\u0435\u0439, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043e\u0448\u0438\u0431\u043e\u043a. \u0420\u0430\u0437\u0431\u043e\u0440 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0432\u043e\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cpp\">void VMCompiler::parseExpression(size_t startIndex, VMImage* destImage) { \tToken tkn; \tcurrentToken = startIndex; \tparseTerm(destImage); \ttkn = parser-&gt;getToken(currentToken); \twhile (tkn.type==TokenType::PLUS || tkn.type==TokenType::MINUS) { \t\t  currentToken++; \t\t  parseTerm(destImage); \t\t  if (tkn.type==TokenType::PLUS) destImage-&gt;emit(OP_ADD); else destImage-&gt;emit(OP_SUB); \t\t  tkn = parser-&gt;getToken(currentToken); \t} }   void VMCompiler::parseTerm(VMImage* destImage) { \tToken tkn; \tparseFactor(destImage); \tcurrentToken++; \ttkn = parser-&gt;getToken(currentToken); \twhile (tkn.type == TokenType::MULTIPLY || tkn.type == TokenType::DIVIDE) { \t\t  currentToken++; \t\t  parseFactor(destImage); \t\t  if (tkn.type == TokenType::MULTIPLY) destImage-&gt;emit(OP_MUL); else destImage-&gt;emit(OP_DIV); \t\t  currentToken++; \t\t  tkn = parser-&gt;getToken(currentToken); \t} }   void VMCompiler::parseFactor(VMImage* destImage) { \tToken tkn = parser-&gt;getToken(currentToken); \tchar buffer[32]; \tstrncpy(buffer, tkn.text, tkn.length); \tbuffer[tkn.length] = 0; \tdestImage-&gt;emit(OP_CONST, atoi(buffer)); }<\/code><\/pre>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u043a\u043e\u0440\u043c\u0438\u0442\u044c \u044d\u0442\u043e\u043c\u0443 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0443 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 &#171;3+5<em>*6+2*<\/em>3+15\/5&#8243;, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0441 \u0432\u044b\u0432\u043e\u0434\u043e\u043c \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0438 \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u043c\u0430\u0448\u0438\u043d\u0443. \u041e\u0436\u0438\u0434\u0430\u0435\u043c, \u0447\u0442\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0441\u0442\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0432\u0435\u0440\u0448\u0438\u043d\u0435 \u0441\u0442\u0435\u043a\u0430 &#8212; 42.<\/p>\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p>\u0423\u0440\u0430! \u041f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c! \u041f\u0435\u0440\u0432\u044b\u0435 \u0448\u0430\u0433\u0438 \u0432 \u0441\u0442\u043e\u0440\u043e\u043d\u0443 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430 \u0441\u0434\u0435\u043b\u0430\u043d\u044b.<\/p>\n<\/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=\"https:\/\/habr.com\/ru\/post\/560986\/\"> https:\/\/habr.com\/ru\/post\/560986\/<\/a><br \/><\/br><\/br><\/p>\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-324380","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/324380","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=324380"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/324380\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=324380"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=324380"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=324380"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}