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