Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Π€ΡƒΠ½Π΄Π°ΠΌΠ΅Π½Ρ‚Π°Π»ΡŒΠ½Ρ‹Π΅ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΡ‹ ΠΈ структуры Π΄Π°Π½Π½Ρ‹Ρ… Π² DelphiΒ». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 90

Автор Π”ΠΆΡƒΠ»ΠΈΠ°Π½ Π‘Π°ΠΊΠ½Π΅Π»Π»

ΠŸΡ€Π°Π²ΠΈΠ»Π° прСдставлСния рСгулярных Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, с ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌΠΈ ΠΌΡ‹ Π±ΡƒΠ΄Π΅ΠΌ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ, ΠΏΠΎΠΊΠ°Π·Π°Π½Ρ‹ Π½Π° рис. 10.5. Они записаны Π² стандартной Ρ„ΠΎΡ€ΠΌΠ΅ BNF (Backu;

Naur Form - Ρ„ΠΎΡ€ΠΌΠ° Бэкуса-Наура, БНЀ). "::=" ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ "ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΎ ΠΊΠ°ΠΊ", Π° "|" ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ "Π˜Π›Π˜". Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ, пСрвая строка ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅: <Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅> являСтся Π»ΠΈΠ±ΠΎ <Ρ‡Π»Π΅Π½ΠΎΠΌ>, Π»ΠΈΠ±ΠΎ <Ρ‡Π»Π΅Π½ΠΎΠΌ>, Π·Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ слСдуСт символ Π²Π΅Ρ€Ρ‚ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎΠΉ Ρ‡Π΅Ρ€Ρ‚Ρ‹, Π° Π·Π° Π½ΠΈΠΌ - Π΅Ρ‰Π΅ ΠΎΠ΄Π½ΠΎ <Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅>. Вторая строка ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚: <Ρ‡Π»Π΅Π½> - это Π»ΠΈΠ±ΠΎ <коэффициСнт>, Π»ΠΈΠ±ΠΎ <коэффициСнт> Π·Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ слСдуСт <Ρ‡Π»Π΅Π½>, ΠΈ Ρ‚.Π΄. Π­Ρ‚ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ грамматичСских ΠΏΡ€Π°Π²ΠΈΠ» (ΠΎΠ½ΠΈ Π½Π°Π·Ρ‹Π²Π°ΡŽΡ‚ΡΡ "грамматичСскими", ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‚ язык. Если ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ справочной систСмС Delphi, Π² Π½Π΅ΠΉ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ грамматичСскиС ΠΏΡ€Π°Π²ΠΈΠ»Π° языка Object Pascal. Они ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Ρ‹ Ρ‚Π°ΠΊΠΈΠΌ ΠΆΠ΅ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ.) ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ для гСнСрирования ΠΏΠΎΠ΄ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ вычислСния рСгулярного выраТСния. ВскорС ΠΌΡ‹ ΡƒΠ²ΠΈΠ΄ΠΈΠΌ, ΠΊΠ°ΠΊ это дСлаСтся. А ΠΏΠΎΠΊΠ° ΠΏΡ€ΠΈΠΌΠΈΡ‚Π΅ ΠΊ свСдСнию, Ρ‡Ρ‚ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ грамматичСских ΠΏΡ€Π°Π²ΠΈΠ» ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ для быстрой ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ Π΄Π°Π½Π½ΠΎΠ΅ рСгулярноС Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ являСтся ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΌ.

ВСроятно, Π»ΡƒΡ‡ΡˆΠ΅ привСсти нСсколько ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠ² рСгулярных Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ. Π­Ρ‚ΠΎ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΠ½ΡΡ‚ΡŒ ΠΈΡ… ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅.


Рис.10.5.ГрамматичСскиС ΠΏΡ€Π°Π²ΠΈΠ»Π° составлСния рСгулярных Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, прСдставлСнныС Π² Ρ„ΠΎΡ€ΠΌΠ΅ БНЀ


