You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Chevrotain解析器中实现数组支持以开发支持数组运算的计算器

实现方案

你提到的按索引多次运行访问器的思路完全可行,Chevrotain场景下有两种低改造成本的实现路径:

方案一:单轮AST遍历 + 广播式运算

该方案仅需遍历一次AST,性能更优:

  • 第一步:统一所有叶子节点输出格式
    • 普通整数标量统一转为与最长运算数组长度一致的填充数组,例如标量2对应长度为5的数组时转成[2,2,2,2,2]
    • 变量节点直接返回映射表中对应的数组,提前校验所有参与运算的数组长度一致,避免维度不匹配报错
  • 第二步:修改运算节点访问器逻辑,对输入的两个数组做逐位运算,示例如下:
// 加法节点访问器示例
addOperation: (node) => {
  const leftVal = this.visit(node.leftChild)
  const rightVal = this.visit(node.rightChild)
  return leftVal.map((item, idx) => item + rightVal[idx])
}

乘法、括号等其他运算节点按相同逻辑改造即可,根节点最终返回的就是完整的结果数组。

方案二:多轮按索引求值(你原思路的落地实现)

该方案不需要修改原有运算节点逻辑,改造成本更低:

  • 第一步:修改变量节点访问器,增加可选索引入参:
// 变量节点访问器示例
variableNode: (node, index = null) => {
  const varName = node.varName
  const val = map[varName]
  // 传入索引时返回对应下标的标量,否则返回完整值
  return Array.isArray(val) && index !== null ? val[index] : val
}
  • 第二步:外层按数组长度循环调用访问器,收集结果:
const result = []
// 提前获取所有数组的统一长度
const arrayLength = map.array1.length
for (let i = 0; i < arrayLength; i++) {
  // 每次调用传入当前索引,返回当前位的运算结果
  const singleRes = visitor.visit(astRoot, i)
  result.push(singleRes)
}

注意:两种方案都需要提前做边界校验,保证所有参与运算的数组长度一致,避免下标越界问题。

内容的提问来源于stack exchange,提问作者eakl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 18:06:04