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

如何编写解析器为a.b[c.d][e].f[g[h[i.j]]]生成JS AST MemberExpression

标准MemberExpression构造实现

核心逻辑遵循JS成员表达式的左递归规则:每一个新的成员访问,都会将已解析的部分作为object,新的属性作为property,生成新的MemberExpression节点。嵌套方括号内的表达式通过递归解析+上下文判断即可完成构造。

// 分词规则兼容原实现逻辑
const tokenPatterns = [
  [/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*/, 'name'],
  [/^\[/, 'open'],
  [/^\]/, 'close'],
  [/^\./, 'dot']
]

// 第一步:将输入字符串拆分为结构化token
function tokenize(str) {
  const tokens = []
  let remaining = str
  while (remaining.length) {
    let matched = false
    for (const [regex, type] of tokenPatterns) {
      const match = remaining.match(regex)
      if (match) {
        tokens.push({ type, value: match[0] })
        remaining = remaining.slice(match[0].length)
        matched = true
        break
      }
    }
    if (!matched) throw new Error(`无效字符:${remaining[0]}`)
  }
  return tokens
}

// 第二步:解析token生成MemberExpression AST
function parseMemberAST(tokens) {
  let pos = 0

  // 解析基础节点(标识符/括号内嵌套表达式)
  function parsePrimary() {
    const token = tokens[pos]
    if (token.type === 'name') {
      pos++
      return { type: 'Identifier', name: token.value }
    }
    if (token.type === 'open') {
      pos++ // 消费左括号
      const expr = parseExpr()
      if (tokens[pos]?.type !== 'close') throw new Error('括号未闭合')
      pos++ // 消费右括号
      return expr
    }
    throw new Error(`位置${pos}出现无效token:${token.type}`)
  }

  // 解析成员表达式链
  function parseExpr() {
    let node = parsePrimary()
    while (pos < tokens.length) {
      const nextToken = tokens[pos]
      // 处理点号访问
      if (nextToken.type === 'dot') {
        pos++
        const prop = parsePrimary()
        node = {
          type: 'MemberExpression',
          object: node,
          property: prop,
          computed: false
        }
      // 处理方括号访问
      } else if (nextToken.type === 'open') {
        pos++
        const prop = parseExpr()
        if (tokens[pos]?.type !== 'close') throw new Error('括号未闭合')
        pos++
        node = {
          type: 'MemberExpression',
          object: node,
          property: prop,
          computed: true
        }
      } else {
        break
      }
    }
    return node
  }

  return parseExpr()
}

// 测试运行
const tokens = tokenize('a.b[c.d][e].f[g[h[i.j]]]')
const ast = parseMemberAST(tokens)
console.log(JSON.stringify(ast, null, 2))

上述代码运行输出的AST和你给出的标准MemberExpression结构完全匹配。如果需要生成自定义链式结构,只需要修改解析阶段的节点生成逻辑,将每次的成员访问项推入数组,嵌套括号内的表达式对应sink类型节点即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 04:06:06