function GetSubString(const S : String; Start, Stop : Integer):   String; begin  SetLength(Result, Stop-Start);  Move(S[Start], Result[1], Stop-Start); end; function ParseTag(const Tag : String; var TagName : String;  Attrs, Values : TStringList): Integer; type  // Возможные состояния  TState = (ReadTag, WaitAttr, WaitAttrOrEq, ReadAttr, WaitValue,  ReadValue, ReadValueSQ, ReadValueDQ); const  // Значения, возвращаемые функцией GetLink  resOK = 0; // разбор прошел успешно  resBadSyntax = -1; // синтаксическая ошибка  // Набор возможных разделительных символов  Delimeters = [' ', #9, #13, #10]; var  State : TState;  StartPos, i : Integer; begin  Result := resOK;  // очищаем список элементов  Attrs.Clear;  Values.Clear;  State := ReadTag; // входное состояние автомата  i := 2; // пропускаем символ '  while (Tag[i]'>') and (i  begin    case State of      ReadTag:      if Tag[i] in Delimeters then      begin        // чтение имени тэга закончено        TagName := GetSubString(Tag, StartPos, i);        State := WaitAttr;      end;      WaitAttr:      if (Tag[i] in Delimeters) = False then      begin        if Tag[i] = '=' then        begin          Result := resBadSyntax;          Exit;        end;        StartPos := i;        State := ReadAttr;      end;      ReadAttr:      if (Tag[i] in Delimeters) or (Tag[i] = '=') then      begin        // чтение имени атрибута закончено, добавляем имя атрибута в список        Attrs.Add(GetSubString(Tag, StartPos, i));        if Tag[i] = '=' then State := WaitValue        else State := WaitAttrOrEq;      end;      WaitAttrOrEq:      if (Tag[i] in Delimeters) = False then      begin        if Tag[i] = '=' then State := WaitValue else        begin          // начинается чтение имени атрибута          // предыдущему атрибуту не присвоено никаких значений,          // добавляем пустую строку в список Values          Values.Add('');          State := ReadAttr;          StartPos := i;        end;      end;      WaitValue:      if (Tag[i] in Delimeters) = False then      begin        if Tag[i] = '=' then        begin          // два символа '=' подряд          Result := resBadSyntax;          Exit;        end;        if Tag[i] = '"' then        begin          // чтение значения начнется со следующего символа после кавычек:          StartPos := i + 1;          State := ReadValueDQ;        end else        if Tag[i] = '''' then        begin          // чтение значения начнется со следующего символа после кавычек:          StartPos := i + 1;          State := ReadValueSQ;        end else        begin          // чтение значения без кавычек          StartPos := i;          State := ReadValue;        end;      end;      ReadValue:      if Tag[i] in Delimeters then      begin        // чтение значения закончено        Values.Add(GetSubString(Tag, StartPos, i));        State := WaitAttr;      end;      ReadValueDQ:      if Tag[i] = '"' then      begin        // чтение значения в двойных кавычках закончено        Values.Add(GetSubString(Tag, StartPos, i));        State := WaitAttr;      end;      ReadValueSQ:      if Tag[i] = '''' then      begin        // чтение значения в одинарных кавычках закончено        Values.Add(GetSubString(Tag, StartPos, i));        State := WaitAttr;      end;    end; // case State of    Inc(i);  end; // while (Body[i]'>') and (i  // проверяем состояние автомата после обработки строки  // последним символом строки должен быть '>'  case State of    ReadValue : Values.Add(GetSubString(Tag, StartPos, i));    ReadAttr : Attrs.Add(GetSubString(Tag, StartPos, i));    ReadTag : TagName := GetSubString(Tag, StartPos, i);    WaitAttr, WaitAttrOrEq: ; // ничего не делаем    else Result := resBadSyntax; // другие состояния недопустимы  end; end; |