Advertisement
Guest User

Untitled

a guest
May 28th, 2017
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 12.64 KB | None | 0 0
  1. //Модуль разбивающий код на лексемы
  2. unit LexParse;
  3.  
  4. interface
  5.  
  6. uses Classes, LexType, SysUtils;
  7.  
  8. type
  9. //Запись для хранения информации о лексеме
  10.   TLexItem = record
  11.     LexType : TLexType; //Тип лексемы
  12.     LexValue: String;   //Значение лексемы
  13.     LexPos  : Integer;  //Позиция лексемы в коде программы (номер строки)
  14. end;
  15.  
  16. type
  17. //Перечень всех возможных состояний конечного автомата
  18. TAutoPos = (
  19.   AP_START,AP_THEN1,AP_THEN2,AP_THEN3,AP_THEN4,
  20.   AP_ELSE1,AP_ELSE2,AP_ELSE3,AP_ELSE4,AP_IF1,AP_IF2,
  21.   AP_ASSIGN,AP_VAR,AP_CONST_NORM,AP_CONST_DROB,AP_CONST_DROB2,
  22.   AP_CONST_LOG,AP_CONST_LOG2,AP_CONST_LOG3,AP_COMM1,AP_COMM2,AP_ERR);
  23.  
  24. function ParseText(sIshodnik: TStrings): Integer;
  25. procedure CheckLexem(chNext: Char; PosNext: TAutoPos);
  26. procedure FinishLexem(LexType: TLexType);
  27. procedure FinishConstNorm;
  28. procedure FinishConstDrob;
  29. procedure FinishConstLog;
  30. procedure AddLexemToList(LexType: TLexType; LexStart, LexFinish, LexPos: Integer);
  31. procedure CreateError(sName: String; ErrorPos: Integer);
  32.  
  33. var
  34.   LexemList: array of TLexItem; //Массив лексем
  35.  
  36.   AutoPos       : TAutoPos;     //Текущее состояние конечного автомата
  37.   i, j,
  38.   iCurPos,                      //Текущая позиция в тексте программы
  39.   iStartPos,                    //Позиция с которой началась текущая лексема
  40.   iLenStr,                      //Длина обрабатываемой строки
  41.   iErrorRow     : Integer;      //Номер строки в которой ошибка
  42.   s             : String;
  43. implementation
  44.  
  45. (*==============================================================================
  46. Проверка следующего символа лексемы *)
  47. procedure CheckLexem(chNext: Char; PosNext: TAutoPos);
  48. begin
  49.   if s[j] in [';','<','>','=',':','/',' ',#9,#10,#13] then begin
  50.     AddLexemToList(LEX_VAR, iStartPos, j - 1, i + 1);
  51.     iStartPos := j;
  52.   end;
  53.  
  54.   case s[j] of
  55.     ';': AddLexemToList(LEX_SEMI, j, j, i + 1);
  56.     '<': AddLexemToList(LEX_MEN,  j, j, i + 1);
  57.     '>': AddLexemToList(LEX_BOL,  j, j, i + 1);
  58.     '=': AddLexemToList(LEX_EQ,   j, j, i + 1);
  59.     ':': AutoPos := AP_ASSIGN;
  60.     '/': AutoPos := AP_COMM1;
  61.     ' ',#9,#10,#13: ;
  62.    
  63.     //Если ни одно условие из вышеперечисленных не выполнилось
  64.     else
  65.       if s[j] = chNext then
  66.         AutoPos := PosNext
  67.       else if s[j] in ['0'..'9','A'..'Z','a'..'z','_'] then
  68.         AutoPos := AP_VAR
  69.       else
  70.         AutoPos := AP_ERR;
  71.   end;
  72. end;
  73.  
  74. (*==============================================================================
  75. Процедура проверки завершения лексемы *)
  76. procedure FinishLexem(LexType: TLexType);
  77. begin
  78.   if s[j] in [';','<','>','=',':','/',' ',#9,#10,#13] then begin
  79.     AddLexemToList(LexType, iStartPos, j - 1, i + 1);
  80.     iStartPos := j;
  81.   end;
  82.  
  83.   case s[j] of
  84.     ';': AddLexemToList(LEX_SEMI, j, j, i + 1);
  85.     '<': AddLexemToList(LEX_MEN,  j, j, i + 1);
  86.     '>': AddLexemToList(LEX_BOL,  j, j, i + 1);
  87.     '=': AddLexemToList(LEX_EQ,   j, j, i + 1);
  88.     ':': AutoPos := AP_ASSIGN;
  89.     '/': AutoPos := AP_COMM1;
  90.     '0'..'9','A'..'Z','a'..'z','_': AutoPos := AP_VAR;
  91.     ' ',#9,#10,#13: ;
  92.  
  93.     //Если ни одно условие из вышеперечисленных не выполнилось
  94.     else
  95.       AutoPos := AP_ERR;
  96.   end;
  97. end;
  98.  
  99. (*==============================================================================
  100. Процедура проверки завершения константы в нормальной форме *)
  101. procedure FinishConstNorm;
  102. begin
  103.   if s[j] in [';','<','>','=',':','/',' ',#9,#10,#13] then begin
  104.     AddLexemToList(LEX_CONST_NORM, iStartPos, j - 1, i + 1);
  105.     iStartPos := j;
  106.   end;
  107.  
  108.   case s[j] of
  109.     ';': AddLexemToList(LEX_SEMI, j, j, i + 1);
  110.     '<': AddLexemToList(LEX_MEN,  j, j, i + 1);
  111.     '>': AddLexemToList(LEX_BOL,  j, j, i + 1);
  112.     '=': AddLexemToList(LEX_EQ,   j, j, i + 1);
  113.     ':': AutoPos := AP_ASSIGN;
  114.     '/': AutoPos := AP_COMM1;
  115.     '0'..'9': AutoPos := AP_CONST_NORM;
  116.     ',': AutoPos := AP_CONST_DROB;
  117.     'E','e': AutoPos := AP_CONST_LOG;
  118.     ' ',#9,#10,#13: ;
  119.  
  120.     //Если ни одно условие из вышеперечисленных не выполнилось
  121.     else
  122.       AutoPos := AP_ERR;
  123.   end;
  124. end;
  125.  
  126. (*==============================================================================
  127. Процедура проверки завершения константы в дробной форме *)
  128. procedure FinishConstDrob;
  129. begin
  130.   if (AutoPos = AP_CONST_DROB2) and
  131.      (s[j] in [';','<','>','=',':','/',' ',#9,#10,#13]) then begin
  132.     AddLexemToList(LEX_CONST_DROB, iStartPos, j - 1, i + 1);
  133.     iStartPos := j;
  134.   end;
  135.  
  136.   case s[j] of
  137.     ';': AddLexemToList(LEX_SEMI, j, j, i + 1);
  138.     '<': AddLexemToList(LEX_MEN,  j, j, i + 1);
  139.     '>': AddLexemToList(LEX_BOL,  j, j, i + 1);
  140.     '=': AddLexemToList(LEX_EQ,   j, j, i + 1);
  141.     ':': AutoPos := AP_ASSIGN;
  142.     '/': AutoPos := AP_COMM1;
  143.     '0'..'9': AutoPos := AP_CONST_DROB2;
  144.     'E','e': AutoPos := AP_CONST_LOG;
  145.     ' ',#9,#10,#13: ;
  146.  
  147.     //Если ни одно условие из вышеперечисленных не выполнилось
  148.     else
  149.       AutoPos := AP_ERR;
  150.   end;
  151. end;
  152.  
  153. (*==============================================================================
  154. Процедура проверки завершения константы в логарифмической форме *)
  155. procedure FinishConstLog;
  156. begin
  157.   if (AutoPos = AP_CONST_LOG3) and
  158.      (s[j] in [';','<','>','=',':','/',' ',#9,#10,#13]) then begin
  159.     AddLexemToList(LEX_CONST_LOG, iStartPos, j - 1, i + 1);
  160.     iStartPos := j;
  161.   end;
  162.  
  163.   case AutoPos of
  164.     AP_CONST_LOG: begin
  165.       case s[j] of
  166.         '-', '+': AutoPos := AP_CONST_LOG2;
  167.         else
  168.           AutoPos := AP_ERR;
  169.       end;
  170.     end;
  171.  
  172.     AP_CONST_LOG2: begin
  173.       case s[j] of
  174.         '0'..'9': AutoPos := AP_CONST_LOG3;
  175.         else
  176.           AutoPos := AP_ERR;
  177.       end;
  178.     end;
  179.  
  180.     else
  181.       case s[j] of
  182.         ';': AddLexemToList(LEX_SEMI, j, j, i + 1);
  183.         '<': AddLexemToList(LEX_MEN,  j, j, i + 1);
  184.         '>': AddLexemToList(LEX_BOL,  j, j, i + 1);
  185.         '=': AddLexemToList(LEX_EQ,   j, j, i + 1);
  186.         ':': AutoPos := AP_ASSIGN;
  187.         '/': AutoPos := AP_COMM1;
  188.         '0'..'9': ;
  189.         ' ',#9,#10,#13: ;
  190.  
  191.         //Если ни одно условие из вышеперечисленных не выполнилось
  192.         else
  193.           AutoPos := AP_ERR;
  194.       end;
  195.   end{case AutoPos};
  196. end;
  197.  
  198. (*==============================================================================
  199. Добавление лексемы в список *)
  200. procedure AddLexemToList(LexType: TLexType; LexStart, LexFinish, LexPos: Integer);
  201. var
  202.   n: Integer;
  203. begin
  204.   n := Length(LexemList);
  205.   SetLength(LexemList, n + 1);
  206.   LexemList[n].LexType  := LexType;
  207.   LexemList[n].LexValue := copy(s, LexStart, LexFinish - LexStart + 1);
  208.   LexemList[n].LexPos   := LexPos;
  209.  
  210.   AutoPos := AP_START;
  211. end;
  212.  
  213. (*==============================================================================
  214. Создание информации об ошибке в нулевом элементе таблицы лексем *)
  215. procedure CreateError(sName: String; ErrorPos: Integer);
  216. begin
  217.   if Length(LexemList) = 0 then
  218.     SetLength(LexemList, 1);
  219.   LexemList[0].LexType  := LEX_ERR;
  220.   LexemList[0].LexValue := sName;
  221.   LexemList[0].LexPos   := ErrorPos;
  222. end;
  223.  
  224. (*==============================================================================
  225. Разбор текста на лексемы *)
  226. function ParseText(sIshodnik: TStrings): Integer;
  227. begin
  228.   Result := 0;           //Результат 0
  229.  
  230.   LexemList := nil;      //Очищаем массив лексем
  231.   iErrorRow := -1;       //Изначально ошибочной строки нету
  232.   AutoPos   := AP_START; //Начальное значение автомата
  233.   iCurPos   := 0;        //Текущая позиция в тексте программы
  234.  
  235. //Цикл перебора каждого символа исходного текста
  236.   for i := 0 to sIshodnik.Count - 1 do begin
  237.     //Считываем строку с номером i и определяем ее длину
  238.     s := sIshodnik.Strings[i];
  239.     iLenStr := Length(s);
  240.  
  241.     //Цикл посимвольно читающий строку
  242.     for j := 1 to iLenStr do begin
  243.       Inc(iCurPos);
  244.  
  245.       case AutoPos of
  246.         AP_START: begin
  247.           iStartPos := j;
  248.           case s[j] of
  249.             'i': AutoPos := AP_IF1;
  250.             't': AutoPos := AP_THEN1;
  251.             'e': AutoPos := AP_ELSE1;
  252.             ':': AutoPos := AP_ASSIGN;
  253.             '/': AutoPos := AP_COMM1;
  254.             ';': AddLexemToList(LEX_SEMI, iStartPos, j, i + 1);
  255.             '<': AddLexemToList(LEX_MEN,  iStartPos, j, i + 1);
  256.             '>': AddLexemToList(LEX_BOL,  iStartPos, j, i + 1);
  257.             '=': AddLexemToList(LEX_EQ,   iStartPos, j, i + 1);
  258.             'A'..'Z',
  259.             'a'..'d',
  260.             'f'..'h',
  261.             'j'..'s',
  262.             'u'..'z', '_' : AutoPos := AP_VAR;
  263.             '0'..'9'      : AutoPos := AP_CONST_NORM;
  264.             ' ',#9,#10,#13: ;
  265.             else
  266.               AutoPos := AP_ERR;
  267.           end{case s[iCurPos]};
  268.         end;
  269.         AP_IF1  : CheckLexem('f', AP_IF2);
  270.         AP_IF2  : FinishLexem(LEX_IF);
  271.         AP_THEN1: CheckLexem('h', AP_THEN2);
  272.         AP_THEN2: CheckLexem('e', AP_THEN3);
  273.         AP_THEN3: CheckLexem('n', AP_THEN4);
  274.         AP_THEN4: FinishLexem(LEX_THEN);
  275.         AP_ELSE1: CheckLexem('l', AP_ELSE2);
  276.         AP_ELSE2: CheckLexem('s', AP_ELSE3);
  277.         AP_ELSE3: CheckLexem('e', AP_ELSE4);
  278.         AP_ELSE4: FinishLexem(LEX_ELSE);
  279.  
  280.         AP_ASSIGN:
  281.           case s[j] of
  282.             '=': AddLexemToList(LEX_ASSIGN, j - 1, j, i + 1);
  283.             else
  284.               Result := i + 1;
  285.               iStartPos := j - 1;
  286.               break;
  287.           end;
  288.         AP_VAR       : FinishLexem(LEX_VAR);
  289.         AP_CONST_NORM: FinishConstNorm;
  290.  
  291.         AP_CONST_DROB,
  292.         AP_CONST_DROB2: FinishConstDrob;
  293.  
  294.         AP_CONST_LOG,
  295.         AP_CONST_LOG2,
  296.         AP_CONST_LOG3 : FinishConstLog;
  297.         AP_COMM1:
  298.           case s[j] of
  299.             '/': begin
  300.               AutoPos := AP_START;
  301.               Inc(iCurPos, iLenStr - j);
  302.               break;
  303.             end;
  304.             else
  305.               Result := i + 1;
  306.               iStartPos := j - 1;
  307.               break;
  308.           end;
  309.       end{case AutoPos};
  310.  
  311.       //Если достигнут конец строки - значит конец текцщей лексемы
  312.       if j = iLenStr then
  313.       begin
  314.         case AutoPos of
  315.           AP_IF2        : AddLexemToList(LEX_IF, iStartPos, j, i + 1);
  316.           AP_THEN4      : AddLexemToList(LEX_THEN, iStartPos, j, i + 1);
  317.           AP_ELSE4      : AddLexemToList(LEX_ELSE, iStartPos, j, i + 1);
  318.           AP_CONST_NORM : AddLexemToList(LEX_CONST_NORM, iStartPos, j, i + 1);
  319.           AP_CONST_DROB : AutoPos := AP_ERR;
  320.           AP_CONST_DROB2: AddLexemToList(LEX_CONST_DROB, iStartPos, j, i + 1);
  321.           AP_CONST_LOG,
  322.           AP_CONST_LOG2 : AutoPos := AP_ERR;
  323.           AP_CONST_LOG3 : AddLexemToList(LEX_CONST_LOG, iStartPos, j, i + 1);
  324.           AP_IF1,
  325.           AP_THEN1,
  326.           AP_THEN2,
  327.           AP_THEN3,
  328.           AP_ELSE1,
  329.           AP_ELSE2,
  330.           AP_ELSE3,
  331.           AP_VAR        : AddLexemToList(LEX_VAR, iStartPos, j, i + 1);
  332.         end{case AutoPos};
  333.       end;
  334.  
  335.       if Result <> 0 then
  336.         Break;
  337.  
  338.       //Если была ошибка в лексемах, то останавливаемся
  339.       if AutoPos = AP_ERR then begin
  340.         Result := i + 1;
  341.         Break;
  342.       end;
  343.     end{for j};
  344.  
  345.     if Result <> 0 then
  346.       Break;
  347.  
  348.     Inc(iCurPos, 2);//Увеличиваем общий счетчик символов на 2
  349.   end{for i};
  350.  
  351. ////Генерация ошибок
  352.   if AutoPos = AP_ASSIGN then begin
  353.     CreateError('Незавершенный знак присваивания', iCurPos);
  354.     exit;
  355.   end;
  356.  
  357.   if AutoPos = AP_COMM1 then begin
  358.     CreateError('Незавершенный комментарий', iCurPos);
  359.     exit;
  360.   end;
  361.  
  362.   if AutoPos = AP_ERR then begin
  363.     CreateError('Незавершенная лексема', iCurPos);
  364.     exit;
  365.   end;
  366. end;
  367.  
  368. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement