Entonces, ¿cómo funciona un analizador de HTML? ¿No usa expresiones regulares para analizar?
Bueno no.
Si regresa en su cerebro a un curso de teoría de la computación, si tomó uno, o un curso de compiladores, o algo similar, puede recordar que existen diferentes tipos de lenguajes y modelos computacionales. No estoy calificado para entrar en todos los detalles, pero puedo revisar algunos de los puntos principales con usted.
El tipo más simple de lenguaje y computación (para estos propósitos) es un lenguaje regular. Estos pueden generarse con expresiones regulares y reconocerse con autómatas finitos. Básicamente, eso significa que las cadenas de "análisis" en estos lenguajes utilizan el estado, pero no la memoria auxiliar. Ciertamente, HTML no es un lenguaje común. Si lo piensa, la lista de etiquetas se puede anidar de forma arbitraria y profunda. Por ejemplo, las tablas pueden contener tablas y cada tabla puede contener muchas etiquetas anidadas. Con expresiones regulares, es posible que pueda elegir un par de etiquetas, pero ciertamente no nada anidado arbitrariamente.
Un lenguaje simple clásico que no es regular tiene paréntesis correctamente emparejados. Por más que lo intente, nunca podrá construir una expresión regular (o un autómata finito) que siempre funcione. Necesita memoria para realizar un seguimiento de la profundidad de anidación.
Una máquina de estado con una pila de memoria es la siguiente fortaleza del modelo computacional. A esto se le llama autómata push-down y reconoce los lenguajes generados por gramáticas libres de contexto. Aquí, podemos reconocer los paréntesis que coinciden correctamente; de hecho, una pila es el modelo de memoria perfecto para ello.
Bueno, ¿es esto lo suficientemente bueno para HTML? Tristemente no. Tal vez para un XML cuidadosamente validado, de hecho, en el que todas las etiquetas siempre se alinean perfectamente. En HTML del mundo real, puede encontrar fácilmente fragmentos como <b><i>wow!</b></i>
. Obviamente, esto no se anida, por lo que para analizarlo correctamente, una pila no es lo suficientemente potente.
El siguiente nivel de computación son los lenguajes generados por gramáticas generales y reconocidos por las máquinas de Turing. En general, se acepta que este es efectivamente el modelo computacional más sólido que existe: una máquina de estado, con memoria auxiliar, cuya memoria se puede modificar en cualquier lugar. Esto es lo que pueden hacer los lenguajes de programación. Este es el nivel de complejidad donde habita HTML.
Para resumir todo aquí en una oración: para analizar HTML general, necesita un lenguaje de programación real, no una expresión regular.
HTML se analiza de la misma forma en que se analizan otros lenguajes: lexing y parsing. El paso de lexing divide el flujo de caracteres individuales en tokens significativos. El paso de análisis ensambla los tokens, utilizando estados y memoria, en un documento lógicamente coherente sobre el que se puede actuar.