preface
Before using
Kotlin writes an interpreter (1) – lexical analysis,
Kotlin writes an interpreter (2) – syntax analysis,
We get an abstract syntax tree, by traversing the abstract syntax tree, we can get the corresponding calculation results.
To calculate
Through the subsequent traversal, we can get the corresponding calculation results.
class Interpreter(private val parser: Parser) {
fun interpret(a):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")}}}}Copy the code
We define an Interpreter class that holds the Parser reference, and by using the Parse method of Parser, we get an abstract syntax tree. Let’s create a visit method, and we’re going to follow through the abstract syntax tree, why we’re going to follow through, because we said earlier when we got the abstract syntax tree, we’re going to keep the priority of the operation by the depth of the node, and we’re going to keep it that way. Previously, our abstract syntax tree had only two types of nodes: BinOp, which represented the operator, left and right child nodes, which represented the computed value, and Num, which represented the concrete value. When the node type is BinOp, the values returned by the left and right children visit are added, subtracted, multiplied and divided according to their tokenType. If the node is Num, the corresponding parameter values are directly returned.
The last
So the whole four operations are basically implemented, write the test code.
fun main(a) {
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()}")}}Copy the code
Related articles
The code has been uploaded to Github and will be updated to CompilerDemo
Kotlin writes an interpreter (1) – lexical analysis
Kotlin writes an interpreter (2) – syntax analysis
Follow my public account “Old Arsenic on skateboard”