kotlin - 在 Kotlin 中编写附加访问者函数
问题描述
我正在尝试在 Kotlin 中编写一个将两个整数相加的访问者函数。我一直在处理一些示例代码,但我无法弄清楚这些.value
或.visit
功能是什么。它似乎没有在示例代码中声明,所以我不确定如何在我的代码中声明它。每当我编译代码时,我都会收到一条错误消息,指出该值是未解析的引用。
相关的 Kotlin 代码:
package backend
import org.antlr.v4.runtime.*
import grammar.*
abstract class Data
class IntData(val value: Int): Data() {
override fun toString(): String
= "Int($value)"
}
class Context(): HashMap<String, Data>() {
constructor(parent: Context): this() {
this.putAll(parent)
}
}
abstract class Expr {
abstract fun eval(scope: Context): Data
fun run(program: Expr) {
try {
val data = program.eval(Context())
println("=> ${data}")
} catch(e: Exception) {
println("[err] ${e}")
}
}
}
class IntLiteral(val value: Int): Expr() {
override fun eval(scope:Context): Data
= IntData(value)
}
enum class Op {
Add,
Sub,
Mul,
Div
}
class Arithmetic(
val op: Op,
val left: Expr,
val right: Expr): Expr() {
override fun eval(scope: Context): Data {
val x = (left.eval(scope) as IntData).value
val y = (right.eval(scope) as IntData).value
return IntData(
when(op) {
Op.Add -> x + y
Op.Mul -> x * y
Op.Sub -> x - y
Op.Div -> x / y
}
)
}
}
}
class Compiler: PLBaseVisitor<Expr>() {
val scope = mutableMapOf<String, Expr>()
override fun visitAddExpr(ctx: PLParser.AddExprContext): Expr {
val xValue = this.visit(ctx.x)
val yValue = this.visit(ctx.y)
val result = xValue.value + yValue.value
return IntLiteral(result)
}
}
相关 Antlr 语法:
expr : x=expr '+' y=expr # addExpr
| x=expr '-' y=expr # subExpr
| x=expr '*' y=expr # mulExpr
| x=expr '/' y=expr # divExpr
;
我试图执行的代码:
val test = """
x=1+2
print(x)
"""
fun parse(source: String): PLParser.ProgramContext {
val input = CharStreams.fromString(source)
val lexer = PLLexer(input)
val tokens = CommonTokenStream(lexer)
val parser = PLParser(tokens)
}
val testTree = parse(source1)
val testTree = parse(source1)
fun execute(program: Expr?) {
if(program == null) {
println("Program is null.")
return
}
try {
val data = program.eval(Context())
println("> ${data}")
} catch(e: Exception) {
println("[err] ${e}")
}
}
execute(testProgram)
示例代码:
data class NodeValue(val value: Int)
val visitor = object: CalcBaseVisitor<NodeValue>() {
override fun visitAddition(ctx: CalcParser.AdditionContext): NodeValue {
val xValue = this.visit(ctx.x)
val yValue = this.visit(ctx.y)
return NodeValue(xValue.value + yValue.value)
}
override fun visitValue(ctx: CalcParser.ValueContext): NodeValue {
val lexeme = ctx.Number().getText()
return NodeValue(lexeme.toInt())
}
}
解决方案
您没有显示您的program.eval()
方法的代码。
eval 函数需要创建一个访问者的实例。(你已经做到了并称之为visitor
)。
您的program
变量中也有根 expr 节点。
现在您将让您的访问者“访问”该节点并保存返回值:
val nodeVal = visitor.visit(program)
那时nodeVal.value
将有访问该表达式的结果。
注意:由于您正在对访问者进行评估,因此您的Arithmetic
课程实际上没有任何用处(除非您重构访问者以使用它而不是仅仅进行数学运算,但作为访问者,我认为这没有多大价值已经很容易阅读了)。
推荐阅读
- node.js - 无法启动 chrome [致命:zygote_host_impl_linux.cc(116)] 没有可用的沙箱
- python - 如何按升序复制数据框中的单元格,直到达到另一个数字?熊猫
- .htaccess - 如何使用引导程序隐藏php中的文件夹结构
- python - matplotlib 条形图自动标准化我的数据
- javascript - 如何检查变量是否不是假的,但 0 在 Javascript 中通过
- android - React 本机 android 构建失败,任务 ':app:lintVitalRelease' 执行失败。无法下载 groovy-all-2..4.15.jar
- mongodb - 在 Spring Data mongo DB 中,我们如何获取城市及其级别数
- python - 数字生成的复杂序列提供了一个意想不到的产品
- json - spring boot json到模型转换错误
- c - 我可以在 C 程序中创建多少个线程,它与我的 CPU 拥有的线程数有什么关系?