我正在从头开始编写C#口译员以获得学习体验,到目前为止,一切都进展顺利。我有一个功能齐全的C#lexer,可以将各种标记输出到解析器。我知道我将如何解析令牌,但我不确定如何构建我的AST(抽象语法树)。
例如,如果我有一个简单的代码片段:
using System.Xml;
解析时树会是什么样子?
喜欢这个吗?
UsingDirective
Identifier(System)
Identifier(Xml)
还是喜欢这个?
UsingDirective
Identifier(System)
Identifier(Xml)
如果我能得到一些建议和/或示例,我可以如何构造带有点的标识符之类的东西,if / else if / else语句,变量声明/赋值组合在一个语句中(int i = 0;) ,功能定义等会有所帮助。我只需要更好地了解如何构建树,我可以自己弄清楚其余部分。感谢。
答案 0 :(得分:2)
你可以看看微软是如何与Roslyn一起做的。您可以看到他们是如何为C#(和VB.NET)声明语法树的,甚至可以在编写它们之前使用它而不是解释器的一部分。
具体来说,using
指令的Roslyn语法树如下所示:
UsingDirective
UsingKeyword
QualifiedName
IdentifierName (System)
DotToken
IdentifierName (Xml)
SemicolonToken
所以,类似于你的第二个版本,但更详细。
我认为你的第一个版本没有多大意义。 Xml
在句法层面上不是System
的孩子(即使您稍后在语义层面上可能有“父命名空间”的概念)。
答案 1 :(得分:2)
我过去曾写过几个解析器,我通常会这样做:
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编写的看起来与众不同 - 它们带有所有这些额外的东西以及更多的信息,如行号和列号。