Π­Ρ‚ΠΎ рСгулярноС Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ соотвСтствуСт ΠΈΠΌΠ΅Π½ΠΈ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π° Π² языкС Pascal. ΠŸΠ΅Ρ€Π²ΠΎΠ΅ Π·Π°ΠΊΠ»ΡŽΡ‡Π΅Π½Π½ΠΎΠ΅ Π² ΠΊΠ²Π°Π΄Ρ€Π°Ρ‚Π½Ρ‹Π΅ скобки ΠΏΠΎΠ΄Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ - класс символов, ΠΈΠ· опрСдСлСния ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ слСдуСт, Ρ‡Ρ‚ΠΎ ΠΏΠ΅Ρ€Π²Ρ‹ΠΌ символом строки, для ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΡƒΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°Ρ‚ΡŒΡΡ соотвСтствиС, Π΄ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ Π±ΡƒΠΊΠ²Π°, прописная ΠΈΠ»ΠΈ строчная, ΠΈΠ»ΠΈ символ подчСркивания. Π’Ρ‚ΠΎΡ€ΠΎΠ΅ Π·Π°ΠΊΠ»ΡŽΡ‡Π΅Π½Π½ΠΎΠ΅ Π² ΠΊΠ²Π°Π΄Ρ€Π°Ρ‚Π½Ρ‹Π΅ скобки ΠΏΠΎΠ΄Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ - Π΅Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ класс символов, ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‰ΠΈΠΉ с ΠΏΠ΅Ρ€Π²Ρ‹ΠΌ, Π·Π° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ Π² Π½Π΅Π³ΠΎ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Ρ‹ Ρ†ΠΈΡ„Ρ€Ρ‹. Π­Ρ‚ΠΎΡ‚ шаблон ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΠ²Ρ‚ΠΎΡ€ΡΡ‚ΡŒΡΡ ноль ΠΈΠ»ΠΈ Π±ΠΎΠ»Π΅Π΅ Ρ€Π°Π· (Ρ‡Ρ‚ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΎ символом * Π² ΠΊΠΎΠ½Ρ†Π΅ рСгулярного выраТСния). Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, этому рСгулярному Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΡŽ соотвСтствуСт Π±ΡƒΠΊΠ²Π° ΠΈΠ»ΠΈ символ подчСркивания, Π·Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ слСдуСт ноль ΠΈΠ»ΠΈ Π±ΠΎΠ»Π΅Π΅ Π±ΡƒΠΊΠ², символов подчСркивания ΠΈΠ»ΠΈ Ρ†ΠΈΡ„Ρ€.

(+|-)?[0-9]+(.[0-9]+)?

Π­Ρ‚ΠΎ рСгулярноС Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ соотвСтствуСт ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»Π΅Π½ΠΈΡŽ Ρ†Π΅Π»ΠΎΠ³ΠΎ числа ΠΈΠ»ΠΈ числа с ΠΏΠ»Π°Π²Π°ΡŽΡ‰Π΅ΠΉ Ρ‚ΠΎΡ‡ΠΊΠΎΠΉ Π² языкС Pascal. Оно ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ Π½Π΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ Π·Π½Π°ΠΊ, ΠΎΠ΄Π½Ρƒ ΠΈΠ»ΠΈ Π±ΠΎΠ»Π΅Π΅ Ρ†ΠΈΡ„Ρ€ ΠΈ Π½Π΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΡƒΡŽ Π΄Ρ€ΠΎΠ±Π½ΡƒΡŽ Ρ‡Π°ΡΡ‚ΡŒ. Дробная Ρ‡Π°ΡΡ‚ΡŒ состоит ΠΈΠ· дСсятичной Ρ‚ΠΎΡ‡ΠΊΠΈ, Π·Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ слСдуСт ΠΎΠ΄Π½Π° ΠΈΠ»ΠΈ Π±ΠΎΠ»Π΅Π΅ Ρ†ΠΈΡ„Ρ€. Если дробная Ρ‡Π°ΡΡ‚ΡŒ отсутствуСт, число являСтся Ρ†Π΅Π»Ρ‹ΠΌ. Если ΠΎΠ½Π° присутствуСт, число являСтся числом с ΠΏΠ»Π°Π²Π°ΡŽΡ‰Π΅ΠΉ Ρ‚ΠΎΡ‡ΠΊΠΎΠΉ.

