2010-09-30 6 views
18

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

Какие особенности современных регулярных выражений не являются регулярными? Примеры были бы полезны.

+2

Это должно быть сообщество wiki –

+0

@webdestroya: Я могу понять CW, но почему бы и нет? – BoltClock

+0

@NullUser - Разве это не очень субъективный вопрос? –

ответ

18

Первое, что приходит на ум обратные_связи:

(\w*)\s\1 

(соответствует группе символов слова, за которым следует пробел, а затем та же группа ранее совпадающая) например: hello hello матчи, hello world Безразлично» т.

Эта конструкция не является регулярной (то есть: не может быть сгенерирована regular grammar).


Еще одна особенность поддерживается Perl Compatible RegExp (PCRE), которая не является регулярным рекурсивные модели:

\((a*|(?R))*\) 

Это может быть использовано, чтобы соответствовать любой комбинации сбалансированных скобок и «а» с (от wikipedia))

+2

Некоторые обратные ссылки могут быть сделаны на обычном языке. Например, '(.) X \ 1' определяет правильный язык:« axa »,« bxb »и т. Д. Я считаю, что только в сочетании с закрытием Kleene эта обратная ссылка делает язык нерегулярным. – Gabe

+1

Вам не нужно место в нем. '(. *) \ 1' сделаю. – Nabb

+0

@Nabb: '.' соответствует гораздо большему диапазону символов, чем просто' \ w * \ s' – BoltClock

3

Детерминированный или недетерминированный конечный автомат распознает только регулярные языки, которые описываются регулярными выражениями. Определение регулярного выражения прост. Пусть S быть алфавитом. Затем пустое множество, пустая строка и каждый элемент S являются регулярными выражениями (более S). Пусть u и v являются регулярными выражениями. Тогда объединение (у | v), конкатенация (уф) и закрытие (у *) из у и v являются регулярными выражениями над S. Это определение легко распространяется на регулярные языки. Никакое другое выражение не является регулярным выражением. Как отмечалось, некоторые обратные ссылки являются примером. Страницы Википедии на регулярных языках и выражениях являются хорошими ссылками.

По существу, определенные «регулярные выражения» не являются регулярными, потому что для их распознавания не может быть создан какой-либо автомат определенного типа. Например, язык

{а^я Ь^I: я < = 0}

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

+0

Судя по первому вопросу, я уверен, что он понимает различие между регулярными и нерегулярными языками. Его вопрос заключается в том, какие особенности современных реализаций «регулярного выражения» определяют языки, которые не являются регулярными, и поэтому не могут быть каким-то образом выражены с помощью перечисленных вами операций. –

+1

Может быть, мне следует внимательно разобраться, тогда! В любом случае, я не думаю, что я причинил вред. – danportin

+2

'a^i b^i', конечно, нерегулярно (это DCFG), но можем ли мы на самом деле выразить это, используя« регулярные выражения »языков программирования? – Nabb

4

Несколько примеров:

  • Регулярные выражения поддержки группировки. Например. в Ruby: /my (group)/.match("my group")[1] выведет «группу». для хранения чего-либо в группе требуется внешнее хранилище, которого нет у конечного автомата.
  • Многие языки, например. C#, захват поддержки, т. Е. Что каждое совпадение будет записано в стеке - например, шаблон (?<MYGROUP>.)* может выполнять несколько захватов «.». в той же группе.
  • Группировка используется для обратного вызова, как указано пользователем NullUserException выше. Для обратного реферирования требуется один или несколько внешних стеков с силой push-down-automaton (вы должны иметь возможность нажимать что-то на стек и заглядывать или всплывать после этого.
  • Некоторые двигатели имеют возможность отдельного нажатия и выталкивания внешнего стеки и проверка того, пуст ли пуст. В .NET на самом деле (?<MYGROUP>test) толкает стек, а (?<-MYGROUP>) создает стек.
  • Некоторые двигатели, такие как движок .NET, имеют сбалансированную концепцию группировки, где внешний стек может быть как нажат, так и выставляется одновременно. Сбалансированный синтаксис группировки - (?<FIRSTGROUP-LASTGROUP>), который выталкивает LASTGROUP и выталкивает захват с индекса LASTGROUP в стек FIRSTGROUP. Фактически это можно использовать для сопоставления бесконечно вложенных конструкций, которые, безусловно, выходят за пределы конечного автомата п. существуют

Возможно другие хорошие примеры :-) Если вы дополнительно interessted в некоторых деталях реализации внешних стеков в сочетании с Regex-х и сбалансированной группировки и, следовательно, более высокого порядка, чем автоматов конечных автоматов, я однажды написал две короткие статьи на этом (http://www.codeproject.com/KB/recipes/Nested_RegEx_explained.aspx и http://www.codeproject.com/KB/recipes/RegEx_Balanced_Grouping.aspx).

Во всяком случае - finitieness или нет - я blieve что сила, этот дополнительный материал приносит регулярных языков велик :-)

Br. Morten

+1

Группировка и захват - это не функции, которые делают язык нерегулярным - все, что они делают, это предоставление метаданных, а не изменение выразительности языка. Очевидно, что все, что связано с стеком (например, обратные ссылки), действительно делает для нерегулярных языков. – Gabe

Смежные вопросы