从零写一个编译器(九):语义分析之构造抽象语法树(AST)

本文介绍了如何从零构建一个编译器的语义分析阶段,重点在于构造抽象语法树(AST)。AST是源代码的抽象表示,对编译器至关重要,用于生成IR或解释执行。文章详细讲解了AST节点的表示、NodeFactory的使用,以及如何在语法分析过程中构造AST。同时,讨论了不同节点在解释执行和代码生成时的差异,并举例说明了构建AST的具体操作。
摘要由CSDN通过智能技术生成

项目的完整代码在 C2j-Compiler

前言

在上一篇完成了符号表的构建,下一步就是输出抽象语法树(Abstract Syntax Tree,AST)

抽象语法树(abstract syntax tree 或者缩写为 AST),是源代码的抽象语法结构的树状表现形式,这里特指编程语言的源代码。树上的每个节点都表示源代码中的一种结构。

AST对于编译器是至关重要的,现在的编译型语言一般通过AST来生成IR,解释型语言也可以不用虚拟机而直接遍历AST来解释执行,之后要写解释器和编译器都依赖这个AST

这一篇主要文件有:

  • AstBuilder.java
  • AstNode.java
  • AstNodeImpl.java
  • NodeKey.java
  • NodeFactory.java

主要数据结构

AST节点的表示

public interface AstNode {

    AstNode addChild(AstNode node);

    AstNode getParent();

    ArrayList<AstNode> getChildren();

    void setAttribute(NodeKey key, Object value);

    Object getAttribute(NodeKey key);

    boolean isChildrenReverse();

    void reverseChildren();

    AstNode copy();

}

这是对AstNode接口的实现,并且继承HashMap,这里的NodeKey是

TokenType, VALUE, SYMBOL, PRODUCTION, TEXT

对应的value,

  1. TokenType就是非终结符的类型
  2. Text用来存储解析对象的文本信息
  3. Symbol对应的就是变量的符号对象
  4. Value是对应对象解析的值,比如int a = 1,那么value的值就为1
public class AstNodeImpl extends HashMap<NodeKey, Object> implements AstNode {
    private Token type;
    private AstNodeImpl parent;
    private ArrayList<AstNode> children;
    String name;

    private boolean isChildrenReverse = false;

    public AstNodeImpl(Token type) {
        this.type = type;
        this.parent = null;
        this.children = new ArrayList<>();
        setAttribute(NodeKey.TokenType, type);
    }

    @Override
    public AstNode addChild(AstNode node) {
        if (node != null) {
            children.add(node);
            ((AstNodeImpl) node).parent = this;
        }

        return node;
    }

    @Override
    public AstNode getParent() {
        return parent;
    }

    @Override
    public void reverseChildren() {
        if (isChildrenReverse) {
            return;
        }

        Collections.reverse(children);
        isChildrenReverse = true;
    }

    @Override
    public boolean isChildrenReverse() {
        return isChildrenReverse;
    }

    @Override
    public ArrayList<AstNode> getChildren() {
        reverseChildren();

        return children;
    }

    @Override
    public void setAttribute(NodeKey key, Object value) {
        if (key == NodeKey.TEXT) {
            name = (String) value;
        }
        put(key, value);
    }

    @Override
    public Object getAttribute(NodeKey key) {
        return get(key);
    }

    @Override
    public String toString() {
        String info = "";
        if (get(NodeKey.VALUE) != null) {
            info += "Node Value is " + get(NodeKey.VALUE).toString();
        }

        if (get(NodeKey.TEXT) != null) {
            info += "\nNode Text is " + get(NodeKey.TEXT).toString();
        }

        if (get(NodeKey.SYMBOL) != null) {
            inf
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值