Можно ли для плагина настраиваемого языка, использующего 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 или, если это правильно, для узлов, подразумеваемых текстом программы.