Как браузер читает html
Обновлено: 21.11.2024
Мое мнение: если я собираюсь создавать быстрые и надежные веб-сайты, мне нужно действительно понимать механизм каждого шага, который браузер выполняет для отображения веб-страницы, чтобы каждый из них мог быть рассмотрен и оптимизирован во время разработки. . Этот пост является кратким изложением моих знаний о сквозном процессе на довольно высоком уровне.
Многое из этого основано на фантастическом (и БЕСПЛАТНО!) курсе по оптимизации производительности веб-сайтов Ильи Григорика и Кэмерона Питтмана на Udacity. Я настоятельно рекомендую проверить это.
Также очень полезной оказалась статья Пола Айриша и Тали Гарсиэль «Как работают браузеры: за кулисами современных веб-браузеров». Он выпущен в 2011 году, но многие основы работы браузеров остаются актуальными на момент написания этой записи в блоге.
Хорошо, поехали. Процесс можно разбить на следующие основные этапы:
1. Начать анализ HTML
Когда браузер начинает получать HTML-данные страницы по сети, он немедленно запускает анализатор для преобразования HTML в объектную модель документа (DOM).
Объектная модель документа (DOM) — это представление данных объектов, составляющих структуру и содержимое документа в Интернете.
Первым этапом этого процесса синтаксического анализа является разбиение HTML на маркеры, представляющие начальные теги, конечные теги и их содержимое. Из этого он может построить DOM.
2. Получить внешние ресурсы
Когда синтаксический анализатор сталкивается с внешним ресурсом, таким как файл CSS или JavaScript, он начинает извлекать эти файлы. Синтаксический анализатор будет продолжать работу по мере загрузки файла CSS, хотя он будет блокировать рендеринг до тех пор, пока он не будет загружен и проанализирован (подробнее об этом чуть позже).
Файлы JavaScript немного отличаются: по умолчанию они блокируют синтаксический анализ HTML, пока файл JavaScript загружается, а затем анализируется. Есть два атрибута, которые можно добавить к тегам script, чтобы смягчить это: defer и async . Оба позволяют продолжить синтаксический анализатор, пока файл JavaScript загружается в фоновом режиме, но они работают по-разному в том, как они выполняются. Об этом чуть позже, но вкратце:
defer означает, что выполнение файла будет отложено до завершения синтаксического анализа документа. Если несколько файлов имеют атрибут defer, они будут выполняться в том порядке, в котором они были обнаружены в HTML.
асинхронный означает, что файл будет выполняться, как только он загрузится, что может произойти во время или после процесса синтаксического анализа, поэтому порядок, в котором выполняются асинхронные скрипты, не может быть гарантирован.
Предварительная загрузка ресурсов
Кроме того, современные браузеры будут продолжать сканировать HTML-код, пока он заблокирован, и «просчитывать» появление внешних ресурсов, а затем предположительно загружать их. То, как они это делают, различается в разных браузерах, поэтому нельзя полагаться на то, что они будут вести себя определенным образом. Чтобы пометить ресурс как важный и, следовательно, с большей вероятностью загрузить его в начале процесса рендеринга, можно использовать тег ссылки с rel="preload".
3. Разобрать CSS и создать CSSOM
Возможно, вы уже слышали о DOM, но слышали ли вы об CSSOM (объектной модели CSS)? Прежде чем я начал исследовать эту тему некоторое время назад, я этого не знал!
Объектная модель CSS (CSSOM) представляет собой карту всех селекторов CSS и соответствующих свойств для каждого селектора в виде дерева с корневым узлом, родственным, потомственным, дочерним и другими отношениями. CSSOM очень похожа на объектную модель документа (DOM). Оба они являются частью критического пути рендеринга, который представляет собой серию шагов, которые должны быть выполнены для правильного рендеринга веб-сайта.
CSOM вместе с DOM строит дерево рендеринга, которое, в свою очередь, используется браузером для компоновки и рисования веб-страницы.
Подобно файлам HTML и DOM, когда файлы CSS загружаются, они должны быть проанализированы и преобразованы в дерево — на этот раз в CSSOM. Он описывает все селекторы CSS на странице, их иерархию и свойства.
Отличие CSSOM от DOM заключается в том, что его нельзя создавать постепенно, поскольку правила CSS могут перезаписывать друг друга в различных точках из-за специфики. Вот почему CSS блокирует отрисовку, так как пока весь CSS не проанализирован и не построена CSSOM, браузер не может знать, где и как расположить каждый элемент на экране.
4. Выполнить JavaScript
От того, как и когда загружаются ресурсы JavaScript, будет зависеть, когда именно это произойдет, но в какой-то момент они будут проанализированы, скомпилированы и выполнены. В разных браузерах есть разные механизмы JavaScript для выполнения этой задачи. Анализ JavaScript может быть дорогостоящим процессом с точки зрения ресурсов компьютера, больше, чем другие типы ресурсов, поэтому его оптимизация так важна для достижения хорошей производительности.Прочтите этот фантастический пост, чтобы глубже понять, как работает движок JavaScript.
Загрузить события
После того, как синхронно загруженные JavaScript и DOM будут полностью проанализированы и готовы, будет сгенерировано событие document.DOMContentLoaded. Для любых сценариев, которым требуется доступ к модели DOM, например, для того, чтобы каким-либо образом манипулировать ею или прослушивать события взаимодействия с пользователем, рекомендуется сначала дождаться этого события перед выполнением сценариев.
После завершения загрузки всего остального, например асинхронного JavaScript, изображений и т. д., запускается событие window.load.
5. Объединить DOM и CSSOM для построения дерева рендеринга
Дерево рендеринга представляет собой комбинацию DOM и CSSOM и представляет все, что будет отображаться на странице. Это не обязательно означает, что все узлы в дереве рендеринга будут визуально присутствовать, например, узлы со стилями непрозрачности: 0 или видимости: скрытые будут включены и могут быть прочитаны программой чтения с экрана и т. д., в то время как те, для которых настроено отображение : none не будет включено. Кроме того, такие теги, как те, которые не содержат никакой визуальной информации, всегда будут опущены.
Как и в случае с механизмами JavaScript, разные браузеры имеют разные механизмы рендеринга.
6. Рассчитать макет и нарисовать
Теперь, когда у нас есть полное дерево рендеринга, браузер знает, что рендерить, но не знает, где это рендерить. Поэтому макет страницы (то есть положение и размер каждого узла) должен быть рассчитан. Механизм рендеринга просматривает дерево рендеринга, начиная сверху вниз, вычисляя координаты, в которых должен отображаться каждый узел.
После того, как это будет завершено, последний шаг – взять информацию о макете и нарисовать пиксели на экране.
И вуаля! После всего этого у нас есть полностью визуализированная веб-страница!
Я хочу подчеркнуть, что когда вы пишете HTML, CSS и JS и пытаетесь открыть файл HTML в своем браузере, браузер считывает необработанные байты HTML с вашего жесткого диска (или из сети). ).
Понял? Браузер читает необработанные байты данных, а не фактические символы кода, который вы написали. Идем дальше.
Браузер получает байты данных, но ничего с ними сделать не может; необработанные байты данных должны быть преобразованы в форму, которую он понимает. Это первый шаг.
От необработанных байтов HTML к DOM
То, с чем объект браузера должен работать, — это объект объектной модели документа (DOM). Итак, как создается объект DOM? Ну, довольно просто.
Сначала необработанные байты данных преобразуются в символы.
Вы можете увидеть это по символам кода, который вы написали. Это преобразование выполняется на основе кодировки символов файла HTML.
На данный момент браузер перешел от необработанных байтов данных к фактическим символам в файле. Персонажи великолепны, но они не являются конечным результатом. Эти символы далее анализируются в нечто, называемое токенами.
Итак, что это за токены?
Куча символов в текстовом файле не приносит движку браузера большой пользы. Без этого процесса токенизации набор символов превратится в набор бессмысленного текста, т. е. HTML-код, а настоящий веб-сайт не получится.
Когда вы сохраняете файл с расширением .html, вы указываете механизму браузера интерпретировать файл как HTML-документ. Браузер интерпретирует этот файл, сначала анализируя его. В процессе синтаксического анализа и особенно во время токенизации учитывается каждый начальный и конечный HTML-тег в файле.
Синтаксический анализатор понимает каждую строку в угловых скобках (например, ,
) и понимает набор правил, применимых к каждому из них.Например, токен, представляющий тег привязки, будет иметь свойства, отличные от свойств токена, представляющего токен абзаца.
Концептуально токен можно рассматривать как некую структуру данных, содержащую информацию об определенном теге HTML. По сути, HTML-файл разбивается на небольшие единицы анализа, называемые токенами. Так браузер начинает понимать, что вы написали.
Если вы помните из веб-дизайна 101, вы не открываете файл CSS или JS в браузере для просмотра веб-страницы. Нет — вы открываете файл HTML, чаще всего в форме index.html. Именно поэтому вы делаете это: браузер должен преобразовать необработанные байты данных HTML в DOM, прежде чем что-либо произойдет.
В зависимости от размера HTML-файла процесс создания модели DOM может занять некоторое время. Независимо от размера файла, это занимает некоторое время.
Но подождите, а как насчет загрузки CSS?
DOM создан. Отлично.
Обычный HTML-файл с некоторыми элементами CSS будет иметь связанную таблицу стилей, как показано ниже:
Пока браузер получает необработанные байты данных и запускает процесс построения DOM, он также делает запрос на получение связанной таблицы стилей main.css. Как только браузер начинает анализировать HTML, обнаружив тег ссылки на файл CSS, он одновременно отправляет запрос на его получение.
Как вы уже догадались, браузер также получает необработанные байты данных CSS из Интернета или с локального диска. Но что именно делается с этими необработанными байтами данных CSS?
От необработанных байтов CSS к CSSOM
Видите ли, аналогичный процесс с необработанными байтами HTML также инициируется, когда браузер получает необработанные байты CSS.
Другими словами, необработанные байты данных преобразуются в символы, а затем размечаются. Также формируются узлы и, наконец, формируется древовидная структура.
Что такое древовидная структура? Ну, большинство людей знают, что есть нечто, называемое DOM. Точно так же существует древовидная структура CSS, называемая объектной моделью CSS (CSSOM).
Видите ли, браузер не может работать ни с необработанными байтами HTML, ни с CSS. Это должно быть преобразовано в форму, которую он распознает, и это оказывается этими древовидными структурами.
В CSS есть нечто, называемое каскадом. Каскад — это то, как браузер определяет, какие стили применяются к элементу. Поскольку стили, влияющие на элемент, могут исходить от родительского элемента (т. е. путем наследования) или быть заданы для самого элемента, древовидная структура CSSOM становится важной.
Почему? Это связано с тем, что браузеру приходится рекурсивно просматривать древовидную структуру CSS и определять стили, влияющие на конкретный элемент.
Все хорошо. Браузер имеет объекты DOM и CSSOM. Можем ли мы сейчас что-нибудь отобразить на экране?
Дерево визуализации
Сейчас у нас есть две независимые древовидные структуры, у которых, похоже, нет общей цели.
Древовидные структуры DOM и CSSOM — это две независимые структуры. DOM содержит всю информацию о взаимосвязях HTML-элементов страницы, а CSSOM содержит информацию о стилях элементов.
Хорошо, теперь браузер объединяет деревья DOM и CSSOM в нечто, называемое деревом рендеринга.
Дерево рендеринга содержит информацию обо всем видимом содержимом DOM на странице и всю необходимую информацию CSSOM для различных узлов. Обратите внимание, что если элемент был скрыт с помощью CSS (например, с помощью display; none ), узел не будет представлен в дереве рендеринга.
Скрытый элемент будет присутствовать в модели DOM, но не в дереве рендеринга. Это связано с тем, что дерево рендеринга объединяет информацию как из DOM, так и из CSSOM, поэтому оно знает, что не следует включать скрытый элемент в дерево.
После построения дерева рендеринга браузер переходит к следующему шагу: компоновке!
Создание дерева рендеринга
После создания дерева рендеринга следующим шагом будет выполнение макета. Прямо сейчас у нас есть информация о содержании и стиле всего видимого содержимого на экране, но на самом деле мы ничего не визуализировали на экране.
Ну, во-первых, браузер должен вычислить точный размер и положение каждого объекта на странице. Это похоже на передачу информации о содержании и стиле всех элементов, которые должны отображаться на странице, талантливому математику. Затем этот математик определяет точное положение и размер каждого элемента в окне просмотра браузера.
На экране отображаются простой текст и изображение. Из предыдущих объяснений браузер считывает необработанные байты HTML-файла с диска (или из сети) и преобразует их в символы.
Что произойдет с этим потоком, когда мы представим JavaScript? Что ж, одна из самых важных вещей, которую следует помнить, это то, что всякий раз, когда браузер встречает тег скрипта, построение DOM приостанавливается! Весь процесс построения DOM останавливается до завершения выполнения скрипта.
Это связано с тем, что JavaScript может изменять как DOM, так и CSSOM. Поскольку браузер не уверен, что будет делать этот конкретный JavaScript, он принимает меры предосторожности, полностью останавливая построение DOM целиком.
Насколько это может быть плохо? Давайте посмотрим.
В базовом HTML-документе, которым я поделился ранее, давайте добавим тег скрипта с базовым кодом JavaScript:
В теге script я обращаюсь к DOM для узла с идентификатором и заголовком , а затем вывожу его в консоль.
Это работает нормально, как показано ниже:
Тем не менее, вы заметили, что этот тег скрипта расположен в нижней части тега body? Поместим его в голову и посмотрим, что получится:
Как только я это сделаю, переменная заголовка будет преобразована в null .
Почему? Довольно просто.
Пока анализатор HTML создавал DOM, был обнаружен тег скрипта. На данный момент тег body и все его содержимое не были проанализированы. Построение DOM останавливается до завершения выполнения скрипта:
К моменту, когда скрипт попытался получить доступ к узлу DOM с идентификатором header , он еще не существовал, потому что DOM еще не завершила синтаксический анализ документа!
Это подводит нас к еще одному важному моменту: расположение вашего скрипта имеет значение.
И это еще не все. Если вы извлечете встроенный скрипт во внешний локальный файл, поведение будет точно таким же. Построение DOM все еще остановлено:
Опять же, это еще не все! Что, если этот файл app.js не является локальным, а его нужно загрузить из Интернета?
Критический путь рендеринга (CRP)
Все это время мы обсуждали этапы между получением байтов HTML, CSS и JS и преобразованием их в визуализированные пиксели на экране.
Весь этот процесс называется критическим путем рендеринга (CRP). Оптимизация ваших веб-сайтов для повышения производительности — это оптимизация CRP. Хорошо оптимизированный сайт должен подвергаться прогрессивному рендерингу и не блокироваться весь процесс.
Это разница между веб-приложением, воспринимаемым как медленное или быстрое.
Продуманная стратегия оптимизации CRP позволяет браузеру загружать страницу как можно быстрее, определяя приоритет загружаемых ресурсов и порядок их загрузки.
Отслеживайте, как отображаются ваши приложения
LogRocket похож на видеорегистратор для веб-приложений, который записывает буквально все, что происходит на вашем сайте. Вместо того, чтобы гадать, как ваше приложение или веб-сайт отображается в конкретных браузерах, вы можете точно увидеть, что испытал пользователь. С помощью LogRocket вы можете понять, как пользователи взаимодействуют с компонентами, и обнаружить любые ошибки, связанные с неправильным отображением элементов.
Кроме того, LogRocket регистрирует все действия и состояние в ваших хранилищах Redux. LogRocket позволяет вашему приложению записывать запросы/ответы с заголовками и телами. Он также записывает HTML и CSS на странице, воссоздавая идеальные до пикселя видеоролики даже самых сложных одностраничных приложений. Модернизируйте способы отладки приложений React — начните мониторинг бесплатно.
Заключение
Поняв основы того, как браузер отображает HTML, CSS и JS, я прошу вас уделить время изучению того, как вы можете воспользоваться этими знаниями для оптимизации скорости своих страниц.
Хорошее место для начала – раздел производительности документации Google Web Fundamentals.
LogRocket: легче отлаживать ошибки JavaScript благодаря пониманию контекста
Отладка кода всегда утомительна. Но чем лучше вы понимаете свои ошибки, тем легче их исправить.
LogRocket позволяет вам понять эти ошибки новыми и уникальными способами. Наше решение для мониторинга внешних интерфейсов отслеживает взаимодействие пользователей с вашими внешними интерфейсами JavaScript, чтобы дать вам возможность узнать, что именно пользователь сделал, что привело к ошибке.
LogRocket записывает журналы консоли, время загрузки страниц, трассировку стека, медленные сетевые запросы и ответы с заголовками и телами, метаданными браузера и пользовательскими журналами. Понимание влияния вашего кода JavaScript никогда не будет таким простым!
Это всеобъемлющее руководство по внутренним операциям WebKit и Gecko является результатом обширных исследований, проведенных израильским разработчиком Тали Гарсиэль. За несколько лет она просмотрела все опубликованные данные о внутреннем устройстве браузера (см. Ресурсы) и потратила много времени на чтение исходного кода веб-браузера. Она написала:
В годы доминирования IE на 90 % ничего особенного не оставалось, кроме как рассматривать браузер как «черный ящик», но теперь, когда на браузеры с открытым исходным кодом приходится более половины доли использования, это хорошо время заглянуть под капот двигателя и посмотреть, что находится внутри веб-браузера. А внутри миллионы строк C++.
Тали опубликовала свое исследование на своем сайте, но мы знали, что оно заслуживает более широкой аудитории, поэтому мы подчистили его и повторно опубликовали здесь.
Как веб-разработчик, изучение внутренних операций браузера поможет вам принимать более обоснованные решения и понимать обоснования передовых методов разработки. Хотя это довольно объемный документ, мы рекомендуем вам потратить некоторое время на его изучение; мы гарантируем, что вы будете рады, что вы сделали. Пол Айриш, специалист по связям с разработчиками Chrome
Эта статья была переведена на несколько языков: HTML5 Rocks поддерживает немецкую, испанскую, японскую, португальскую, русскую и упрощенную китайскую версии. Вы также можете просматривать переводы на корейский и турецкий языки, размещенные на внешних серверах.
Введение
Содержание
Браузеры, о которых мы поговорим
Сегодня на настольных компьютерах используется пять основных браузеров: Chrome, Internet Explorer, Firefox, Safari и Opera. На мобильных устройствах основными браузерами являются Android Browser, iPhone, Opera Mini и Opera Mobile, UC Browser, браузеры Nokia S40/S60 и Chrome — все они, за исключением браузеров Opera, основаны на WebKit. Я приведу примеры из браузеров с открытым исходным кодом Firefox и Chrome, а также Safari (который является частично открытым исходным кодом). Согласно статистике StatCounter (по состоянию на июнь 2013 г.), на Chrome, Firefox и Safari приходится около 71% использования настольных браузеров в мире. На мобильных устройствах Android Browser, iPhone и Chrome составляют около 54 % использования.
Основные функции браузера
Основная функция браузера — представить выбранный вами веб-ресурс, запросив его с сервера и отобразив в окне браузера. Ресурс обычно представляет собой HTML-документ, но также может быть PDF-файлом, изображением или другим типом контента. Расположение ресурса указывается пользователем с помощью URI (унифицированного идентификатора ресурса).
То, как браузер интерпретирует и отображает HTML-файлы, указано в спецификациях HTML и CSS.Эти спецификации поддерживаются организацией W3C (Консорциум World Wide Web), которая является организацией по стандартизации для Интернета. В течение многих лет браузеры соответствовали только части спецификаций и разрабатывали собственные расширения. Это вызвало серьезные проблемы совместимости для веб-авторов. Сегодня большинство браузеров более или менее соответствуют спецификациям.
- Адресная строка для вставки URI
- Кнопки «Назад» и «Вперед».
- Параметры закладок
- Кнопки «Обновить» и «Стоп» для обновления или остановки загрузки текущих документов.
- Кнопка "Главная", которая открывает главную страницу.
Как ни странно, пользовательский интерфейс браузера не указан ни в какой официальной спецификации, он просто основан на передовом опыте, сформированном многолетним опытом, и браузерами, имитирующими друг друга. Спецификация HTML5 не определяет элементы пользовательского интерфейса, которые должен иметь браузер, но перечисляет некоторые общие элементы. Среди них адресная строка, строка состояния и панель инструментов. Конечно, есть функции, уникальные для конкретного браузера, такие как менеджер загрузок Firefox.
Структура верхнего уровня браузера
Основные компоненты браузера (1.1):
Важно отметить, что такие браузеры, как Chrome, запускают несколько экземпляров механизма рендеринга: по одному для каждой вкладки. Каждая вкладка выполняется в отдельном процессе.
Механизм рендеринга
Ответственность механизма рендеринга хорошо. Рендеринг, то есть отображение запрошенного содержимого на экране браузера.
По умолчанию механизм рендеринга может отображать документы и изображения HTML и XML. Он может отображать другие типы данных через плагины или расширения; например, отображение PDF-документов с помощью подключаемого модуля для просмотра PDF-файлов. Однако в этой главе мы сосредоточимся на основном варианте использования: отображении HTML и изображений, отформатированных с помощью CSS.
Двигатели рендеринга
Разные браузеры используют разные механизмы визуализации: Internet Explorer использует Trident, Firefox использует Gecko, Safari использует WebKit. Chrome и Opera (начиная с версии 15) используют Blink, ответвление WebKit.
Основной поток
Механизм рендеринга начнет получать содержимое запрошенного документа с сетевого уровня. Обычно это делается фрагментами по 8 КБ.
После этого основной поток движка рендеринга:
Рис. : Основной процесс рендеринга
Механизм рендеринга начнет синтаксический анализ HTML-документа и преобразует элементы в узлы DOM в дереве, которое называется "дерево контента". Движок будет анализировать данные стиля как во внешних файлах CSS, так и в элементах стиля. Информация о стилях вместе с визуальными инструкциями в HTML будет использоваться для создания другого дерева: дерева рендеринга.
Дерево рендеринга содержит прямоугольники с визуальными атрибутами, такими как цвет и размеры. Прямоугольники расположены в правильном порядке для отображения на экране.
После построения дерева рендеринга оно проходит через процесс "макетирования". Это означает предоставление каждому узлу точных координат, где он должен появиться на экране. Следующим этапом является отрисовка: дерево рендеринга будет пройдено, и каждый узел будет отрисован с использованием внутреннего слоя пользовательского интерфейса.
Важно понимать, что это постепенный процесс. Для лучшего взаимодействия с пользователем механизм рендеринга попытается отобразить содержимое на экране как можно скорее. Он не будет ждать, пока весь HTML будет проанализирован, прежде чем начать построение и компоновку дерева рендеринга. Части содержимого будут проанализированы и отображены, в то время как процесс продолжится с остальным содержимым, которое продолжает поступать из сети.
Примеры основного потока
Рисунок : Основной поток WebKit Рисунок : Основной поток механизма рендеринга Mozilla Gecko (3.6)
Из рисунков 3 и 4 видно, что, хотя WebKit и Gecko используют немного разную терминологию, процесс в основном одинаков.
Gecko называет дерево визуально отформатированных элементов "Деревом фреймов". Каждый элемент представляет собой рамку. WebKit использует термин «Дерево рендеринга» и состоит из «Объектов рендеринга». WebKit использует термин «макет» для размещения элементов, а Gecko называет его «перекомпоновкой». «Вложение» — это термин WebKit для соединения узлов DOM и визуальной информации для создания дерева рендеринга. Небольшое несемантическое отличие заключается в том, что у Gecko есть дополнительный слой между HTML и деревом DOM. Он называется «приемником контента» и представляет собой фабрику по созданию элементов DOM. Мы поговорим о каждой части потока:
Синтаксический анализ — общее
Поскольку синтаксический анализ — очень важный процесс в механизме рендеринга, мы углубимся в него. Начнем с небольшого введения в синтаксический анализ.
Синтаксический анализ документа означает преобразование его в структуру, которую может использовать код. Результатом синтаксического анализа обычно является дерево узлов, представляющее структуру документа.Это называется деревом разбора или синтаксическим деревом.
Например, синтаксический анализ выражения 2 + 3 - 1 может вернуть следующее дерево:
Рисунок : узел дерева математических выражений
Грамматика
Синтаксический анализ основан на правилах синтаксиса, которым подчиняется документ: язык или формат, в котором он был написан. Каждый формат, который вы можете анализировать, должен иметь детерминированную грамматику, состоящую из словаря и правил синтаксиса. Это называется контекстно-свободной грамматикой. Человеческие языки не являются такими языками и поэтому не могут быть проанализированы с помощью обычных методов синтаксического анализа.
Комбинация парсер-лексер
Синтаксический анализ можно разделить на два подпроцесса: лексический анализ и синтаксический анализ.
Лексический анализ — это процесс разбиения входных данных на токены. Токены — это словарный запас языка: набор действительных строительных блоков. В человеческом языке это будут все слова, встречающиеся в словаре этого языка.
Синтаксический анализ — это применение правил синтаксиса языка.
Синтаксические анализаторы обычно делят работу между двумя компонентами: лексером (иногда называемым токенизатором), который отвечает за разбиение входных данных на допустимые токены, и синтаксическим анализатором, который отвечает за построение дерева синтаксического анализа путем анализа структуры документа в соответствии с языком. правила синтаксиса. Лексер знает, как удалить ненужные символы, такие как пробелы и разрывы строк.
Рисунок : от исходного документа к деревьям синтаксического анализа
Процесс синтаксического анализа повторяется. Парсер обычно запрашивает у лексера новый токен и пытается сопоставить токен с одним из правил синтаксиса. Если правило соответствует, узел, соответствующий токену, будет добавлен в дерево синтаксического анализа, и синтаксический анализатор запросит другой токен.
Если ни одно правило не соответствует, синтаксический анализатор сохранит токен внутри и будет запрашивать токены до тех пор, пока не будет найдено правило, соответствующее всем хранящимся внутри маркерам. Если правило не найдено, парсер выдаст исключение. Это означает, что документ недействителен и содержит синтаксические ошибки.
Перевод
Во многих случаях дерево синтаксического анализа не является конечным продуктом. Синтаксический анализ часто используется при переводе: преобразование входного документа в другой формат. Пример - компиляция. Компилятор, который компилирует исходный код в машинный код, сначала преобразует его в дерево синтаксического анализа, а затем переводит это дерево в документ с машинным кодом.
Рисунок : поток компиляции
Пример синтаксического анализа
На рисунке 5 мы построили дерево синтаксического анализа из математического выражения. Давайте попробуем определить простой математический язык и посмотрим на процесс синтаксического анализа.
Словарный запас: наш язык может включать целые числа, знаки плюс и минус.
- Основными элементами синтаксиса языка являются выражения, термины и операции.
- Наш язык может включать любое количество выражений.
- Выражение определяется как «термин», за которым следует «операция», за которой следует еще один термин.
- Операция – это плюс или минус.
- Термин — это целочисленный токен или выражение.
Формальные определения словарного запаса и синтаксиса
Словарь обычно выражается регулярными выражениями.
Например, наш язык будет определен как: Как видите, целые числа определяются регулярным выражением.
Синтаксис обычно определяется в формате BNF. Наш язык будет определен как:
Мы сказали, что язык может быть проанализирован обычными синтаксическими анализаторами, если его грамматика является контекстно-свободной грамматикой. Интуитивное определение контекстно-свободной грамматики — это грамматика, которая может быть полностью выражена в БНФ. Формальное определение см. в статье Википедии о контекстно-свободной грамматике
Типы парсеров
Существует два типа парсеров: парсеры "сверху вниз" и парсеры "снизу вверх". Интуитивное объяснение состоит в том, что синтаксические анализаторы сверху вниз изучают высокоуровневую структуру синтаксиса и пытаются найти соответствие правилу. Синтаксические анализаторы снизу вверх начинают с входных данных и постепенно преобразуют их в синтаксические правила, начиная с правил нижнего уровня до тех пор, пока не будут соблюдены правила высокого уровня.
Давайте посмотрим, как два типа синтаксических анализаторов будут анализировать наш пример.
Парсер сверху вниз начнет с правила более высокого уровня: он идентифицирует 2 + 3 как выражение. Затем он идентифицирует 2 + 3 - 1 как выражение (процесс определения выражения развивается в соответствии с другими правилами, но отправной точкой является правило самого высокого уровня).
Синтаксический анализатор снизу вверх будет сканировать ввод до тех пор, пока не будет найдено соответствие правилу. Затем он заменит соответствующий ввод правилом. Это будет продолжаться до конца ввода.Частично совпавшее выражение помещается в стек парсера.
Стек | Ввод |
---|---|
2 + 3 - 1 | |
термин | + 3 - 1 |
термин операция | 3 - 1 |
выражение | - 1 |
операция выражения | 1 |
выражение | - |
Автоматическое создание парсеров
Существуют инструменты, которые могут создавать синтаксический анализатор. Вы скармливаете им грамматику вашего языка — его словарный запас и правила синтаксиса — и они генерируют работающий синтаксический анализатор. Создание синтаксического анализатора требует глубокого понимания синтаксического анализа, а создать оптимизированный синтаксический анализатор вручную непросто, поэтому генераторы синтаксических анализаторов могут быть очень полезными.
WebKit использует два известных генератора синтаксических анализаторов: Flex для создания лексера и Bison для создания синтаксического анализатора (вы можете встретить их с именами Lex и Yacc). Входные данные Flex — это файл, содержащий определения регулярных выражений токенов. Ввод Bison — это правила синтаксиса языка в формате BNF.
Синтаксический анализатор HTML
Задачей синтаксического анализатора HTML является преобразование HTML-разметки в дерево синтаксического анализа.
Определение грамматики HTML
Словарь и синтаксис HTML определены в спецификациях, созданных организацией W3C.
Не контекстно-свободная грамматика
Как мы видели во введении к синтаксическому анализу, синтаксис грамматики можно формально определить с помощью таких форматов, как BNF.
К сожалению, все темы, посвященные обычным парсерам, неприменимы к HTML (я привел их не просто для развлечения — они будут использоваться при разборе CSS и JavaScript). HTML не может быть легко определен контекстно-свободной грамматикой, которая нужна синтаксическим анализаторам.
Существует формальный формат для определения HTML — DTD (определение типа документа), но это не контекстно-свободная грамматика.
На первый взгляд это кажется странным; HTML довольно близок к XML. Существует множество доступных парсеров XML. Существует XML-вариация HTML — XHTML — так в чем же большая разница?
Разница в том, что HTML-подход более "щадящий": он позволяет опустить определенные теги (которые затем добавляются неявно), а иногда и начальные или конечные теги и т. д. В целом это «мягкий» синтаксис, в отличие от жесткого и требовательного синтаксиса XML.
Эта, казалось бы, небольшая деталь имеет огромное значение. С одной стороны, это основная причина популярности HTML: он прощает ваши ошибки и облегчает жизнь веб-автору. С другой стороны, это затрудняет написание формальной грамматики. Подводя итог, можно сказать, что HTML не может быть легко проанализирован обычными синтаксическими анализаторами, поскольку его грамматика не является контекстно-свободной. HTML не может быть проанализирован синтаксическими анализаторами XML.
HTML DTD
Определение HTML находится в формате DTD. Этот формат используется для определения языков семейства SGML. Формат содержит определения для всех разрешенных элементов, их атрибутов и иерархии. Как мы видели ранее, HTML DTD не формирует контекстно-свободную грамматику.
Выходное дерево ("дерево синтаксического анализа") представляет собой дерево элементов DOM и узлов атрибутов. DOM — это сокращение от объектной модели документа. Это объектное представление HTML-документа и интерфейс HTML-элементов с внешним миром, такой как JavaScript.
Корнем дерева является объект "Документ".
DOM почти полностью связан с разметкой. Например: эта разметка будет преобразована в следующее дерево DOM:
Рисунок : DOM-дерево примера разметки
Когда я говорю, что дерево содержит узлы DOM, я имею в виду, что дерево состоит из элементов, реализующих один из интерфейсов DOM. Браузеры используют конкретные реализации, которые имеют другие атрибуты, используемые браузером внутри.
Алгоритм синтаксического анализа
Как мы видели в предыдущих разделах, HTML нельзя анализировать с помощью обычных парсеров "сверху вниз" или "снизу вверх".
- Снисходительный характер языка.
- Тот факт, что браузеры имеют традиционную устойчивость к ошибкам для поддержки хорошо известных случаев недопустимого HTML.
- Процесс синтаксического анализа является повторным. Для других языков источник не меняется во время синтаксического анализа, но в HTML динамический код (например, элементы скрипта, содержащие вызовы document.write()) могут добавлять дополнительные токены, поэтому процесс синтаксического анализа фактически изменяет ввод.
Не имея возможности использовать обычные методы синтаксического анализа, браузеры создают собственные синтаксические анализаторы для анализа HTML.
Алгоритм синтаксического анализа подробно описан в спецификации HTML5. Алгоритм состоит из двух этапов: токенизация и построение дерева.
Токенизация – это лексический анализ, который преобразует входные данные в токены.Среди маркеров HTML есть начальные теги, конечные теги, имена атрибутов и значения атрибутов.
Токенизатор распознает токен, передает его конструктору дерева и использует следующий символ для распознавания следующего токена и так далее до конца ввода.
Рис. : Процесс синтаксического анализа HTML (взято из спецификации HTML5)
Алгоритм токенизации
Выводом алгоритма является токен HTML. Алгоритм выражается в виде конечного автомата. Каждое состояние использует один или несколько символов входного потока и обновляет следующее состояние в соответствии с этими символами. На решение влияет текущее состояние токенизации и состояние построения дерева. Это означает, что один и тот же использованный символ будет давать разные результаты для правильного следующего состояния в зависимости от текущего состояния. Алгоритм слишком сложен для полного описания, поэтому давайте рассмотрим простой пример, который поможет нам понять принцип.
Базовый пример — токенизация следующего HTML:
Исходным состоянием является "Состояние данных". Когда персонаж встречается, состояние меняется на «Состояние тега открыто». Использование символа az вызывает создание «токена начального тега», состояние изменяется на «состояние имени тега». Мы остаемся в этом состоянии до тех пор, пока символ > не будет израсходован. Каждый символ добавляется к новому имени токена. В нашем случае созданный токен является токеном html.
При достижении тега > выдается текущий токен, и состояние снова меняется на «Состояние данных». Тег будет обрабатываться теми же шагами. До сих пор были испущены теги html и body. Теперь мы вернулись к «состоянию данных». Использование символа H Hello world приведет к созданию и выдаче маркера персонажа, это продолжается до тех пор, пока не будет выполнено
Получите полный доступ к Head First HTML and CSS, 2-е издание и более чем к 60 тысячам других игр с бесплатной 10-дневной пробной версией O'Reilly.
Есть также прямые онлайн-мероприятия, интерактивный контент, материалы для подготовки к сертификации и многое другое.
Единственное, что стоит между вами и выходом в Сеть, — это научиться говорить на языке:
Язык гипертекстовой разметки, или сокращенно HTML. Итак, приготовьтесь к урокам языка. После этой главы вы не только поймете некоторые основные элементы HTML, но и сможете немного говорить на языке HTML. Черт возьми, к концу этой книги вы будете говорить на HTML так, как будто вы выросли в Webville.
Хотите поделиться своей идеей? Продать что-нибудь? Просто нужен творческий выход? Обратитесь к Интернету — нам не нужно говорить вам, что он стал универсальной формой общения. Более того, это форма общения, в которой ВЫ можете участвовать.
Но если вы действительно хотите эффективно использовать Интернет, вам необходимо кое-что узнать о HTML, не говоря уже о том, как работает Интернет. Давайте посмотрим с высоты 30 000 футов:
Веб-серверы постоянно работают в Интернете, неустанно ожидая запросов от веб-браузеров. Какие запросы? Запросы на веб-страницы, изображения, звуки или даже видео. Когда сервер получает запрос на любой из этих ресурсов, он находит ресурс и отправляет его обратно в браузер.
Вы уже знаете, как работает браузер: вы путешествуете по Интернету и нажимаете ссылку, чтобы перейти на страницу. Этот щелчок заставляет ваш браузер запрашивать HTML-страницу с веб-сервера, извлекать ее и отображать страницу в окне браузера.
Но как браузер узнает, как отображать страницу? Вот тут-то и появляется HTML. HTML сообщает браузеру все о содержании и структуре страницы. Давайте посмотрим, как это работает.
Итак, вы знаете, что HTML — это ключ к отображению ваших страниц в браузере, но как именно выглядит HTML? И что он делает?
Давайте взглянем на HTML. представьте, что вы собираетесь создать веб-страницу для рекламы Head First Lounge, местной тусовки с хорошими мелодиями, освежающими эликсирами и беспроводным доступом. Вот что вы написали бы в HTML:
Мы пока не ожидаем, что вы знаете HTML.
К этому моменту вы должны получить представление о том, как выглядит HTML; мы собираемся подробно рассказать обо всем чуть позже.А пока изучите HTML и посмотрите, как он будет представлен в браузере на следующей странице. Обязательно внимательно следите за каждой буквенной аннотацией и тем, как и где она отображается в браузере.
Когда браузер читает ваш HTML-код, он интерпретирует все теги, окружающие ваш текст. Теги — это просто слова или символы в угловых скобках, например,
Проверим, как браузер интерпретирует теги в Head First Lounge:
Глупых вопросов не бывает
В: Значит, HTML — это просто набор тегов, которыми я обрамляю свой текст?
О: Для начала. Помните, что HTML означает язык гипертекстовой разметки, поэтому HTML дает вам возможность «разметить» ваш текст с помощью тегов, которые сообщают браузеру, как структурирован ваш текст. Но есть еще и гипертекстовый аспект HTML, о котором мы поговорим чуть позже в этой книге.
В: Как браузер решает, как отображать HTML?
A: HTML сообщает вашему браузеру о структуре вашего документа: где находятся заголовки, где находятся абзацы, какой текст нужно выделить и так далее. Учитывая эту информацию, браузеры имеют встроенные правила по умолчанию для отображения каждого из этих элементов.
Но вам не нужно соглашаться на настройки по умолчанию. Вы можете добавить свой собственный стиль и правила форматирования с помощью CSS, которые определяют шрифт, цвета, размер и множество других характеристик вашей страницы. Мы вернемся к CSS позже в этой главе.
В: В HTML-коде Head First Lounge есть всевозможные отступы и интервалы, но я не вижу этого, когда он отображается в браузер. Почему?
A: Правильно, хороший улов. Браузеры игнорируют табуляции, возвраты и большинство пробелов в документах HTML. Вместо этого они полагаются на вашу разметку, чтобы определить, где происходит разрыв строки и абзаца.
Так зачем же мы вставили собственное форматирование, если браузер его просто проигнорирует? Чтобы нам было легче читать документ, когда мы редактируем HTML. По мере усложнения HTML-документов вы обнаружите несколько пробелов, возвратов и табуляции здесь и там, которые действительно помогают улучшить читабельность HTML.
В: Итак, есть два уровня заголовков,
?
A: На самом деле их шесть,
, который браузер обычно отображает с последовательно меньшим размером шрифта. Если вы не создаете сложный и большой документ, вы обычно не будете использовать заголовки за пределами
.
В: Зачем мне тег? Разве не очевидно, что это HTML-документ?
A: Тег сообщает браузеру, что ваш документ на самом деле HTML. В то время как некоторые браузеры простят вам, если вы его опустите, некоторые нет, и по мере того, как мы будем двигаться к «промышленному HTML» позже в книге, вы увидите, что очень важно включать этот тег.
< p>Q: Что делает файл файлом HTML?A: HTML-файл – это простой текстовый файл. В отличие от файла обработки текста, в него не встроено специальное форматирование. По соглашению мы добавляем «.html» в конец имени файла, чтобы дать операционной системе лучшее представление о том, что это за файл. Но, как вы видели, действительно важно то, что мы помещаем внутрь файла.
В: Все говорят о HTML5. Используем ли мы его? Если да, то почему мы не говорим «HTML-FIVE» вместо «HTML»?
О: Вы изучаете HTML, а HTML5 — это последняя версия HTML. В последнее время HTML5 привлекает большое внимание, потому что он упрощает многие способы написания HTML и предоставляет некоторые новые функции, которые мы собираемся рассмотреть в этой книге. Он также предоставляет некоторые расширенные функции через свои интерфейсы программирования приложений (API) JavaScript, и они описаны в Head First HTML5 Programming.
В: Разметка кажется глупой. Приложения типа «что видишь, то и получишь» существуют с 70-х? Почему Интернет не основан на таком формате, как Microsoft Word или аналогичное приложение?
О: Интернет создается из текстовых файлов без каких-либо специальных символов форматирования. Это позволяет любому браузеру в любой части мира извлекать веб-страницу и понимать ее содержимое. Существуют приложения WYSIWYG, такие как Dreamweaver, и они прекрасно работают. Но в этой книге мы собираемся свести все к голому железу и начать с текста. Тогда вы в хорошей форме, чтобы понять, что ваше приложение Dreamweaver делает за кулисами.
В: Можно ли как-нибудь оставить комментарии для себя в HTML?
О: Да, если вы разместите свои комментарии между ними, браузер их полностью проигнорирует. Скажем, вы хотели написать комментарий «Вот начало контента гостиной». Вы можете сделать это следующим образом:
Обратите внимание, что вы можете размещать комментарии в нескольких строках. Имейте в виду, что все, что вы поместите между « », даже HTML, будет игнорироваться браузером.
Наточите карандаш
Вы ближе к изучению HTML, чем думаете.
Вот снова HTML-код для Head First Lounge.Взгляните на теги и посмотрите, сможете ли вы угадать, что они сообщают браузеру о содержимом. Запишите свои ответы в поле справа; мы уже сделали первую пару для вас.
Читайте также: