Так как же работает парсер HTML? Разве он не использует регулярные выражения для анализа?
Ну нет.
Если вы вернетесь в свой мозг к курсу теории вычислений, если вы его проходили, или к курсу компиляторов, или к чему-то подобному, вы можете вспомнить, что существуют разные типы языков и вычислительных моделей. Я не в состоянии вдаваться во все детали, но я могу обсудить с вами несколько основных моментов.
Самый простой тип языка и вычислений (для этих целей) - это обычный язык. Их можно сгенерировать с помощью регулярных выражений и распознать с помощью конечных автоматов. По сути, это означает, что «синтаксический анализ» строк на этих языках использует состояние, но не вспомогательную память. HTML определенно не является обычным языком. Если задуматься, список тегов может быть вложен сколь угодно глубоко. Например, таблицы могут содержать таблицы, и каждая таблица может содержать множество вложенных тегов. С помощью регулярных выражений вы можете выбрать пару тегов, но, конечно, не что-либо произвольно вложенное.
Классический простой язык, который не является регулярным, - это правильные скобки. Как бы вы ни старались, вы никогда не сможете построить регулярное выражение (или конечный автомат), которое всегда будет работать. Вам нужна память, чтобы отслеживать глубину вложенности.
Конечный автомат со стеком для памяти - следующая сильная сторона вычислительной модели. Это называется выталкивающим автоматом, и он распознает языки, созданные с помощью контекстно-свободных грамматик. Здесь мы можем распознать правильно подобранные круглые скобки - действительно, стек является для него идеальной моделью памяти.
Хорошо, этого достаточно для HTML? К сожалению нет. Может быть, для супер-пупер-проверенного XML, на самом деле, в котором все теги всегда идеально выстраиваются в линию. В реальном HTML вы можете легко найти такие фрагменты, как <b><i>wow!</b></i>
. Очевидно, что это не гнездо, поэтому для правильного анализа стек просто недостаточно мощный.
Следующий уровень вычислений - это языки, генерируемые общими грамматиками и распознаваемые машинами Тьюринга. По общему мнению, это самая сильная вычислительная модель из существующих - конечный автомат со вспомогательной памятью, память которой можно изменять где угодно. Это то, что могут делать языки программирования. На этом уровне сложности живет HTML.
Подытоживая все в одном предложении: для синтаксического анализа обычного HTML вам нужен настоящий язык программирования, а не регулярное выражение.
HTML анализируется так же, как и другие языки: лексирование и разбор. На этапе лексирования поток отдельных символов разбивается на значимые токены. На этапе синтаксического анализа токены собираются с использованием состояний и памяти в логически согласованный документ, с которым можно работать.