Spec-Zone.ru › Elisp

Использование парсера Tree-sitter

В этом разделе описывается, как создать и настроить парсер tree-sitter. В Emacs каждый парсер tree-sitter связан с буфером. По мере редактирования буфера пользователем связанный парсер и синтаксическое дерево автоматически обновляются.

Переменная: treesit-max-buffer-size

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

Переменная: treesit-languages-require-line-column-tracking

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

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

Пользователь может использовать treesit-tracking-line-column-p и treesit-parser-tracking-line-column-p, чтобы проверить, отслеживает ли буфер или парсер строки и столбцы соответственно.

Функция: treesit-parser-create language &optional buffer no-reuse tag

Создаёт парсер для указанного буфера и языка (см. Грамматика языка Tree-sitter) с тегом tag. Если buffer не указан или равен nil, подразумевается текущий буфер.

По умолчанию эта функция повторно использует парсер, если в buffer уже существует парсер для language с тегом tag, но если no-reuse не равен nil, эта функция всегда создаёт новый парсер.

tag может быть любым символом, кроме t, и по умолчанию равен nil. У разных парсеров могут быть одинаковые теги.

Имея парсер, можно запросить информацию о нём: treesit-parser-buffer возвращает буфер, связанный с парсером, а treesit-parser-language возвращает язык, используемый парсером. Тег парсера можно получить с помощью treesit-parser-tag. Кроме того, каждый парсер может иметь уровень вложения, который можно задать с помощью treesit-parser-set-embed-level и получить с помощью treesit-parser-embed-level (подробнее об уровне вложения см. parser-embed-level). Наконец, treesit-parser-p сообщает, является ли объект парсером tree-sitter.

Нет необходимости явно выполнять синтаксический анализ буфера, поскольку он выполняется автоматически и отложенно. Парсер выполняет анализ только тогда, когда программа на Lisp запрашивает узел синтаксического дерева. Поэтому при первом создании парсер не анализирует буфер, а ждёт первого запроса узла от программы на Lisp. Аналогично, при изменении буфера парсер не выполняет повторный анализ немедленно.

При выполнении синтаксического анализа парсер проверяет размер буфера. Tree-sitter может обрабатывать буферы размером не более примерно 4 ГБ. Если размер превышает это значение, Emacs выдаёт ошибку treesit-buffer-too-large, а размер буфера передаётся в качестве данных сигнала.

После создания парсера Emacs автоматически добавляет его во внутренний список парсеров. При каждом изменении буфера Emacs обновляет парсеры из этого списка, чтобы они могли инкрементально обновлять свои синтаксические деревья.

Функция: treesit-parser-list &optional buffer language tag

Эта функция возвращает список парсеров для buffer, отфильтрованный по language и tag. Если buffer равен nil или не указан, по умолчанию используется текущий буфер.

Если language не равен nil, включаются только парсеры для этого языка и только парсеры с тегом tag. По умолчанию tag равен nil. Если tag равен t, в возвращаемый список включаются парсеры независимо от их тегов.

Функция: treesit-parser-delete parser

Эта функция удаляет parser.

Обычно парсер «видит» весь буфер, но если буфер сужен (см. Сужение области буфера), парсер будет видеть только доступную часть буфера. С точки зрения парсера скрытая область удалена. Когда позднее область буфера расширяется, парсер считает, что текст вставлен в начале и в конце. Хотя парсеры учитывают сужение буфера, режимам не следует использовать его для обработки буфера с несколькими языками; вместо этого задайте диапазоны, в которых должен работать парсер. См. Синтаксический анализ текста на нескольких языках.

Поскольку парсер выполняет синтаксический анализ отложенно, сужение буфера пользователем или программой на Lisp не влияет на парсер немедленно: пока режим не запрашивает узел при суженном буфере, парсер не замечает сужения.

Помимо создания парсера для буфера, программа на Lisp может также выполнять синтаксический анализ строки. В отличие от буфера, анализ строки выполняется однократно, и обновить результат невозможно.

Функция: treesit-parse-string string language

Эта функция выполняет синтаксический анализ string с использованием language и возвращает корневой узел созданного синтаксического дерева. Не используйте эту функцию в цикле: это вспомогательная функция для однократного использования, не оптимизированная для производительности; для интенсивной нагрузки используйте временный буфер.

Получение уведомлений об изменениях дерева разбора

Программе на Lisp может потребоваться получать уведомления о тексте, затронутом инкрементальным синтаксическим анализом. Например, вставка закрывающего комментарий токена превращает предшествующий этому токену текст в комментарий. Хотя этот текст непосредственно не редактировался, он всё равно считается «изменённым».

Emacs позволяет программе на Lisp регистрировать функции обратного вызова (также называемые уведомителями) для таких изменений. Функция-уведомитель принимает два аргумента: ranges и parser. ranges — это список конс-ячеек вида (start . end), где start и end обозначают начальную и конечную позиции диапазона. parser — это парсер, отправивший уведомление.

При каждом повторном анализе буфера парсер сравнивает старое и новое дерево разбора, вычисляет диапазоны, в которых изменились узлы, и передаёт их функциям-уведомителям. Обратите внимание, что первоначальный анализ также считается «изменением», поэтому функции-уведомители вызываются и при первоначальном анализе, причём диапазоном служит весь буфер.

Функция: treesit-parser-add-notifier parser function

Эта функция добавляет function в список функций-уведомителей parser, вызываемых после изменения. function должна быть символом функции, а не лямбда-функцией (см. Анонимные функции).

Функция: treesit-parser-remove-notifier parser function

Эта функция удаляет function из списка функций-уведомителей parser, вызываемых после изменения. function должна быть символом функции, а не лямбда-функцией.

Функция: treesit-parser-notifiers parser

Эта функция возвращает список функций-уведомителей parser.

Программа на Lisp также может принудительно запустить повторный синтаксический анализ парсером и немедленно получить изменённые области с помощью treesit-parser-changed-regions.

Функция: treesit-parser-changed-regions parser

Эта функция принудительно запускает повторный синтаксический анализ с помощью parser и возвращает затронутые области: список (start . end). Если парсеру нечего анализировать заново или затронутые области пусты, эта функция возвращает nil.

Подстановка парсера для другого языка

Иногда грамматика языка B является строгим надмножеством грамматики другого языка A. В этом случае имеет смысл повторно использовать настройки языка A (правила font-lock, правила отступов и т. д.) для языка B. Для этого treesit-language-remap-alist позволяет пользователям переназначать язык A на язык B.

Переменная: treesit-language-remap-alist

Значение этой переменной должно быть ассоциативным списком пар (language-a . language-b). Если такая пара присутствует в списке, создание парсера для language-a фактически создаёт парсер для language-b. Соответственно, любые действия, создающие узел или выполняющие запрос для language-a, будут перенаправлены на language-b. Это сопоставление полностью прозрачно: созданный парсер будет сообщать, что использует language-b, и то же относится к узлам, созданным этим парсером.

В частности, парсер, созданный с помощью treesit-parser-create, будет сообщать об использовании языка, переданного ему в качестве language. Например, если язык cpp сопоставлен с cuda:

(setq treesit-language-remap-alist '((cpp . cuda)))

(treesit-parser-language (treesit-parser-create 'cpp))
  ⇒ 'cpp

(treesit-parser-language (treesit-parser-create 'cuda))
  ⇒ 'cuda

хотя оба парсера на самом деле являются парсерами cuda.

Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Using-Parser.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API