{[^}]*}

Π­Ρ‚ΠΎΡ‚ послСдний ΠΏΡ€ΠΈΠΌΠ΅Ρ€ рСгулярного выраТСния соотвСтствуСт ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΡŽ Π² языкС Pascal, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ помСщаСтся Π² Ρ„ΠΈΠ³ΡƒΡ€Π½Ρ‹Π΅ скобки. Π’Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΉ Ρ„ΠΈΠ³ΡƒΡ€Π½ΠΎΠΉ скобки, Π·Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ слСдуСт ноль ΠΈΠ»ΠΈ Π±ΠΎΠ»Π΅Π΅ символов, Π½ΠΈ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π½Π΅ являСтся Π·Π°ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΉ скобкой, Π° Π·Π°Ρ‚Π΅ΠΌ слСдуСт Π·Π°ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π°Ρ фигурная скобка.

ИспользованиС рСгулярных Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ

БущСствуСт Ρ‚Ρ€ΠΈ этапа использования рСгулярного выраТСния. На ΠΏΠ΅Ρ€Π²ΠΎΠΌ рСгулярноС Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ разбиваСтся Π½Π° ΡΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠ΅ Π΅Π³ΠΎ лСксСмы, Π½Π° Π²Ρ‚ΠΎΡ€ΠΎΠΌ ΠΎΠ½ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΡŽΡ‚ΡΡ Ρ„ΠΎΡ€ΠΌΡƒ, ΠΏΡ€ΠΈΠ³ΠΎΠ΄Π½ΡƒΡŽ для установки соотвСтствия (компиляция рСгулярного выраТСния) ΠΈ Π½Π° Π·Π°ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΌ этапС скомпилированная Ρ„ΠΎΡ€ΠΌΠ° рСгулярного выраТСния ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для собствСнно установки соотвСтствия со строками. Π­Ρ‚ΠΎΡ‚ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π» ΠΈΠ·Π»ΠΎΠΆΠ΅Π½ Π² Π΄Π°Π½Π½ΠΎΠΉ Π³Π»Π°Π²Π΅ ΠΏΠΎΡ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ скомпилированная Ρ„ΠΎΡ€ΠΌΠ° рСгулярного выраТСния рСализуСтся Π² Π²ΠΈΠ΄Π΅ NFA-Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚Π°.

БинтаксичСский Π°Π½Π°Π»ΠΈΠ· рСгулярных Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ

ΠŸΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ рассмотрим Ρ‚Ρ€ΠΈ упомянутых Π²Ρ‹ΡˆΠ΅ этапа. Π’ ΠΏΠ΅Ρ€Π²ΡƒΡŽ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ синтаксичСского Π°Π½Π°Π»ΠΈΠ·Π° Π΄Π°Π½Π½ΠΎΠΉ строки рСгулярного выраТСния. ЦСлью этого процСсса являСтся простая ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ строка рСгулярного выраТСния соотвСтствуСт синтаксису, ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠΌΡƒ грамматичСскими ΠΏΡ€Π°Π²ΠΈΠ»Π°ΠΌΠΈ.

