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<Length(Tag)) do
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<Length(Tag)) do
// проверяем состояние автомата после обработки строки
// последним символом строки должен быть
'>'
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;
|