As implementações de regex ampliadas podem analisar HTML?

Eu sei o que você está pensando – “oh meu deus, sério, não de novo” – mas por favor, tenha comigo, a minha pergunta é mais do que o título. Antes de começarmos, prometo que nunca tentarei analisar HTML arbitrário com uma regex ou perguntar a qualquer outra pessoa como.

Todas as muitas, muitas respostas aqui explicando porque você não pode fazer isso dependem da definição formal de expressões regulares. Eles analisam linguagens regulares, o HTML é livre de contexto, mas não regular, então você não pode fazê-lo. Mas também ouvi dizer que muitas implementações regex em vários idiomas não são estritamente regulares; eles vêm com truques extras que fogem dos limites das expressões regulares formais.

Como não conheço os detalhes de nenhuma implementação específica, como o perl, minhas perguntas são:

  1. Quais resources das ferramentas de regex são não regulares? São as referências de volta? E em quais idiomas eles são encontrados?
  2. Algum desses truques extras é suficiente para analisar todas as linguagens livres de contexto?
  3. Se “não” para # 2, existe uma categoria formal ou uma class de idiomas que esses resources extras cubram exatamente? Como podemos saber rapidamente se o problema que estamos tentando resolver está dentro do poder de nossas expressões não necessariamente regulares?

A resposta à sua pergunta é que sim, os chamados “regexes estendidos” – que são talvez mais propriamente chamados de padrões do que expressões regulares no sentido formal – como os encontrados em Perl e PCRE são de fato capazes de análise recursiva de descendentes de contexto. gramáticas livres .

O par de abordagens desta postagem ilustra não tanto limites teóricos quanto práticos para aplicar expressões regulares a X / HTML. A primeira abordagem dada lá, aquela rotulada de ingênua, é mais parecida com o tipo que você está apto a encontrar na maioria dos programas que fazem tal tentativa. Isso pode ser feito para trabalhar em X / HTML não-genérico bem definido, geralmente com muito pouco esforço. Essa é a sua melhor aplicação, assim como o X / HTML aberto é o pior.

A segunda abordagem, rotulada como mago, usa uma gramática real para análise. Como tal, é tão poderosa quanto qualquer outra abordagem gramatical. No entanto, também está muito além dos poderes da esmagadora maioria dos programadores casuais. Também corre o risco de recriar uma roda perfeitamente fina para benefício negativo. Escrevi para mostrar o que pode ser feito, mas sob praticamente nenhuma circunstância que deva ser feita. Eu queria mostrar às pessoas por que elas querem usar um analisador em X / HTML aberto, mostrando a elas o quão diabolicamente difícil é chegar ainda mais perto de acertar, mesmo usando alguns dos mais poderosos resources de correspondência de padrões atualmente disponíveis.

Muitos interpretaram mal minha postagem como de alguma forma defendendo o oposto do que estou realmente dizendo. Por favor, não se enganem: estou dizendo que é muito complicado de usar. É uma prova pelo contra-exemplo. Eu esperava que, mostrando como fazer isso com regexes, as pessoas percebessem por que não queriam ir por esse caminho. Embora todas as coisas sejam possíveis, nem todas são convenientes.

Minha regra prática é que, se a regex necessária for apenas da primeira categoria, posso usá-la, mas se ela exigir o tratamento gramatical completo da segunda categoria, usei o analisador já escrito de outra pessoa. Então, mesmo que eu possa escrever um analisador, não vejo razão para isso, e muitas vezes não.

Quando cuidadosamente elaborados para esse propósito explícito, os padrões podem ser mais resisilientes a X / HTML malformados do que os analisadores padrão tendem a ser, particularmente se você não tiver uma oportunidade real de hackear os analisadores para torná-los mais resistentes à falha comum casos que os navegadores da Web tendem a tolerar, mas os validadores não. No entanto, os padrões gramaticais que eu forneci acima foram projetados apenas para HTML bem formado, mas razoavelmente genérico (embora sem substituição de entidade, que é facilmente adicionado). A recuperação de erros nos analisadores é um problema separado, e de modo algum agradável.

Padrões, especialmente os não-gramaticais mais comuns, que a maioria das pessoas está acostumada a ver e usar, são muito mais adequados para pegar pedaços discretos um por vez do que para produzir uma análise sintática completa. Em outras palavras, os regexes geralmente funcionam melhor para lexing do que para análise. Sem regexes gramaticais, você não deve tentar analisar gramáticas.

Mas não leve isso longe demais. Certamente não pretendo sugerir que você deva recorrer imediatamente a um analisador completo apenas porque deseja abordar algo que seja recursivamente definido. O exemplo mais fácil e mais comumente visto desse tipo de coisa é um padrão para detectar itens nesteds, como parênteses. É extremamente comum para mim simplesmente baixar algo simples como este no meu código e acabar com isso:

# delete all nested parens s/\((?:[^()]*+|(?0))*\)//g; 

Sim, as extensões em perguntas são backreferences, e tecnicamente fazem “regexps” NP-complete, veja o parágrafo de Wikipedia .