一、AST节点

Node类型是所有AST节点的根节点,是所有其他AST节点类型的直接或间接父类。Decl类型是所有声明节点的根节点,变量定义(VarDecl)、函数定义(FuncDecl)、类定义(ClassDecl)、扩展定义(ExtendDecl)、宏定义(MacroDecl)都是Decl类型的子类型。Expr类型是所有表达式节点的根节点,TypeNode节点是所有类型节点的根节点,Pattern类型表示所有模式匹配节点的根节点。

二、Tokens与AST节点的相互转换

Tokens类型转AST类型,使用parse开头的函数,AST类型转Tokens类型,可以使用toTokens函数

package Study
// 导包
import Study.define.*
import std.ast.*


main () {
    let tokens: Tokens = quote(var num = 3 + 5)
    try {
        let decl: Decl = parseDecl(tokens)
        println(decl.toTokens())
    } catch (_) {
        println("无法转换")
    }
}

三、BinaryExpr节点

BinaryExpr表示二元表达式节点

package Study
// 导包
import Study.define.*
import std.ast.*


main () {
    let tokens = quote(2 + 4)
    let expr:BinaryExpr = BinaryExpr(tokens)
    println(expr.dump())
}

四、Decl节点

package Study
// 导包
import Study.define.*
import std.ast.*


main () {
    let tokens = quote(
        public func hi() {
            println("你好")
        }
    )
    let decl = parseDecl(tokens)
    // 获取修饰符
    for (modifier in decl.modifiers) {
        modifier.dump()
    }
    // 获取关键字
    decl.keyword.dump()
    // 获取函数名
    decl.identifier.dump()
}

五、VarDecl节点

VarDecl类表示变量声明对应的AST节点

package Study
// 导包
import Study.define.*
import std.ast.*


main () {
    let tokens = quote(public static var num: Int64 = 114514)
    let varDecl = VarDecl(tokens)

    print("修饰符: ")
    for (modifier in varDecl.modifiers) {
        println("\t ${modifier.keyword.dump()}")
    }

    println("\n关键字: ${varDecl.keyword.value}")
    println("变量名: ${varDecl.identifier.value}")
    println("变量类型: ")
    varDecl.declType.dump()
    println("初始值")
    varDecl.expr.dump()
}

六、FuncDecl节点

funcParams可以查看函数的参数列表

package Study
// 导包
import Study.define.*
import std.ast.*


main () {
    let tokens = quote(
        func demo(param!: Int64 = 10) {
            println("param=${param}")
        }
    )

    let funcDecl = FuncDecl(tokens)
    // 获取函数唯一参数
    let funcParam = funcDecl.funcParams[0]
    println("函数名: ${funcParam.identifier.value}")
    println("参数类型: ${funcParam.paramType.toTokens()}")
    if (funcParam.not.value == "!") {
        println("是命名参数")
        if (funcParam.colon.value == ":") {
            println("默认值: ${funcParam.expr.toTokens()}")
        } else {
            println("无默认值")
        }
    } else {
        println("不是命名参数")
    }
}

block属性表示函数体

package Study
// 导包
import Study.define.*
import std.ast.*


main () {
    let tokens = quote(
        public func add(x: Int64, y: Int64) {
            let sum = x + y
            return sum
        }
    )

    let funcDecl = FuncDecl(tokens)
    let funcbody = funcDecl.block.nodes

    for (body in funcbody) {
        println(body.toTokens())
    }
}

七、ClassDecl节点

ClassDecl类表示类声明对应的AST节点,该类继承了Decl类

package Study
// 导包
import Study.define.*
import std.ast.*

main () {
    let tokens = quote(
        class Person {
            Person(var name: String, var age: Int64, var sex: String){}

            init(name: String, age: Int64) {
                this.name = name
                this.age = age
            }

            func show() {
                println("姓名: ${this.name}, 年龄: ${this.age}, 性别: ${this.sex}")
            }
        }
    )

    let classDecl = ClassDecl(tokens)
    for (body in classDecl.body.decls) {
        if (body is VarDecl) {
            println("变量声明: \n${body.toTokens()}")
        }

        if (body is PrimaryCtorDecl) {
            let primaryInit = (body as PrimaryCtorDecl).getOrThrow()
            println("主构造函数: ")
            println("函数名: ${primaryInit.identifier.value}")
            println("参数列表: ${primaryInit.funcParams.toTokens()}")

            println("参数列表中的成员变量参数")
            let params = primaryInit.funcParams
            for (param in params) {
                if (param.isMemberParam()) {
                    println("${param.identifier.value}")
                }
            }
        }

        if (body is FuncDecl) {
            let initBody = (body as FuncDecl).getOrThrow()
            if (initBody.identifier.value == "init") {
                println("普通构造函数:")
                println("函数名: ${initBody.identifier.value}")
                println("参数列表: ${initBody.funcParams.toTokens()}")
            }
            println("函数声明: \n${body.toTokens()}")
        }
    }
}

八、遍历AST节点

package Study
// 导包
import Study.define.*
import std.ast.*

class MyVisitor <: Visitor {
    protected override func visit(funcDecl: FuncDecl) {
        println("函数名: ${funcDecl.identifier.value}")
        // breakTraverse用于重写visit函数,子节点将不会被调用
        breakTraverse()
    }

    protected override func visit(incOrDecExpr: IncOrDecExpr) {
        println(incOrDecExpr.toTokens())
    }
}

main () {
    let tokens = quote(
        class Demo {
            let x: Int64 = 3
            let y: Int64 = 4

            func add() {
                this.x + this.y
            }

            func sub() {
                this.x - this.y
            }
        }
    )

    let classDecl = ClassDecl(tokens)
    classDecl.traverse(MyVisitor())
}

九、小结

本章为大家详细的介绍了仓颉编程语言中AST的内容,下一章,为大家带来非属性宏和属性宏的内容。最后,创作不易,如果大家觉得我的文章对学习仓颉服务端开发有帮助的话,就动动小手,点个免费的赞吧!收到的赞越多,我的创作动力也会越大哦,谢谢大家🌹🌹🌹!!!

Logo

昇腾计算产业是基于昇腾系列(HUAWEI Ascend)处理器和基础软件构建的全栈 AI计算基础设施、行业应用及服务,https://devpress.csdn.net/organization/setting/general/146749包括昇腾系列处理器、系列硬件、CANN、AI计算框架、应用使能、开发工具链、管理运维工具、行业应用及服务等全产业链

更多推荐