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

如何用JavaScript结合PEG.js解析带上下文变量的ODK XForm计算表达式?

实现ODK XForm计算表达式解析器的PEG.js方案

核心思路

PEG.js可以直接生成带语义动作的解析器,将用户输入的表达式解析成结构化的AST(抽象语法树),再通过遍历AST结合上下文执行计算,完全规避直接执行用户代码的安全风险。针对concat("hello", ${some_field})这类表达式,我们可以分语法解析和AST执行两步实现需求。

步骤1:编写PEG.js语法规则

先针对ODK XForm计算表达式的核心语法(函数调用、变量引用、字符串字面量)定义PEG.js规则,解析时直接生成描述执行逻辑的AST节点。

创建odk-expression.pegjs文件,内容如下:

// 起始入口
start = expression

// 表达式:支持函数调用、变量、字符串字面量
expression = functionCall / variable / stringLiteral

// 函数调用规则:匹配类似concat(arg1, arg2)的结构
functionCall = identifier "(" (expression ("," expression)*)? ")" {
  return {
    type: 'functionCall',
    name: text().split('(')[0],
    args: Array.from(arguments[2] || [])
  };
}

// 变量引用规则:匹配${some_field}格式
variable = "${" identifier "}" {
  return {
    type: 'variable',
    name: text().slice(2, -1)
  };
}

// 字符串字面量规则:匹配带双引号的字符串
stringLiteral = "\"" chars:([^"]*) "\"" {
  return {
    type: 'string',
    value: chars.join('')
  };
}

// 标识符规则:匹配函数名、变量名
identifier = [a-zA-Z_][a-zA-Z0-9_]*

用PEG.js命令行工具生成解析器:

pegjs odk-expression.pegjs

生成的odk-expression.js就是可直接导入的解析模块。

步骤2:实现AST执行器

编写execute函数,遍历解析得到的AST,结合上下文和预设的ODK内置函数完成计算:

const Parser = require('./odk-expression');

// 预设ODK内置函数白名单
const builtInFunctions = {
  concat: (...args) => args.join(''),
  // 可扩展其他ODK函数:sum、if、boolean等
};

function execute(ast, context) {
  switch (ast.type) {
    case 'functionCall':
      // 先递归解析所有参数
      const resolvedArgs = ast.args.map(arg => execute(arg, context));
      if (!builtInFunctions[ast.name]) {
        throw new Error(`未知函数: ${ast.name}`);
      }
      return builtInFunctions[ast.name](...resolvedArgs);
    case 'variable':
      if (!(ast.name in context)) {
        throw new Error(`未找到变量: ${ast.name}`);
      }
      return context[ast.name];
    case 'string':
      return ast.value;
    default:
      throw new Error(`未知节点类型: ${ast.type}`);
  }
}

// 使用示例
const expr = 'concat("hello", ${some_field})';
const ast = Parser.parse(expr);
const result = execute(ast, { some_field: 'world' });
console.log(result); // 输出 "helloworld"

关键安全保障

  • 禁用动态代码执行:完全通过AST遍历执行逻辑,绝不使用eval或new Function处理用户输入。
  • 函数白名单机制:仅允许预设的ODK内置函数,禁止调用任意JS全局函数。
  • 上下文隔离:仅暴露用户指定的变量,避免访问敏感全局对象。

扩展建议

  • 补充更多ODK语法支持:添加数字字面量、算术/逻辑运算、条件表达式等规则,完善PEG.js语法定义。
  • 优化错误提示:在PEG.js中添加错误捕获规则,返回更精准的解析错误位置和信息。
  • AST缓存:对重复执行的表达式缓存解析后的AST,提升执行效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 18:27:36