本章节对应仓库
2.抽象语法树 Github
什么是抽象语法树
抽象语法树是一种用于表示语法的树,简而言之,我们输入的各种运算符、操作符、表达式,经过解析后,形成一种树形结构,树上的每个节点都表示源代码中的一种结构。
例如,a = b * (3 + 5)在语法树里,表示为:
graph TD
= --> a
= --> *
* --> b
* --> +
+ --> 3
+ --> 5
通过将语法转换为树,对于语法解析会更为方便。
设计抽象语法树
classDiagram
ASTNode <|-- ASTLeaf
ASTNode <|-- ASTList
IEnumerable~ASTNode~ *.. ASTList
class ASTLeaf{
}
class ASTList{
+IReadOnlyList~ASTNode~ Children
+this(int i) ASTNode
}
class IEnumerable~ASTNode~{
<<interface>>
}
语法树的基类为ASTNode,目前基类没有提供任何的抽象函数或方法
ASTLeaf代表叶节点,底下没有其他节点
ASTList代表枝干,底下还有其他节点
ASTNode.cs
namespace SwordScript;
public abstract class ASTNode
{
}
ASTLeaf.cs
namespace SwordScript;
public abstract class ASTLeaf : ASTNode
{
}
ASTList.cs
using System.Collections;
using System.Collections.Generic;
namespace SwordScript;
public abstract class ASTList : ASTNode, IEnumerable<ASTNode>
{
public ASTList()
{
}
public ASTList(IEnumerable<ASTNode> list)
{
_children.AddRange(list);
}
private List<ASTNode> _children = new List<ASTNode>();
public IReadOnlyList<ASTNode> Children => _children;
public ASTNode this[int i] => _children[i];
public IEnumerator<ASTNode> GetEnumerator()
{
return _children.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
叶节点
叶节点通常代表着没有子物体的节点,在这里,叶节点可以分为两种:代表实体的标识符节点、代表基础类型的字面量节点
标识符节点
ASTIdentifier.cs
namespace SwordScript;
public class ASTIdentifier : ASTLeaf
{
public ASTIdentifier(string name)
{
Name = name;
}
public string Name { get; }
public override string ToString()
{
return Name;
}
}
标识符节点相对比较简单,只需要能够获取标识符字符串即可。
字面量节点
根据上一章节的定义,可以得知目前有整形、浮点、字符串、布尔、空类型五种类型
对这五种类型分别创建对应的字面量节点
ASTLiteral.cs
using System.Globalization;
namespace SwordScript;
public abstract class ASTLiteral : ASTLeaf
{
}
public class ASTLongIntegerLiteral : ASTLiteral
{
public ASTLongIntegerLiteral(long value)
{
Value = value;
}
public long Value { get; }
public override string ToString()
{
return Value.ToString();
}
}
public class ASTDoubleFloatLiteral : ASTLiteral
{
public ASTDoubleFloatLiteral(double value)
{
Value = value;
}
public double Value { get; }
public override string ToString()
{
return Value.ToString(CultureInfo.InvariantCulture);
}
}
public class ASTStringLiteral : ASTLiteral
{
public ASTStringLiteral(string value)
{
Value = value;
}
public string Value { get; }
public override string ToString()
{
return """ + Value + """;
}
}
public class ASTBooleanLiteral : ASTLiteral
{
public ASTBooleanLiteral(bool value)
{
Value = value;
}
public bool Value { get; }
public override string ToString()
{
return Value.ToString().ToLower();
}
}
public class ASTNullLiteral : ASTLiteral
{
public ASTNullLiteral()
{
}
public override string ToString()
{
return "null";
}
}
枝干节点
枝干节点代表着底下有其他节点的节点,例如二元表达式,就是此类。
如1+2
graph TD
+ --> 1
+ --> 2
+号节点便是一个二元表达式。
二元表达式
先定义二元表达式节点基类,具体的表达式节点待下一章定义。
ASTBinaryExpr.cs
namespace SwordScript;
public abstract class ASTBinaryExpr : ASTList
{
public ASTBinaryExpr(ASTNode left, ASTNode right) : base(new []{left, right})
{
}
public ASTNode Left => this[0];
public ASTNode Right => this[1];
}
结语
在本章中,我们定义了一些基本的抽象语法树节点,这些节点目前还没有实际意义。但是在下一章中,我们就会使用语法解析把语句机械成语法树。