Вычисление деревьев синтаксического анализа

После создания полного анализатора и преобразования текста в AST1 мы можем теперь оценить его. Оценка AST состоит из Visitor.Callback или простого обратного вызова лямбды. Ниже приведен базовый пример использования вымышленной грамматики:

val parser = constructParser()

val (node, _) = parser.parse(input)

// simple visiting, such as finding all nodes of a particular type and not caring about the structure
node.visit { node ->
    // do something with each node as it is entered in the tree
}

// alternatively, visit with a full set of callbacks to also introspect the parse-tree's structure
node.visit(object : Visitor.Callback {
    var depth: Int = 0
    override fun enter(node: Node) {
        depth++
    }
    override fun exit(node: Node) {
        depth--
    }
    override fun onStart() { }
    override fun onFinish() { }
})

А вот уже мой пример, который использует грамматику из прошлых примеров. Носколько такой пример корректен — не знаю.

package com.github.KuzyaGlebkin

import com.copperleaf.kudzu.node.Node
import com.copperleaf.kudzu.visitor.Visitor
import com.copperleaf.kudzu.parser.ParserContext
import com.copperleaf.kudzu.parser.expression.ExpressionParser
import com.copperleaf.kudzu.parser.expression.Operator
import com.copperleaf.kudzu.parser.value.IntLiteralParser
import com.copperleaf.kudzu.visit

fun Int.pow(exponentVal: Int): Int {
    val base = this
    var exponent = exponentVal
    var result: Int = if (exponentVal >= 0) { 1 } else { 0 }

    while (exponent > 0) {
        result *= base
        exponent -= 1
    }

    return result
}
fun constructParser() : ExpressionParser<Int> {
    return ExpressionParser<Int>(
        termParser = { IntLiteralParser() },

        // precedence — приоритет
        Operator.Infix(op = "+", precedence = 40) { l, r -> l + r },
        Operator.Infix(op = "-", precedence = 40) { l, r -> l - r },
        Operator.Infix(op = "*", precedence = 60) { l, r -> l * r },
        Operator.Infix(op = "/", precedence = 60) { l, r -> l / r },

        Operator.Prefix(op = "-", precedence = 80) { r -> -r },
        Operator.Infixr(op = "^", precedence = 70) { l, r -> l.pow(r) },
    )
}

fun main() {
    val parser = constructParser()
    val input = ParserContext.fromString("2 ^ ((4 - 2) * 2) + 2 ^ (-3)", skipWhitespace = true)

    val (node, _) = parser.parse(input)

// simple visiting, such as finding all nodes of a particular type and not caring about the structure
    node.visit { node ->
        println(node)
    }

// alternatively, visit with a full set of callbacks to also introspect the parse-tree's structure
    node.visit(object : Visitor.Callback {
        var depth: Int = 0
        override fun enter(node: Node) {
            depth++
        }
        override fun exit(node: Node) {
            depth--
        }
        override fun onStart() { }
        override fun onFinish() { }
    })
}
1

До этого говорилось, что Кудзу не создает абстрактное синтаксическое дерево, что тут имелось в виду спрошу у автора. Update Автор сказал, что обновит документацию в следующим релизе.