Создание PsiElement из ASTNode с подразумеваемыми узлами и вышедшими из строя дочерними элементами - PullRequest
0 голосов
/ 06 мая 2020

Можно ли для плагина настраиваемого языка, использующего SDK плагина IntelliJ, создать дерево PSIElement , где

  • некоторые PSIElement s не связаны ASTNode , поэтому где myPsiElement.getNode() == null
  • некоторые PSIElement s имеют дочерние элементы вне очереди, например myPsiElement.children()[0].getStartOffsetInParent() > myPsiElement.children()[1].getStartOffsetInParent()
  • some PSIElement s соответствуют нулевым символам в источнике: myPsiElement.getTextLength() == 0

Может ли какое-либо из этих свойств усложнить использование преимуществ языковых плагинов SDK?


Для фона:

Я создаю настраиваемый языковой плагин для IntelliJ для " Реализация синтаксического анализатора и PSI ."

В нижней части диаграммы из документации показана взаимосвязь между ASTNode s и PsiElement s.

IIU C, сначала лексер сегментирует текст на токены. Затем синтаксический анализатор удаляет отметки начала и конца узла между токенами, чтобы указать структуру дерева синтаксического анализа. Внутренние элементы Intellij поднимают этот поток токенов с помощью маркеров в (не очень абстрактное) дерево ASTNode . Наконец, код плагина c для конкретного языка строит дерево PSI из AST.

Из этой диаграммы похоже, что каждый узел в дереве Psi связан с ASTElement .

Это соотношение кажется двунаправленным для PsiElement.getNode(). На диаграмме не показана стрелка между MyPsiFile и MyElementType.FILE ASTNode , но PsiFile.getNode() предполагает, что должен быть один .

По причинам, связанным с языком c, мой существующий синтаксический анализатор создает дерево, которое явно не соответствует этой модели.

  • Узлы могут появляться не по порядку. Выражение a + b выполняет синтаксический анализ до узла типа (call + a b). Обратите внимание, что инфиксные и постфиксные операторы сдвигаются влево перед их первым операндом.
  • Парсер синтезирует некоторые узлы, которые не соответствуют никаким токенам, поэтому связь между ними и узлом AST неясна. Например, мне нужно создать отдельные деревья для

    • for (x;;) body
    • for (;x;) body
    • for (;;x) body

    , поэтому синтаксический анализатор вставляет символы, такие как init= в (for init= x body), которые определение для может использовать, чтобы решить, что делать с x.

Существует концепция «нефизического» * ​​1095 * PSIElement :

/**
 * Checks if an actual source or class file corresponds to the element. Non-physical elements include,
 * for example, PSI elements created for the watch expressions in the debugger.
 * Non-physical elements do not generate tree change events.
 * Also, {@link PsiDocumentManager#getDocument(PsiFile)} returns null for non-physical elements.

, но мне неясно, связаны ли они с ASTNode s или, если это правильно, для узлов, подразумеваемых текстом программы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...