Π’Π°ΠΊ ΠΊΠ°ΠΊ ΠΆΠ΅, располагая ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ΠΌ грамматичСских ΠΏΡ€Π°Π²ΠΈΠ» ΠΈ рСгулярным Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ΠΌ, ΠΌΠΎΠΆΠ½ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ считываниС символов строки ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ рСгулярноС Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π² Ρ†Π΅Π»ΠΎΠΌ Π½Π° ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚ соотвСтствия грамматичСским ΠΏΡ€Π°Π²ΠΈΠ»Π°ΠΌ? ΠŸΡ€ΠΎΡ‰Π΅ всСго ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ для этого нисходящий синтаксичСский Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€ (top-down parser), ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΈΠ½ΠΎΠ³Π΄Π° Π΅Ρ‰Π΅ Π½Π°Π·Ρ‹Π²Π°ΡŽΡ‚ рСкурсивным нисходящим синтаксичСским Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€ΠΎΠΌ (recursive descent parser). ΠŸΡ€ΠΈ условии, Ρ‡Ρ‚ΠΎ грамматичСскиС ΠΏΡ€Π°Π²ΠΈΠ»Π° Ρ‡Π΅Ρ‚ΠΊΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Ρ‹, эта Π·Π°Π΄Π°Ρ‡Π° достаточно проста.

ΠŸΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ нисходящСго синтаксичСского Π°Π½Π°Π»ΠΈΠ·Π° каТдая продукция (production) Π² грамматичСском ΠΏΡ€Π°Π²ΠΈΠ»Π΅ становится ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΏΠΎΠ΄ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΎΠΉ. (продукция - это ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠΉ Π³Ρ€Π°ΠΌΠΌΠ°Ρ‚ΠΈΠΊΠΈ, Ρ‚.Π΅. ΠΎΠ΄Π½Π° ΠΈΠ· строк, содСрТащих символ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ "::=".) ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅ΠΌ ΠΏΠ΅Ρ€Π²ΡƒΡŽ ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ†ΠΈΡŽ Π³Ρ€Π°ΠΌΠΌΠ°Ρ‚ΠΈΠΊΠΈ (ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‰ΡƒΡŽ < Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅> ) Π² ΠΌΠ΅Ρ‚ΠΎΠ΄ ParseExpr.

Π§Ρ‚ΠΎ ΠΆΠ΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π΄Π΅Π»Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄ ParseExpr? ΠŸΡ€ΠΎΠ΄ΡƒΠΊΡ†ΠΈΡ ΡƒΡ‚Π²Π΅Ρ€ΠΆΠ΄Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ < Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅> - это Π»ΠΈΠ±ΠΎ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ <Ρ‡Π»Π΅Π½>, Π»ΠΈΠ±ΠΎ <Ρ‡Π»Π΅Π½>, Π·Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ слСдуСт символ Π²Π΅Ρ€Ρ‚ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎΠΉ Ρ‡Π΅Ρ€Ρ‚Ρ‹, Π° Π·Π° Π½ΠΈΠΌ Π΅Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ <Ρ‡Π»Π΅Π½>. ΠŸΡ€Π΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, Ρ‡Ρ‚ΠΎ сущСствуСт ΠΌΠ΅Ρ‚ΠΎΠ΄ ParseTerm, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ выполняСт синтаксичСский Π°Π½Π°Π»ΠΈΠ· <Ρ‡Π»Π΅Π½Π°>. Π’ любом случаС, ΠΏΡ€Π΅ΠΆΠ΄Π΅ всСго, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ эту ΠΏΠΎΠ΄ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ для выполнСния синтаксичСского Π°Π½Π°Π»ΠΈΠ·Π° <Ρ‡Π»Π΅Π½Π°>. Если послС Π²ΠΎΠ·Π²Ρ€Π°Ρ‚Π° ΠΈΠ· Π½Π΅Π΅ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌ символом являСтся символ Π²Π΅Ρ€Ρ‚ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎΠΉ Ρ‡Π΅Ρ€Ρ‚Ρ‹, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚ΡŒ ΠΈ рСкурсивно Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ ΠΏΠΎΠ΄ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ ParseExpr, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ синтаксичСский Π°Π½Π°Π»ΠΈΠ· ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ выраТСниях Π­Ρ‚ΠΎ всС, Ρ‡Ρ‚ΠΎ касаСтся ΠΏΠΎΠ΄ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ParseExpr.

На Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ врСмя оставим Π±Π΅Π· внимания Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° ParseTerm (вскорС станСт понятно, ΠΏΠΎΡ‡Π΅ΠΌΡƒ) ΠΈ рассмотрим ΠΌΠ΅Ρ‚ΠΎΠ΄ ParseFactor, Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‰ΠΈΠΉ синтаксичСский Π°Π½Π°Π»ΠΈΠ· коэффициСнтах Как ΠΈ Π² ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΌ случаС, ΠΊΠΎΠ΄ достаточно прост. Π’Π½Π°Ρ‡Π°Π»Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ синтаксичСский Π°Π½Π°Π»ΠΈΠ· < элСмСнта> ΠΏΡƒΡ‚Π΅ΠΌ Π²Ρ‹Π·ΠΎΠ²Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π° ParseAtom, Π° Π·Π°Ρ‚Π΅ΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ Π½Π° Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ· Ρ‚Ρ€Π΅Ρ… мСтасимволов: "*", "+" ΠΈΠ»ΠΈ "?". {ΠœΠ΅Ρ‚Π°ΡΠΈΠΌΠ²ΠΎΠ» - это символ, ΠΈΠΌΠ΅ΡŽΡ‰ΠΈΠΉ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ с Ρ‚ΠΎΡ‡ΠΊΠΈ зрСния грамматичСских ΠΏΡ€Π°Π²ΠΈΠ» - Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π·Π²Π΅Π·Π΄ΠΎΡ‡ΠΊΠ°, Π·Π½Π°ΠΊ плюса, ΠΊΡ€ΡƒΠ³Π»Ρ‹Π΅ скобки ΠΈ Ρ‚.ΠΏ. Π”Ρ€ΡƒΠ³ΠΈΠ΅ символы Π½Π΅ ΠΈΠΌΠ΅ΡŽΡ‚ Π½ΠΈΠΊΠ°ΠΊΠΎΠ³ΠΎ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ значСния.}

ΠšΠΎΠ΄ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° ParseAtom достаточно Ρ‚Ρ€ΠΈΠ²ΠΈΠ°Π»ΡŒΠ½ΠΎ. Π­Π»Π΅ΠΌΠ΅Π½Ρ‚ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ < символом> ΠΈΠ»ΠΈ Ρ‚ΠΎΡ‡ΠΊΠΎΠΉ;

ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΉ ΠΊΡ€ΡƒΠ³Π»ΠΎΠΉ скобкой, Π·Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΡΠ»Π΅Π΄ΡƒΡŽΡ‚ < Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅> ΠΈ Π·Π°ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π°Ρ круглая скобка;

ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΉ ΠΊΠ²Π°Π΄Ρ€Π°Ρ‚Π½ΠΎΠΉ скобкой, Π·Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΡΠ»Π΅Π΄ΡƒΡŽΡ‚ < класс символов> ΠΈ Π·Π°ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π°Ρ квадратная скобка;

ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΉ ΠΊΠ²Π°Π΄Ρ€Π°Ρ‚Π½ΠΎΠΉ скобкой, Π·Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΡΠ»Π΅Π΄ΡƒΡŽΡ‚ символ "А", <класс символов> ΠΈ Π·Π°ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π°Ρ квадратная скобка. ИмСнно эту Ρ„ΠΎΡ€ΠΌΡƒ ΠΌΡ‹ ΠΈ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅ΠΌ Π² ΠΊΠΎΠ΄Π΅. ΠžΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠ΅ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ†ΠΈΠΈ, ΡΡ‚ΠΎΠ»ΡŒ ΠΆΠ΅ просты. ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ Π² этих ΠΌΠ΅Ρ‚ΠΎΠ΄Π°Ρ… Ρ€Π΅Π°Π»ΡŒΠ½ΡƒΡŽ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ выполняСт ΠΌΠ΅Ρ‚ΠΎΠ΄ самого Π½ΠΈΠΆΠ½Π΅Π³ΠΎ уровня. НапримСр, ΠΌΠ΅Ρ‚ΠΎΠ΄ ParseAtom Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡΡ‚ΡŒ Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ Π·Π°ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΉ ΠΊΡ€ΡƒΠ³Π»ΠΎΠΉ скобки послС Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ синтаксичСского Π°Π½Π°Π»ΠΈΠ·Π° ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½Ρ‹ ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π°Ρ круглая скобка ΠΈ <Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅>. ΠœΠ΅Ρ‚ΠΎΠ΄ PacseChar удостовСряСтся, Ρ‡Ρ‚ΠΎ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ символ Π½Π΅ являСтся мСтасимволом. И Ρ‚Π°ΠΊ Π΄Π°Π»Π΅Π΅. Код, созданный Π² соотвСтствии с ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Ρ‹ΠΌΠΈ рассуТдСниями, ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ Π² листингС 10.5.

