Parsing 从包含隐含节点和无序子节点的ASTNode创建元素

Parsing 从包含隐含节点和无序子节点的ASTNode创建元素,parsing,intellij-idea,abstract-syntax-tree,intellij-plugin,Parsing,Intellij Idea,Abstract Syntax Tree,Intellij Plugin,使用IntelliJ的plugin SDK的自定义语言插件可以生成PSIElement树吗 某些PSIelement没有关联的ASTNode,因此wheremyPsiElement.getNode()==null 某些PSIelement的子元素顺序不正确,例如,myPsiElement.children()[0]。getStartOffsetInParent()>myPsiElement.children()[1]。getStartOffsetInParent() 某些PSIelement对

使用IntelliJ的plugin SDK的自定义语言插件可以生成PSIElement树吗

  • 某些PSIelement没有关联的ASTNode,因此where
    myPsiElement.getNode()==null
  • 某些PSIelement的子元素顺序不正确,例如,
    myPsiElement.children()[0]。getStartOffsetInParent()>myPsiElement.children()[1]。getStartOffsetInParent()
  • 某些PSIelement对应于源代码中的零个字符:
    myPsiElement.getTextLength()==0
这些属性是否会使语言插件SDK功能的利用变得更加困难


背景资料:

我正在为IntelliJ per创建一个自定义语言插件

文档中图表的底部显示了ASTNodes和元素之间的关系

IIUC,首先,lexer将文本分割成标记。然后,解析器在令牌之间删除节点开始和结束标记,以指定解析树结构。Intellij内部将带有标记的令牌流提升到(不是非常抽象的)ASTNode树中。最后,特定于语言的插件代码从AST构建一个PSI树

从该图来看,Psi树中的每个节点都与一个ASTElement关联

这种关系似乎是双向的。该图没有显示MyPsiFile和MyElementType.FILE节点之间的箭头,但是 这意味着必须有一个

由于特定于语言的原因,我现有的解析器生成的树显然不适合此模型

  • 节点可能出现无序。 表达式
    a+b
    解析为类似
    (call+ab)
    的节点。请注意,中缀和后缀运算符在第一个操作数之前向左移位
  • 解析器合成了一些不对应令牌的节点,因此它们与AST节点之间的关系不清楚。例如,我需要生产不同的树木

    • (x;;)主体的
    • (;x;)主体的
    • (;;x)主体的
    因此,解析器在
    (对于init=x body)
    中插入类似
    init=
    的符号,for的定义可以使用这些符号来决定如何处理
    x

有一个概念是:


但我不清楚这些是否与ASTNodes相关,或者这是否适用于程序文本所暗示的节点。

我想了解您关于语言特定于元素/节点关系的声明。我本以为这就是解析树和AST之间的区别。前缀符号语言的解析树不同于中缀变体,但AST是相同的,不是吗?你也找到答案了吗?@ChrisMountford,我还没有找到一个好答案。对我对
a+b
的解析树是
[InfixPlus,[Leaf,“a”],“+”,[Leaf,“b”]
,而AST是
(+ab)
。在上面显示Intellij解析器管道的图中,没有解析树→AST步;现在,我创建了一个Intellij AST来包装我的解析树,并使用位置元数据将我的解析树节点映射到我的AST节点。这可以让我的插件代码找到对应于Intellij AST节点的我的AST。我想了解您关于特定语言偏离元素/节点关系的陈述。我本以为这就是解析树和AST之间的区别。前缀符号语言的解析树不同于中缀变体,但AST是相同的,不是吗?你也找到答案了吗?@ChrisMountford,我还没有找到一个好答案。对我对
a+b
的解析树是
[InfixPlus,[Leaf,“a”],“+”,[Leaf,“b”]
,而AST是
(+ab)
。在上面显示Intellij解析器管道的图中,没有解析树→AST步;现在,我创建了一个Intellij AST来包装我的解析树,并使用位置元数据将我的解析树节点映射到我的AST节点。这使我的插件代码可以找到对应于Intellij AST节点的AST。
/**
 * 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.