Перейти к основному содержимому

Этап парсера

примечание

Эта страница переведена при помощи нейросети GigaChat.

Этап синтаксического анализа состоит из двух частей:

  • Парсер, определенный в gram.y и scan.l, построен с помощью Unix-инструментов bison и flex.
  • Процесс преобразования вносит изменения и дополнения в структуры данных, возвращаемые синтаксическим анализатором.

Парсер

Парсер должен проверить строку запроса (которая поступает в виде обычного текста) на правильность синтаксиса. Если синтаксис правильный, строится дерево разбора и передается обратно, в противном случае возвращается ошибка. Парсер и лексер реализованы с помощью известных Unix-инструментов bison и flex.

Лексер определяется в файле scan.l и отвечает за распознавание идентификаторов, ключевых слов SQL и т. д. Для каждого найденного ключевого слова или идентификатора генерируется токен, который передается парсеру.

Парсер определяется в файле gram.y и состоит из набора правил грамматики и действий, которые выполняются каждый раз, когда срабатывает правило. Код действий (который на самом деле является кодом на языке C) используется для построения дерева разбора.

Файл scan.l преобразуется в исходный файл scan.c на языке Си с помощью программы flex, а gram.y преобразуется в gram.c с помощью bison. После этих преобразований для создания парсера можно использовать обычный компилятор Си. Никогда не вносите никаких изменений в сгенерированные C-файлы, так как они будут перезаписаны при следующем вызове flex или bison.

Подробное описание bison или правил грамматики, приведенных в gram.y, выходит за рамки данного руководства. Существует множество книг и документов, посвященных flex и bison. Необходимо быть знакомым с bison до того, как начнете изучать грамматику, приведенную в gram.y, иначе непонятно, что там происходит.

Примечание:

Упомянутые преобразования и компиляции обычно выполняются автоматически с использованием файлов make, поставляемых с исходным дистрибутивом PostgreSQL

Подробное описание bison или правил грамматики, приведенных в gram.y, выходит за рамки этого руководства. Есть много книг и документов, посвященных bison и flex. Прежде, чем начинать изучать грамматику, приведенную в gram.y, необходимо ознакомиться с bison.

Процесс преобразования

Этап парсера создает дерево разбора, используя только фиксированные правила о синтаксической структуре SQL. Он не производит никаких поисков в системных каталогах, поэтому нет возможности понять подробную семантику запрашиваемых операций. После завершения работы синтаксического анализа процесс преобразования принимает дерево, переданное синтаксическим анализатором, в качестве входных данных и выполняет семантическую интерпретацию, необходимую для понимания на какие таблицы, функции и операторы ссылается запрос. Структура данных, которая строится для представления этой информации, называется деревом запроса.

Причина разделения необработанного разбора и семантического анализа заключается в том, что поиск в системном каталоге может выполняться только в рамках транзакции, а начинать транзакцию сразу после получения строки запроса нельзя. Этапа необработанного разбора достаточно для определения команд управления транзакцией (BEGIN, ROLLBACK и т. д.), которые затем могут быть корректно выполнены без дополнительного анализа. Как только станет понятно, что обрабатывается реальный запрос (например, SELECT или UPDATE), можно начинать транзакцию, если она еще не начата. Только после этого можно вызывать процесс преобразования.

Дерево запросов, созданное в процессе преобразования, в большинстве мест структурно похоже на исходное дерево разбора, но имеет много отличий в деталях. Например, узел FuncCall в дереве разбора представляет собой нечто, синтаксически похожее на вызов функции. Он может быть преобразован в узел FuncExpr или Aggref в зависимости от того, окажется ли имя ссылки обычной или агрегированной функцией. Кроме того, в дерево запросов добавляется информация о фактических типах данных столбцов и результатов вычислений.