Листинг 10.5. ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° синтаксичСского Π°Π½Π°Π»ΠΈΠ·Π° рСгулярных Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ type


TtdRegexParser = class private

FRegexStr : string;

{$IFDEF Delphi1}

FRegexStrZ: PAnsiChar;

{$ENDIF}

FPosn : PAnsiChar;

protected


procedure rpParseAtom;

procedure rpParseCCChar;

procedure rpParseChar;

procedure rpParseCharClass;

procedure rpParseCharRange;

procedure rpParseExpr;

procedure rpParseFactor;

procedure rpParseTerm;

public


constructor Create(const aRegexStr : string);

destructor Destroy; override;

function Parse(var aErrorPos : integer): boolean;

end;

constructor TtdRegexParser.Create(const aRegexStr : string);

begin

inherited Create;

FRegexStr := aRegexStr;

{$IFDEF Delphi1}

FRegexStrZ := StrAlloc(succ( length (aRegexStr)));

StrPCopy(FRegexStrZ, aRegexStr);

{$ENDIF}

end;

destructor TtdRegexParser.Destroy;

begin

{$IFDEF Delphi1}

StrDispose(FRegexStrZ);

{$ENDIF}

inherited Destroy;

end;


function TtdRegexParser.Parse(var aErrorPos : integer): boolean;

begin

Result := true;

aErrorPos := 0;

{$IFDEF Delphi1}

FPosn := FRegexStrZ;

{$ELSE}

FPosn := PAnsiChar (FRegexStr);

{$ENDIF}

try

rpParseExpr;

if (FPosn^ <> #0) then begin

Result := false;

{$IFDEF Delphi1}

aErrorPos := FPosn - FRegexStrZ + 1;

{$ELSE}

aErrorPos := FPosn - PAnsiChar(FRegexStr) + 1;

{$ENDIF}

end;

except on E: Exception do

begin

Result false;

{$IFDEF Delphi1}

aErrorPos := FPosn - FRegexStrZ + 1;

{$ELSE}

aErrorPos := FPosn - PAnsiChar (FRegexStr) + 1;

{$ENDIF}

end;

end;

end;


procedure TtdRegexParser.rpParseAtom;

begin

case FPosn^ of

'(' : begin

inc(FPosn);

writeln (' Open paren');

rpParseExpr;

if (FPosn^ <> ')') then

raise Exception.Create('Regex error: expecting a closing parenthesis');

inc(FPosn);

writeln (' close paren');

end;

'[' : begin

inc(FPosn);

if (FPosn^ = 'A') then begin

inc(FPosn);

writeln('negated char class');

rpParseCharClass;

end

else begin

writeln('normal char class');

rpParseCharClass;

end;

inc(FPosn);

end;

'.' : begin

inc(FPosn);

writeln (' any character');

end;

else

rpParseChar;

end; {case}

end;


procedure TtdRegexParser.rpParseCCChar;

begin

if (FPosn^ = #0) then

raise Exception.Create('Regex error: expecting a normal character, found null terminator');

if FPosn^ in [']', '-'] then

raise Exception.Create('Regex error: expecting a normal character, found a metacharacter');

if (FPosn^ = '\') then begin

inc(FPosn);

writeln(' escaped ccchar ', FPosn^ );

inc(FPosn);

end

else begin

writeln('ccchar ', FPosn^ );

inc(FPosn);

end;

end;


procedure TtdRegexParser.rpParseChar;

begin