Чтение онлайн

на главную - закладки

Жанры

Фундаментальные алгоритмы и структуры данных в Delphi

Бакнелл Джулиан М.

Шрифт:

Deque.Enqueue(MustScan);

{поставить в очередь первое состояние}

Deque.Enqueue(FStartState);

{подготовить индекс строки}

StrInx := StartPosn - 1;

{выполнять цикл до тех пор, пока очередь не будет пуста, или пока строка не закончится}

while (StrInx <= length (S)) and not Deque.IsEmpty do

begin {вытолкнуть верхнее состояние из очереди}

State := Deque.Pop;

{вначале выполнить обработку состояния "необходимо выполнить сканирование "}

if (State = MustScan) then begin

{если очередь пуста, вполне вероятно,

что задача выполнена, поскольку не осталось никаких состояний для обработки новых символов}

if not Deque.IsEmpty then begin

{если строка не закончилась, нужно извлечь символ и снова поставить в очередь состояние "необходимо выполнить сканирование"}

inc(StrInx);

if (StrInx <= length(S)) then begin

Ch := S[StrInx];

Deque.Enqueue(MustScan);

end;

end;

end

{в противном случае необходимо обработать состояние}

else with PNFAState (FTable [ State ])^ do

begin

case sdMatchType of

mtNone : begin

{для бесплатных переходов необходимо заталкивать в очередь следующие состояния}

Deque.Push(sdNextState2);

Deque.Push(sdNextState1);

end;

mtAnyChar : begin

{для сопоставления с любым символом необходимо поставить в очередь следующее состояние}

Deque.Enqueue(sdNextState1);

end;

mtChar : begin

{для сопоставления с символом необходимо поставить в очередь следующее состояние}

if (Ch = sdChar) then

Deque.Enqueue(sdNextState1);

end;

mtClass : begin

{для сопоставления с символом, входящим в состав класса, необходимо поставить в очередь следующее состояние}

if (Ch in sdClass^ ) then

Deque.Enqueue(sdNextState1);

end;

mtNegClass : begin

{для сопоставления с символом, не входящим в состав класса, необходимо поставить в очередь следующее состояние}

if not (Ch in sdClass^ ) then

Deque.Enqueue(sdNextState1);

end;

mtTerminal : begin

случае достижения конечного состояния строка соответствует регулярному выражению, если регулярное выражение не содержало никакого символа привязки или достигнут конец строки}

if (not FAnchorEnd) or (StrInx > length(S)) then begin

Result := true;

Exit;

end;

end;

end;

end;

end;

{достижение этой точки свидетельствует либо о том, что очередь исчерпана, либо о достижении конца строки. В первом случае подстрока не соответствует регулярному выражению, поскольку отсутствуют состояния для сопоставления. Во втором случае необходимо проверить состояния, расположенные слева от очереди, чтобы проверить, не является ли одно из них конечным. Если это так, строка соответствует регулярному выражению, определенному таблицей переходов}

while not Deque.IsEmpty do

begin

State := Deque.Pop;

with PNFAState (FTable [ State ])^ do

begin

case sdMatchType of

mtNone : begin

{для бесплатных переходов необходимо заталкивать в очередь следующие состояния}

Deque.Push(sdNextState2);

Deque.Push(sdNextState1);

end;

mtTerminal : begin

случае достижения конечного состояния строка соответствует регулярному выражению, если регулярное выражение не содержало никакого символа привязки или достигнут конец строки}

if (not FAnchorEnd) or (StrInx > length(S)) then begin

Result := true;

Exit;

end;

end;

end; {case}

end;

end;

finally

Deque.Free;

end;

end;

Было бы желательно, чтобы подпрограмму сопоставления можно было бы применять не только к любой начальной позиции строки, но, при необходимости, и только ко всей строке.

