阅读 109
Kotlin写一个解释器(3)---解释执行

Kotlin写一个解释器(3)---解释执行

前言

之前通过

Kotlin写一个解释器(1)---词法分析

Kotlin写一个解释器(2)---语法分析

我们得到了一个抽象语法树,通过遍历抽象语法树,我们就可以得到相应的计算结果。

计算

通过后续遍历,我们可以得到相应的计算结果。

class Interpreter(private val parser: Parser) {
    fun interpret():Int {
        val ast = parser.parse()
        return visit(ast)
    }

    private fun visit(ast: AST): Int {
        when (ast) {
            is BinOp -> {
                return when (ast.op.tokenType) {
                    TokenType.PLUS -> {
                        visit(ast.left) + visit(ast.right)
                    }
                    TokenType.MIN -> {
                        visit(ast.left) - visit(ast.right)
                    }
                    TokenType.MUL -> {
                        visit(ast.left) * visit(ast.right)
                    }
                    TokenType.DIV -> {
                        visit(ast.left) / visit(ast.right)
                    }
                    else -> {
                        throw RuntimeException("error ast")
                    }
                }
            }
            is Num -> {
                return ast.token.value.toInt()
            }
            else -> {
                throw RuntimeException("error ast")
            }
        }
    }
}
复制代码

我们定义一个Interpreter类,该来持有Parser引用,通过条用Parser的parse方法,我们可以得到一个抽象语法树。创建一个visit方法,这里我们后续遍历抽象语法树,为什么采用后序遍历,因为之前在得到抽象语法树的时候,我们曾经说过,通过节点的深度我们来保证运算的优先级,后续遍历帮我们保持了这种特性。之前我们的抽象语法树只有两种类型的节点,一是BinOp,用来代表运算符,左右两个子节点为计算的值,一个是Num,代表具体的数值。当节点类型是BinOp的时候,根据他们的tokenType,将它的左右子节点visit后返回的值进行加减乘除相应的处理,如果是Num节点,则直接返回相应参数值。

最后

这样整个一个四则运算基本就实现了,写上测试代码。

fun main() {
    while (true) {
        val scanner = Scanner(System.`in`)
        val text = scanner.nextLine()
        val lexer = Lexer(text)
//        var nextToken = lexer.getNextToken()
//        while (TokenType.EOF != nextToken.tokenType) {
//            println(nextToken.toString())
//            nextToken = lexer.getNextToken()
//        }
        val parser = Parser(lexer)
        val interpreter=Interpreter(parser)
        println("result is ${interpreter.interpret()}")
    }
}
复制代码

相关文章

代码已经上传到github,后续会不断更新 CompilerDemo

Kotlin写一个解释器(1)---词法分析

Kotlin写一个解释器(2)---语法分析

关注我的公众号”滑板上的老砒霜“

文章分类
Android
文章标签