Изменения

Перейти к: навигация, поиск

Простой сопоставитель регулярных выражений

114 байт добавлено, 21:23, 3 декабря 2016
Нет описания правки
=== Псевдокод ===
<font color=darkgreen>// поиск вхождения регулярного выражения в любом месте текста</font> '''function''' match(regexp: '''charstring'''*, text: '''charstring'''*): '''boolean''' <font color=darkgreen>/ поиск вхождения регулярного выражения в любом месте текста</font> '''if''' (regexp[0] == '^') '''return''' matchHere(regexp + .drop(1), text) <font color=darkgreen>// drop(n) возвращает строку без первых n элементов</font> '''doint'''i = 0 '''while''' i <tex>\leqslant</tex> text.length '''if''' (matchHere(regexp, text.drop(i))
'''return''' ''true''
'''while''' (*text i++ != '\0')
'''return''' ''false''
<font color=darkgreen>// поиск вхождения регулярного выражения в начале текста</font> '''function''' matchHere(regexp: '''charstring'''*, text: '''charstring'''*): '''boolean''' <font color=darkgreen>/ поиск вхождения регулярного выражения в начале текста</font> '''if''' (regexp[0] == '\0')
'''return''' ''true''
'''if''' (regexp[1] == '*') '''return''' matchStar(regexp[0], regexp + .drop(2), text) '''if''' (regexp[0] == '$' '''and''' regexp[1] == '\0') '''return''' *text == '\0'; '''if''' (*text[0] !='\0' '''and''' (regexp[0] == '.' '''or''' regexp[0] == *text)[0]) '''return''' matchHere(regexp + .drop(1), text + .drop(1))
'''return''' ''false''
<font color=darkgreen>// сопоставление с регулярным выражением вида: c*</font> '''function''' matchStar(c : '''char''', regexp: '''charstring'''*, text: '''charstring'''*): '''boolean''' '''int''' i = 0 '''while''' i <font color=darkgreentex>/ сопоставление с регулярным выражением вида: c*\leqslant</fonttex> text.length '''and''' (text[i] == c '''or'do''c == '.') '''if''' (matchHere(regexp, text.drop(i))
'''return''' ''true''
'''while''' (*text != '\0' '''and''' (*text i++ == c '''or''' c == '.')) <font color=darkgreen>/Цикл '''do-while''' используется вместо '''while''', так как * допускает пустую строку</font>
'''return''' ''false''
Рассмотрим возможные случаи:
# Если в ходе рекурсии регулярное выражение осталось пустым <tex>(regexp[0] == \backslash0)</tex>, то текст допускается этим регулярным выражением.
# Если регулярное выражение имеет вид <tex>c*</tex>, то вызывается функция mathchStar, которая пытается сопоставить повторение символа <tex>c</tex>, начиная с нуля повторений и увеличивая их количество, пока не найдет совпадение с оставшимся текстом. Если совпадение не будет найдено, то регулярное выражение не допускает текст. Текущая реализация ищет "кратчайшее совпадение", которое хорошо подходит для сопоставления с образцом, как в '''grep'''<ref>[https://ru.wikipedia.org/wiki/Grep '''grep''']</ref>, где нужно как можно быстрее найти совпадение. "Наидлиннейшее совпадение" более интуитивно и больше подходит для текстовых редакторов, где найденное заменят на что-то. Большинство современных библиотек для работы с регулярными выражениями предоставляют оба варианта.
# Если регулярное выражение это <tex>\mathdollar</tex>, то оно допускает этот текст тогда и только тогда, когда текст закончился.
# Если первый символ текста совпал с первым символом регулярного выражения, то нужно проверить совпадают ли следующий символ регулярного выражения со следующим символом текста, сделав рекурсивный вызов <tex>\mathrm{matchHere}</tex>.
Данный алгоритм прост и лаконичен, но у него есть недостаток. Для регулярного выражения содержащего несколько <tex>.*</tex> подряд этот алгоритм может работать очень медленно. Рассмотрим время работы '''grep'а''' (наш алгоритм схож со стандартным '''grep'ом'''). Например команда: "<tex>grep</tex> <tex>a.*a.*a.*a.a</tex>" потребует 20 секунд, чтобы обработать текстовой файл размером 4MB на обычной машине. В то же время алгоритм, который конвертирует [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]] в [[Детерминированные конечные автоматы|детерминированный конечный автомат]] (например, '''egrep'''<ref>[https://ru.wikipedia.org/wiki/Grep '''egrep''']</ref>), потребует менее одной десятой доли секунды на обработку тех же данных.
===Модификации===
=== Псевдокод ===
'''function''' matchStar(c : '''char''', regexp: '''charstring'''*, text: '''charstring'''*): '''boolean''' '''charint''' *ti '''for''' (t i = 0; text; *t [i] != '\0' '''and''' (*t text[i] == c '''or''' c == '.'); ti++) '''dowhile'''i <tex>\geqslant</tex> 0 '''if''' (matchHere(regexp, text.drop(i))
'''return''' ''true''
'''while''' (*text != '\0' '''and''' (*text++ == c '''or''' c == '.')) i--
'''return''' ''false''
type: '''int''' <font color=darkgreen>/ тип элемента: STAR, QUESTION, PLUS, SYMBOL, ...</font>
c: '''char''' <font color=darkgreen>/ сам символ</font>
cs: '''char'''* [] <font color=darkgreen>/ для случая [...]</font>
ncs: '''bool''' <font color=darkgreen>/ для случая отрицания cs: [^...]</font>
== Источники информации ==
* [http://www.cs.princeton.edu/courses/archive/spr10/cos333/beautiful.html A Regular Expression Matcher]
 
== Примечания ==
<references/>
[[Категория: Теория формальных языков]]
[[Категория: Автоматы и регулярные языки]]
59
правок

Навигация