Como estou estudando para o meu curso formal de idiomas, me deparei com esses posts fascinantes ( Um Dois ) que descrevem como encontrar um número primo usando uma expressão regular . Como eu disse, um regexp , não uma expressão regular . Como uma expressão regular pode corresponder a seqüências de caracteres calculadas por um autômato de estado finito e a descoberta de um número primo não pode ser feita por uma FSA, a regexp mostrada na postagem do blog não é uma expressão inteiramente regular, pois faz o retrocesso para corresponder à sequência.
Desde que eu realmente nunca usei nenhuma expressão regular, agora, minha pergunta:
Como posso reconhecer imediatamente um regexp de uma expressão regular "verdadeira" apenas olhando para ele?
Definições: Por expressão regular, refiro-me à noção definida em linguagens formais. Por regexp, quero dizer a noção suportada pelas linguagens de programação modernas; a sintaxe regexp geralmente contém recursos adicionais, como referências posteriores. Os regexps, como vistos nas linguagens de programação, são estritamente mais poderosos do que as expressões regulares no estilo das linguagens formais.
fonte
Respostas:
tl; dr backrefs.
Assim que houver um
\1
(ou qualquer número que não seja usado para escapar do unicode) no regexp, não será uma expressão regular.Backrefs permite combinar
(a+)b\1
quais correspondências n vezesa
seguidas de b seguidas de n vezesa
para qualquer n> 1. Este não é um idioma comum (é o filho de um idioma não comum).É necessário e quase suficiente que o backref faça referência a um grupo que contenha uma regexp que corresponda a uma cadeia arbitrariamente longa ou que contenha um
*
ou+
. A única exceção (que eu encontrei) de uma expressão regular da forma em(A)B\1
que A é uma linguagem finita (pode ser substituída por uma enumeração de todas as palavras que as aceitam). Você pode convertê-lo paraword1+Bword1|word2+Bword2
etc. porque A é finito.Grupos de pesquisa não removem a regularidade da regexp.
A(?=B)C
é a seção transversal de expressões regularesAB.*
eAC
a seção transversal de 2 idiomas regulares é regular. A aparência negativa é semelhante, exceto usando o complemento deB.*
(complementos de idiomas regulares sendo regulares). Lookbehind é exatamente o mesmo, assim comoA(?<=B)C
a seção transversal deAC
e.*BC
.fonte
(a)\1
, ao usar um backref, é equivalenteaa
e, portanto, trivialmente Regular. Também estou me perguntando se as asserções lookahead podem usar para reconhecer idiomas não regulares.(a)\1
não é uma expressão regular, mas reconhece um idioma regular.