如何设计抽象语法树的部分

本文关键字:语法树 抽象 | 更新日期: 2023-09-27 18:26:54

我正在从头开始为学习体验编写一个C#解释器,到目前为止一切都很顺利。我有一个功能齐全的C#lexer,它向解析器输出各种各样的令牌。我知道我将如何解析令牌,但我不确定我应该如何构建AST(抽象语法树)。

例如,如果我有一个简单的代码片段:

using System.Xml;

解析树时会是什么样子?

像这样?

UsingDirective
   Identifier(System)
      Identifier(Xml)

还是像这样?

UsingDirective
   Identifier(System)
   Identifier(Xml)

如果我能得到一些关于如何构建带点的标识符、If/else-If/else语句、组合在一个语句中的变量声明/赋值(int I=0;)、函数定义等内容的建议和/或示例,那将很有帮助。我只需要更好地了解如何构建这棵树,剩下的我自己就能搞定。谢谢

如何设计抽象语法树的部分

我过去写过几个解析器,通常我会选择这样的东西:

UsingDirective
   IdentifierList
     Identifier (LeftNode) (System)
     Identifier (RightNode) (Xml)

在这种using System.Collections.Generic 的情况下

UsingDirective
   IdentifierList
       IdentifierList (LeftNode)
           Identifier (LeftNode) (System)
           Identifier (RightNode) (Collections)
       Identifier (RightNode) (Generic)

与Roslyn不同,我更喜欢通过不包括分号、using关键字等标记来保持我的AST的轻量级,因为编译器不需要它们。

我专门为IDE编写的解析器看起来不一样——它们携带了所有这些额外的东西以及更多的信息,比如行号和列号。

您可以看看微软是如何利用Roslyn做到这一点的。你可以在那里看到他们是如何为C#(和VB.NET)声明语法树的,也许你甚至可以在编写它们之前使用它来代替解释器的一部分。

具体来说,using指令的Roslyn语法树如下所示:

UsingDirective
    UsingKeyword
    QualifiedName
        IdentifierName (System)
        DotToken
        IdentifierName (Xml)
    SemicolonToken

所以,类似于您的第二个版本,但更详细。

我认为你的第一个版本没有多大意义。在句法层面上,Xml不是System的子级(尽管稍后在语义层面上可能会有"父命名空间"的概念)。