如何编写解析器为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
相关产品推荐
相关产品推荐