Поэтому представим два новых символа операций регулярных выражений: символы операций привязки "^" и "$". Знак вставки "^" означает, что любое соответствие должно иметь место только с начала строки. Знак доллара "$" означает, что совпадение должно происходить на всем пути до самого конца строки. Так, например, регулярное выражение "^function" означает "совпадение со словом function с начала строки", a "^end.$" означает, что вся строка должна состоять из символов е, n, d и точки. Она не должна содержать никаких других символов. Символы ^ и $ могут присутствовать, соответственно, только в начале и конце регулярного выражения. Они не могут находиться ни в какой другой позиции.

Это обусловливает небольшое изменение определенных нами грамматических правил. Изменение не очень велико, но, как мы видели, корректная формулировка грамматических правил существенно упрощает создание кода. Код реализации нового правила и соответствующего метода синтаксического анализа приведен в листинге 10.16. Естественно, интерфейсный метод Parse также изменен, чтобы вызывать именно его, а не первоначальный метод.

Листинг 10.16. Использование операций привязки

{<anchorexpr> ::= <expr> | '^' <ехрr> | <expr> '$' | '^' <ехрr> '$'}

function TtdRegexEngine.rcParseAnchorExpr : integer;

begin

{проверить на наличие начального символа '^'}

if (FPosn^ = '^') then begin

FAnchorStart :=true;

inc(FPosn);

end;

{выполнить синтаксический анализ выражения}

Result := rcParseExpr;

{в случае успеха необходимо выполнить проверку на наличие конечного символа '$'}

if (Result <> ErrorState) then begin

if (FPosn^ = '$') then begin

FAnchorEnd := true;

inc(FPosn);

end;

end;

end;

Теперь код выполнения сопоставления строк можно изменить для сопоставления как целых строк, так и подстрок. Если регулярное выражение начинается с символа "А", нужно просто попытаться становить соответствие строки, начиная с первого символа. Если нет, необходимо попытаться установить соответствие с каждой из подстрок, образованных из исходной строки. Код метода MatchString, в котором принимается это решение, приведен в листинге 10.17.

Поделиться:
Популярные книги

Стеллар. Трибут

Прокофьев Роман Юрьевич
2. Стеллар
Фантастика:
боевая фантастика
рпг
8.75
рейтинг книги
Стеллар. Трибут

Его огонь горит для меня. Том 2

Муратова Ульяна
2. Мир Карастели
Фантастика:
юмористическая фантастика
5.40
рейтинг книги
Его огонь горит для меня. Том 2

На границе империй. Том 9. Часть 4

INDIGO
17. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 4

Наследник

Кулаков Алексей Иванович
1. Рюрикова кровь
Фантастика:
научная фантастика
попаданцы
альтернативная история
8.69
рейтинг книги
Наследник

Совершенно несекретно

Иванов Дмитрий
15. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Совершенно несекретно

Ваше Сиятельство 2

Моури Эрли
2. Ваше Сиятельство
Фантастика:
фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Ваше Сиятельство 2

Прометей: каменный век II

Рави Ивар
2. Прометей
Фантастика:
альтернативная история
7.40
рейтинг книги
Прометей: каменный век II

Единственная для темного эльфа 3

Мазарин Ан
3. Мир Верея. Драконья невеста
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Единственная для темного эльфа 3

Жандарм

Семин Никита
1. Жандарм
Фантастика:
попаданцы
альтернативная история
аниме
4.11
рейтинг книги
Жандарм

Долгий путь домой

Русич Антон
Вселенная EVE Online
Фантастика:
космическая фантастика
попаданцы
6.20
рейтинг книги
Долгий путь домой

Прогрессор поневоле

Распопов Дмитрий Викторович
2. Фараон
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Прогрессор поневоле

Наследие Маозари 6

Панежин Евгений
6. Наследие Маозари
Фантастика:
попаданцы
постапокалипсис
рпг
фэнтези
эпическая фантастика
5.00
рейтинг книги
Наследие Маозари 6

Я еще не барон

Дрейк Сириус
1. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я еще не барон

Лолита

Набоков Владимир Владимирович
Проза:
классическая проза
современная проза
8.05
рейтинг книги
Лолита